Masking problem

I have problem with an OpenVG application (on OMAP3530) whereby whenever masking is used everything slows up and eventually hangs. Masking works on a one-off basis but repetitive masking operations causes the failure. The following code causes the problem…

#include <VG/openvg.h>
#include <EGL/egl.h>
#include <stdio.h>

int main()
{
VGPath m_avgPath[2];
VGPaint m_avgColourPaint[2];
EGLDisplay eglDisplay = 0;
EGLConfig eglConfig = 0;
EGLSurface eglSurface = 0;
EGLContext eglContext = 0;
EGLint i32NumConfigs, i32MajorVersion, i32MinorVersion;

EGLNativeWindowType sWindow = (EGLNativeWindowType)0;
eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);
if(!eglInitialize(eglDisplay, &i32MajorVersion, &i32MinorVersion))
{
    printf("Error: eglInitialize() failed.

");
goto cleanup;
}

eglBindAPI(EGL_OPENVG_API);

static const EGLint ai32ConfigAttribs[] =
{
    EGL_LEVEL,          0,
    EGL_BUFFER_SIZE,         16,
    EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
    EGL_NONE
};

if(!eglChooseConfig(eglDisplay, ai32ConfigAttribs, &eglConfig, 1, &i32NumConfigs) || (i32NumConfigs != 1))
{
    printf("Error: eglChooseConfig() failed.

");
goto cleanup;
}

eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, sWindow, NULL);
if((eglGetError() != EGL_SUCCESS) || (eglSurface == EGL_NO_SURFACE))
{
    printf("Error: eglCreateWindowSurface() failed.

");
goto cleanup;
}

eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
if((eglGetError() != EGL_SUCCESS) || (eglContext == EGL_NO_CONTEXT))
{
    printf("Error: eglCreateContext() failed.

");
goto cleanup;
}

eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
if(eglGetError() != EGL_SUCCESS)
{
    printf("Error: eglMakeCurrent() failed.

");
goto cleanup;
}

EGLint i32WindowWidth, i32WindowHeight;
eglQuerySurface(eglDisplay, eglSurface, EGL_WIDTH, &i32WindowWidth);
eglQuerySurface(eglDisplay, eglSurface, EGL_HEIGHT, &i32WindowHeight);

vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();

VGfloat afClearColor[4];
afClearColor[0] = 0.0f;
afClearColor[1] = 0.0f;
afClearColor[2] = 0.0f;
afClearColor[3] = 1.0f;

vgSetfv(VG_CLEAR_COLOR, 4, afClearColor);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);

float fWidth = i32WindowWidth * 0.5f;
float fHeight= i32WindowHeight * 0.5f;

m_avgPath[0] = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 4, 3, (unsigned int)VG_PATH_CAPABILITY_ALL);
VGubyte aui8PathSegments[4] = {
    VG_MOVE_TO,
    VG_LINE_TO,
    VG_LINE_TO,
    VG_CLOSE_PATH,
};
VGfloat afPoints[6] = {
        fWidth - 80.0f, fHeight - 50.0f,
        fWidth + 80.0f, fHeight - 50.0f,
        fWidth, fHeight + 80.0f
};
vgAppendPathData(m_avgPath[0], 4, aui8PathSegments, afPoints);

m_avgPath[1] = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 5, 4, (unsigned int)VG_PATH_CAPABILITY_ALL);
VGubyte aui8PathSegments2[5] = {
    VG_MOVE_TO,
    VG_LINE_TO,
    VG_LINE_TO,
    VG_LINE_TO,
    VG_CLOSE_PATH
};
VGfloat afPoints2[8] = {
        fWidth - 20.0f, fHeight - 20.0f,
        fWidth + 20.0f, fHeight - 20.0f,
        fWidth + 20.0f, fHeight + 20.0f,
        fWidth - 20.0f, fHeight + 20.0f
};

vgAppendPathData(m_avgPath[1], 5, aui8PathSegments2, afPoints2);

m_avgColourPaint[0] = vgCreatePaint();
vgSetParameteri(m_avgColourPaint[0], VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetColor(m_avgColourPaint[0], 0xFFFFAAFF);

int i;
for(i = 0; i &lt; 100; ++i)
{
    VGfloat afClearColour[] = { 0.6f, 0.8f, 1.0f, 1.0f };
    vgSetfv(VG_CLEAR_COLOR, 4, afClearColour);
    vgClear(0, 0, i32WindowWidth, i32WindowHeight);
    vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, i32WindowWidth, i32WindowHeight);
    vgRenderToMask(m_avgPath[1], VG_FILL_PATH, VG_SET_MASK);
    vgSeti(VG_MASKING, VG_TRUE);
    vgSetPaint(m_avgColourPaint[0], VG_FILL_PATH);
    vgDrawPath(m_avgPath[0], VG_STROKE_PATH | VG_FILL_PATH);
    vgSeti(VG_MASKING, VG_FALSE);

    eglSwapBuffers(eglDisplay, eglSurface);
    if (eglGetError() != EGL_SUCCESS)
    {
        printf("Error!

");
}
}

eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(eglDisplay);

return 0;

}

The code simply draws a triangle through a small square mask. It draws successfully and takes approx one second for each repetition until it finally freezes. Maybe im not doing it right but any help would be much appreciated.

Thanx in advance

If I had to guess (besides the obvious - “it’s a driver bug”), I’d say you’re drawing too quickly. What’s probably happening is that each vgMask call is allocating a screen sized buffer for the mask. The call is dispatched to be drawn, and your loop continues. Because the first render call is still drawing, it can’t free the memory used for the first alpha mask and hence it allocates another one. Since you’re rendering faster than the render can keep up, you keep allocating more and more graphics memory until things come to screeching halt.
Try putting a vgFinish() after the eglSwapBuffers() and see if it alleviates the problem. (if it doesn’t, it sounds like just a plain memory leak in the driver.)

Thanks for your reply Ivo. Your guess does make alot of sense, i tend to agree its probably a memory leak problem. Unfortunately using vgFinish has no effect. I guess ill see if TI have any ideas. Cheers

Hi there,

Sorry to hear you are having trouble with masking performance, I’m unsure what the conditions of the problem are, but if you can provide a bit more info about the platform and driver version, that could help.

One thing I have noticed that you could try, is to remove the vgMask command that is clearing the mask each frame, this is redundant as the vgRenderToMask call with VG_SET_MASK will completely replace the mask contents.

Without knowing what your app will eventually be doing, one thing I can also recommend is that if the mask contents are static (i.e. not animating from frame to frame) then just set it up once before you start rendering, the mask buffer is persistent across frames.

If you are still having issues with your OMAP/SGX/OpenVG platform in particular then please by all means get in touch with the developer relations team here at Imagination Technologies either directly, or via our forums, and we can try and assist you.

Kind Regards,

Alex

Masks didn’t perform so well with some older SGX drivers, if by some chance the driver your using is based on one of these older drivers, it’s possible you might see the same issues.

You can see if your driver vendor has any driver updates.

-Joel