driwindows_glx.c revision 01e04c3f
101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2014 Jon Turney
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "glxclient.h"
2501e04c3fSmrg#include "glx_error.h"
2601e04c3fSmrg#include "dri_common.h"
2701e04c3fSmrg#include "util/macros.h"
2801e04c3fSmrg#include "windows/xwindowsdri.h"
2901e04c3fSmrg#include "windows/windowsgl.h"
3001e04c3fSmrg
3101e04c3fSmrgstruct driwindows_display
3201e04c3fSmrg{
3301e04c3fSmrg   __GLXDRIdisplay base;
3401e04c3fSmrg   int event_base;
3501e04c3fSmrg};
3601e04c3fSmrg
3701e04c3fSmrgstruct driwindows_context
3801e04c3fSmrg{
3901e04c3fSmrg   struct glx_context base;
4001e04c3fSmrg   windowsContext *windowsContext;
4101e04c3fSmrg};
4201e04c3fSmrg
4301e04c3fSmrgstruct driwindows_config
4401e04c3fSmrg{
4501e04c3fSmrg   struct glx_config base;
4601e04c3fSmrg   int pxfi;
4701e04c3fSmrg};
4801e04c3fSmrg
4901e04c3fSmrgstruct driwindows_screen
5001e04c3fSmrg{
5101e04c3fSmrg   struct glx_screen base;
5201e04c3fSmrg   __DRIscreen *driScreen;
5301e04c3fSmrg   __GLXDRIscreen vtable;
5401e04c3fSmrg   Bool copySubBuffer;
5501e04c3fSmrg};
5601e04c3fSmrg
5701e04c3fSmrgstruct driwindows_drawable
5801e04c3fSmrg{
5901e04c3fSmrg   __GLXDRIdrawable base;
6001e04c3fSmrg   windowsDrawable *windowsDrawable;
6101e04c3fSmrg};
6201e04c3fSmrg
6301e04c3fSmrg/**
6401e04c3fSmrg * GLXDRI functions
6501e04c3fSmrg */
6601e04c3fSmrg
6701e04c3fSmrgstatic void
6801e04c3fSmrgdriwindows_destroy_context(struct glx_context *context)
6901e04c3fSmrg{
7001e04c3fSmrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
7101e04c3fSmrg
7201e04c3fSmrg   driReleaseDrawables(&pcp->base);
7301e04c3fSmrg
7401e04c3fSmrg   free((char *) context->extensions);
7501e04c3fSmrg
7601e04c3fSmrg   windows_destroy_context(pcp->windowsContext);
7701e04c3fSmrg
7801e04c3fSmrg   free(pcp);
7901e04c3fSmrg}
8001e04c3fSmrg
8101e04c3fSmrgstatic int
8201e04c3fSmrgdriwindows_bind_context(struct glx_context *context, struct glx_context *old,
8301e04c3fSmrg                        GLXDrawable draw, GLXDrawable read)
8401e04c3fSmrg{
8501e04c3fSmrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
8601e04c3fSmrg   struct driwindows_drawable *pdraw, *pread;
8701e04c3fSmrg
8801e04c3fSmrg   pdraw = (struct driwindows_drawable *) driFetchDrawable(context, draw);
8901e04c3fSmrg   pread = (struct driwindows_drawable *) driFetchDrawable(context, read);
9001e04c3fSmrg
9101e04c3fSmrg   driReleaseDrawables(&pcp->base);
9201e04c3fSmrg
9301e04c3fSmrg   if (pdraw == NULL || pread == NULL)
9401e04c3fSmrg      return GLXBadDrawable;
9501e04c3fSmrg
9601e04c3fSmrg   if (windows_bind_context(pcp->windowsContext,
9701e04c3fSmrg                           pdraw->windowsDrawable, pread->windowsDrawable))
9801e04c3fSmrg      return Success;
9901e04c3fSmrg
10001e04c3fSmrg   return GLXBadContext;
10101e04c3fSmrg}
10201e04c3fSmrg
10301e04c3fSmrgstatic void
10401e04c3fSmrgdriwindows_unbind_context(struct glx_context *context, struct glx_context *new)
10501e04c3fSmrg{
10601e04c3fSmrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
10701e04c3fSmrg
10801e04c3fSmrg   windows_unbind_context(pcp->windowsContext);
10901e04c3fSmrg}
11001e04c3fSmrg
11101e04c3fSmrgstatic void
11201e04c3fSmrgdriwindows_bind_tex_image(Display * dpy,
11301e04c3fSmrg                    GLXDrawable drawable,
11401e04c3fSmrg                    int buffer, const int *attrib_list)
11501e04c3fSmrg{
11601e04c3fSmrg   struct glx_context *gc = __glXGetCurrentContext();
11701e04c3fSmrg   struct driwindows_context *pcp = (struct driwindows_context *) gc;
11801e04c3fSmrg   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
11901e04c3fSmrg   struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base;
12001e04c3fSmrg
12101e04c3fSmrg   __glXInitialize(dpy);
12201e04c3fSmrg
12301e04c3fSmrg   if (pdraw != NULL) {
12401e04c3fSmrg      windows_setTexBuffer(pcp->windowsContext,
12501e04c3fSmrg                          pdraw->base.textureTarget,
12601e04c3fSmrg                          pdraw->base.textureFormat,
12701e04c3fSmrg                          pdraw->windowsDrawable);
12801e04c3fSmrg   }
12901e04c3fSmrg}
13001e04c3fSmrg
13101e04c3fSmrgstatic void
13201e04c3fSmrgdriwindows_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
13301e04c3fSmrg{
13401e04c3fSmrg   struct glx_context *gc = __glXGetCurrentContext();
13501e04c3fSmrg   struct driwindows_context *pcp = (struct driwindows_context *) gc;
13601e04c3fSmrg   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
13701e04c3fSmrg   struct glx_display *dpyPriv = __glXInitialize(dpy);
13801e04c3fSmrg   struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base;
13901e04c3fSmrg
14001e04c3fSmrg   if (dpyPriv != NULL && pdraw != NULL) {
14101e04c3fSmrg      windows_releaseTexBuffer(pcp->windowsContext,
14201e04c3fSmrg                              pdraw->base.textureTarget,
14301e04c3fSmrg                              pdraw->windowsDrawable);
14401e04c3fSmrg      }
14501e04c3fSmrg}
14601e04c3fSmrg
14701e04c3fSmrgstatic const struct glx_context_vtable driwindows_context_vtable = {
14801e04c3fSmrg   .destroy             = driwindows_destroy_context,
14901e04c3fSmrg   .bind                = driwindows_bind_context,
15001e04c3fSmrg   .unbind              = driwindows_unbind_context,
15101e04c3fSmrg   .wait_gl             = NULL,
15201e04c3fSmrg   .wait_x              = NULL,
15301e04c3fSmrg   .use_x_font          = DRI_glXUseXFont,
15401e04c3fSmrg   .bind_tex_image      = driwindows_bind_tex_image,
15501e04c3fSmrg   .release_tex_image   = driwindows_release_tex_image,
15601e04c3fSmrg   .get_proc_address    = NULL,
15701e04c3fSmrg};
15801e04c3fSmrg
15901e04c3fSmrgstatic struct glx_context *
16001e04c3fSmrgdriwindows_create_context(struct glx_screen *base,
16101e04c3fSmrg                          struct glx_config *config_base,
16201e04c3fSmrg                          struct glx_context *shareList, int renderType)
16301e04c3fSmrg{
16401e04c3fSmrg   struct driwindows_context *pcp, *pcp_shared;
16501e04c3fSmrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
16601e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
16701e04c3fSmrg   windowsContext *shared = NULL;
16801e04c3fSmrg
16901e04c3fSmrg   if (!psc->base.driScreen)
17001e04c3fSmrg      return NULL;
17101e04c3fSmrg
17201e04c3fSmrg   /* Check the renderType value */
17301e04c3fSmrg   if (!validate_renderType_against_config(config_base, renderType))
17401e04c3fSmrg       return NULL;
17501e04c3fSmrg
17601e04c3fSmrg   if (shareList) {
17701e04c3fSmrg      /* If the shareList context is not on this renderer, we cannot possibly
17801e04c3fSmrg       * create a context that shares with it.
17901e04c3fSmrg       */
18001e04c3fSmrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
18101e04c3fSmrg         return NULL;
18201e04c3fSmrg      }
18301e04c3fSmrg
18401e04c3fSmrg      pcp_shared = (struct driwindows_context *) shareList;
18501e04c3fSmrg      shared = pcp_shared->windowsContext;
18601e04c3fSmrg   }
18701e04c3fSmrg
18801e04c3fSmrg   pcp = calloc(1, sizeof *pcp);
18901e04c3fSmrg   if (pcp == NULL)
19001e04c3fSmrg      return NULL;
19101e04c3fSmrg
19201e04c3fSmrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
19301e04c3fSmrg      free(pcp);
19401e04c3fSmrg      return NULL;
19501e04c3fSmrg   }
19601e04c3fSmrg
19701e04c3fSmrg   pcp->base.renderType = renderType;
19801e04c3fSmrg
19901e04c3fSmrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
20001e04c3fSmrg
20101e04c3fSmrg   pcp->windowsContext = windows_create_context(config->pxfi, shared);
20201e04c3fSmrg
20301e04c3fSmrg   if (!pcp->windowsContext) {
20401e04c3fSmrg      free(pcp);
20501e04c3fSmrg      return NULL;
20601e04c3fSmrg   }
20701e04c3fSmrg
20801e04c3fSmrg   pcp->base.vtable = &driwindows_context_vtable;
20901e04c3fSmrg
21001e04c3fSmrg   return &pcp->base;
21101e04c3fSmrg}
21201e04c3fSmrg
21301e04c3fSmrgstatic struct glx_context *
21401e04c3fSmrgdriwindows_create_context_attribs(struct glx_screen *base,
21501e04c3fSmrg                                  struct glx_config *config_base,
21601e04c3fSmrg                                  struct glx_context *shareList,
21701e04c3fSmrg                                  unsigned num_attribs,
21801e04c3fSmrg                                  const uint32_t *attribs,
21901e04c3fSmrg                                  unsigned *error)
22001e04c3fSmrg{
22101e04c3fSmrg   struct driwindows_context *pcp, *pcp_shared;
22201e04c3fSmrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
22301e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
22401e04c3fSmrg   windowsContext *shared = NULL;
22501e04c3fSmrg
22601e04c3fSmrg   int i;
22701e04c3fSmrg   uint32_t renderType = GLX_RGBA_TYPE;
22801e04c3fSmrg
22901e04c3fSmrg   /* Extract renderType from attribs */
23001e04c3fSmrg   for (i = 0; i < num_attribs; i++) {
23101e04c3fSmrg      switch (attribs[i * 2]) {
23201e04c3fSmrg      case GLX_RENDER_TYPE:
23301e04c3fSmrg         renderType = attribs[i * 2 + 1];
23401e04c3fSmrg         break;
23501e04c3fSmrg      }
23601e04c3fSmrg   }
23701e04c3fSmrg
23801e04c3fSmrg   /*
23901e04c3fSmrg     Perhaps we should map GLX tokens to WGL tokens, but they appear to have
24001e04c3fSmrg     identical values, so far
24101e04c3fSmrg   */
24201e04c3fSmrg
24301e04c3fSmrg   if (!psc->base.driScreen)
24401e04c3fSmrg      return NULL;
24501e04c3fSmrg
24601e04c3fSmrg   /* Check the renderType value */
24701e04c3fSmrg   if (!validate_renderType_against_config(config_base, renderType)) {
24801e04c3fSmrg       return NULL;
24901e04c3fSmrg   }
25001e04c3fSmrg
25101e04c3fSmrg   if (shareList) {
25201e04c3fSmrg      /* If the shareList context is not on this renderer, we cannot possibly
25301e04c3fSmrg       * create a context that shares with it.
25401e04c3fSmrg       */
25501e04c3fSmrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
25601e04c3fSmrg         return NULL;
25701e04c3fSmrg      }
25801e04c3fSmrg
25901e04c3fSmrg      pcp_shared = (struct driwindows_context *) shareList;
26001e04c3fSmrg      shared = pcp_shared->windowsContext;
26101e04c3fSmrg   }
26201e04c3fSmrg
26301e04c3fSmrg   pcp = calloc(1, sizeof *pcp);
26401e04c3fSmrg   if (pcp == NULL)
26501e04c3fSmrg      return NULL;
26601e04c3fSmrg
26701e04c3fSmrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
26801e04c3fSmrg      free(pcp);
26901e04c3fSmrg      return NULL;
27001e04c3fSmrg   }
27101e04c3fSmrg
27201e04c3fSmrg   pcp->base.renderType = renderType;
27301e04c3fSmrg
27401e04c3fSmrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
27501e04c3fSmrg
27601e04c3fSmrg   pcp->windowsContext = windows_create_context_attribs(config->pxfi,
27701e04c3fSmrg                                                      shared,
27801e04c3fSmrg                                                      (const int *)attribs);
27901e04c3fSmrg   if (pcp->windowsContext == NULL) {
28001e04c3fSmrg      free(pcp);
28101e04c3fSmrg      return NULL;
28201e04c3fSmrg   }
28301e04c3fSmrg
28401e04c3fSmrg   pcp->base.vtable = &driwindows_context_vtable;
28501e04c3fSmrg
28601e04c3fSmrg   return &pcp->base;
28701e04c3fSmrg}
28801e04c3fSmrg
28901e04c3fSmrgstatic void
29001e04c3fSmrgdriwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)
29101e04c3fSmrg{
29201e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
29301e04c3fSmrg
29401e04c3fSmrg   windows_destroy_drawable(pdp->windowsDrawable);
29501e04c3fSmrg
29601e04c3fSmrg   free(pdp);
29701e04c3fSmrg}
29801e04c3fSmrg
29901e04c3fSmrgstatic __GLXDRIdrawable *
30001e04c3fSmrgdriwindowsCreateDrawable(struct glx_screen *base, XID xDrawable,
30101e04c3fSmrg                         GLXDrawable drawable, struct glx_config *modes)
30201e04c3fSmrg{
30301e04c3fSmrg   struct driwindows_drawable *pdp;
30401e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
30501e04c3fSmrg
30601e04c3fSmrg   pdp = calloc(1, sizeof(*pdp));
30701e04c3fSmrg   if (!pdp)
30801e04c3fSmrg      return NULL;
30901e04c3fSmrg
31001e04c3fSmrg   pdp->base.xDrawable = xDrawable;
31101e04c3fSmrg   pdp->base.drawable = drawable;
31201e04c3fSmrg   pdp->base.psc = &psc->base;
31301e04c3fSmrg
31401e04c3fSmrg   /*
31501e04c3fSmrg      By this stage, the X drawable already exists, but the GLX drawable may
31601e04c3fSmrg      not.
31701e04c3fSmrg
31801e04c3fSmrg      Query the server with the XID to find the correct HWND, HPBUFFERARB or
31901e04c3fSmrg      HBITMAP
32001e04c3fSmrg   */
32101e04c3fSmrg
32201e04c3fSmrg   unsigned int type;
32301e04c3fSmrg   void *handle;
32401e04c3fSmrg
32501e04c3fSmrg   if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &type, &handle))
32601e04c3fSmrg   {
32701e04c3fSmrg      free(pdp);
32801e04c3fSmrg      return NULL;
32901e04c3fSmrg   }
33001e04c3fSmrg
33101e04c3fSmrg   /* No handle found is a failure */
33201e04c3fSmrg   if (!handle) {
33301e04c3fSmrg      free(pdp);
33401e04c3fSmrg      return NULL;
33501e04c3fSmrg   }
33601e04c3fSmrg
33701e04c3fSmrg   /* Create a new drawable */
33801e04c3fSmrg   pdp->windowsDrawable = windows_create_drawable(type, handle);
33901e04c3fSmrg
34001e04c3fSmrg   if (!pdp->windowsDrawable) {
34101e04c3fSmrg      free(pdp);
34201e04c3fSmrg      return NULL;
34301e04c3fSmrg   }
34401e04c3fSmrg
34501e04c3fSmrg   pdp->base.destroyDrawable = driwindowsDestroyDrawable;
34601e04c3fSmrg
34701e04c3fSmrg   return &pdp->base;
34801e04c3fSmrg}
34901e04c3fSmrg
35001e04c3fSmrgstatic int64_t
35101e04c3fSmrgdriwindowsSwapBuffers(__GLXDRIdrawable * pdraw,
35201e04c3fSmrg                 int64_t target_msc, int64_t divisor, int64_t remainder,
35301e04c3fSmrg                 Bool flush)
35401e04c3fSmrg{
35501e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
35601e04c3fSmrg
35701e04c3fSmrg   (void) target_msc;
35801e04c3fSmrg   (void) divisor;
35901e04c3fSmrg   (void) remainder;
36001e04c3fSmrg
36101e04c3fSmrg   if (flush) {
36201e04c3fSmrg      glFlush();
36301e04c3fSmrg   }
36401e04c3fSmrg
36501e04c3fSmrg   windows_swap_buffers(pdp->windowsDrawable);
36601e04c3fSmrg
36701e04c3fSmrg   return 0;
36801e04c3fSmrg}
36901e04c3fSmrg
37001e04c3fSmrgstatic void
37101e04c3fSmrgdriwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,
37201e04c3fSmrg                   int x, int y, int width, int height, Bool flush)
37301e04c3fSmrg{
37401e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
37501e04c3fSmrg
37601e04c3fSmrg   if (flush) {
37701e04c3fSmrg      glFlush();
37801e04c3fSmrg   }
37901e04c3fSmrg
38001e04c3fSmrg   windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height);
38101e04c3fSmrg}
38201e04c3fSmrg
38301e04c3fSmrgstatic void
38401e04c3fSmrgdriwindowsDestroyScreen(struct glx_screen *base)
38501e04c3fSmrg{
38601e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
38701e04c3fSmrg
38801e04c3fSmrg   /* Free the direct rendering per screen data */
38901e04c3fSmrg   psc->driScreen = NULL;
39001e04c3fSmrg   free(psc);
39101e04c3fSmrg}
39201e04c3fSmrg
39301e04c3fSmrgstatic const struct glx_screen_vtable driwindows_screen_vtable = {
39401e04c3fSmrg   .create_context         = driwindows_create_context,
39501e04c3fSmrg   .create_context_attribs = driwindows_create_context_attribs,
39601e04c3fSmrg   .query_renderer_integer = NULL,
39701e04c3fSmrg   .query_renderer_string  = NULL,
39801e04c3fSmrg};
39901e04c3fSmrg
40001e04c3fSmrgstatic Bool
40101e04c3fSmrgdriwindowsBindExtensions(struct driwindows_screen *psc)
40201e04c3fSmrg{
40301e04c3fSmrg   Bool result = 1;
40401e04c3fSmrg
40501e04c3fSmrg   const struct
40601e04c3fSmrg   {
40701e04c3fSmrg      char *wglext;
40801e04c3fSmrg      char *glxext;
40901e04c3fSmrg      Bool mandatory;
41001e04c3fSmrg   } extensionMap[] = {
41101e04c3fSmrg      { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 },
41201e04c3fSmrg      { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
41301e04c3fSmrg      { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
41401e04c3fSmrg//      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
41501e04c3fSmrg// Not exactly equivalent, needs some more glue to be written
41601e04c3fSmrg      { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
41701e04c3fSmrg      { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
41801e04c3fSmrg      { "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 },
41901e04c3fSmrg      { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
42001e04c3fSmrg      { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
42101e04c3fSmrg      { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
42201e04c3fSmrg      { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
42301e04c3fSmrg   };
42401e04c3fSmrg
42501e04c3fSmrg   char *wgl_extensions;
42601e04c3fSmrg   char *gl_extensions;
42701e04c3fSmrg   int i;
42801e04c3fSmrg
42901e04c3fSmrg   windows_extensions(&gl_extensions, &wgl_extensions);
43001e04c3fSmrg
43101e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(extensionMap); i++) {
43201e04c3fSmrg      if (strstr(wgl_extensions, extensionMap[i].wglext)) {
43301e04c3fSmrg          __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext);
43401e04c3fSmrg          InfoMessageF("enabled %s\n", extensionMap[i].glxext);
43501e04c3fSmrg      }
43601e04c3fSmrg      else if (extensionMap[i].mandatory) {
43701e04c3fSmrg         ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext);
43801e04c3fSmrg         result = 0;
43901e04c3fSmrg      }
44001e04c3fSmrg   }
44101e04c3fSmrg
44201e04c3fSmrg   /*
44301e04c3fSmrg       Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
44401e04c3fSmrg       only be in GL_EXTENSIONS
44501e04c3fSmrg   */
44601e04c3fSmrg   if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
44701e04c3fSmrg      psc->copySubBuffer = 1;
44801e04c3fSmrg      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
44901e04c3fSmrg      InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n");
45001e04c3fSmrg   }
45101e04c3fSmrg
45201e04c3fSmrg   free(gl_extensions);
45301e04c3fSmrg   free(wgl_extensions);
45401e04c3fSmrg
45501e04c3fSmrg   return result;
45601e04c3fSmrg}
45701e04c3fSmrg
45801e04c3fSmrgstatic struct glx_config *
45901e04c3fSmrgdriwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs)
46001e04c3fSmrg{
46101e04c3fSmrg   struct glx_config head, *tail, *m;
46201e04c3fSmrg
46301e04c3fSmrg   tail = &head;
46401e04c3fSmrg   head.next = NULL;
46501e04c3fSmrg
46601e04c3fSmrg   for (m = configs; m; m = m->next) {
46701e04c3fSmrg      int fbconfigID = GLX_DONT_CARE;
46801e04c3fSmrg      if (fbconfigs) {
46901e04c3fSmrg         /*
47001e04c3fSmrg           visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig
47101e04c3fSmrg           with matching visualID and get the fbconfigID from there
47201e04c3fSmrg         */
47301e04c3fSmrg         struct glx_config *f;
47401e04c3fSmrg         for (f = fbconfigs; f; f = f->next) {
47501e04c3fSmrg            if (f->visualID == m->visualID)
47601e04c3fSmrg               fbconfigID = f->fbconfigID;
47701e04c3fSmrg         }
47801e04c3fSmrg      }
47901e04c3fSmrg      else {
48001e04c3fSmrg         fbconfigID = m->fbconfigID;
48101e04c3fSmrg      }
48201e04c3fSmrg
48301e04c3fSmrg      int pxfi;
48401e04c3fSmrg      XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi);
48501e04c3fSmrg      if (pxfi == 0)
48601e04c3fSmrg         continue;
48701e04c3fSmrg
48801e04c3fSmrg      struct driwindows_config *config = malloc(sizeof(*config));
48901e04c3fSmrg
49001e04c3fSmrg      tail->next = &config->base;
49101e04c3fSmrg      if (tail->next == NULL)
49201e04c3fSmrg         continue;
49301e04c3fSmrg
49401e04c3fSmrg      config->base = *m;
49501e04c3fSmrg      config->pxfi = pxfi;
49601e04c3fSmrg
49701e04c3fSmrg      tail = tail->next;
49801e04c3fSmrg   }
49901e04c3fSmrg
50001e04c3fSmrg   return head.next;
50101e04c3fSmrg}
50201e04c3fSmrg
50301e04c3fSmrgstatic struct glx_screen *
50401e04c3fSmrgdriwindowsCreateScreen(int screen, struct glx_display *priv)
50501e04c3fSmrg{
50601e04c3fSmrg   __GLXDRIscreen *psp;
50701e04c3fSmrg   struct driwindows_screen *psc;
50801e04c3fSmrg   struct glx_config *configs = NULL, *visuals = NULL;
50901e04c3fSmrg   int directCapable;
51001e04c3fSmrg
51101e04c3fSmrg   psc = calloc(1, sizeof *psc);
51201e04c3fSmrg   if (psc == NULL)
51301e04c3fSmrg      return NULL;
51401e04c3fSmrg
51501e04c3fSmrg   if (!glx_screen_init(&psc->base, screen, priv)) {
51601e04c3fSmrg      free(psc);
51701e04c3fSmrg      return NULL;
51801e04c3fSmrg   }
51901e04c3fSmrg
52001e04c3fSmrg   if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) ||
52101e04c3fSmrg       !directCapable) {
52201e04c3fSmrg      ErrorMessageF("Screen is not Windows-DRI capable\n");
52301e04c3fSmrg      goto handle_error;
52401e04c3fSmrg   }
52501e04c3fSmrg
52601e04c3fSmrg   /* discover native supported extensions */
52701e04c3fSmrg   if (!driwindowsBindExtensions(psc)) {
52801e04c3fSmrg      goto handle_error;
52901e04c3fSmrg   }
53001e04c3fSmrg
53101e04c3fSmrg   /* Augment configs with pxfi information */
53201e04c3fSmrg   configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL);
53301e04c3fSmrg   visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs);
53401e04c3fSmrg
53501e04c3fSmrg   if (!configs || !visuals) {
53601e04c3fSmrg       ErrorMessageF("No fbConfigs or visuals found\n");
53701e04c3fSmrg       goto handle_error;
53801e04c3fSmrg   }
53901e04c3fSmrg
54001e04c3fSmrg   glx_config_destroy_list(psc->base.configs);
54101e04c3fSmrg   psc->base.configs = configs;
54201e04c3fSmrg   glx_config_destroy_list(psc->base.visuals);
54301e04c3fSmrg   psc->base.visuals = visuals;
54401e04c3fSmrg
54501e04c3fSmrg   psc->base.vtable = &driwindows_screen_vtable;
54601e04c3fSmrg   psp = &psc->vtable;
54701e04c3fSmrg   psc->base.driScreen = psp;
54801e04c3fSmrg   psp->destroyScreen = driwindowsDestroyScreen;
54901e04c3fSmrg   psp->createDrawable = driwindowsCreateDrawable;
55001e04c3fSmrg   psp->swapBuffers = driwindowsSwapBuffers;
55101e04c3fSmrg
55201e04c3fSmrg   if (psc->copySubBuffer)
55301e04c3fSmrg      psp->copySubBuffer = driwindowsCopySubBuffer;
55401e04c3fSmrg
55501e04c3fSmrg   return &psc->base;
55601e04c3fSmrg
55701e04c3fSmrghandle_error:
55801e04c3fSmrg   glx_screen_cleanup(&psc->base);
55901e04c3fSmrg
56001e04c3fSmrg   return NULL;
56101e04c3fSmrg}
56201e04c3fSmrg
56301e04c3fSmrg/* Called from __glXFreeDisplayPrivate.
56401e04c3fSmrg */
56501e04c3fSmrgstatic void
56601e04c3fSmrgdriwindowsDestroyDisplay(__GLXDRIdisplay * dpy)
56701e04c3fSmrg{
56801e04c3fSmrg   free(dpy);
56901e04c3fSmrg}
57001e04c3fSmrg
57101e04c3fSmrg/*
57201e04c3fSmrg * Allocate, initialize and return a  __GLXDRIdisplay object.
57301e04c3fSmrg * This is called from __glXInitialize() when we are given a new
57401e04c3fSmrg * display pointer.
57501e04c3fSmrg */
57601e04c3fSmrg_X_HIDDEN __GLXDRIdisplay *
57701e04c3fSmrgdriwindowsCreateDisplay(Display * dpy)
57801e04c3fSmrg{
57901e04c3fSmrg   struct driwindows_display *pdpyp;
58001e04c3fSmrg
58101e04c3fSmrg   int eventBase, errorBase;
58201e04c3fSmrg   int major, minor, patch;
58301e04c3fSmrg
58401e04c3fSmrg   /* Verify server has Windows-DRI extension */
58501e04c3fSmrg   if (!XWindowsDRIQueryExtension(dpy, &eventBase, &errorBase)) {
58601e04c3fSmrg      ErrorMessageF("Windows-DRI extension not available\n");
58701e04c3fSmrg      return NULL;
58801e04c3fSmrg   }
58901e04c3fSmrg
59001e04c3fSmrg   if (!XWindowsDRIQueryVersion(dpy, &major, &minor, &patch)) {
59101e04c3fSmrg      ErrorMessageF("Fetching Windows-DRI extension version failed\n");
59201e04c3fSmrg      return NULL;
59301e04c3fSmrg   }
59401e04c3fSmrg
59501e04c3fSmrg   if (!windows_check_renderer()) {
59601e04c3fSmrg      ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n");
59701e04c3fSmrg      return NULL;
59801e04c3fSmrg   }
59901e04c3fSmrg
60001e04c3fSmrg   pdpyp = malloc(sizeof *pdpyp);
60101e04c3fSmrg   if (pdpyp == NULL)
60201e04c3fSmrg      return NULL;
60301e04c3fSmrg
60401e04c3fSmrg   pdpyp->base.destroyDisplay = driwindowsDestroyDisplay;
60501e04c3fSmrg   pdpyp->base.createScreen = driwindowsCreateScreen;
60601e04c3fSmrg
60701e04c3fSmrg   pdpyp->event_base = eventBase;
60801e04c3fSmrg
60901e04c3fSmrg   return &pdpyp->base;
61001e04c3fSmrg}
611