egl: Initialize display configs with the display.
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d.c
index aa4f01221694fc6247b5a51435a8b82189e6ad13..8a73e81d4ac0d94c432162e0a4bf642ea768d707 100644 (file)
@@ -243,17 +243,6 @@ egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
    return EGL_TRUE;
 }
 
-/**
- * Return the current context of the given API.
- */
-static struct egl_g3d_context *
-egl_g3d_get_current_context(EGLint api)
-{
-   _EGLThreadInfo *t = _eglGetCurrentThread();
-   EGLint api_index = _eglConvertApiToIndex(api);
-   return egl_g3d_context(t->CurrentContexts[api_index]);
-}
-
 /**
  * Return the state tracker for the given context.
  */
@@ -475,18 +464,18 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
       struct egl_g3d_config *gconf;
       EGLBoolean valid;
 
+      gconf = CALLOC_STRUCT(egl_g3d_config);
+      if (!gconf)
+         continue;
+
+      _eglInitConfig(&gconf->base, dpy, id);
+
       api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
       if (!api_mask) {
          _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
                native_configs[i]->mode.visualID);
-         continue;
       }
 
-      gconf = CALLOC_STRUCT(egl_g3d_config);
-      if (!gconf)
-         continue;
-
-      _eglInitConfig(&gconf->base, id);
       valid = _eglConfigFromContextModesRec(&gconf->base,
             &native_configs[i]->mode, api_mask, api_mask);
       if (valid) {
@@ -642,7 +631,7 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
       return NULL;
    }
 
-   if (!_eglInitContext(drv, &gctx->base, conf, attribs)) {
+   if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
       free(gctx);
       return NULL;
    }
@@ -672,21 +661,30 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
    return &gctx->base;
 }
 
-static EGLBoolean
-egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+/**
+ * Destroy a context.
+ */
+static void
+destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
 {
    struct egl_g3d_context *gctx = egl_g3d_context(ctx);
 
-   if (_eglIsContextBound(&gctx->base))
-      return EGL_TRUE;
+   /* FIXME a context might live longer than its display */
+   if (!dpy->Initialized)
+      _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
 
    egl_g3d_realloc_context(dpy, &gctx->base);
-
-   /* it will destroy pipe context */
+   /* it will destroy the associated pipe context */
    gctx->stapi->st_destroy_context(gctx->st_ctx);
 
    free(gctx);
+}
 
+static EGLBoolean
+egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+   if (!_eglIsContextBound(ctx))
+      destroy_context(dpy, ctx);
    return EGL_TRUE;
 }
 
@@ -715,7 +713,7 @@ egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) {
+   if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) {
       free(gsurf);
       return NULL;
    }
@@ -755,7 +753,7 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) {
+   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) {
       free(gsurf);
       return NULL;
    }
@@ -792,7 +790,7 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!_eglInitSurface(drv, &gsurf->base, EGL_PBUFFER_BIT, conf, attribs)) {
+   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
       free(gsurf);
       return NULL;
    }
@@ -817,17 +815,28 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
    return &gsurf->base;
 }
 
-static EGLBoolean
-egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+/**
+ * Destroy a surface.
+ */
+static void
+destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
 {
    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
 
-   if (_eglIsSurfaceBound(&gsurf->base))
-         return EGL_TRUE;
+   /* FIXME a surface might live longer than its display */
+   if (!dpy->Initialized)
+      _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
 
    pipe_surface_reference(&gsurf->render_surface, NULL);
    gsurf->native->destroy(gsurf->native);
    free(gsurf);
+}
+
+static EGLBoolean
+egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+{
+   if (!_eglIsSurfaceBound(surf))
+      destroy_surface(dpy, surf);
    return EGL_TRUE;
 }
 
@@ -836,18 +845,14 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
                      _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
 {
    struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+   struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
    struct egl_g3d_context *old_gctx;
-   EGLint api;
    EGLBoolean ok = EGL_TRUE;
 
-   /* find the old context */
-   api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI();
-   old_gctx = egl_g3d_get_current_context(api);
-   if (old_gctx && !_eglIsContextLinked(&old_gctx->base))
-         old_gctx = NULL;
-
-   if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
+   /* bind the new context and return the "orphaned" one */
+   if (!_eglBindContext(&ctx, &draw, &read))
       return EGL_FALSE;
+   old_gctx = egl_g3d_context(ctx);
 
    if (old_gctx) {
       /* flush old context */
@@ -863,8 +868,6 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
    }
 
    if (gctx) {
-      struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
-
       ok = egl_g3d_realloc_context(dpy, &gctx->base);
       if (ok) {
          ok = gctx->stapi->st_make_current(gctx->st_ctx,
@@ -884,6 +887,13 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
       old_gctx->base.WindowRenderBuffer = EGL_NONE;
    }
 
+   if (ctx && !_eglIsContextLinked(ctx))
+      destroy_context(dpy, ctx);
+   if (draw && !_eglIsSurfaceLinked(draw))
+      destroy_surface(dpy, draw);
+   if (read && read != draw && !_eglIsSurfaceLinked(read))
+      destroy_surface(dpy, read);
+
    return ok;
 }
 
@@ -1077,7 +1087,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
                        _EGLSurface *surf, EGLint buffer)
 {
    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-   struct egl_g3d_context *gctx;
+   _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
+   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
    enum pipe_format target_format;
    int target;
 
@@ -1108,14 +1119,12 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
    }
 
    /* flush properly if the surface is bound */
-   if (gsurf->base.Binding) {
-      gctx = egl_g3d_context(gsurf->base.Binding);
+   if (gsurf->base.CurrentContext) {
+      gctx = egl_g3d_context(gsurf->base.CurrentContext);
       gctx->stapi->st_flush(gctx->st_ctx,
             PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
    }
 
-   /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
-   gctx = egl_g3d_get_current_context(EGL_OPENGL_API);
    if (gctx) {
       if (!gsurf->render_surface)
          return EGL_FALSE;
@@ -1141,10 +1150,8 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
       return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
 
    if (gsurf->render_surface) {
-      _EGLThreadInfo *t = _eglGetCurrentThread();
-      /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
-      struct egl_g3d_context *gctx = egl_g3d_context(
-            t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]);
+      _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
+      struct egl_g3d_context *gctx = egl_g3d_context(ctx);
 
       /* what if the context the surface binds to is no longer current? */
       if (gctx)
@@ -1173,7 +1180,7 @@ egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!_eglInitSurface(drv, &gsurf->base,
+   if (!_eglInitSurface(&gsurf->base, dpy,
             EGL_SCREEN_BIT_MESA, conf, attribs)) {
       free(gsurf);
       return NULL;