glx: Add screen privates for dri drivers and moved some fields there
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 19 Jul 2010 18:57:59 +0000 (14:57 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 20 Jul 2010 02:45:50 +0000 (22:45 -0400)
GLXscreenConfigs is badly named and a dumping ground for a lot of stuff.
This patch creates private screen structs for the dri drivers and moves
some of their fields over there.

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

index be48194b143f453d754b2953f0ef1f29fd9f7b0b..b35663d5ede1a0adc90d380221284f31473bad1d 100644 (file)
@@ -75,6 +75,16 @@ struct dri2_display
    const __DRIextension *loader_extensions[4];
 };
 
+struct dri2_screen {
+   __GLXscreenConfigs base;
+
+   __GLXDRIscreen driScreen;
+   const __DRIdri2Extension *dri2;
+   const __DRIcoreExtension *core;
+   void *driver;
+   int fd;
+};
+
 struct dri2_context
 {
    __GLXDRIcontext base;
@@ -94,43 +104,44 @@ struct dri2_drawable
 };
 
 static void
-dri2DestroyContext(__GLXDRIcontext * context,
-                   __GLXscreenConfigs * psc, Display * dpy)
+dri2DestroyContext(__GLXDRIcontext *context,
+                  __GLXscreenConfigs *base, Display *dpy)
 {
    struct dri2_context *pcp = (struct dri2_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct dri2_screen *psc = (struct dri2_screen *) base;
 
-   (*core->destroyContext) (pcp->driContext);
+   (*psc->core->destroyContext) (pcp->driContext);
 
    Xfree(pcp);
 }
 
 static Bool
-dri2BindContext(__GLXDRIcontext * context,
-                __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+dri2BindContext(__GLXDRIcontext *context,
+               __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
 {
    struct dri2_context *pcp = (struct dri2_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct dri2_screen *psc = (struct dri2_screen *) pcp->psc;
 
-   return (*core->bindContext) (pcp->driContext,
-                                draw->driDrawable, read->driDrawable);
+   return (*psc->core->bindContext) (pcp->driContext,
+                                    draw->driDrawable, read->driDrawable);
 }
 
 static void
-dri2UnbindContext(__GLXDRIcontext * context)
+dri2UnbindContext(__GLXDRIcontext *context)
 {
    struct dri2_context *pcp = (struct dri2_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct dri2_screen *psc = (struct dri2_screen *) pcp->psc;
 
-   (*core->unbindContext) (pcp->driContext);
+   (*psc->core->unbindContext) (pcp->driContext);
 }
 
 static __GLXDRIcontext *
-dri2CreateContext(__GLXscreenConfigs * psc,
+dri2CreateContext(__GLXscreenConfigs *base,
                   const __GLcontextModes * mode,
                   GLXContext gc, GLXContext shareList, int renderType)
 {
    struct dri2_context *pcp, *pcp_shared;
+   struct dri2_screen *psc = (struct dri2_screen *) base;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
    __DRIcontext *shared = NULL;
 
@@ -143,9 +154,9 @@ dri2CreateContext(__GLXscreenConfigs * psc,
    if (pcp == NULL)
       return NULL;
 
-   pcp->psc = psc;
+   pcp->psc = &psc->base;
    pcp->driContext =
-      (*psc->dri2->createNewContext) (psc->__driScreen,
+      (*psc->dri2->createNewContext) (psc->base.__driScreen,
                                       config->driConfig, shared, pcp);
    gc->__driContext = pcp->driContext;
 
@@ -164,7 +175,7 @@ dri2CreateContext(__GLXscreenConfigs * psc,
 static void
 dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
 {
-   const __DRIcoreExtension *core = pdraw->psc->core;
+   struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
    __GLXdisplayPrivate *dpyPriv;
    struct dri2_display *pdp;
 
@@ -172,17 +183,17 @@ dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
    pdp = (struct dri2_display *)dpyPriv->dri2Display;
 
    __glxHashDelete(pdp->dri2Hash, pdraw->xDrawable);
-   (*core->destroyDrawable) (pdraw->driDrawable);
-   DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable);
+   (*psc->core->destroyDrawable) (pdraw->driDrawable);
+   DRI2DestroyDrawable(psc->base.dpy, pdraw->xDrawable);
    Xfree(pdraw);
 }
 
 static __GLXDRIdrawable *
-dri2CreateDrawable(__GLXscreenConfigs * psc,
-                   XID xDrawable,
-                   GLXDrawable drawable, const __GLcontextModes * modes)
+dri2CreateDrawable(__GLXscreenConfigs *base, XID xDrawable,
+                  GLXDrawable drawable, const __GLcontextModes * modes)
 {
    struct dri2_drawable *pdraw;
+   struct dri2_screen *psc = (struct dri2_screen *) base;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
    __GLXdisplayPrivate *dpyPriv;
    struct dri2_display *pdp;
@@ -195,13 +206,14 @@ dri2CreateDrawable(__GLXscreenConfigs * psc,
    pdraw->base.destroyDrawable = dri2DestroyDrawable;
    pdraw->base.xDrawable = xDrawable;
    pdraw->base.drawable = drawable;
-   pdraw->base.psc = psc;
+   pdraw->base.psc = &psc->base;
    pdraw->bufferCount = 0;
    pdraw->swap_interval = 1; /* default may be overridden below */
    pdraw->have_back = 0;
 
-   if (psc->config)
-      psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode);
+   if (psc->base.config)
+      psc->base.config->configQueryi(psc->base.__driScreen,
+                                    "vblank_mode", &vblank_mode);
 
    switch (vblank_mode) {
    case DRI_CONF_VBLANK_NEVER:
@@ -215,24 +227,24 @@ dri2CreateDrawable(__GLXscreenConfigs * psc,
       break;
    }
 
-   DRI2CreateDrawable(psc->dpy, xDrawable);
+   DRI2CreateDrawable(psc->base.dpy, xDrawable);
 
-   dpyPriv = __glXInitialize(psc->dpy);
+   dpyPriv = __glXInitialize(psc->base.dpy);
    pdp = (struct dri2_display *)dpyPriv->dri2Display;;
    /* Create a new drawable */
    pdraw->base.driDrawable =
-      (*psc->dri2->createNewDrawable) (psc->__driScreen,
+      (*psc->dri2->createNewDrawable) (psc->base.__driScreen,
                                        config->driConfig, pdraw);
 
    if (!pdraw->base.driDrawable) {
-      DRI2DestroyDrawable(psc->dpy, xDrawable);
+      DRI2DestroyDrawable(psc->base.dpy, xDrawable);
       Xfree(pdraw);
       return NULL;
    }
 
    if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) {
       (*psc->core->destroyDrawable) (pdraw->base.driDrawable);
-      DRI2DestroyDrawable(psc->dpy, xDrawable);
+      DRI2DestroyDrawable(psc->base.dpy, xDrawable);
       Xfree(pdraw);
       return None;
    }
@@ -244,7 +256,7 @@ dri2CreateDrawable(__GLXscreenConfigs * psc,
     * drawable.
     */
    if (pdp->swapAvailable)
-      DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval);
+      DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval);
 #endif
 
    return &pdraw->base;
@@ -377,12 +389,15 @@ dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
 
 
 static void
-dri2DestroyScreen(__GLXscreenConfigs * psc)
+dri2DestroyScreen(__GLXscreenConfigs *base)
 {
+   struct dri2_screen *psc = (struct dri2_screen *) base;
+
    /* Free the direct rendering per screen data */
-   (*psc->core->destroyScreen) (psc->__driScreen);
+   (*psc->core->destroyScreen) (psc->base.__driScreen);
    close(psc->fd);
-   psc->__driScreen = NULL;
+   base->__driScreen = NULL;
+   Xfree(psc);
 }
 
 /**
@@ -610,26 +625,30 @@ static const struct glx_context_vtable dri2_context_vtable = {
    dri2_release_tex_image,
 };
 
-static __GLXDRIscreen *
-dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
-                 __GLXdisplayPrivate * priv)
+static __GLXscreenConfigs *
+dri2CreateScreen(int screen, __GLXdisplayPrivate * priv)
 {
    const __DRIconfig **driver_configs;
    const __DRIextension **extensions;
    const struct dri2_display *const pdp = (struct dri2_display *)
       priv->dri2Display;
+   struct dri2_screen *psc;
    __GLXDRIscreen *psp;
    char *driverName, *deviceName;
    drm_magic_t magic;
    int i;
 
-   psp = Xmalloc(sizeof *psp);
-   if (psp == NULL)
+   psc = Xmalloc(sizeof *psc);
+   if (psc == NULL)
       return NULL;
 
-   if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
+   memset(psc, 0, sizeof *psc);
+   if (!glx_screen_init(&psc->base, screen, priv))
+       return NULL;
+
+   if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen),
                    &driverName, &deviceName)) {
-      XFree(psp);
+      XFree(psc);
       return NULL;
    }
 
@@ -668,7 +687,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
       goto handle_error;
    }
 
-   if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
+   if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) {
       ErrorMessageF("failed to authenticate magic %d\n", magic);
       goto handle_error;
    }
@@ -677,25 +696,30 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
    /* If the server does not support the protocol for
     * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
     */
-   psc->__driScreen =
+   psc->base.__driScreen =
       psc->dri2->createNewScreen(screen, psc->fd,
                                 (const __DRIextension **)
                                 &pdp->loader_extensions[0],
                                 &driver_configs, psc);
 
-   if (psc->__driScreen == NULL) {
+   if (psc->base.__driScreen == NULL) {
       ErrorMessageF("failed to create dri screen\n");
       goto handle_error;
    }
 
-   driBindCommonExtensions(psc);
-   dri2BindExtensions(psc);
+   extensions = psc->core->getExtensions(psc->base.__driScreen);
+   driBindCommonExtensions(&psc->base, extensions);
+   dri2BindExtensions(&psc->base, extensions);
 
-   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
-   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+   psc->base.configs =
+      driConvertConfigs(psc->core, psc->base.configs, driver_configs);
+   psc->base.visuals =
+      driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
 
-   psc->driver_configs = driver_configs;
+   psc->base.driver_configs = driver_configs;
 
+   psp = &psc->driScreen;
+   psc->base.driScreen = psp;
    psp->destroyScreen = dri2DestroyScreen;
    psp->createContext = dri2CreateContext;
    psp->createDrawable = dri2CreateDrawable;
@@ -721,26 +745,26 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
       psp->getSwapInterval = dri2GetSwapInterval;
 #endif
 #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
-      __glXEnableDirectExtension(psc, "GLX_OML_sync_control");
+      __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
 #endif
    }
 
    /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
     * available.*/
    psp->copySubBuffer = dri2CopySubBuffer;
-   __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
+   __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
 
-   psc->direct_context_vtable = &dri2_context_vtable;
+   psc->base.direct_context_vtable = &dri2_context_vtable;
 
    Xfree(driverName);
    Xfree(deviceName);
 
-   return psp;
+   return &psc->base;
 
 handle_error:
    Xfree(driverName);
    Xfree(deviceName);
-   XFree(psp);
+   XFree(psc);
 
    /* FIXME: clean up here */
 
index 429fc6d89126d91cf495e713134d390bb79f12ed..19936ff57a61b3133fd8a98b00044e92f6610f9a 100644 (file)
@@ -338,13 +338,10 @@ driConvertConfigs(const __DRIcoreExtension * core,
 
 /* Bind DRI1 specific extensions */
 _X_HIDDEN void
-driBindExtensions(__GLXscreenConfigs *psc)
+driBindExtensions(__GLXscreenConfigs *psc, const __DRIextension **extensions)
 {
-   const __DRIextension **extensions;
    int i;
 
-   extensions = psc->core->getExtensions(psc->__driScreen);
-
    for (i = 0; extensions[i]; i++) {
 #ifdef __DRI_SWAP_CONTROL
       /* No DRI2 support for swap_control at the moment, since SwapBuffers
@@ -375,13 +372,11 @@ driBindExtensions(__GLXscreenConfigs *psc)
 
 /* Bind DRI2 specific extensions */
 _X_HIDDEN void
-dri2BindExtensions(__GLXscreenConfigs *psc)
+dri2BindExtensions(__GLXscreenConfigs *psc,
+                  const __DRIextension **extensions)
 {
-   const __DRIextension **extensions;
    int i;
 
-   extensions = psc->core->getExtensions(psc->__driScreen);
-
    for (i = 0; extensions[i]; i++) {
 #ifdef __DRI_TEX_BUFFER
       if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
@@ -413,13 +408,11 @@ dri2BindExtensions(__GLXscreenConfigs *psc)
 
 /* Bind extensions common to DRI1 and DRI2 */
 _X_HIDDEN void
-driBindCommonExtensions(__GLXscreenConfigs *psc)
+driBindCommonExtensions(__GLXscreenConfigs *psc,
+                       const __DRIextension **extensions)
 {
-   const __DRIextension **extensions;
    int i;
 
-   extensions = psc->core->getExtensions(psc->__driScreen);
-
    for (i = 0; extensions[i]; i++) {
 #ifdef __DRI_COPY_SUB_BUFFER
       if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
index bb178db7875ff327212e65c8b46e4edcc4a69cf2..7cd9ac2dac0faf490f2559eafce1bed21581900b 100644 (file)
@@ -56,8 +56,11 @@ extern void ErrorMessageF(const char *f, ...);
 
 extern void *driOpenDriver(const char *driverName);
 
-extern void driBindExtensions(__GLXscreenConfigs * psc);
-extern void dri2BindExtensions(__GLXscreenConfigs * psc);
-extern void driBindCommonExtensions(__GLXscreenConfigs * psc);
+extern void driBindExtensions(__GLXscreenConfigs * psc,
+                             const __DRIextension **extensions);
+extern void dri2BindExtensions(__GLXscreenConfigs * psc,
+                              const __DRIextension **extensions);
+extern void driBindCommonExtensions(__GLXscreenConfigs * psc,
+                                   const __DRIextension **extensions);
 
 #endif /* _DRI_COMMON_H */
index b3ae5e6b7841b947b68696ca3e5b44a98e2bb3a5..e14bc62e63beed50a52b45f5f1786919bb18c52c 100644 (file)
@@ -59,6 +59,17 @@ struct dri_display
    int driPatch;
 };
 
+struct dri_screen
+{
+   __GLXscreenConfigs base;
+
+   __GLXDRIscreen driScreen;
+   const __DRIlegacyExtension *legacy;
+   const __DRIcoreExtension *core;
+   void *driver;
+   int fd;
+};
+
 struct dri_context
 {
    __GLXDRIcontext base;
@@ -290,7 +301,7 @@ static const __DRIextension *loader_extensions[] = {
  *          the client-side driver on success, or \c NULL on failure.
  */
 static void *
-CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
+CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
                     struct dri_display * driDpy)
 {
    void *psp = NULL;
@@ -421,16 +432,18 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
       goto handle_error;
    }
 
-   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
-   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+   psc->base.configs =
+      driConvertConfigs(psc->core, psc->base.configs, driver_configs);
+   psc->base.visuals =
+      driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
 
-   psc->driver_configs = driver_configs;
+   psc->base.driver_configs = driver_configs;
 
    /* Visuals with depth != screen depth are subject to automatic compositing
     * in the X server, so DRI1 can't render to them properly. Mark them as
     * non-conformant to prevent apps from picking them up accidentally.
     */
-   for (visual = psc->visuals; visual; visual = visual->next) {
+   for (visual = psc->base.visuals; visual; visual = visual->next) {
       XVisualInfo template;
       XVisualInfo *visuals;
       int num_visuals;
@@ -472,47 +485,49 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
 
 static void
 driDestroyContext(__GLXDRIcontext * context,
-                  __GLXscreenConfigs * psc, Display * dpy)
+                  __GLXscreenConfigs *base, Display * dpy)
 {
    struct dri_context *pcp = (struct dri_context *) context;
+   struct dri_screen *psc = (struct dri_screen *) base;
 
    (*psc->core->destroyContext) (pcp->driContext);
 
-   XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+   XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
    Xfree(pcp);
 }
 
 static Bool
-driBindContext(__GLXDRIcontext * context,
-               __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+driBindContext(__GLXDRIcontext *context,
+              __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
 {
    struct dri_context *pcp = (struct dri_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct dri_screen *psc = (struct dri_screen *) pcp->psc;
 
-   return (*core->bindContext) (pcp->driContext,
-                                draw->driDrawable, read->driDrawable);
+   return (*psc->core->bindContext) (pcp->driContext,
+                                    draw->driDrawable, read->driDrawable);
 }
 
 static void
 driUnbindContext(__GLXDRIcontext * context)
 {
    struct dri_context *pcp = (struct dri_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct dri_screen *psc = (struct dri_screen *) pcp->psc;
 
-   (*core->unbindContext) (pcp->driContext);
+   (*psc->core->unbindContext) (pcp->driContext);
 }
 
 static __GLXDRIcontext *
-driCreateContext(__GLXscreenConfigs * psc,
+driCreateContext(__GLXscreenConfigs *base,
                  const __GLcontextModes * mode,
                  GLXContext gc, GLXContext shareList, int renderType)
 {
    struct dri_context *pcp, *pcp_shared;
+   struct dri_screen *psc = (struct dri_screen *) base;
    drm_context_t hwContext;
    __DRIcontext *shared = NULL;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
 
-   if (!psc || !psc->driScreen)
+   if (!psc->base.driScreen)
       return NULL;
 
    if (shareList) {
@@ -524,8 +539,8 @@ driCreateContext(__GLXscreenConfigs * psc,
    if (pcp == NULL)
       return NULL;
 
-   pcp->psc = psc;
-   if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
+   pcp->psc = &psc->base;
+   if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
                                        mode->visualID,
                                        &pcp->hwContextID, &hwContext)) {
       Xfree(pcp);
@@ -533,11 +548,11 @@ driCreateContext(__GLXscreenConfigs * psc,
    }
 
    pcp->driContext =
-      (*psc->legacy->createNewContext) (psc->__driScreen,
+      (*psc->legacy->createNewContext) (psc->base.__driScreen,
                                         config->driConfig,
                                         renderType, shared, hwContext, pcp);
    if (pcp->driContext == NULL) {
-      XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+      XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
       Xfree(pcp);
       return NULL;
    }
@@ -552,15 +567,15 @@ driCreateContext(__GLXscreenConfigs * psc,
 static void
 driDestroyDrawable(__GLXDRIdrawable * pdraw)
 {
-   __GLXscreenConfigs *psc = pdraw->psc;
+   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
 
    (*psc->core->destroyDrawable) (pdraw->driDrawable);
-   XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
+   XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
    Xfree(pdraw);
 }
 
 static __GLXDRIdrawable *
-driCreateDrawable(__GLXscreenConfigs * psc,
+driCreateDrawable(__GLXscreenConfigs *base,
                   XID xDrawable,
                   GLXDrawable drawable, const __GLcontextModes * modes)
 {
@@ -568,6 +583,7 @@ driCreateDrawable(__GLXscreenConfigs * psc,
    drm_drawable_t hwDrawable;
    void *empty_attribute_list = NULL;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+   struct dri_screen *psc = (struct dri_screen *) base;
 
    /* Old dri can't handle GLX 1.3+ drawable constructors. */
    if (xDrawable != drawable)
@@ -578,23 +594,24 @@ driCreateDrawable(__GLXscreenConfigs * psc,
       return NULL;
 
    pdraw->drawable = drawable;
-   pdraw->psc = psc;
+   pdraw->psc = &psc->base;
 
-   if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) {
+   if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
+                             drawable, &hwDrawable)) {
       Xfree(pdraw);
       return NULL;
    }
 
    /* Create a new drawable */
    pdraw->driDrawable =
-      (*psc->legacy->createNewDrawable) (psc->__driScreen,
+      (*psc->legacy->createNewDrawable) (psc->base.__driScreen,
                                          config->driConfig,
                                          hwDrawable,
                                          GLX_WINDOW_BIT,
                                          empty_attribute_list, pdraw);
 
    if (!pdraw->driDrawable) {
-      XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
+      XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
       Xfree(pdraw);
       return NULL;
    }
@@ -608,7 +625,9 @@ static int64_t
 driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
               int64_t unused3)
 {
-   (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
+   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
+
+   (*psc->core->swapBuffers) (pdraw->driDrawable);
    return 0;
 }
 
@@ -621,12 +640,14 @@ driCopySubBuffer(__GLXDRIdrawable * pdraw,
 }
 
 static void
-driDestroyScreen(__GLXscreenConfigs * psc)
+driDestroyScreen(__GLXscreenConfigs *base)
 {
+   struct dri_screen *psc = (struct dri_screen *) base;
+
    /* Free the direct rendering per screen data */
-   if (psc->__driScreen)
-      (*psc->core->destroyScreen) (psc->__driScreen);
-   psc->__driScreen = NULL;
+   if (psc->base.__driScreen)
+      (*psc->core->destroyScreen) (psc->base.__driScreen);
+   psc->base.__driScreen = NULL;
    if (psc->driver)
       dlclose(psc->driver);
 }
@@ -636,36 +657,40 @@ static const struct glx_context_vtable dri_context_vtable = {
    NULL,
 };
 
-static __GLXDRIscreen *
-driCreateScreen(__GLXscreenConfigs * psc, int screen,
-                __GLXdisplayPrivate * priv)
+static __GLXscreenConfigs *
+driCreateScreen(int screen, __GLXdisplayPrivate *priv)
 {
    struct dri_display *pdp;
    __GLXDRIscreen *psp;
    const __DRIextension **extensions;
+   struct dri_screen *psc;
    char *driverName;
    int i;
 
-   psp = Xcalloc(1, sizeof *psp);
-   if (psp == NULL)
+   psc = Xcalloc(1, sizeof *psc);
+   if (psc == NULL)
       return NULL;
 
+   memset(psc, 0, sizeof *psc);
+   if (!glx_screen_init(&psc->base, screen, priv))
+       return NULL;
+
    if (!driGetDriverName(priv->dpy, screen, &driverName)) {
-      Xfree(psp);
+      Xfree(psc);
       return NULL;
    }
 
    psc->driver = driOpenDriver(driverName);
    Xfree(driverName);
    if (psc->driver == NULL) {
-      Xfree(psp);
+      Xfree(psc);
       return NULL;
    }
 
    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
    if (extensions == NULL) {
       ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
-      Xfree(psp);
+      Xfree(psc);
       return NULL;
    }
 
@@ -677,22 +702,26 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
    }
 
    if (psc->core == NULL || psc->legacy == NULL) {
-      Xfree(psp);
+      Xfree(psc);
       return NULL;
    }
 
    pdp = (struct dri_display *) priv->driDisplay;
-   psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp);
-   if (psc->__driScreen == NULL) {
+   psc->base.__driScreen =
+      CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
+   if (psc->base.__driScreen == NULL) {
       dlclose(psc->driver);
-      Xfree(psp);
+      Xfree(psc);
       return NULL;
    }
 
-   driBindExtensions(psc);
-   driBindCommonExtensions(psc);
+   extensions = psc->core->getExtensions(psc->base.__driScreen);
+   driBindExtensions(&psc->base, extensions);
+   driBindCommonExtensions(&psc->base, extensions);
 
-   if (psc->driCopySubBuffer)
+   psp = &psc->driScreen;
+   psc->base.driScreen = psp;
+   if (psc->base.driCopySubBuffer)
       psp->copySubBuffer = driCopySubBuffer;
 
    psp->destroyScreen = driDestroyScreen;
@@ -702,9 +731,9 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
    psp->waitX = NULL;
    psp->waitGL = NULL;
 
-   psc->direct_context_vtable = &dri_context_vtable;
+   psc->base.direct_context_vtable = &dri_context_vtable;
 
-   return psp;
+   return &psc->base;
 }
 
 /* Called from __glXFreeDisplayPrivate.
index 3b9e8139af5c2f2295a8c497528bf8aee5153f39..4ed13a3ac76fc8b91ada5913526ccc2c72a82c2b 100644 (file)
@@ -40,6 +40,16 @@ struct drisw_context
    __GLXscreenConfigs *psc;
 };
 
+struct drisw_screen
+{
+   __GLXscreenConfigs base;
+
+   __GLXDRIscreen driScreen;
+   const __DRIcoreExtension *core;
+   const __DRIswrastExtension *swrast;
+   void *driver;
+};
+
 struct drisw_drawable
 {
    __GLXDRIdrawable base;
@@ -225,52 +235,50 @@ static const __DRIextension *loader_extensions[] = {
  */
 
 static void
-driDestroyContext(__GLXDRIcontext * context,
-                  __GLXscreenConfigs * psc, Display * dpy)
+driDestroyContext(__GLXDRIcontext *context,
+                 __GLXscreenConfigs *base, Display *dpy)
 {
    struct drisw_context *pcp = (struct drisw_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct drisw_screen *psc = (struct drisw_screen *) base;
 
-   (*core->destroyContext) (pcp->driContext);
+   (*psc->core->destroyContext) (pcp->driContext);
 
    Xfree(pcp);
 }
 
 static Bool
 driBindContext(__GLXDRIcontext * context,
-               __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+              __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
 {
    struct drisw_context *pcp = (struct drisw_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct drisw_screen *psc = (struct drisw_screen *) pcp->psc;
 
-   return (*core->bindContext) (pcp->driContext,
-                                draw->driDrawable, read->driDrawable);
+   return (*psc->core->bindContext) (pcp->driContext,
+                                    draw->driDrawable, read->driDrawable);
 }
 
 static void
 driUnbindContext(__GLXDRIcontext * context)
 {
    struct drisw_context *pcp = (struct drisw_context *) context;
-   const __DRIcoreExtension *core = pcp->psc->core;
+   struct drisw_screen *psc = (struct drisw_screen *) pcp->psc;
 
-   (*core->unbindContext) (pcp->driContext);
+   (*psc->core->unbindContext) (pcp->driContext);
 }
 
 static __GLXDRIcontext *
-driCreateContext(__GLXscreenConfigs * psc,
-                 const __GLcontextModes * mode,
-                 GLXContext gc, GLXContext shareList, int renderType)
+driCreateContext(__GLXscreenConfigs *base,
+                const __GLcontextModes *mode,
+                GLXContext gc, GLXContext shareList, int renderType)
 {
    struct drisw_context *pcp, *pcp_shared;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
-   const __DRIcoreExtension *core;
+   struct drisw_screen *psc = (struct drisw_screen *) base;
    __DRIcontext *shared = NULL;
 
-   if (!psc || !psc->driScreen)
+   if (!psc->base.driScreen)
       return NULL;
 
-   core = psc->core;
-
    if (shareList) {
       pcp_shared = (struct drisw_context *) shareList->driContext;
       shared = pcp_shared->driContext;
@@ -280,10 +288,10 @@ driCreateContext(__GLXscreenConfigs * psc,
    if (pcp == NULL)
       return NULL;
 
-   pcp->psc = psc;
+   pcp->psc = &psc->base;
    pcp->driContext =
-      (*core->createNewContext) (psc->__driScreen,
-                                 config->driConfig, shared, pcp);
+      (*psc->core->createNewContext) (psc->base.__driScreen,
+                                     config->driConfig, shared, pcp);
    if (pcp->driContext == NULL) {
       Xfree(pcp);
       return NULL;
@@ -300,22 +308,23 @@ static void
 driDestroyDrawable(__GLXDRIdrawable * pdraw)
 {
    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
-   const __DRIcoreExtension *core = pdraw->psc->core;
+   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
 
-   (*core->destroyDrawable) (pdraw->driDrawable);
+   (*psc->core->destroyDrawable) (pdraw->driDrawable);
 
    XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
    Xfree(pdp);
 }
 
 static __GLXDRIdrawable *
-driCreateDrawable(__GLXscreenConfigs * psc,
-                  XID xDrawable,
-                  GLXDrawable drawable, const __GLcontextModes * modes)
+driCreateDrawable(__GLXscreenConfigs *base, XID xDrawable,
+                 GLXDrawable drawable, const __GLcontextModes * modes)
 {
    __GLXDRIdrawable *pdraw;
    struct drisw_drawable *pdp;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+   struct drisw_screen *psc = (struct drisw_screen *) base;
+
    const __DRIswrastExtension *swrast = psc->swrast;
 
    /* Old dri can't handle GLX 1.3+ drawable constructors. */
@@ -329,16 +338,17 @@ driCreateDrawable(__GLXscreenConfigs * psc,
    pdraw = &(pdp->base);
    pdraw->xDrawable = xDrawable;
    pdraw->drawable = drawable;
-   pdraw->psc = psc;
+   pdraw->psc = &psc->base;
 
-   XCreateDrawable(pdp, psc->dpy, xDrawable, modes->visualID);
+   XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
 
    /* Create a new drawable */
    pdraw->driDrawable =
-      (*swrast->createNewDrawable) (psc->__driScreen, config->driConfig, pdp);
+      (*swrast->createNewDrawable) (psc->base.__driScreen,
+                                   config->driConfig, pdp);
 
    if (!pdraw->driDrawable) {
-      XDestroyDrawable(pdp, psc->dpy, xDrawable);
+      XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
       Xfree(pdp);
       return NULL;
    }
@@ -352,21 +362,26 @@ static int64_t
 driSwapBuffers(__GLXDRIdrawable * pdraw,
                int64_t target_msc, int64_t divisor, int64_t remainder)
 {
+   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
+   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
+
    (void) target_msc;
    (void) divisor;
    (void) remainder;
 
-   (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
+   (*psc->core->swapBuffers) (pdraw->driDrawable);
 
    return 0;
 }
 
 static void
-driDestroyScreen(__GLXscreenConfigs * psc)
+driDestroyScreen(__GLXscreenConfigs *base)
 {
+   struct drisw_screen *psc = (struct drisw_screen *) base;
+
    /* Free the direct rendering per screen data */
-   (*psc->core->destroyScreen) (psc->__driScreen);
-   psc->__driScreen = NULL;
+   (*psc->core->destroyScreen) (psc->base.__driScreen);
+   psc->base.__driScreen = NULL;
    if (psc->driver)
       dlclose(psc->driver);
 }
@@ -385,19 +400,23 @@ driOpenSwrast(void)
    return driver;
 }
 
-static __GLXDRIscreen *
-driCreateScreen(__GLXscreenConfigs * psc, int screen,
-                __GLXdisplayPrivate * priv)
+static __GLXscreenConfigs *
+driCreateScreen(int screen, __GLXdisplayPrivate *priv)
 {
    __GLXDRIscreen *psp;
    const __DRIconfig **driver_configs;
    const __DRIextension **extensions;
+   struct drisw_screen *psc;
    int i;
 
-   psp = Xcalloc(1, sizeof *psp);
-   if (psp == NULL)
+   psc = Xcalloc(1, sizeof *psc);
+   if (psc == NULL)
       return NULL;
 
+   memset(psc, 0, sizeof *psc);
+   if (!glx_screen_init(&psc->base, screen, priv))
+       return NULL;
+
    psc->driver = driOpenSwrast();
    if (psc->driver == NULL)
       goto handle_error;
@@ -410,9 +429,9 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
 
    for (i = 0; extensions[i]; i++) {
       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
-         psc->core = (__DRIcoreExtension *) extensions[i];
+        psc->core = (__DRIcoreExtension *) extensions[i];
       if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
-         psc->swrast = (__DRIswrastExtension *) extensions[i];
+        psc->swrast = (__DRIswrastExtension *) extensions[i];
    }
 
    if (psc->core == NULL || psc->swrast == NULL) {
@@ -420,22 +439,27 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
       goto handle_error;
    }
 
-   psc->__driScreen =
-      psc->swrast->createNewScreen(screen,
-                                   loader_extensions, &driver_configs, psc);
-   if (psc->__driScreen == NULL) {
+   psc->base.__driScreen =
+      psc->swrast->createNewScreen(screen, loader_extensions,
+                                  &driver_configs, psc);
+   if (psc->base.__driScreen == NULL) {
       ErrorMessageF("failed to create dri screen\n");
       goto handle_error;
    }
 
-   driBindExtensions(psc);
-   driBindCommonExtensions(psc);
+   extensions = psc->core->getExtensions(psc->base.__driScreen);
+   driBindExtensions(&psc->base, extensions);
+   driBindCommonExtensions(&psc->base, extensions);
 
-   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
-   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+   psc->base.configs =
+      driConvertConfigs(psc->core, psc->base.configs, driver_configs);
+   psc->base.visuals =
+      driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
 
-   psc->driver_configs = driver_configs;
+   psc->base.driver_configs = driver_configs;
 
+   psp = &psc->driScreen;
+   psc->base.driScreen = psp;
    psp->destroyScreen = driDestroyScreen;
    psp->createContext = driCreateContext;
    psp->createDrawable = driCreateDrawable;
@@ -443,10 +467,10 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
    psp->waitX = NULL;
    psp->waitGL = NULL;
 
-   return psp;
+   return &psc->base;
 
  handle_error:
-   Xfree(psp);
+   Xfree(psc);
 
    if (psc->driver)
       dlclose(psc->driver);
index f6f931df7d2d38d6eed05d1eca8894c76874f91a..bbdba34ebdefa216144e4dbd154400daa39e4646 100644 (file)
@@ -191,7 +191,7 @@ CreateDRIDrawable(Display *dpy, const __GLcontextModes *fbconfig,
    __GLXDRIdrawable *pdraw;
    __GLXscreenConfigs *psc;
 
-   psc = &priv->screenConfigs[fbconfig->screen];
+   psc = priv->screenConfigs[fbconfig->screen];
    if (psc->driScreen == NULL)
       return;
 
@@ -217,7 +217,7 @@ DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
    int screen;
    __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
    __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
-   __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
+   __GLXscreenConfigs *psc = priv->screenConfigs[screen];
 
    if (pdraw != NULL) {
       if (destroy_xdrawable)
index ef46a399281832dd0bd1c61d54b0809a88e45a42..10baedea4c6077bf431fc176f516f275468e84f3 100644 (file)
@@ -121,8 +121,7 @@ struct __GLXDRIdisplayRec
      */
    void (*destroyDisplay) (__GLXDRIdisplay * display);
 
-   __GLXDRIscreen *(*createScreen) (__GLXscreenConfigs * psc, int screen,
-                                    __GLXdisplayPrivate * priv);
+   __GLXscreenConfigs *(*createScreen)(int screen, __GLXdisplayPrivate * priv);
 };
 
 struct __GLXDRIscreenRec {
@@ -530,14 +529,9 @@ struct __GLXscreenConfigsRec
      * Per screen direct rendering interface functions and data.
      */
    __DRIscreen *__driScreen;
-   const __DRIcoreExtension *core;
-   const __DRIlegacyExtension *legacy;
-   const __DRIswrastExtension *swrast;
-   const __DRIdri2Extension *dri2;
    __glxHashTable *drawHash;
    Display *dpy;
-   int scr, fd;
-   void *driver;
+   int scr;
 
    __GLXDRIscreen *driScreen;
 
@@ -638,7 +632,7 @@ struct __GLXdisplayPrivateRec
      * Also, per screen data which now includes the server \c GLX_EXTENSION
      * string.
      */
-   __GLXscreenConfigs *screenConfigs;
+   __GLXscreenConfigs **screenConfigs;
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
     /**
@@ -650,6 +644,10 @@ struct __GLXdisplayPrivateRec
 #endif
 };
 
+extern int
+glx_screen_init(__GLXscreenConfigs *psc,
+               int screen, __GLXdisplayPrivate * priv);
+
 extern __GLXDRIdrawable *
 dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id);
 
index 16c4eef6ba8fdd92bc46d9d450f9617b02034750..0721c27827d7493d5ce323aac7be2b09b0098195 100644 (file)
@@ -137,7 +137,7 @@ GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
       return NULL;
 
    for (i = 0; i < screen_count; i++) {
-      psc = &priv->screenConfigs[i];
+      psc = priv->screenConfigs[i];
       if (psc->drawHash == NULL)
          continue;
 
@@ -175,7 +175,7 @@ GetGLXScreenConfigs(Display * dpy, int scrn)
 
    return (priv
            && priv->screenConfigs !=
-           NULL) ? &priv->screenConfigs[scrn] : NULL;
+           NULL) ? priv->screenConfigs[scrn] : NULL;
 }
 
 
@@ -202,7 +202,7 @@ GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
    }
 
    /* Check to see if the GL is supported on this screen */
-   *ppsc = &((*ppriv)->screenConfigs[scrn]);
+   *ppsc = (*ppriv)->screenConfigs[scrn];
    if ((*ppsc)->configs == NULL) {
       /* No support for GL on this screen regardless of visual */
       return GLX_BAD_VISUAL;
@@ -233,7 +233,7 @@ ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
 
    if (priv != NULL) {
       for (i = 0; i < num_screens; i++) {
-         for (modes = priv->screenConfigs[i].configs; modes != NULL;
+         for (modes = priv->screenConfigs[i]->configs; modes != NULL;
               modes = modes->next) {
             if (modes == (__GLcontextModes *) config) {
                return (__GLcontextModes *) config;
@@ -992,7 +992,7 @@ glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
       __GLXscreenConfigs *psc;
       __GLcontextModes *modes;
 
-      psc = &priv->screenConfigs[vis->screen];
+      psc = priv->screenConfigs[vis->screen];
       if (psc->driScreen == NULL)
          break;
       modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
@@ -1045,7 +1045,7 @@ glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
       int screen;
       __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
       __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen);
-      __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
+      __GLXscreenConfigs *psc = priv->screenConfigs[screen];
 
       if (pdraw != NULL) {
          (*pdraw->destroyDrawable) (pdraw);
@@ -1958,14 +1958,14 @@ glXGetFBConfigs(Display * dpy, int screen, int *nelements)
    *nelements = 0;
    if (priv && (priv->screenConfigs != NULL)
        && (screen >= 0) && (screen <= ScreenCount(dpy))
-       && (priv->screenConfigs[screen].configs != NULL)
-       && (priv->screenConfigs[screen].configs->fbconfigID
+       && (priv->screenConfigs[screen]->configs != NULL)
+       && (priv->screenConfigs[screen]->configs->fbconfigID
           != (int) GLX_DONT_CARE)) {
       unsigned num_configs = 0;
       __GLcontextModes *modes;
 
 
-      for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+      for (modes = priv->screenConfigs[screen]->configs; modes != NULL;
            modes = modes->next) {
          if (modes->fbconfigID != (int) GLX_DONT_CARE) {
             num_configs++;
@@ -1977,7 +1977,7 @@ glXGetFBConfigs(Display * dpy, int screen, int *nelements)
       if (config != NULL) {
          *nelements = num_configs;
          i = 0;
-         for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+         for (modes = priv->screenConfigs[screen]->configs; modes != NULL;
               modes = modes->next) {
             if (modes->fbconfigID != (int) GLX_DONT_CARE) {
                config[i] = modes;
@@ -2544,7 +2544,7 @@ __glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
 #ifdef GLX_DIRECT_RENDERING
    pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
 #endif
-   psc = &priv->screenConfigs[i];
+   psc = priv->screenConfigs[i];
 
 #if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
    if (pdraw && psc->sbc && psc->msc)
index 691e8dfadf2ca1ceaba5eb895794220cab51ba6d..c423ffcbdf8288c1939b8644531a91b667fab018 100644 (file)
@@ -295,7 +295,7 @@ FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc)
    if (priv == NULL)
       return NULL;
 
-   psc = &priv->screenConfigs[gc->screen];
+   psc = priv->screenConfigs[gc->screen];
    if (psc->drawHash == NULL)
       return NULL;
 
index 69a7b29eb27c7a0e734846f595f66a694d317df4..320246cc4f27e0d7e55f9657ea652f8b2628445f 100644 (file)
@@ -244,9 +244,9 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
    GLint i, screens;
 
    /* Free screen configuration information */
-   psc = priv->screenConfigs;
    screens = ScreenCount(priv->dpy);
-   for (i = 0; i < screens; i++, psc++) {
+   for (i = 0; i < screens; i++) {
+      psc = priv->screenConfigs[i];
       if (psc->configs) {
          _gl_context_modes_destroy(psc->configs);
          if (psc->effectiveGLXexts)
@@ -268,11 +268,14 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
          psc->driver_configs = NULL;
       }
       if (psc->driScreen) {
-         psc->driScreen->destroyScreen(psc);
          __glxHashDestroy(psc->drawHash);
-         XFree(psc->driScreen);
+         psc->driScreen->destroyScreen(psc);
          psc->driScreen = NULL;
+      } else {
+        Xfree(psc);
       }
+#else
+      Xfree(psc);
 #endif
    }
    XFree((char *) priv->screenConfigs);
@@ -672,15 +675,15 @@ createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
 }
 
 static GLboolean
-getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+getVisualConfigs(__GLXscreenConfigs *psc,
+                __GLXdisplayPrivate *priv, int screen)
 {
    xGLXGetVisualConfigsReq *req;
-   __GLXscreenConfigs *psc;
    xGLXGetVisualConfigsReply reply;
+   Display *dpy = priv->dpy;
 
    LockDisplay(dpy);
 
-   psc = priv->screenConfigs + screen;
    psc->visuals = NULL;
    GetReq(GLXGetVisualConfigs, req);
    req->reqType = priv->majorOpcode;
@@ -701,15 +704,14 @@ getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
 }
 
 static GLboolean
-getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen)
 {
    xGLXGetFBConfigsReq *fb_req;
    xGLXGetFBConfigsSGIXReq *sgi_req;
    xGLXVendorPrivateWithReplyReq *vpreq;
    xGLXGetFBConfigsReply reply;
-   __GLXscreenConfigs *psc;
+   Display *dpy = priv->dpy;
 
-   psc = priv->screenConfigs + screen;
    psc->serverGLXexts =
       __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
 
@@ -748,6 +750,35 @@ getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
    return psc->configs != NULL;
 }
 
+_X_HIDDEN Bool
+glx_screen_init(__GLXscreenConfigs *psc,
+               int screen, __GLXdisplayPrivate * priv)
+{
+   /* Initialize per screen dynamic client GLX extensions */
+   psc->ext_list_first_time = GL_TRUE;
+   psc->scr = screen;
+   psc->dpy = priv->dpy;
+   psc->drawHash = __glxHashCreate();
+   if (psc->drawHash == NULL)
+      return GL_FALSE;
+
+   getVisualConfigs(psc, priv, screen);
+   getFBConfigs(psc, priv, screen);
+
+   return GL_TRUE;
+}
+
+static __GLXscreenConfigs *
+createIndirectScreen()
+{
+   __GLXscreenConfigs *psc;
+
+   psc = Xmalloc(sizeof *psc);
+   memset(psc, 0, sizeof *psc);
+
+   return psc;
+}
+
 /*
 ** Allocate the memory for the per screen configs for each screen.
 ** If that works then fetch the per screen configs data.
@@ -762,12 +793,9 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
     ** First allocate memory for the array of per screen configs.
     */
    screens = ScreenCount(dpy);
-   psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
-   if (!psc) {
+   priv->screenConfigs = Xmalloc(screens * sizeof *priv->screenConfigs);
+   if (!priv->screenConfigs)
       return GL_FALSE;
-   }
-   memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
-   priv->screenConfigs = psc;
 
    priv->serverGLXversion =
       __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
@@ -777,33 +805,22 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
    }
 
    for (i = 0; i < screens; i++, psc++) {
-      getVisualConfigs(dpy, priv, i);
-      getFBConfigs(dpy, priv, i);
-
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
-      psc->scr = i;
-      psc->dpy = dpy;
-      psc->drawHash = __glxHashCreate();
-      if (psc->drawHash == NULL)
-         continue;
-
-      /* Initialize per screen dynamic client GLX extensions */
-      psc->ext_list_first_time = GL_TRUE;
-
       if (priv->dri2Display)
-         psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
-
-      if (psc->driScreen == NULL && priv->driDisplay)
-         psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
-
-      if (psc->driScreen == NULL && priv->driswDisplay)
-         psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
-
-      if (psc->driScreen == NULL) {
+        psc = (*priv->dri2Display->createScreen) (i, priv);
+      if (psc == NULL && priv->driDisplay)
+        psc = (*priv->driDisplay->createScreen) (i, priv);
+      if (psc == NULL && priv->driswDisplay)
+        psc = (*priv->driswDisplay->createScreen) (i, priv);
+      if (psc == NULL)
+        psc = createIndirectScreen (i, priv);
+
+      if (psc == NULL) {
          __glxHashDestroy(psc->drawHash);
          psc->drawHash = NULL;
       }
 #endif
+      priv->screenConfigs[i] = psc;
    }
    SyncHandle();
    return GL_TRUE;