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 const struct glx_context_vtable driwindows_context_vtable = {
11201e04c3fSmrg   .destroy             = driwindows_destroy_context,
11301e04c3fSmrg   .bind                = driwindows_bind_context,
11401e04c3fSmrg   .unbind              = driwindows_unbind_context,
11501e04c3fSmrg   .wait_gl             = NULL,
11601e04c3fSmrg   .wait_x              = NULL,
11701e04c3fSmrg};
11801e04c3fSmrg
11901e04c3fSmrgstatic struct glx_context *
12001e04c3fSmrgdriwindows_create_context(struct glx_screen *base,
12101e04c3fSmrg                          struct glx_config *config_base,
12201e04c3fSmrg                          struct glx_context *shareList, int renderType)
12301e04c3fSmrg{
12401e04c3fSmrg   struct driwindows_context *pcp, *pcp_shared;
12501e04c3fSmrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
12601e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
12701e04c3fSmrg   windowsContext *shared = NULL;
12801e04c3fSmrg
12901e04c3fSmrg   if (!psc->base.driScreen)
13001e04c3fSmrg      return NULL;
13101e04c3fSmrg
13201e04c3fSmrg   /* Check the renderType value */
13301e04c3fSmrg   if (!validate_renderType_against_config(config_base, renderType))
13401e04c3fSmrg       return NULL;
13501e04c3fSmrg
13601e04c3fSmrg   if (shareList) {
13701e04c3fSmrg      /* If the shareList context is not on this renderer, we cannot possibly
13801e04c3fSmrg       * create a context that shares with it.
13901e04c3fSmrg       */
14001e04c3fSmrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
14101e04c3fSmrg         return NULL;
14201e04c3fSmrg      }
14301e04c3fSmrg
14401e04c3fSmrg      pcp_shared = (struct driwindows_context *) shareList;
14501e04c3fSmrg      shared = pcp_shared->windowsContext;
14601e04c3fSmrg   }
14701e04c3fSmrg
14801e04c3fSmrg   pcp = calloc(1, sizeof *pcp);
14901e04c3fSmrg   if (pcp == NULL)
15001e04c3fSmrg      return NULL;
15101e04c3fSmrg
15201e04c3fSmrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
15301e04c3fSmrg      free(pcp);
15401e04c3fSmrg      return NULL;
15501e04c3fSmrg   }
15601e04c3fSmrg
15701e04c3fSmrg   pcp->base.renderType = renderType;
15801e04c3fSmrg
15901e04c3fSmrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
16001e04c3fSmrg
16101e04c3fSmrg   pcp->windowsContext = windows_create_context(config->pxfi, shared);
16201e04c3fSmrg
16301e04c3fSmrg   if (!pcp->windowsContext) {
16401e04c3fSmrg      free(pcp);
16501e04c3fSmrg      return NULL;
16601e04c3fSmrg   }
16701e04c3fSmrg
16801e04c3fSmrg   pcp->base.vtable = &driwindows_context_vtable;
16901e04c3fSmrg
17001e04c3fSmrg   return &pcp->base;
17101e04c3fSmrg}
17201e04c3fSmrg
17301e04c3fSmrgstatic struct glx_context *
17401e04c3fSmrgdriwindows_create_context_attribs(struct glx_screen *base,
17501e04c3fSmrg                                  struct glx_config *config_base,
17601e04c3fSmrg                                  struct glx_context *shareList,
17701e04c3fSmrg                                  unsigned num_attribs,
17801e04c3fSmrg                                  const uint32_t *attribs,
17901e04c3fSmrg                                  unsigned *error)
18001e04c3fSmrg{
18101e04c3fSmrg   struct driwindows_context *pcp, *pcp_shared;
18201e04c3fSmrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
18301e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
18401e04c3fSmrg   windowsContext *shared = NULL;
18501e04c3fSmrg
18601e04c3fSmrg   int i;
18701e04c3fSmrg   uint32_t renderType = GLX_RGBA_TYPE;
18801e04c3fSmrg
18901e04c3fSmrg   /* Extract renderType from attribs */
19001e04c3fSmrg   for (i = 0; i < num_attribs; i++) {
19101e04c3fSmrg      switch (attribs[i * 2]) {
19201e04c3fSmrg      case GLX_RENDER_TYPE:
19301e04c3fSmrg         renderType = attribs[i * 2 + 1];
19401e04c3fSmrg         break;
19501e04c3fSmrg      }
19601e04c3fSmrg   }
19701e04c3fSmrg
19801e04c3fSmrg   /*
19901e04c3fSmrg     Perhaps we should map GLX tokens to WGL tokens, but they appear to have
20001e04c3fSmrg     identical values, so far
20101e04c3fSmrg   */
20201e04c3fSmrg
2037ec681f3Smrg   if (!psc->base.driScreen || !config_base)
20401e04c3fSmrg      return NULL;
20501e04c3fSmrg
20601e04c3fSmrg   /* Check the renderType value */
20701e04c3fSmrg   if (!validate_renderType_against_config(config_base, renderType)) {
20801e04c3fSmrg       return NULL;
20901e04c3fSmrg   }
21001e04c3fSmrg
21101e04c3fSmrg   if (shareList) {
21201e04c3fSmrg      /* If the shareList context is not on this renderer, we cannot possibly
21301e04c3fSmrg       * create a context that shares with it.
21401e04c3fSmrg       */
21501e04c3fSmrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
21601e04c3fSmrg         return NULL;
21701e04c3fSmrg      }
21801e04c3fSmrg
21901e04c3fSmrg      pcp_shared = (struct driwindows_context *) shareList;
22001e04c3fSmrg      shared = pcp_shared->windowsContext;
22101e04c3fSmrg   }
22201e04c3fSmrg
22301e04c3fSmrg   pcp = calloc(1, sizeof *pcp);
22401e04c3fSmrg   if (pcp == NULL)
22501e04c3fSmrg      return NULL;
22601e04c3fSmrg
22701e04c3fSmrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
22801e04c3fSmrg      free(pcp);
22901e04c3fSmrg      return NULL;
23001e04c3fSmrg   }
23101e04c3fSmrg
23201e04c3fSmrg   pcp->base.renderType = renderType;
23301e04c3fSmrg
23401e04c3fSmrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
23501e04c3fSmrg
23601e04c3fSmrg   pcp->windowsContext = windows_create_context_attribs(config->pxfi,
23701e04c3fSmrg                                                      shared,
23801e04c3fSmrg                                                      (const int *)attribs);
23901e04c3fSmrg   if (pcp->windowsContext == NULL) {
24001e04c3fSmrg      free(pcp);
24101e04c3fSmrg      return NULL;
24201e04c3fSmrg   }
24301e04c3fSmrg
24401e04c3fSmrg   pcp->base.vtable = &driwindows_context_vtable;
24501e04c3fSmrg
24601e04c3fSmrg   return &pcp->base;
24701e04c3fSmrg}
24801e04c3fSmrg
24901e04c3fSmrgstatic void
25001e04c3fSmrgdriwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)
25101e04c3fSmrg{
25201e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
25301e04c3fSmrg
25401e04c3fSmrg   windows_destroy_drawable(pdp->windowsDrawable);
25501e04c3fSmrg
25601e04c3fSmrg   free(pdp);
25701e04c3fSmrg}
25801e04c3fSmrg
25901e04c3fSmrgstatic __GLXDRIdrawable *
26001e04c3fSmrgdriwindowsCreateDrawable(struct glx_screen *base, XID xDrawable,
26101e04c3fSmrg                         GLXDrawable drawable, struct glx_config *modes)
26201e04c3fSmrg{
26301e04c3fSmrg   struct driwindows_drawable *pdp;
26401e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
26501e04c3fSmrg
26601e04c3fSmrg   pdp = calloc(1, sizeof(*pdp));
26701e04c3fSmrg   if (!pdp)
26801e04c3fSmrg      return NULL;
26901e04c3fSmrg
27001e04c3fSmrg   pdp->base.xDrawable = xDrawable;
27101e04c3fSmrg   pdp->base.drawable = drawable;
27201e04c3fSmrg   pdp->base.psc = &psc->base;
27301e04c3fSmrg
27401e04c3fSmrg   /*
27501e04c3fSmrg      By this stage, the X drawable already exists, but the GLX drawable may
27601e04c3fSmrg      not.
27701e04c3fSmrg
27801e04c3fSmrg      Query the server with the XID to find the correct HWND, HPBUFFERARB or
27901e04c3fSmrg      HBITMAP
28001e04c3fSmrg   */
28101e04c3fSmrg
28201e04c3fSmrg   unsigned int type;
28301e04c3fSmrg   void *handle;
28401e04c3fSmrg
28501e04c3fSmrg   if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &type, &handle))
28601e04c3fSmrg   {
28701e04c3fSmrg      free(pdp);
28801e04c3fSmrg      return NULL;
28901e04c3fSmrg   }
29001e04c3fSmrg
29101e04c3fSmrg   /* No handle found is a failure */
29201e04c3fSmrg   if (!handle) {
29301e04c3fSmrg      free(pdp);
29401e04c3fSmrg      return NULL;
29501e04c3fSmrg   }
29601e04c3fSmrg
29701e04c3fSmrg   /* Create a new drawable */
29801e04c3fSmrg   pdp->windowsDrawable = windows_create_drawable(type, handle);
29901e04c3fSmrg
30001e04c3fSmrg   if (!pdp->windowsDrawable) {
30101e04c3fSmrg      free(pdp);
30201e04c3fSmrg      return NULL;
30301e04c3fSmrg   }
30401e04c3fSmrg
30501e04c3fSmrg   pdp->base.destroyDrawable = driwindowsDestroyDrawable;
30601e04c3fSmrg
30701e04c3fSmrg   return &pdp->base;
30801e04c3fSmrg}
30901e04c3fSmrg
31001e04c3fSmrgstatic int64_t
31101e04c3fSmrgdriwindowsSwapBuffers(__GLXDRIdrawable * pdraw,
31201e04c3fSmrg                 int64_t target_msc, int64_t divisor, int64_t remainder,
31301e04c3fSmrg                 Bool flush)
31401e04c3fSmrg{
31501e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
31601e04c3fSmrg
31701e04c3fSmrg   (void) target_msc;
31801e04c3fSmrg   (void) divisor;
31901e04c3fSmrg   (void) remainder;
32001e04c3fSmrg
32101e04c3fSmrg   if (flush) {
32201e04c3fSmrg      glFlush();
32301e04c3fSmrg   }
32401e04c3fSmrg
32501e04c3fSmrg   windows_swap_buffers(pdp->windowsDrawable);
32601e04c3fSmrg
32701e04c3fSmrg   return 0;
32801e04c3fSmrg}
32901e04c3fSmrg
33001e04c3fSmrgstatic void
33101e04c3fSmrgdriwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,
33201e04c3fSmrg                   int x, int y, int width, int height, Bool flush)
33301e04c3fSmrg{
33401e04c3fSmrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
33501e04c3fSmrg
33601e04c3fSmrg   if (flush) {
33701e04c3fSmrg      glFlush();
33801e04c3fSmrg   }
33901e04c3fSmrg
34001e04c3fSmrg   windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height);
34101e04c3fSmrg}
34201e04c3fSmrg
34301e04c3fSmrgstatic void
34401e04c3fSmrgdriwindowsDestroyScreen(struct glx_screen *base)
34501e04c3fSmrg{
34601e04c3fSmrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
34701e04c3fSmrg
34801e04c3fSmrg   /* Free the direct rendering per screen data */
34901e04c3fSmrg   psc->driScreen = NULL;
35001e04c3fSmrg   free(psc);
35101e04c3fSmrg}
35201e04c3fSmrg
35301e04c3fSmrgstatic const struct glx_screen_vtable driwindows_screen_vtable = {
35401e04c3fSmrg   .create_context         = driwindows_create_context,
35501e04c3fSmrg   .create_context_attribs = driwindows_create_context_attribs,
35601e04c3fSmrg   .query_renderer_integer = NULL,
35701e04c3fSmrg   .query_renderer_string  = NULL,
35801e04c3fSmrg};
35901e04c3fSmrg
36001e04c3fSmrgstatic Bool
36101e04c3fSmrgdriwindowsBindExtensions(struct driwindows_screen *psc)
36201e04c3fSmrg{
36301e04c3fSmrg   Bool result = 1;
36401e04c3fSmrg
36501e04c3fSmrg   const struct
36601e04c3fSmrg   {
36701e04c3fSmrg      char *wglext;
36801e04c3fSmrg      char *glxext;
36901e04c3fSmrg      Bool mandatory;
37001e04c3fSmrg   } extensionMap[] = {
37101e04c3fSmrg      { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 },
37201e04c3fSmrg      { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
37301e04c3fSmrg      { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
37401e04c3fSmrg//      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
37501e04c3fSmrg// Not exactly equivalent, needs some more glue to be written
37601e04c3fSmrg      { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
37701e04c3fSmrg      { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
37801e04c3fSmrg      { "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 },
37901e04c3fSmrg      { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
38001e04c3fSmrg      { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
38101e04c3fSmrg      { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
38201e04c3fSmrg      { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
38301e04c3fSmrg   };
38401e04c3fSmrg
38501e04c3fSmrg   char *wgl_extensions;
38601e04c3fSmrg   char *gl_extensions;
38701e04c3fSmrg   int i;
38801e04c3fSmrg
38901e04c3fSmrg   windows_extensions(&gl_extensions, &wgl_extensions);
39001e04c3fSmrg
39101e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(extensionMap); i++) {
39201e04c3fSmrg      if (strstr(wgl_extensions, extensionMap[i].wglext)) {
39301e04c3fSmrg          __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext);
39401e04c3fSmrg          InfoMessageF("enabled %s\n", extensionMap[i].glxext);
39501e04c3fSmrg      }
39601e04c3fSmrg      else if (extensionMap[i].mandatory) {
39701e04c3fSmrg         ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext);
39801e04c3fSmrg         result = 0;
39901e04c3fSmrg      }
40001e04c3fSmrg   }
40101e04c3fSmrg
40201e04c3fSmrg   /*
40301e04c3fSmrg       Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
40401e04c3fSmrg       only be in GL_EXTENSIONS
40501e04c3fSmrg   */
40601e04c3fSmrg   if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
40701e04c3fSmrg      psc->copySubBuffer = 1;
40801e04c3fSmrg      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
40901e04c3fSmrg      InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n");
41001e04c3fSmrg   }
41101e04c3fSmrg
41201e04c3fSmrg   free(gl_extensions);
41301e04c3fSmrg   free(wgl_extensions);
41401e04c3fSmrg
41501e04c3fSmrg   return result;
41601e04c3fSmrg}
41701e04c3fSmrg
41801e04c3fSmrgstatic struct glx_config *
41901e04c3fSmrgdriwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs)
42001e04c3fSmrg{
42101e04c3fSmrg   struct glx_config head, *tail, *m;
42201e04c3fSmrg
42301e04c3fSmrg   tail = &head;
42401e04c3fSmrg   head.next = NULL;
42501e04c3fSmrg
42601e04c3fSmrg   for (m = configs; m; m = m->next) {
42701e04c3fSmrg      int fbconfigID = GLX_DONT_CARE;
42801e04c3fSmrg      if (fbconfigs) {
42901e04c3fSmrg         /*
43001e04c3fSmrg           visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig
43101e04c3fSmrg           with matching visualID and get the fbconfigID from there
43201e04c3fSmrg         */
43301e04c3fSmrg         struct glx_config *f;
43401e04c3fSmrg         for (f = fbconfigs; f; f = f->next) {
43501e04c3fSmrg            if (f->visualID == m->visualID)
43601e04c3fSmrg               fbconfigID = f->fbconfigID;
43701e04c3fSmrg         }
43801e04c3fSmrg      }
43901e04c3fSmrg      else {
44001e04c3fSmrg         fbconfigID = m->fbconfigID;
44101e04c3fSmrg      }
44201e04c3fSmrg
44301e04c3fSmrg      int pxfi;
44401e04c3fSmrg      XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi);
44501e04c3fSmrg      if (pxfi == 0)
44601e04c3fSmrg         continue;
44701e04c3fSmrg
44801e04c3fSmrg      struct driwindows_config *config = malloc(sizeof(*config));
44901e04c3fSmrg
45001e04c3fSmrg      tail->next = &config->base;
45101e04c3fSmrg      if (tail->next == NULL)
45201e04c3fSmrg         continue;
45301e04c3fSmrg
45401e04c3fSmrg      config->base = *m;
45501e04c3fSmrg      config->pxfi = pxfi;
45601e04c3fSmrg
45701e04c3fSmrg      tail = tail->next;
45801e04c3fSmrg   }
45901e04c3fSmrg
46001e04c3fSmrg   return head.next;
46101e04c3fSmrg}
46201e04c3fSmrg
46301e04c3fSmrgstatic struct glx_screen *
46401e04c3fSmrgdriwindowsCreateScreen(int screen, struct glx_display *priv)
46501e04c3fSmrg{
46601e04c3fSmrg   __GLXDRIscreen *psp;
46701e04c3fSmrg   struct driwindows_screen *psc;
46801e04c3fSmrg   struct glx_config *configs = NULL, *visuals = NULL;
46901e04c3fSmrg   int directCapable;
47001e04c3fSmrg
47101e04c3fSmrg   psc = calloc(1, sizeof *psc);
47201e04c3fSmrg   if (psc == NULL)
47301e04c3fSmrg      return NULL;
47401e04c3fSmrg
47501e04c3fSmrg   if (!glx_screen_init(&psc->base, screen, priv)) {
47601e04c3fSmrg      free(psc);
47701e04c3fSmrg      return NULL;
47801e04c3fSmrg   }
47901e04c3fSmrg
48001e04c3fSmrg   if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) ||
48101e04c3fSmrg       !directCapable) {
48201e04c3fSmrg      ErrorMessageF("Screen is not Windows-DRI capable\n");
48301e04c3fSmrg      goto handle_error;
48401e04c3fSmrg   }
48501e04c3fSmrg
48601e04c3fSmrg   /* discover native supported extensions */
48701e04c3fSmrg   if (!driwindowsBindExtensions(psc)) {
48801e04c3fSmrg      goto handle_error;
48901e04c3fSmrg   }
49001e04c3fSmrg
49101e04c3fSmrg   /* Augment configs with pxfi information */
49201e04c3fSmrg   configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL);
49301e04c3fSmrg   visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs);
49401e04c3fSmrg
49501e04c3fSmrg   if (!configs || !visuals) {
49601e04c3fSmrg       ErrorMessageF("No fbConfigs or visuals found\n");
49701e04c3fSmrg       goto handle_error;
49801e04c3fSmrg   }
49901e04c3fSmrg
50001e04c3fSmrg   glx_config_destroy_list(psc->base.configs);
50101e04c3fSmrg   psc->base.configs = configs;
50201e04c3fSmrg   glx_config_destroy_list(psc->base.visuals);
50301e04c3fSmrg   psc->base.visuals = visuals;
50401e04c3fSmrg
50501e04c3fSmrg   psc->base.vtable = &driwindows_screen_vtable;
50601e04c3fSmrg   psp = &psc->vtable;
50701e04c3fSmrg   psc->base.driScreen = psp;
50801e04c3fSmrg   psp->destroyScreen = driwindowsDestroyScreen;
50901e04c3fSmrg   psp->createDrawable = driwindowsCreateDrawable;
51001e04c3fSmrg   psp->swapBuffers = driwindowsSwapBuffers;
51101e04c3fSmrg
51201e04c3fSmrg   if (psc->copySubBuffer)
51301e04c3fSmrg      psp->copySubBuffer = driwindowsCopySubBuffer;
51401e04c3fSmrg
51501e04c3fSmrg   return &psc->base;
51601e04c3fSmrg
51701e04c3fSmrghandle_error:
51801e04c3fSmrg   glx_screen_cleanup(&psc->base);
51901e04c3fSmrg
52001e04c3fSmrg   return NULL;
52101e04c3fSmrg}
52201e04c3fSmrg
52301e04c3fSmrg/* Called from __glXFreeDisplayPrivate.
52401e04c3fSmrg */
52501e04c3fSmrgstatic void
52601e04c3fSmrgdriwindowsDestroyDisplay(__GLXDRIdisplay * dpy)
52701e04c3fSmrg{
52801e04c3fSmrg   free(dpy);
52901e04c3fSmrg}
53001e04c3fSmrg
53101e04c3fSmrg/*
53201e04c3fSmrg * Allocate, initialize and return a  __GLXDRIdisplay object.
53301e04c3fSmrg * This is called from __glXInitialize() when we are given a new
53401e04c3fSmrg * display pointer.
53501e04c3fSmrg */
53601e04c3fSmrg_X_HIDDEN __GLXDRIdisplay *
53701e04c3fSmrgdriwindowsCreateDisplay(Display * dpy)
53801e04c3fSmrg{
53901e04c3fSmrg   struct driwindows_display *pdpyp;
54001e04c3fSmrg
54101e04c3fSmrg   int eventBase, errorBase;
54201e04c3fSmrg   int major, minor, patch;
54301e04c3fSmrg
54401e04c3fSmrg   /* Verify server has Windows-DRI extension */
54501e04c3fSmrg   if (!XWindowsDRIQueryExtension(dpy, &eventBase, &errorBase)) {
54601e04c3fSmrg      ErrorMessageF("Windows-DRI extension not available\n");
54701e04c3fSmrg      return NULL;
54801e04c3fSmrg   }
54901e04c3fSmrg
55001e04c3fSmrg   if (!XWindowsDRIQueryVersion(dpy, &major, &minor, &patch)) {
55101e04c3fSmrg      ErrorMessageF("Fetching Windows-DRI extension version failed\n");
55201e04c3fSmrg      return NULL;
55301e04c3fSmrg   }
55401e04c3fSmrg
55501e04c3fSmrg   if (!windows_check_renderer()) {
55601e04c3fSmrg      ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n");
55701e04c3fSmrg      return NULL;
55801e04c3fSmrg   }
55901e04c3fSmrg
56001e04c3fSmrg   pdpyp = malloc(sizeof *pdpyp);
56101e04c3fSmrg   if (pdpyp == NULL)
56201e04c3fSmrg      return NULL;
56301e04c3fSmrg
56401e04c3fSmrg   pdpyp->base.destroyDisplay = driwindowsDestroyDisplay;
56501e04c3fSmrg   pdpyp->base.createScreen = driwindowsCreateScreen;
56601e04c3fSmrg
56701e04c3fSmrg   pdpyp->event_base = eventBase;
56801e04c3fSmrg
56901e04c3fSmrg   return &pdpyp->base;
57001e04c3fSmrg}
571