Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[mesa.git] / src / egl / main / eglcontext.c
index 461679db0906068c439e4ffde414afc56dc7444a..b094f49bfc16fcfd332db77cb99cf27dd0ee3675 100644 (file)
  * in the attrib_list.
  */
 EGLBoolean
-_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
-                EGLConfig config, const EGLint *attrib_list)
+_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
+                _EGLConfig *conf, const EGLint *attrib_list)
 {
-   _EGLConfig *conf;
-   _EGLDisplay *display = _eglLookupDisplay(dpy);
    EGLint i;
    const EGLenum api = eglQueryAPI();
 
@@ -27,12 +25,6 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
       return EGL_FALSE;
    }
 
-   conf = _eglLookupConfig(drv, dpy, config);
-   if (!conf) {
-      _eglError(EGL_BAD_CONFIG, "_eglInitContext");
-      return EGL_FALSE;
-   }
-
    memset(ctx, 0, sizeof(_EGLContext));
 
    ctx->ClientVersion = 1; /* the default, per EGL spec */
@@ -49,7 +41,6 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
       }
    }
 
-   ctx->Display = display;
    ctx->Config = conf;
    ctx->DrawSurface = EGL_NO_SURFACE;
    ctx->ReadSurface = EGL_NO_SURFACE;
@@ -59,89 +50,28 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
 }
 
 
-/**
- * Save a new _EGLContext into the hash table.
- */
-void
-_eglSaveContext(_EGLContext *ctx)
-{
-   /* no-op.
-    * Public EGLContext handle and private _EGLContext are the same.
-    */
-}
-
-
-/**
- * Remove the given _EGLContext object from the hash table.
- */
-void
-_eglRemoveContext(_EGLContext *ctx)
-{
-   /* no-op.
-    * Public EGLContext handle and private _EGLContext are the same.
-    */
-}
-
-
-/**
- * Return the public handle for the given private context ptr.
- * This is the inverse of _eglLookupContext().
- */
-EGLContext
-_eglGetContextHandle(_EGLContext *ctx)
-{
-   /* just a cast! */
-   return (EGLContext) ctx;
-}
-
-
-/**
- * Return the _EGLContext object that corresponds to the given
- * EGLContext handle.
- * This is the inverse of _eglGetContextHandle().
- */
-_EGLContext *
-_eglLookupContext(EGLContext ctx)
-{
-   /* just a cast since EGLContext is just a void ptr */
-   return (_EGLContext *) ctx;
-}
-
-
-/**
- * Return the currently bound _EGLContext object, or NULL.
- */
-_EGLContext *
-_eglGetCurrentContext(void)
-{
-   _EGLThreadInfo *t = _eglGetCurrentThread();
-   return t->CurrentContext;
-}
-
-
 /**
  * Just a placeholder/demo function.  Real driver will never use this!
  */
-EGLContext
-_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
-                  EGLContext share_list, const EGLint *attrib_list)
+_EGLContext *
+_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+                  _EGLContext *share_list, const EGLint *attrib_list)
 {
 #if 0 /* example code */
    _EGLContext *context;
 
    context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
    if (!context)
-      return EGL_NO_CONTEXT;
+      return NULL;
 
-   if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
+   if (!_eglInitContext(drv, context, conf, attrib_list)) {
       free(context);
-      return EGL_NO_CONTEXT;
+      return NULL;
    }
 
-   _eglSaveContext(context);
-   return (EGLContext) context;
+   return context;
 #endif
-   return EGL_NO_CONTEXT;
+   return NULL;
 }
 
 
@@ -149,39 +79,21 @@ _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
  * Default fallback routine - drivers should usually override this.
  */
 EGLBoolean
-_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
+_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
 {
-   _EGLContext *context = _eglLookupContext(ctx);
-   if (context) {
-      if (context->IsBound) {
-         context->DeletePending = EGL_TRUE;
-      }
-      else {
-         free(context);
-      }
-      return EGL_TRUE;
-   }
-   else {
-      _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
-      return EGL_TRUE;
-   }
+   if (!_eglIsContextBound(ctx))
+      free(ctx);
+   return EGL_TRUE;
 }
 
 
 EGLBoolean
-_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
+_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
                  EGLint attribute, EGLint *value)
 {
-   _EGLContext *c = _eglLookupContext(ctx);
-
    (void) drv;
    (void) dpy;
 
-   if (!c) {
-      _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
-      return EGL_FALSE;
-   }
-
    switch (attribute) {
    case EGL_CONFIG_ID:
       *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
@@ -203,90 +115,100 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
 
 /**
  * Drivers will typically call this to do the error checking and
- * update the various IsBound and DeletePending flags.
+ * update the various flags.
  * Then, the driver will do its device-dependent Make-Current stuff.
  */
 EGLBoolean
-_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
-                EGLSurface r, EGLContext context)
+_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
+                _EGLSurface *read, _EGLContext *ctx)
 {
    _EGLThreadInfo *t = _eglGetCurrentThread();
-   _EGLContext *ctx = _eglLookupContext(context);
-   _EGLSurface *draw = _eglLookupSurface(d);
-   _EGLSurface *read = _eglLookupSurface(r);
+   _EGLContext *oldContext = NULL;
+   _EGLSurface *oldDrawSurface = NULL;
+   _EGLSurface *oldReadSurface = NULL;
+   EGLint apiIndex;
 
-   _EGLContext *oldContext = _eglGetCurrentContext();
-   _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
-   _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
+   if (_eglIsCurrentThreadDummy())
+      return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
 
-   /* error checking */
    if (ctx) {
-      if (draw == NULL || read == NULL) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
-      if (draw->Config != ctx->Config) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
-      if (read->Config != ctx->Config) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
+      /* error checking */
+      if (ctx->Binding && ctx->Binding != t)
+         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+      if (draw == NULL || read == NULL)
+         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+      if (draw->Config != ctx->Config || read->Config != ctx->Config)
+         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+      if ((draw->Binding && draw->Binding->Binding != t) ||
+          (read->Binding && read->Binding->Binding != t))
+         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+
+#ifdef EGL_VERSION_1_4
+      /* OpenGL and OpenGL ES are conflicting */
+      switch (ctx->ClientAPI) {
+      case EGL_OPENGL_ES_API:
+         if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
+            return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+         break;
+      case EGL_OPENGL_API:
+         if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
+            return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+         break;
+      default:
+         break;
       }
+#endif
+      apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
+   }
+   else {
+      if (draw != NULL || read != NULL)
+         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+      apiIndex = t->CurrentAPIIndex;
    }
 
-   /*
-    * check if the old context or surfaces need to be deleted
-    */
-   if (oldDrawSurface != NULL) {
-      oldDrawSurface->IsBound = EGL_FALSE;
-      if (oldDrawSurface->DeletePending) {
-         /* make sure we don't try to rebind a deleted surface */
-         if (draw == oldDrawSurface || draw == oldReadSurface) {
-            draw = NULL;
-         }
-         /* really delete surface now */
-         drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
+   oldContext = t->CurrentContexts[apiIndex];
+   if (oldContext) {
+      oldDrawSurface = oldContext->DrawSurface;
+      oldReadSurface = oldContext->ReadSurface;
+      assert(oldDrawSurface);
+      assert(oldReadSurface);
+
+      /* break old bindings */
+      t->CurrentContexts[apiIndex] = NULL;
+      oldContext->Binding = NULL;
+      oldContext->DrawSurface = NULL;
+      oldContext->ReadSurface = NULL;
+      oldDrawSurface->Binding = NULL;
+      oldReadSurface->Binding = NULL;
+
+      /*
+       * check if the old context or surfaces need to be deleted
+       */
+      if (!_eglIsSurfaceLinked(oldDrawSurface)) {
+         assert(draw != oldDrawSurface && read != oldDrawSurface);
+         drv->API.DestroySurface(drv, dpy, oldDrawSurface);
       }
-   }
-   if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
-      oldReadSurface->IsBound = EGL_FALSE;
-      if (oldReadSurface->DeletePending) {
-         /* make sure we don't try to rebind a deleted surface */
-         if (read == oldDrawSurface || read == oldReadSurface) {
-            read = NULL;
-         }
-         /* really delete surface now */
-         drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
+      if (oldReadSurface != oldDrawSurface &&
+          !_eglIsSurfaceLinked(oldReadSurface)) {
+         assert(draw != oldReadSurface && read != oldReadSurface);
+         drv->API.DestroySurface(drv, dpy, oldReadSurface);
       }
-   }
-   if (oldContext != NULL) {
-      oldContext->IsBound = EGL_FALSE;
-      if (oldContext->DeletePending) {
-         /* make sure we don't try to rebind a deleted context */
-         if (ctx == oldContext) {
-            ctx = NULL;
-         }
-         /* really delete context now */
-         drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext));
+      if (!_eglIsContextLinked(oldContext)) {
+         assert(ctx != oldContext);
+         drv->API.DestroyContext(drv, dpy, oldContext);
       }
    }
 
+   /* build new bindings */
    if (ctx) {
-      /* check read/draw again, in case we deleted them above */
-      if (draw == NULL || read == NULL) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
+      t->CurrentContexts[apiIndex] = ctx;
+      ctx->Binding = t;
       ctx->DrawSurface = draw;
       ctx->ReadSurface = read;
-      ctx->IsBound = EGL_TRUE;
-      draw->IsBound = EGL_TRUE;
-      read->IsBound = EGL_TRUE;
+      draw->Binding = ctx;
+      read->Binding = ctx;
    }
 
-   t->CurrentContext = ctx;
-
    return EGL_TRUE;
 }