eglGetDisplay now returns the same display handle for every call.
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Fri, 29 Jun 2012 13:28:21 +0000 (17:28 +0400)
committerEvgeny Voevodin <e.voevodin@samsung.com>
Fri, 6 Jul 2012 08:29:02 +0000 (12:29 +0400)
Fixed races in gles.
Replaced unpack alignment with pack/unpack alignment.

hw/gles2.c
hw/gles2.h
hw/gles2_egl_calls.c
hw/gles2_escommon_calls.c
hw/gles2_kernel_calls.c

index 00928a7..82cbcf8 100644 (file)
@@ -535,6 +535,7 @@ void *gles2_init(CPUArchState *env)
     s->env = env;
     s->abi = gles2_abi_arm_hardfp;
     s->quality = gles2_quality;
+    pthread_mutex_init(&s->m, NULL);
 
     GLES2_PRINT("GLES2 quality: %d\n", s->quality);
 
@@ -593,6 +594,7 @@ gles2_ebo* gles2_ebo_find(unsigned int name, gles2_ebo* list)
 gles2_ebo* gles2_ebo_add(unsigned int name, gles2_ebo* list)
 {
     gles2_ebo* ebo = malloc(sizeof(gles2_ebo));
+    memset(ebo, 0, sizeof(*ebo));
     ebo->name = name;
     ebo->data = NULL;
     ebo->next = NULL;
index e653bec..76af97f 100644 (file)
@@ -250,6 +250,7 @@ struct gles2_State
     MemoryRegion io_egl;
     MemoryRegion io_es11;
     MemoryRegion io_es20;
+    pthread_mutex_t m;
 };
 
 #if(GLES2_DEBUG==1)
index d29c7b7..5db62ad 100644 (file)
@@ -108,9 +108,23 @@ GLES2_CB(eglGetDisplay)
     GLES2_PRINT("\tGot host display %p...\n", dpy);
 
     GLES2_BARRIER_RET;
-    gles2_ret_TEGLDisplay(s, gles2_handle_create(s, dpy));
 
-    dpy_updatecaption(get_displaystate());
+    pthread_mutex_lock(&s->m);
+
+    uint32_t handle = gles2_handle_find(s, dpy);
+
+    if (!handle)
+    {
+        handle = gles2_handle_create(s, dpy);
+        gles2_ret_TEGLDisplay(s, handle);
+        dpy_updatecaption(get_displaystate());
+    }
+    else
+    {
+        gles2_ret_TEGLDisplay(s, handle);
+    }
+
+    pthread_mutex_unlock(&s->m);
 }
 
 GLES2_CB(eglInitialize)
@@ -119,16 +133,20 @@ GLES2_CB(eglInitialize)
     GLES2_ARG(Tptr, majorp);
     GLES2_ARG(Tptr, minorp);
 
-    GLES2_BARRIER_ARG_NORET;
+    GLES2_BARRIER_ARG;
+
+    pthread_mutex_lock(&s->m);
 
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
 
+    pthread_mutex_unlock(&s->m);
+
     GLES2_PRINT("Request to initialize display %p...\n", dpy);
 
     EGLint major, minor;
     if (eglInitialize(dpy, &major, &minor)) {
         GLES2_PRINT("Display initialized (EGL %d.%d)!\n", major, minor);
-        //GLES2_BARRIER_RET;
+        GLES2_BARRIER_RET;
         gles2_put_TEGLint(s, majorp, major);
         gles2_put_TEGLint(s, minorp, minor);
         gles2_ret_TEGLBoolean(s, EGL_TRUE);
@@ -136,7 +154,7 @@ GLES2_CB(eglInitialize)
     }
 
     GLES2_PRINT("Failed to initialize...\n");
-    //GLES2_BARRIER_RET;
+    GLES2_BARRIER_RET;
     gles2_ret_TEGLBoolean(s, EGL_FALSE);
 }
 
@@ -149,8 +167,12 @@ GLES2_CB(eglGetConfigs)
 
     GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
+
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
 
+    pthread_mutex_unlock(&s->m);
+
     EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
 
     EGLint num_config;
@@ -160,6 +182,7 @@ GLES2_CB(eglGetConfigs)
     if (configs) {
         EGLint i;
 
+        pthread_mutex_lock(&s->m);
         for (i = 0; i < num_config; ++i) {
             uint32_t handle;
             if (!(handle = gles2_handle_find(s, configs[i]))) {
@@ -167,6 +190,7 @@ GLES2_CB(eglGetConfigs)
             }
             gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
         }
+        pthread_mutex_unlock(&s->m);
 
         free(configs);
     }
@@ -199,18 +223,24 @@ GLES2_CB(eglChooseConfig)
     }
     attrib_list[attrib_list_n] = EGL_NONE;
 
+    pthread_mutex_lock(&s->m);
+
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
 
-    GLES2_BARRIER_ARG_NORET;
+    pthread_mutex_unlock(&s->m);
+
+    GLES2_BARRIER_ARG;
     EGLConfig* configs = configsp ? malloc(sizeof(EGLConfig)*config_size) : NULL;
 
     EGLint num_config;
     EGLBoolean ret = eglChooseConfig(dpy, attrib_list, configs, config_size, &num_config);
     free(attrib_list);
-    //GLES2_BARRIER_RET;
+    GLES2_BARRIER_RET;
     if (configs) {
         EGLint i;
 
+        pthread_mutex_lock(&s->m);
+
         for (i = 0; i < num_config; ++i) {
             uint32_t handle;
             if (!(handle = gles2_handle_find(s, configs[i]))) {
@@ -219,6 +249,8 @@ GLES2_CB(eglChooseConfig)
             gles2_put_TEGLConfig(s, configsp + i*sizeof(TEGLConfig), handle);
         }
 
+        pthread_mutex_unlock(&s->m);
+
         free(configs);
     }
     gles2_put_TEGLint(s, num_configp, num_config);
@@ -234,12 +266,15 @@ GLES2_CB(eglGetConfigAttrib)
     GLES2_ARG(Tptr, valuep);
     GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
 
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
 
     EGLint value;
     EGLBoolean ret = eglGetConfigAttrib(dpy, gles2_handle_get(s, config), attribute, &value);
 
+    pthread_mutex_unlock(&s->m);
+
     GLES2_BARRIER_RET;
 
     gles2_put_TEGLint(s, valuep, value);
@@ -253,9 +288,13 @@ GLES2_CB(eglCreateWindowSurface)
     GLES2_ARG(Tptr, winp);
     GLES2_ARG(Tptr, attrib_listp);
 
+    pthread_mutex_lock(&s->m);
 
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
+
+    pthread_mutex_unlock(&s->m);
+
     (void)attrib_listp;
 
     gles2_Surface* fsurf;
@@ -268,6 +307,8 @@ GLES2_CB(eglCreateWindowSurface)
         return;
     }
 
+    memset(fsurf, 0, sizeof(*fsurf));
+
     fsurf->id = surf_id++;
 
     fsurf->ddrawp = winp;
@@ -299,7 +340,11 @@ GLES2_CB(eglCreateWindowSurface)
     GLES2_PRINT("Created at %p!\n", fsurf);
     GLES2_BARRIER_RET;
     gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
+    pthread_mutex_lock(&s->m);
+
     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
+
+    pthread_mutex_unlock(&s->m);
 }
 
 GLES2_CB(eglCreatePixmapSurface)
@@ -309,8 +354,13 @@ GLES2_CB(eglCreatePixmapSurface)
     GLES2_ARG(Tptr, pixmapp);
     GLES2_ARG(Tptr, attrib_listp);
 
+    pthread_mutex_lock(&s->m);
+
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
+
+    pthread_mutex_unlock(&s->m);
+
     (void)attrib_listp;
 
     gles2_Surface* fsurf;
@@ -323,6 +373,8 @@ GLES2_CB(eglCreatePixmapSurface)
         return;
     }
 
+    memset(fsurf, 0, sizeof(*fsurf));
+
     fsurf->id = surf_id++;
     fsurf->ddrawp = pixmapp;
     fsurf->pixmap = 1;
@@ -354,7 +406,9 @@ GLES2_CB(eglCreatePixmapSurface)
     GLES2_PRINT("Created at %p!\n", fsurf);
     GLES2_BARRIER_RET;
     gles2_transfer_compile(&fsurf->tfr, s, fsurf->pixelsp, nbytes);
+    pthread_mutex_lock(&s->m);
     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
+    pthread_mutex_unlock(&s->m);
 }
 
 GLES2_CB(eglCreatePbufferSurface)
@@ -363,8 +417,10 @@ GLES2_CB(eglCreatePbufferSurface)
     GLES2_ARG(TEGLConfig, config_);
     GLES2_ARG(Tptr, attrib_listp);
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
+    pthread_mutex_unlock(&s->m);
      EGLint attrib_list_n = 0;
     while (gles2_get_TEGLint(s, attrib_listp
         + attrib_list_n*sizeof(EGLint)) != EGL_NONE) {
@@ -389,6 +445,8 @@ GLES2_CB(eglCreatePbufferSurface)
         return;
     }
 
+    memset(fsurf, 0, sizeof(*fsurf));
+
     fsurf->id = surf_id++;
 
     fsurf->ddrawp = 0;
@@ -407,7 +465,9 @@ GLES2_CB(eglCreatePbufferSurface)
 
     GLES2_PRINT("Created at %p!\n", fsurf);
     GLES2_BARRIER_RET;
+    pthread_mutex_lock(&s->m);
     gles2_ret_TEGLSurface(s, gles2_handle_create(s, fsurf));
+    pthread_mutex_unlock(&s->m);
 }
 
 GLES2_CB(eglDestroySurface)
@@ -416,9 +476,11 @@ GLES2_CB(eglDestroySurface)
     GLES2_ARG(TEGLSurface, surface_);
     GLES2_BARRIER_ARG_NORET;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Surface* fsurf = (EGLSurface)gles2_handle_get(s, surface_);
     gles2_handle_free(s, surface_);
+    pthread_mutex_unlock(&s->m);
 
     GLES2_PRINT("Destroyed surface ID = %d...\n", fsurf->id);
     fsurf->id = -1;
@@ -440,8 +502,10 @@ GLES2_CB(eglBindTexImage)
     GLES2_ARG(TEGLint, buffer);
     gles2_CompiledTransfer tfr;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Surface* fsurf = (gles2_Surface*)gles2_handle_get(s, surface_);
+    pthread_mutex_unlock(&s->m);
 
     // FIXME: Not a very clean way..
     uint32_t pixelsp = gles2_get_dword(s, fsurf->ddrawp + 4*sizeof(uint32_t));
@@ -475,8 +539,10 @@ GLES2_CB(eglReleaseTexImage)
     GLES2_ARG(TEGLint, buffer);
     GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Surface* fsurf = (gles2_Surface*)gles2_handle_get(s, surface_);
+    pthread_mutex_unlock(&s->m);
 
     GLES2_PRINT("Unbinding surface ID = %d!\n", fsurf->id);
 
@@ -491,11 +557,12 @@ GLES2_CB(eglCreateContext)
     GLES2_ARG(TEGLConfig, config_);
     GLES2_ARG(TEGLContext, share_context_);
     GLES2_ARG(Tptr, attrib_listp);
-    GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     EGLConfig config = (EGLConfig)gles2_handle_get(s, config_);
     gles2_Context* share_context = gles2_handle_get(s, share_context_);
+    pthread_mutex_unlock(&s->m);
 
 
     EGLint *attribs= NULL;
@@ -516,7 +583,7 @@ GLES2_CB(eglCreateContext)
                     + i*sizeof(EGLint));
         }
     }
-
+    GLES2_BARRIER_ARG;
     GLES2_PRINT("Host context creation requested...\n");
     EGLContext hctx = eglCreateContext(dpy, config, share_context?share_context->hctx:NULL, attribs);
     GLES2_BARRIER_RET;
@@ -527,6 +594,7 @@ GLES2_CB(eglCreateContext)
         gles2_ret_TEGLContext(s, 0);
     } else {
         gles2_Context * ctx = malloc(sizeof(gles2_Context));
+        memset(ctx, 0, sizeof(*ctx));
         ctx->hctx = hctx;
         int version = 1;
         //if OpenGL ES check for client version from attrib_list
@@ -556,8 +624,11 @@ GLES2_CB(eglCreateContext)
         ctx->ebo_list->next = NULL;
         if (attribs)
             free(attribs);
+        memset(ctx->ebo_list, 0, sizeof(*ctx->ebo_list));
         GLES2_PRINT("Created at %p!\n", ctx);
+        pthread_mutex_lock(&s->m);
         gles2_ret_TEGLContext(s, gles2_handle_create(s, ctx));
+        pthread_mutex_unlock(&s->m);
     }
 }
 
@@ -567,6 +638,7 @@ GLES2_CB(eglDestroyContext)
     GLES2_ARG(TEGLContext, ctx_);
     GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Context* ctx = (gles2_Context*) gles2_handle_get(s, ctx_);
     EGLBoolean ret = eglDestroyContext(dpy, ctx->hctx);
@@ -578,6 +650,7 @@ GLES2_CB(eglDestroyContext)
         gles2_handle_free(s, ctx_);
         GLES2_PRINT("Destroyed %p!\n", ctx);
     }
+    pthread_mutex_unlock(&s->m);
 
     GLES2_BARRIER_RET;
     gles2_ret_TEGLBoolean(s,ret);
@@ -591,10 +664,21 @@ GLES2_CB(eglMakeCurrent)
     GLES2_ARG(TEGLContext, ctx_);
     GLES2_BARRIER_ARG;
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Surface* draw = (EGLSurface)gles2_handle_get(s, draw_);
     gles2_Surface* read = (EGLSurface)gles2_handle_get(s, read_);
     gles2_Context* ctx = (gles2_Context*)gles2_handle_get(s, ctx_);
+    pthread_mutex_unlock(&s->m);
+
+    if (!dpy)
+    {
+        /*
+         * Evas sets 'dpy' to NULL and calls this function after it
+         * destroys a context
+         */
+        dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    }
 
     GLES2_PRINT("Making host context current...\n");
 
@@ -623,11 +707,7 @@ GLES2_CB(eglMakeCurrent)
             }
             int i;
             for (i = 0; i < ctx->narrays; ++i) {
-                    ctx->arrays[i].type = GL_NONE;
-                    ctx->arrays[i].enabled = 0;
-                    ctx->arrays[i].ptr = 0;
-                    ctx->arrays[i].apply = 0;
-                    ctx->arrays[i].tptr = 0;
+                    memset(&ctx->arrays[i], 0, sizeof(ctx->arrays[i]));
             }
         }
     }
@@ -645,8 +725,10 @@ GLES2_CB(eglSwapBuffers)
     GLES2_ARG(TEGLDisplay, dpy_);
     GLES2_ARG(TEGLSurface, surface_);
 
+    pthread_mutex_lock(&s->m);
     EGLDisplay dpy = (EGLDisplay)gles2_handle_get(s, dpy_);
     gles2_Surface* fsurf = (EGLSurface)gles2_handle_get(s, surface_);
+    pthread_mutex_unlock(&s->m);
     if (!fsurf) {
         fprintf(stderr, "ERROR: Trying to swap NULL surface!\n");
         GLES2_BARRIER_ARG;
index 7e31424..3aafdfe 100644 (file)
@@ -16,11 +16,11 @@ static unsigned gles2_glTexParameterCount(TGLenum pname)
     return count;
 }
 
-static unsigned gles2_get_stride(unsigned width, unsigned bpp)
+static unsigned gles2_get_stride(GLuint alignment_type, unsigned width, unsigned bpp)
 {
     unsigned alignment = 0;
 
-    hgl.glGetIntegerv(GL_UNPACK_ALIGNMENT, (GLint *)&alignment);
+    hgl.glGetIntegerv(alignment_type, (GLint *)&alignment);
 
     if (!alignment)
     {
@@ -845,7 +845,7 @@ GLES2_CB(glReadPixels)
 
         GLES2_PRINT("Reading %dx%dx%d image at %d,%d...\n",
                     width, height, bpp, x, y);
-        nbytes = height*gles2_get_stride(width, bpp);
+        nbytes = height*gles2_get_stride(GL_PACK_ALIGNMENT, width, bpp);
         pixels = malloc(nbytes);
     }
     hgl.glReadPixels(x, y, width, height, format, type, pixels);
@@ -933,7 +933,7 @@ GLES2_CB(glTexImage2D)
     GLES2_PRINT("Uploading %dx%dx%d image...\n", width, height, bpp);
     char* pixels = NULL;
     if (pixelsp && width > 0 && height > 0) {
-        TGLsizei nbytes = height*gles2_get_stride(width, bpp);
+        TGLsizei nbytes = height*gles2_get_stride(GL_UNPACK_ALIGNMENT, width, bpp);
         pixels = malloc(nbytes);
         gles2_transfer(s, pixelsp, nbytes, pixels, 0);
     }
@@ -1039,7 +1039,7 @@ GLES2_CB(glTexSubImage2D)
 
     char *pixels = NULL;
     if (pixelsp && width > 0 && height > 0) {
-        TGLsizei nbytes = height*gles2_get_stride(width, bpp);
+        TGLsizei nbytes = height*gles2_get_stride(GL_UNPACK_ALIGNMENT, width, bpp);
         pixels = malloc(nbytes);
         gles2_transfer(s, pixelsp, nbytes, pixels, 0);
     }
index 0b2a425..e995be9 100644 (file)
@@ -48,6 +48,7 @@ GLES2_CB(init)
     GLES2_PRINT("Selected ABI %d\n", s->abi);
 
     client = malloc(sizeof(*client));
+    memset(client, 0, sizeof(*client));
     client->s = s;
     client->nr = i + 1;
     client->rendering_api = EGL_OPENGL_ES_API;