Cookies info

This website uses Google cookies to analyse traffic. Information about your use of our site is shared with Google for that purpose. See details.

How to use AmanithVG in a multi-thread application/environment

AmanithVG is thread-safe: all the exposed functions can be called from multiple threads at the same time. When using AmanithVG in a multi-thread application, you have to take some important aspects into consideration:

Here is a general example of a possible multi-thread application that uses AmanithVG to draw vector graphic contents concurrently:

// global mutex
Mutex mutex;
// global list of OpenVG contents to be rendered by threads
ContentsList contents;
// index of the next OpenVG content to be rendered
int current;

static void threadRender(Content c,
                         void* vgContext) {

    // create an OpenVG drawing surface; in general, surface
    // dimensions are dictated by the content itself
    void* vgSurface = vgPrivSurfaceCreateMZT(c.width, c.height,
                                             // non-linear premultiplied color space
                                             VG_FALSE, VG_TRUE,
                                             // alpha mask enabled
    // get the actual dimensions
    int width = vgPrivGetSurfaceWidthMZT(vgSurface);
    int height = vgPrivGetSurfaceHeightMZT(vgSurface);

    // bind context and surface
    vgPrivMakeCurrentMZT(vgContext, vgSurface);

    // clear the drawing surface
    vgClear(0, 0, width, height);

    // OpenVG rendering code, according to content

    // AmanithVG GLE
    // use the native OpenGL (ES) swap buffers function, or do
    // something with the bound OpenGL framebuffer object
    // AmanithVG SRE
    // get surface pixels by calling vgPrivGetSurfacePixelsMZT(vgSurface)
    // and do something with them (e.g. dump a PNG, send the content
    // via network, blit the pixels on screen, ...)

    // acknowledge AmanithVG that we have performed a swapbuffers-like operation

    // unbind context and surface
    vgPrivMakeCurrentMZT(NULL, NULL);

    // destroy the OpenVG drawing surface

// thread function
static void threadFunc(void) {

    bool done = false;
    // create and initialize an OpenVG context
    void* vgContext = vgPrivContextCreateMZT(NULL);

    while (!done) {
        // lock the global mutex
        // if there are still OpenVG contents to render...
        if (current < contents.count) {
            // ... extract the next one
            Content c = contents[current++];
            // unlock the global mutex
            // draw it
            threadRender(c, vgContext);
        else {
            // unlock the global mutex
            // there are no more SVG to render, this thread can exit
            done = true;

    // destroy the OpenVG context

// main entry point
int main(int argc,
         char *argv[]) {

    int i;
    ThreadList threads;
    // the maximum number of different threads that can "work"
    // (e.g. create surfaces, draw paths, etc) concurrently
    // in AmanithVG
    int vgThreads = (int)vgConfigGetMZT(VG_CONFIG_MAX_CURRENT_THREADS_MZT);
    // get the number of concurrent threads supported by the
    // hardware/os platform
    int hardwareThreads = hardware_concurrency();
    // the actual number of threads that we'll spawn
    int maxThreads = min(vgThreads, hardwareThreads);

    // initialize AmanithVG library, after initialization it is possible
    // to create contexts and drawing surfaces; in a multi-thread program
    // it is recommended to initialize the library once before the creation
    // of threads

    // set quality parameters
    // set other parameters, if desired...

    // spwan rendering threads
    for (i = 0; i < maxThreads; i++) {
        // start a new thread

    // wait for all threads to finish
    for (i = 0; i < threads.count; i++) {

    // release AmantihVG library

    return EXIT_SUCCESS;