glx: Refactor and simplify context creation
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 23 Jul 2010 20:15:31 +0000 (16:15 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Sat, 24 Jul 2010 02:05:53 +0000 (22:05 -0400)
This lets us better separate context creation between the different
backends.

src/glx/dri2_glx.c
src/glx/dri_glx.c
src/glx/drisw_glx.c
src/glx/glxclient.h
src/glx/glxcmds.c
src/glx/glxext.c

index 02c0f9f24eec084eda7ac4228d511d141660ecf1..58f09ed86af66f9e63fffd5f8b39c1b1c40144f8 100644 (file)
@@ -154,9 +154,9 @@ dri2UnbindContext(__GLXcontext *context)
 }
 
 static __GLXcontext *
-dri2CreateContext(__GLXscreenConfigs *base,
-                  const __GLcontextModes * mode,
-                  GLXContext shareList, int renderType)
+dri2_create_context(__GLXscreenConfigs *base,
+                   const __GLcontextModes * mode,
+                   GLXContext shareList, int renderType)
 {
    struct dri2_context *pcp, *pcp_shared;
    struct dri2_screen *psc = (struct dri2_screen *) base;
@@ -718,6 +718,9 @@ dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions)
    }
 }
 
+static const struct glx_screen_vtable dri2_screen_vtable = {
+   dri2_create_context
+};
 
 static __GLXscreenConfigs *
 dri2CreateScreen(int screen, __GLXdisplayPrivate * priv)
@@ -811,10 +814,10 @@ dri2CreateScreen(int screen, __GLXdisplayPrivate * priv)
 
    psc->driver_configs = driver_configs;
 
+   psc->base.vtable = &dri2_screen_vtable;
    psp = &psc->vtable;
    psc->base.driScreen = psp;
    psp->destroyScreen = dri2DestroyScreen;
-   psp->createContext = dri2CreateContext;
    psp->createDrawable = dri2CreateDrawable;
    psp->swapBuffers = dri2SwapBuffers;
    psp->getDrawableMSC = NULL;
index ff7ca5ef7d6b9b48a7bb6d02b145983217c66956..95cded792d916417cef047e11010e22c35360583 100644 (file)
@@ -550,9 +550,9 @@ static const struct glx_context_vtable dri_context_vtable = {
 };
 
 static __GLXcontext *
-driCreateContext(__GLXscreenConfigs *base,
-                 const __GLcontextModes * mode,
-                 GLXContext shareList, int renderType)
+dri_create_context(__GLXscreenConfigs *base,
+                  const __GLcontextModes *mode,
+                  GLXContext shareList, int renderType)
 {
    struct dri_context *pcp, *pcp_shared;
    struct dri_screen *psc = (struct dri_screen *) base;
@@ -821,6 +821,10 @@ driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
    }
 }
 
+static const struct glx_screen_vtable dri_screen_vtable = {
+   dri_create_context
+};
+
 static __GLXscreenConfigs *
 driCreateScreen(int screen, __GLXdisplayPrivate *priv)
 {
@@ -882,13 +886,13 @@ driCreateScreen(int screen, __GLXdisplayPrivate *priv)
    extensions = psc->core->getExtensions(psc->driScreen);
    driBindExtensions(psc, extensions);
 
+   psc->base.vtable = &dri_screen_vtable;
    psp = &psc->vtable;
    psc->base.driScreen = psp;
    if (psc->driCopySubBuffer)
       psp->copySubBuffer = driCopySubBuffer;
 
    psp->destroyScreen = driDestroyScreen;
-   psp->createContext = driCreateContext;
    psp->createDrawable = driCreateDrawable;
    psp->swapBuffers = driSwapBuffers;
 
index c971de2f76fb52e09c366a9d317f60e4480aebd6..4265f564120a87564ec66f76d753fc35d0145517 100644 (file)
@@ -289,9 +289,9 @@ static const struct glx_context_vtable drisw_context_vtable = {
 };
 
 static __GLXcontext *
-driCreateContext(__GLXscreenConfigs *base,
-                const __GLcontextModes *mode,
-                GLXContext shareList, int renderType)
+drisw_create_context(__GLXscreenConfigs *base,
+                    const __GLcontextModes *mode,
+                    GLXContext shareList, int renderType)
 {
    struct drisw_context *pcp, *pcp_shared;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
@@ -426,6 +426,10 @@ driOpenSwrast(void)
    return driver;
 }
 
+static const struct glx_screen_vtable drisw_screen_vtable = {
+   drisw_create_context
+};
+
 static __GLXscreenConfigs *
 driCreateScreen(int screen, __GLXdisplayPrivate *priv)
 {
@@ -482,10 +486,10 @@ driCreateScreen(int screen, __GLXdisplayPrivate *priv)
 
    psc->driver_configs = driver_configs;
 
+   psc->base.vtable = &drisw_screen_vtable;
    psp = &psc->vtable;
    psc->base.driScreen = psp;
    psp->destroyScreen = driDestroyScreen;
-   psp->createContext = driCreateContext;
    psp->createDrawable = driCreateDrawable;
    psp->swapBuffers = driSwapBuffers;
 
index 20c452913152ff9e964ccb7982dd39973cc61f94..48b5501fe9ee292fd53302055000956a618ced5d 100644 (file)
@@ -504,8 +504,16 @@ extern void __glFreeAttributeState(__GLXcontext *);
  * One of these records exists per screen of the display.  It contains
  * a pointer to the config data for that screen (if the screen supports GL).
  */
+struct glx_screen_vtable {
+   __GLXcontext *(*create_context)(__GLXscreenConfigs *psc,
+                                  const __GLcontextModes *mode,
+                                  GLXContext shareList, int renderType);
+};
+
 struct __GLXscreenConfigsRec
 {
+   const struct glx_screen_vtable *vtable;
+
     /**
      * GLX extension string reported by the X-server.
      */
@@ -799,4 +807,7 @@ GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable);
 
 #endif
 
+extern __GLXscreenConfigs *
+indirect_create_screen(int screen, __GLXdisplayPrivate * priv);
+
 #endif /* !__GLX_client_h__ */
index 72ac3ecd7d7fc38b30f4020c83f60514c7eb427a..1ded6247ef3642db0fd2b3e3195f7daad6830289 100644 (file)
@@ -234,6 +234,55 @@ ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
    return NULL;
 }
 
+#ifdef GLX_USE_APPLEGL
+
+static const struct glx_context_vtable applegl_context_vtable;
+
+static __GLcontext *
+applegl_create_context(__GLXscreenConfigs *psc,
+                       const __GLcontextModes *mode,
+                       GLXContext shareList, int renderType)
+{
+   __GLXcontext *gc;
+   int errorcode;
+   bool x11error;
+
+   /* TODO: Integrate this with apple_glx_create_context and make
+    * struct apple_glx_context inherit from __GLXcontext. */
+
+   gc = Xmalloc(sizeof *gc);
+   if (pcp == NULL)
+      return NULL;
+
+   memset(gc, 0, sizeof *gc);
+   if (!glx_context_init(&gc->base, &psc->base, mode)) {
+      Xfree(gc);
+      return NULL;
+   }
+
+   gc->vtable = &applegl_context_vtable;
+   gc->driContext = NULL;
+   gc->do_destroy = False;
+
+   /* TODO: darwin: Integrate with above to do indirect */
+   if(apple_glx_create_context(&gc->driContext, dpy, screen, fbconfig, 
+                              shareList ? shareList->driContext : NULL,
+                              &errorcode, &x11error)) {
+      __glXSendError(dpy, errorcode, 0, X_GLXCreateContext, x11error);
+      gc->vtable->destroy(gc);
+      return NULL;
+   }
+
+   gc->currentContextTag = -1;
+   gc->mode = fbconfig;
+   gc->isDirect = allowDirect;
+   gc->xid = 1; /* Just something not None, so we know when to destroy
+                * it in MakeContextCurrent. */
+
+   return gc;
+}
+#endif
+
 
 /**
  * \todo It should be possible to move the allocate of \c client_state_private
@@ -246,17 +295,16 @@ ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
  * does all the initialization (including the pixel pack / unpack).
  */
 static GLXContext
-AllocateGLXContext(Display * dpy)
+indirect_create_context(__GLXscreenConfigs *psc,
+                       const __GLcontextModes *mode,
+                       GLXContext shareList, int renderType)
 {
    GLXContext gc;
    int bufSize;
    CARD8 opcode;
    __GLXattribute *state;
 
-   if (!dpy)
-      return NULL;
-
-   opcode = __glXSetupForCommand(dpy);
+   opcode = __glXSetupForCommand(psc->dpy);
    if (!opcode) {
       return NULL;
    }
@@ -269,6 +317,8 @@ AllocateGLXContext(Display * dpy)
    }
    memset(gc, 0, sizeof(struct __GLXcontextRec));
 
+   glx_context_init(gc, psc, mode);
+   gc->isDirect = GL_FALSE;
    gc->vtable = &indirect_context_vtable;
    state = Xmalloc(sizeof(struct __GLXattributeRec));
    if (state == NULL) {
@@ -287,7 +337,7 @@ AllocateGLXContext(Display * dpy)
     ** packet for the GLXRenderReq header.
     */
 
-   bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
+   bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
    gc->buf = (GLubyte *) Xmalloc(bufSize);
    if (!gc->buf) {
       Xfree(gc->client_state_private);
@@ -339,14 +389,31 @@ AllocateGLXContext(Display * dpy)
    }
    gc->maxSmallRenderCommandSize = bufSize;
    
-#ifdef GLX_USE_APPLEGL
-   gc->driContext = NULL;
-   gc->do_destroy = False;   
-#endif
 
    return gc;
 }
 
+struct glx_screen_vtable indirect_screen_vtable = {
+   indirect_create_context
+};
+
+_X_HIDDEN __GLXscreenConfigs *
+indirect_create_screen(int screen, __GLXdisplayPrivate * priv)
+{
+   __GLXscreenConfigs *psc;
+
+   psc = Xmalloc(sizeof *psc);
+   if (psc == NULL)
+      return NULL;
+
+   memset(psc, 0, sizeof *psc);
+   glx_screen_init(psc, screen, priv);
+   psc->vtable = &indirect_screen_vtable;
+
+   return psc;
+}
+
+
 _X_HIDDEN Bool
 glx_context_init(__GLXcontext *gc,
                 __GLXscreenConfigs *psc, const __GLcontextModes *fbconfig)
@@ -382,27 +449,19 @@ CreateContext(Display * dpy, int generic_id,
 {
    GLXContext gc = NULL;
    __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
-#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_APPLEGL)
-   int errorcode;
-   bool x11error;
-#endif
-    
+
    if (dpy == NULL)
       return NULL;
 
    if (generic_id == None)
       return NULL;
 
-#ifndef GLX_USE_APPLEGL  /* TODO: darwin indirect */
-#ifdef GLX_DIRECT_RENDERING
-   if (allowDirect && psc->driScreen) {
-      gc = psc->driScreen->createContext(psc, fbconfig,
-                                        shareList, renderType);
-   }
-#endif
-
+   gc = NULL;
+   if (allowDirect && psc->vtable->create_context)
+      gc = psc->vtable->create_context(psc, fbconfig,
+                                     shareList, renderType);
    if (!gc)
-      gc = AllocateGLXContext(dpy);
+      gc = indirect_create_context(psc, fbconfig, shareList, renderType);
    if (!gc)
       return NULL;
 
@@ -469,26 +528,10 @@ CreateContext(Display * dpy, int generic_id,
 
    UnlockDisplay(dpy);
    SyncHandle();
-#endif
 
    gc->imported = GL_FALSE;
    gc->renderType = renderType;
 
-   /* TODO: darwin: Integrate with above to do indirect */
-#ifdef GLX_USE_APPLEGL
-   if(apple_glx_create_context(&gc->driContext, dpy, screen, fbconfig, 
-                               shareList ? shareList->driContext : NULL,
-                               &errorcode, &x11error)) {
-      __glXSendError(dpy, errorcode, 0, X_GLXCreateContext, x11error);
-      gc->vtable->destroy(gc);
-      return NULL;
-   }
-   
-   gc->currentContextTag = -1;
-   gc->mode = fbconfig;
-   gc->isDirect = allowDirect;
-#endif
-
    return gc;
 }
 
@@ -1633,122 +1676,103 @@ GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
           glXGetCurrentDisplay)
 
 #ifndef GLX_USE_APPLEGL
-/**
- * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
- * to the X-server.
- *
- * \param dpy  Display where \c ctx was created.
- * \param ctx  Context to query.
- * \returns  \c Success on success.  \c GLX_BAD_CONTEXT if \c ctx is invalid,
- *           or zero if the request failed due to internal problems (i.e.,
- *           unable to allocate temporary memory, etc.)
- *
- * \note
- * This function dynamically determines whether to use the EXT_import_context
- * version of the protocol or the GLX 1.3 version of the protocol.
- */
-static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
+PUBLIC GLXContext
+glXImportContextEXT(Display *dpy, GLXContextID contextID)
 {
    __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   __GLXscreenConfigs *psc;
    xGLXQueryContextReply reply;
    CARD8 opcode;
-   GLuint numValues;
-   int retval;
+   GLXContext ctx;
+   int propList[__GLX_MAX_CONTEXT_PROPS * 2], *pProp, nPropListBytes;
+   int i, renderType;
+   XID share;
+   __GLcontextModes *mode;
+
+   if (contextID == None || __glXIsDirect(dpy, contextID))
+      return NULL;
 
-   if (ctx == NULL) {
-      return GLX_BAD_CONTEXT;
-   }
    opcode = __glXSetupForCommand(dpy);
-   if (!opcode) {
+   if (!opcode)
       return 0;
-   }
 
    /* Send the glXQueryContextInfoEXT request */
    LockDisplay(dpy);
 
-   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+   if (priv->majorVersion > 1 || priv->minorVersion >= 3) {
       xGLXQueryContextReq *req;
 
       GetReq(GLXQueryContext, req);
 
       req->reqType = opcode;
       req->glxCode = X_GLXQueryContext;
-      req->context = (unsigned int) (ctx->xid);
+      req->context = contextID;
    }
    else {
       xGLXVendorPrivateReq *vpreq;
       xGLXQueryContextInfoEXTReq *req;
 
       GetReqExtra(GLXVendorPrivate,
-                  sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
-                  vpreq);
+                 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
+                 vpreq);
       req = (xGLXQueryContextInfoEXTReq *) vpreq;
       req->reqType = opcode;
       req->glxCode = X_GLXVendorPrivateWithReply;
       req->vendorCode = X_GLXvop_QueryContextInfoEXT;
-      req->context = (unsigned int) (ctx->xid);
+      req->context = contextID;
    }
 
    _XReply(dpy, (xReply *) & reply, 0, False);
 
-   numValues = reply.n;
-   if (numValues == 0)
-      retval = Success;
-   else if (numValues > __GLX_MAX_CONTEXT_PROPS)
-      retval = 0;
-   else {
-      int *propList, *pProp;
-      int nPropListBytes;
-
-      nPropListBytes = numValues << 3;
-      propList = (int *) Xmalloc(nPropListBytes);
-      if (NULL == propList) {
-         retval = 0;
-      }
-      else {
-        unsigned i;
-
-         _XRead(dpy, (char *) propList, nPropListBytes);
-
-        /* Look up screen first so we can look up visuals/fbconfigs later */
-         pProp = propList;
-         for (i = 0; i < numValues; i++, pProp += 2)
-            if (pProp[0] == GLX_SCREEN) {
-                ctx->screen = pProp[1];
-                ctx->psc = GetGLXScreenConfigs(dpy, ctx->screen);
-            }
-
-         pProp = propList;
-         for (i = 0; i < numValues; i++) {
-            switch (*pProp++) {
-            case GLX_SHARE_CONTEXT_EXT:
-               ctx->share_xid = *pProp++;
-               break;
-            case GLX_VISUAL_ID_EXT:
-               ctx->mode =
-                  _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
-               break;
-            case GLX_FBCONFIG_ID:
-               ctx->mode =
-                  _gl_context_modes_find_fbconfig(ctx->psc->configs,
-                                                  *pProp++);
-               break;
-            case GLX_RENDER_TYPE:
-               ctx->renderType = *pProp++;
-               break;
-            case GLX_SCREEN:
-            default:
-               pProp++;
-               continue;
-            }
-         }
-         Xfree((char *) propList);
-         retval = Success;
-      }
-   }
+   if (reply.n <= __GLX_MAX_CONTEXT_PROPS)
+      nPropListBytes = reply.n * 2 * sizeof propList[0];
+   else
+      nPropListBytes = 0;
+   _XRead(dpy, (char *) propList, nPropListBytes);
    UnlockDisplay(dpy);
    SyncHandle();
-   return retval;
+
+   /* Look up screen first so we can look up visuals/fbconfigs later */
+   psc = NULL;
+   for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2)
+      if (pProp[0] == GLX_SCREEN)
+        psc = GetGLXScreenConfigs(dpy, pProp[1]);
+   if (psc == NULL)
+      return NULL;
+
+   share = None;
+   mode = NULL;
+   renderType = 0;
+   pProp = propList;
+
+   for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2)
+      switch (pProp[0]) {
+      case GLX_SHARE_CONTEXT_EXT:
+        share = pProp[1];
+        break;
+      case GLX_VISUAL_ID_EXT:
+        mode = _gl_context_modes_find_visual(psc->visuals, pProp[1]);
+        break;
+      case GLX_FBCONFIG_ID:
+        mode = _gl_context_modes_find_fbconfig(psc->configs, pProp[1]);
+        break;
+      case GLX_RENDER_TYPE:
+        renderType = pProp[1];
+        break;
+      }
+
+   if (mode == NULL)
+      return NULL;
+
+   ctx = indirect_create_context(psc, mode, NULL, renderType);
+   if (ctx == NULL)
+      return NULL;
+
+   ctx->xid = contextID;
+   ctx->imported = GL_TRUE;
+   ctx->share_xid = share;
+
+   return ctx;
 }
 
 #endif
@@ -1756,38 +1780,21 @@ static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
 PUBLIC int
 glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
 {
-#ifndef GLX_USE_APPLEGL
-   int retVal;
-
-   /* get the information from the server if we don't have it already */
-#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
-   if (!ctx->driContext && (ctx->mode == NULL)) {
-#else
-   if (ctx->mode == NULL) {
-#endif
-      retVal = __glXQueryContextInfo(dpy, ctx);
-      if (Success != retVal)
-         return retVal;
-   }
-#endif
-
    switch (attribute) {
-#ifndef GLX_USE_APPLEGL
       case GLX_SHARE_CONTEXT_EXT:
-      *value = (int) (ctx->share_xid);
+      *value = ctx->share_xid;
       break;
    case GLX_VISUAL_ID_EXT:
       *value = ctx->mode ? ctx->mode->visualID : None;
       break;
-#endif
    case GLX_SCREEN:
-      *value = (int) (ctx->screen);
+      *value = ctx->screen;
       break;
    case GLX_FBCONFIG_ID:
       *value = ctx->mode ? ctx->mode->fbconfigID : None;
       break;
    case GLX_RENDER_TYPE:
-      *value = (int) (ctx->renderType);
+      *value = ctx->renderType;
       break;
    default:
       return GLX_BAD_ATTRIBUTE;
@@ -1805,35 +1812,6 @@ PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
    return ctx->xid;
 }
 
-PUBLIC GLXContext
-glXImportContextEXT(Display * dpy, GLXContextID contextID)
-{
-#ifdef GLX_USE_APPLEGL
-   return NULL;
-#else
-   GLXContext ctx;
-
-   if (contextID == None) {
-      return NULL;
-   }
-   if (__glXIsDirect(dpy, contextID)) {
-      return NULL;
-   }
-
-   ctx = AllocateGLXContext(dpy);
-   if (NULL != ctx) {
-      ctx->xid = contextID;
-      ctx->imported = GL_TRUE;
-
-      if (Success != __glXQueryContextInfo(dpy, ctx)) {
-        ctx->vtable->destroy(ctx);
-        ctx = NULL;
-      }
-   }
-   return ctx;
-#endif
-}
-
 PUBLIC void
 glXFreeContextEXT(Display * dpy, GLXContext ctx)
 {
@@ -1841,11 +1819,6 @@ glXFreeContextEXT(Display * dpy, GLXContext ctx)
 }
 
 
-
-/*
- * GLX 1.3 functions - these are just stubs for now!
- */
-
 PUBLIC GLXFBConfig *
 glXChooseFBConfig(Display * dpy, int screen,
                   const int *attribList, int *nitems)
index 324230f5e3e3b1b516aefb585e267864d0c2e9ba..f9a5f7ce5d730f6f14f477ec2f5ada8a3ed08d68 100644 (file)
@@ -738,21 +738,6 @@ glx_screen_init(__GLXscreenConfigs *psc,
    return GL_TRUE;
 }
 
-static __GLXscreenConfigs *
-createIndirectScreen(int screen, __GLXdisplayPrivate * priv)
-{
-   __GLXscreenConfigs *psc;
-
-   psc = Xmalloc(sizeof *psc);
-   if (psc == NULL)
-      return NULL;
-
-   memset(psc, 0, sizeof *psc);
-   glx_screen_init(psc, screen, priv);
-
-   return psc;
-}
-
 /*
 ** Allocate the memory for the per screen configs for each screen.
 ** If that works then fetch the per screen configs data.
@@ -789,7 +774,7 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
         psc = (*priv->driswDisplay->createScreen) (i, priv);
 #endif
       if (psc == NULL)
-        psc = createIndirectScreen (i, priv);
+        psc = indirect_create_screen(i, priv);
       priv->screenConfigs[i] = psc;
    }
    SyncHandle();