LWJGL Forum

Programming => Bug Reports / RFE => Topic started by: mudlee on December 01, 2019, 09:10:23

Title: NVG memleak?
Post by: mudlee on December 01, 2019, 09:10:23
When I draw an image with NV (after it was rasterized from SVG), after a while my app get killed by osx. Any idea?

I have no problem with drawing other images.

https://gist.github.com/mudlee/ad4d36dfde5ca04d2adf7f2bf76dc2e7 (https://gist.github.com/mudlee/ad4d36dfde5ca04d2adf7f2bf76dc2e7)
Title: Re: NVG memleak?
Post by: spasi on December 01, 2019, 11:43:07
The crash looks like a double-free bug. It also looks like there's rendering going on inside an event callback. Could you please post an MCVE (https://stackoverflow.com/help/minimal-reproducible-example)?
Title: Re: NVG memleak?
Post by: mudlee on December 01, 2019, 15:34:33
Well, yes and no. I have very limited time and the rendering code (https://github.com/mudlee/spck (https://github.com/mudlee/spck)) I wrote is at a complexity level where to provide a MCVE takes a little bit more time, but I try to copy here some code parts that might be interesting.

Image rendering:
Code: [Select]
public void beginFrame(int screenWidth, int screenHeight, int devicePixelRatio) {
        nvgBeginFrame(pointer, screenWidth, screenHeight, devicePixelRatio);
        nvgFontFace(pointer, defaultFont);
    }

    public void endFrame() {
        nvgEndFrame(pointer);
        restoreGLState();
    }

    public void renderImage(UIImage image) {
        checkIfInitialised();

        int width = image.getWidth();
        int height = image.getHeight();
        float x = image.getScreenCoords().x;
        float y = image.getScreenCoords().y;

        if(image.handle==null){
            image.handle = nvglCreateImageFromHandle(pointer, image.getTextureId(), width, height, 0);
        }

        //int imageID = nvglCreateImageFromHandle(pointer, image.getTextureId(), width, height, 0);
        NVGPaint paint = NVGPaint.create();
        nvgImagePattern(pointer, x, y, width, height, 0, image.handle, 1f, paint);
        nvgBeginPath(pointer);
        nvgRect(pointer, x, y, width, height);
        nvgFillPaint(pointer, paint);
        nvgFill(pointer);
    }

Texture Creation:
Code: [Select]
long rast = nsvgCreateRasterizer();

        float scaleX = Engine.window.getPreferences().getDeviceScaleX().orElseThrow();
        float scaleY = Engine.window.getPreferences().getDeviceScaleY().orElseThrow();
        int width = (int) (svg.width() * scaleX);
        int height = (int) (svg.height() * scaleY);

        ByteBuffer image = memAlloc(width * height * 4);
        nsvgRasterize(rast, svg, 0, 0, min(scaleX, scaleY), image, width, height, width * 4);
        nsvgDeleteRasterizer(rast);

        // creating texture
        int id = GL.genTextureContext(GL41.GL_TEXTURE_2D, textureId -> {
            GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_MAG_FILTER, GL41.GL_LINEAR);
            GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_MIN_FILTER, GL41.GL_LINEAR);
            GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_WRAP_S, GL41.GL_CLAMP_TO_EDGE);
            GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_WRAP_T, GL41.GL_CLAMP_TO_EDGE);

            premultiplyAlpha(image, width, height, width * 4);

            GL41.glTexImage2D(GL41.GL_TEXTURE_2D, 0, GL41.GL_RGBA, width, height, 0, GL41.GL_RGBA, GL41.GL_UNSIGNED_BYTE, image);
        });