1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2014 Jon Turney
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21b8e80941Smrg * IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg#include "glxclient.h"
25b8e80941Smrg#include "glx_error.h"
26b8e80941Smrg#include "dri_common.h"
27b8e80941Smrg#include "util/macros.h"
28b8e80941Smrg#include "windows/xwindowsdri.h"
29b8e80941Smrg#include "windows/windowsgl.h"
30b8e80941Smrg
31b8e80941Smrgstruct driwindows_display
32b8e80941Smrg{
33b8e80941Smrg   __GLXDRIdisplay base;
34b8e80941Smrg   int event_base;
35b8e80941Smrg};
36b8e80941Smrg
37b8e80941Smrgstruct driwindows_context
38b8e80941Smrg{
39b8e80941Smrg   struct glx_context base;
40b8e80941Smrg   windowsContext *windowsContext;
41b8e80941Smrg};
42b8e80941Smrg
43b8e80941Smrgstruct driwindows_config
44b8e80941Smrg{
45b8e80941Smrg   struct glx_config base;
46b8e80941Smrg   int pxfi;
47b8e80941Smrg};
48b8e80941Smrg
49b8e80941Smrgstruct driwindows_screen
50b8e80941Smrg{
51b8e80941Smrg   struct glx_screen base;
52b8e80941Smrg   __DRIscreen *driScreen;
53b8e80941Smrg   __GLXDRIscreen vtable;
54b8e80941Smrg   Bool copySubBuffer;
55b8e80941Smrg};
56b8e80941Smrg
57b8e80941Smrgstruct driwindows_drawable
58b8e80941Smrg{
59b8e80941Smrg   __GLXDRIdrawable base;
60b8e80941Smrg   windowsDrawable *windowsDrawable;
61b8e80941Smrg};
62b8e80941Smrg
63b8e80941Smrg/**
64b8e80941Smrg * GLXDRI functions
65b8e80941Smrg */
66b8e80941Smrg
67b8e80941Smrgstatic void
68b8e80941Smrgdriwindows_destroy_context(struct glx_context *context)
69b8e80941Smrg{
70b8e80941Smrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
71b8e80941Smrg
72b8e80941Smrg   driReleaseDrawables(&pcp->base);
73b8e80941Smrg
74b8e80941Smrg   free((char *) context->extensions);
75b8e80941Smrg
76b8e80941Smrg   windows_destroy_context(pcp->windowsContext);
77b8e80941Smrg
78b8e80941Smrg   free(pcp);
79b8e80941Smrg}
80b8e80941Smrg
81b8e80941Smrgstatic int
82b8e80941Smrgdriwindows_bind_context(struct glx_context *context, struct glx_context *old,
83b8e80941Smrg                        GLXDrawable draw, GLXDrawable read)
84b8e80941Smrg{
85b8e80941Smrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
86b8e80941Smrg   struct driwindows_drawable *pdraw, *pread;
87b8e80941Smrg
88b8e80941Smrg   pdraw = (struct driwindows_drawable *) driFetchDrawable(context, draw);
89b8e80941Smrg   pread = (struct driwindows_drawable *) driFetchDrawable(context, read);
90b8e80941Smrg
91b8e80941Smrg   driReleaseDrawables(&pcp->base);
92b8e80941Smrg
93b8e80941Smrg   if (pdraw == NULL || pread == NULL)
94b8e80941Smrg      return GLXBadDrawable;
95b8e80941Smrg
96b8e80941Smrg   if (windows_bind_context(pcp->windowsContext,
97b8e80941Smrg                           pdraw->windowsDrawable, pread->windowsDrawable))
98b8e80941Smrg      return Success;
99b8e80941Smrg
100b8e80941Smrg   return GLXBadContext;
101b8e80941Smrg}
102b8e80941Smrg
103b8e80941Smrgstatic void
104b8e80941Smrgdriwindows_unbind_context(struct glx_context *context, struct glx_context *new)
105b8e80941Smrg{
106b8e80941Smrg   struct driwindows_context *pcp = (struct driwindows_context *) context;
107b8e80941Smrg
108b8e80941Smrg   windows_unbind_context(pcp->windowsContext);
109b8e80941Smrg}
110b8e80941Smrg
111b8e80941Smrgstatic void
112b8e80941Smrgdriwindows_bind_tex_image(Display * dpy,
113b8e80941Smrg                    GLXDrawable drawable,
114b8e80941Smrg                    int buffer, const int *attrib_list)
115b8e80941Smrg{
116b8e80941Smrg   struct glx_context *gc = __glXGetCurrentContext();
117b8e80941Smrg   struct driwindows_context *pcp = (struct driwindows_context *) gc;
118b8e80941Smrg   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
119b8e80941Smrg   struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base;
120b8e80941Smrg
121b8e80941Smrg   __glXInitialize(dpy);
122b8e80941Smrg
123b8e80941Smrg   if (pdraw != NULL) {
124b8e80941Smrg      windows_setTexBuffer(pcp->windowsContext,
125b8e80941Smrg                          pdraw->base.textureTarget,
126b8e80941Smrg                          pdraw->base.textureFormat,
127b8e80941Smrg                          pdraw->windowsDrawable);
128b8e80941Smrg   }
129b8e80941Smrg}
130b8e80941Smrg
131b8e80941Smrgstatic void
132b8e80941Smrgdriwindows_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
133b8e80941Smrg{
134b8e80941Smrg   struct glx_context *gc = __glXGetCurrentContext();
135b8e80941Smrg   struct driwindows_context *pcp = (struct driwindows_context *) gc;
136b8e80941Smrg   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
137b8e80941Smrg   struct glx_display *dpyPriv = __glXInitialize(dpy);
138b8e80941Smrg   struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base;
139b8e80941Smrg
140b8e80941Smrg   if (dpyPriv != NULL && pdraw != NULL) {
141b8e80941Smrg      windows_releaseTexBuffer(pcp->windowsContext,
142b8e80941Smrg                              pdraw->base.textureTarget,
143b8e80941Smrg                              pdraw->windowsDrawable);
144b8e80941Smrg      }
145b8e80941Smrg}
146b8e80941Smrg
147b8e80941Smrgstatic const struct glx_context_vtable driwindows_context_vtable = {
148b8e80941Smrg   .destroy             = driwindows_destroy_context,
149b8e80941Smrg   .bind                = driwindows_bind_context,
150b8e80941Smrg   .unbind              = driwindows_unbind_context,
151b8e80941Smrg   .wait_gl             = NULL,
152b8e80941Smrg   .wait_x              = NULL,
153b8e80941Smrg   .use_x_font          = DRI_glXUseXFont,
154b8e80941Smrg   .bind_tex_image      = driwindows_bind_tex_image,
155b8e80941Smrg   .release_tex_image   = driwindows_release_tex_image,
156b8e80941Smrg   .get_proc_address    = NULL,
157b8e80941Smrg};
158b8e80941Smrg
159b8e80941Smrgstatic struct glx_context *
160b8e80941Smrgdriwindows_create_context(struct glx_screen *base,
161b8e80941Smrg                          struct glx_config *config_base,
162b8e80941Smrg                          struct glx_context *shareList, int renderType)
163b8e80941Smrg{
164b8e80941Smrg   struct driwindows_context *pcp, *pcp_shared;
165b8e80941Smrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
166b8e80941Smrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
167b8e80941Smrg   windowsContext *shared = NULL;
168b8e80941Smrg
169b8e80941Smrg   if (!psc->base.driScreen)
170b8e80941Smrg      return NULL;
171b8e80941Smrg
172b8e80941Smrg   /* Check the renderType value */
173b8e80941Smrg   if (!validate_renderType_against_config(config_base, renderType))
174b8e80941Smrg       return NULL;
175b8e80941Smrg
176b8e80941Smrg   if (shareList) {
177b8e80941Smrg      /* If the shareList context is not on this renderer, we cannot possibly
178b8e80941Smrg       * create a context that shares with it.
179b8e80941Smrg       */
180b8e80941Smrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
181b8e80941Smrg         return NULL;
182b8e80941Smrg      }
183b8e80941Smrg
184b8e80941Smrg      pcp_shared = (struct driwindows_context *) shareList;
185b8e80941Smrg      shared = pcp_shared->windowsContext;
186b8e80941Smrg   }
187b8e80941Smrg
188b8e80941Smrg   pcp = calloc(1, sizeof *pcp);
189b8e80941Smrg   if (pcp == NULL)
190b8e80941Smrg      return NULL;
191b8e80941Smrg
192b8e80941Smrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
193b8e80941Smrg      free(pcp);
194b8e80941Smrg      return NULL;
195b8e80941Smrg   }
196b8e80941Smrg
197b8e80941Smrg   pcp->base.renderType = renderType;
198b8e80941Smrg
199b8e80941Smrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
200b8e80941Smrg
201b8e80941Smrg   pcp->windowsContext = windows_create_context(config->pxfi, shared);
202b8e80941Smrg
203b8e80941Smrg   if (!pcp->windowsContext) {
204b8e80941Smrg      free(pcp);
205b8e80941Smrg      return NULL;
206b8e80941Smrg   }
207b8e80941Smrg
208b8e80941Smrg   pcp->base.vtable = &driwindows_context_vtable;
209b8e80941Smrg
210b8e80941Smrg   return &pcp->base;
211b8e80941Smrg}
212b8e80941Smrg
213b8e80941Smrgstatic struct glx_context *
214b8e80941Smrgdriwindows_create_context_attribs(struct glx_screen *base,
215b8e80941Smrg                                  struct glx_config *config_base,
216b8e80941Smrg                                  struct glx_context *shareList,
217b8e80941Smrg                                  unsigned num_attribs,
218b8e80941Smrg                                  const uint32_t *attribs,
219b8e80941Smrg                                  unsigned *error)
220b8e80941Smrg{
221b8e80941Smrg   struct driwindows_context *pcp, *pcp_shared;
222b8e80941Smrg   struct driwindows_config *config = (struct driwindows_config *) config_base;
223b8e80941Smrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
224b8e80941Smrg   windowsContext *shared = NULL;
225b8e80941Smrg
226b8e80941Smrg   int i;
227b8e80941Smrg   uint32_t renderType = GLX_RGBA_TYPE;
228b8e80941Smrg
229b8e80941Smrg   /* Extract renderType from attribs */
230b8e80941Smrg   for (i = 0; i < num_attribs; i++) {
231b8e80941Smrg      switch (attribs[i * 2]) {
232b8e80941Smrg      case GLX_RENDER_TYPE:
233b8e80941Smrg         renderType = attribs[i * 2 + 1];
234b8e80941Smrg         break;
235b8e80941Smrg      }
236b8e80941Smrg   }
237b8e80941Smrg
238b8e80941Smrg   /*
239b8e80941Smrg     Perhaps we should map GLX tokens to WGL tokens, but they appear to have
240b8e80941Smrg     identical values, so far
241b8e80941Smrg   */
242b8e80941Smrg
243b8e80941Smrg   if (!psc->base.driScreen)
244b8e80941Smrg      return NULL;
245b8e80941Smrg
246b8e80941Smrg   /* Check the renderType value */
247b8e80941Smrg   if (!validate_renderType_against_config(config_base, renderType)) {
248b8e80941Smrg       return NULL;
249b8e80941Smrg   }
250b8e80941Smrg
251b8e80941Smrg   if (shareList) {
252b8e80941Smrg      /* If the shareList context is not on this renderer, we cannot possibly
253b8e80941Smrg       * create a context that shares with it.
254b8e80941Smrg       */
255b8e80941Smrg      if (shareList->vtable->destroy != driwindows_destroy_context) {
256b8e80941Smrg         return NULL;
257b8e80941Smrg      }
258b8e80941Smrg
259b8e80941Smrg      pcp_shared = (struct driwindows_context *) shareList;
260b8e80941Smrg      shared = pcp_shared->windowsContext;
261b8e80941Smrg   }
262b8e80941Smrg
263b8e80941Smrg   pcp = calloc(1, sizeof *pcp);
264b8e80941Smrg   if (pcp == NULL)
265b8e80941Smrg      return NULL;
266b8e80941Smrg
267b8e80941Smrg   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
268b8e80941Smrg      free(pcp);
269b8e80941Smrg      return NULL;
270b8e80941Smrg   }
271b8e80941Smrg
272b8e80941Smrg   pcp->base.renderType = renderType;
273b8e80941Smrg
274b8e80941Smrg   InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
275b8e80941Smrg
276b8e80941Smrg   pcp->windowsContext = windows_create_context_attribs(config->pxfi,
277b8e80941Smrg                                                      shared,
278b8e80941Smrg                                                      (const int *)attribs);
279b8e80941Smrg   if (pcp->windowsContext == NULL) {
280b8e80941Smrg      free(pcp);
281b8e80941Smrg      return NULL;
282b8e80941Smrg   }
283b8e80941Smrg
284b8e80941Smrg   pcp->base.vtable = &driwindows_context_vtable;
285b8e80941Smrg
286b8e80941Smrg   return &pcp->base;
287b8e80941Smrg}
288b8e80941Smrg
289b8e80941Smrgstatic void
290b8e80941SmrgdriwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)
291b8e80941Smrg{
292b8e80941Smrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
293b8e80941Smrg
294b8e80941Smrg   windows_destroy_drawable(pdp->windowsDrawable);
295b8e80941Smrg
296b8e80941Smrg   free(pdp);
297b8e80941Smrg}
298b8e80941Smrg
299b8e80941Smrgstatic __GLXDRIdrawable *
300b8e80941SmrgdriwindowsCreateDrawable(struct glx_screen *base, XID xDrawable,
301b8e80941Smrg                         GLXDrawable drawable, struct glx_config *modes)
302b8e80941Smrg{
303b8e80941Smrg   struct driwindows_drawable *pdp;
304b8e80941Smrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
305b8e80941Smrg
306b8e80941Smrg   pdp = calloc(1, sizeof(*pdp));
307b8e80941Smrg   if (!pdp)
308b8e80941Smrg      return NULL;
309b8e80941Smrg
310b8e80941Smrg   pdp->base.xDrawable = xDrawable;
311b8e80941Smrg   pdp->base.drawable = drawable;
312b8e80941Smrg   pdp->base.psc = &psc->base;
313b8e80941Smrg
314b8e80941Smrg   /*
315b8e80941Smrg      By this stage, the X drawable already exists, but the GLX drawable may
316b8e80941Smrg      not.
317b8e80941Smrg
318b8e80941Smrg      Query the server with the XID to find the correct HWND, HPBUFFERARB or
319b8e80941Smrg      HBITMAP
320b8e80941Smrg   */
321b8e80941Smrg
322b8e80941Smrg   unsigned int type;
323b8e80941Smrg   void *handle;
324b8e80941Smrg
325b8e80941Smrg   if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &type, &handle))
326b8e80941Smrg   {
327b8e80941Smrg      free(pdp);
328b8e80941Smrg      return NULL;
329b8e80941Smrg   }
330b8e80941Smrg
331b8e80941Smrg   /* No handle found is a failure */
332b8e80941Smrg   if (!handle) {
333b8e80941Smrg      free(pdp);
334b8e80941Smrg      return NULL;
335b8e80941Smrg   }
336b8e80941Smrg
337b8e80941Smrg   /* Create a new drawable */
338b8e80941Smrg   pdp->windowsDrawable = windows_create_drawable(type, handle);
339b8e80941Smrg
340b8e80941Smrg   if (!pdp->windowsDrawable) {
341b8e80941Smrg      free(pdp);
342b8e80941Smrg      return NULL;
343b8e80941Smrg   }
344b8e80941Smrg
345b8e80941Smrg   pdp->base.destroyDrawable = driwindowsDestroyDrawable;
346b8e80941Smrg
347b8e80941Smrg   return &pdp->base;
348b8e80941Smrg}
349b8e80941Smrg
350b8e80941Smrgstatic int64_t
351b8e80941SmrgdriwindowsSwapBuffers(__GLXDRIdrawable * pdraw,
352b8e80941Smrg                 int64_t target_msc, int64_t divisor, int64_t remainder,
353b8e80941Smrg                 Bool flush)
354b8e80941Smrg{
355b8e80941Smrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
356b8e80941Smrg
357b8e80941Smrg   (void) target_msc;
358b8e80941Smrg   (void) divisor;
359b8e80941Smrg   (void) remainder;
360b8e80941Smrg
361b8e80941Smrg   if (flush) {
362b8e80941Smrg      glFlush();
363b8e80941Smrg   }
364b8e80941Smrg
365b8e80941Smrg   windows_swap_buffers(pdp->windowsDrawable);
366b8e80941Smrg
367b8e80941Smrg   return 0;
368b8e80941Smrg}
369b8e80941Smrg
370b8e80941Smrgstatic void
371b8e80941SmrgdriwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,
372b8e80941Smrg                   int x, int y, int width, int height, Bool flush)
373b8e80941Smrg{
374b8e80941Smrg   struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
375b8e80941Smrg
376b8e80941Smrg   if (flush) {
377b8e80941Smrg      glFlush();
378b8e80941Smrg   }
379b8e80941Smrg
380b8e80941Smrg   windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height);
381b8e80941Smrg}
382b8e80941Smrg
383b8e80941Smrgstatic void
384b8e80941SmrgdriwindowsDestroyScreen(struct glx_screen *base)
385b8e80941Smrg{
386b8e80941Smrg   struct driwindows_screen *psc = (struct driwindows_screen *) base;
387b8e80941Smrg
388b8e80941Smrg   /* Free the direct rendering per screen data */
389b8e80941Smrg   psc->driScreen = NULL;
390b8e80941Smrg   free(psc);
391b8e80941Smrg}
392b8e80941Smrg
393b8e80941Smrgstatic const struct glx_screen_vtable driwindows_screen_vtable = {
394b8e80941Smrg   .create_context         = driwindows_create_context,
395b8e80941Smrg   .create_context_attribs = driwindows_create_context_attribs,
396b8e80941Smrg   .query_renderer_integer = NULL,
397b8e80941Smrg   .query_renderer_string  = NULL,
398b8e80941Smrg};
399b8e80941Smrg
400b8e80941Smrgstatic Bool
401b8e80941SmrgdriwindowsBindExtensions(struct driwindows_screen *psc)
402b8e80941Smrg{
403b8e80941Smrg   Bool result = 1;
404b8e80941Smrg
405b8e80941Smrg   const struct
406b8e80941Smrg   {
407b8e80941Smrg      char *wglext;
408b8e80941Smrg      char *glxext;
409b8e80941Smrg      Bool mandatory;
410b8e80941Smrg   } extensionMap[] = {
411b8e80941Smrg      { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 },
412b8e80941Smrg      { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
413b8e80941Smrg      { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
414b8e80941Smrg//      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
415b8e80941Smrg// Not exactly equivalent, needs some more glue to be written
416b8e80941Smrg      { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
417b8e80941Smrg      { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
418b8e80941Smrg      { "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 },
419b8e80941Smrg      { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
420b8e80941Smrg      { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
421b8e80941Smrg      { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
422b8e80941Smrg      { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
423b8e80941Smrg   };
424b8e80941Smrg
425b8e80941Smrg   char *wgl_extensions;
426b8e80941Smrg   char *gl_extensions;
427b8e80941Smrg   int i;
428b8e80941Smrg
429b8e80941Smrg   windows_extensions(&gl_extensions, &wgl_extensions);
430b8e80941Smrg
431b8e80941Smrg   for (i = 0; i < ARRAY_SIZE(extensionMap); i++) {
432b8e80941Smrg      if (strstr(wgl_extensions, extensionMap[i].wglext)) {
433b8e80941Smrg          __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext);
434b8e80941Smrg          InfoMessageF("enabled %s\n", extensionMap[i].glxext);
435b8e80941Smrg      }
436b8e80941Smrg      else if (extensionMap[i].mandatory) {
437b8e80941Smrg         ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext);
438b8e80941Smrg         result = 0;
439b8e80941Smrg      }
440b8e80941Smrg   }
441b8e80941Smrg
442b8e80941Smrg   /*
443b8e80941Smrg       Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
444b8e80941Smrg       only be in GL_EXTENSIONS
445b8e80941Smrg   */
446b8e80941Smrg   if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
447b8e80941Smrg      psc->copySubBuffer = 1;
448b8e80941Smrg      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
449b8e80941Smrg      InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n");
450b8e80941Smrg   }
451b8e80941Smrg
452b8e80941Smrg   free(gl_extensions);
453b8e80941Smrg   free(wgl_extensions);
454b8e80941Smrg
455b8e80941Smrg   return result;
456b8e80941Smrg}
457b8e80941Smrg
458b8e80941Smrgstatic struct glx_config *
459b8e80941SmrgdriwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs)
460b8e80941Smrg{
461b8e80941Smrg   struct glx_config head, *tail, *m;
462b8e80941Smrg
463b8e80941Smrg   tail = &head;
464b8e80941Smrg   head.next = NULL;
465b8e80941Smrg
466b8e80941Smrg   for (m = configs; m; m = m->next) {
467b8e80941Smrg      int fbconfigID = GLX_DONT_CARE;
468b8e80941Smrg      if (fbconfigs) {
469b8e80941Smrg         /*
470b8e80941Smrg           visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig
471b8e80941Smrg           with matching visualID and get the fbconfigID from there
472b8e80941Smrg         */
473b8e80941Smrg         struct glx_config *f;
474b8e80941Smrg         for (f = fbconfigs; f; f = f->next) {
475b8e80941Smrg            if (f->visualID == m->visualID)
476b8e80941Smrg               fbconfigID = f->fbconfigID;
477b8e80941Smrg         }
478b8e80941Smrg      }
479b8e80941Smrg      else {
480b8e80941Smrg         fbconfigID = m->fbconfigID;
481b8e80941Smrg      }
482b8e80941Smrg
483b8e80941Smrg      int pxfi;
484b8e80941Smrg      XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi);
485b8e80941Smrg      if (pxfi == 0)
486b8e80941Smrg         continue;
487b8e80941Smrg
488b8e80941Smrg      struct driwindows_config *config = malloc(sizeof(*config));
489b8e80941Smrg
490b8e80941Smrg      tail->next = &config->base;
491b8e80941Smrg      if (tail->next == NULL)
492b8e80941Smrg         continue;
493b8e80941Smrg
494b8e80941Smrg      config->base = *m;
495b8e80941Smrg      config->pxfi = pxfi;
496b8e80941Smrg
497b8e80941Smrg      tail = tail->next;
498b8e80941Smrg   }
499b8e80941Smrg
500b8e80941Smrg   return head.next;
501b8e80941Smrg}
502b8e80941Smrg
503b8e80941Smrgstatic struct glx_screen *
504b8e80941SmrgdriwindowsCreateScreen(int screen, struct glx_display *priv)
505b8e80941Smrg{
506b8e80941Smrg   __GLXDRIscreen *psp;
507b8e80941Smrg   struct driwindows_screen *psc;
508b8e80941Smrg   struct glx_config *configs = NULL, *visuals = NULL;
509b8e80941Smrg   int directCapable;
510b8e80941Smrg
511b8e80941Smrg   psc = calloc(1, sizeof *psc);
512b8e80941Smrg   if (psc == NULL)
513b8e80941Smrg      return NULL;
514b8e80941Smrg
515b8e80941Smrg   if (!glx_screen_init(&psc->base, screen, priv)) {
516b8e80941Smrg      free(psc);
517b8e80941Smrg      return NULL;
518b8e80941Smrg   }
519b8e80941Smrg
520b8e80941Smrg   if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) ||
521b8e80941Smrg       !directCapable) {
522b8e80941Smrg      ErrorMessageF("Screen is not Windows-DRI capable\n");
523b8e80941Smrg      goto handle_error;
524b8e80941Smrg   }
525b8e80941Smrg
526b8e80941Smrg   /* discover native supported extensions */
527b8e80941Smrg   if (!driwindowsBindExtensions(psc)) {
528b8e80941Smrg      goto handle_error;
529b8e80941Smrg   }
530b8e80941Smrg
531b8e80941Smrg   /* Augment configs with pxfi information */
532b8e80941Smrg   configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL);
533b8e80941Smrg   visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs);
534b8e80941Smrg
535b8e80941Smrg   if (!configs || !visuals) {
536b8e80941Smrg       ErrorMessageF("No fbConfigs or visuals found\n");
537b8e80941Smrg       goto handle_error;
538b8e80941Smrg   }
539b8e80941Smrg
540b8e80941Smrg   glx_config_destroy_list(psc->base.configs);
541b8e80941Smrg   psc->base.configs = configs;
542b8e80941Smrg   glx_config_destroy_list(psc->base.visuals);
543b8e80941Smrg   psc->base.visuals = visuals;
544b8e80941Smrg
545b8e80941Smrg   psc->base.vtable = &driwindows_screen_vtable;
546b8e80941Smrg   psp = &psc->vtable;
547b8e80941Smrg   psc->base.driScreen = psp;
548b8e80941Smrg   psp->destroyScreen = driwindowsDestroyScreen;
549b8e80941Smrg   psp->createDrawable = driwindowsCreateDrawable;
550b8e80941Smrg   psp->swapBuffers = driwindowsSwapBuffers;
551b8e80941Smrg
552b8e80941Smrg   if (psc->copySubBuffer)
553b8e80941Smrg      psp->copySubBuffer = driwindowsCopySubBuffer;
554b8e80941Smrg
555b8e80941Smrg   return &psc->base;
556b8e80941Smrg
557b8e80941Smrghandle_error:
558b8e80941Smrg   glx_screen_cleanup(&psc->base);
559b8e80941Smrg
560b8e80941Smrg   return NULL;
561b8e80941Smrg}
562b8e80941Smrg
563b8e80941Smrg/* Called from __glXFreeDisplayPrivate.
564b8e80941Smrg */
565b8e80941Smrgstatic void
566b8e80941SmrgdriwindowsDestroyDisplay(__GLXDRIdisplay * dpy)
567b8e80941Smrg{
568b8e80941Smrg   free(dpy);
569b8e80941Smrg}
570b8e80941Smrg
571b8e80941Smrg/*
572b8e80941Smrg * Allocate, initialize and return a  __GLXDRIdisplay object.
573b8e80941Smrg * This is called from __glXInitialize() when we are given a new
574b8e80941Smrg * display pointer.
575b8e80941Smrg */
576b8e80941Smrg_X_HIDDEN __GLXDRIdisplay *
577b8e80941SmrgdriwindowsCreateDisplay(Display * dpy)
578b8e80941Smrg{
579b8e80941Smrg   struct driwindows_display *pdpyp;
580b8e80941Smrg
581b8e80941Smrg   int eventBase, errorBase;
582b8e80941Smrg   int major, minor, patch;
583b8e80941Smrg
584b8e80941Smrg   /* Verify server has Windows-DRI extension */
585b8e80941Smrg   if (!XWindowsDRIQueryExtension(dpy, &eventBase, &errorBase)) {
586b8e80941Smrg      ErrorMessageF("Windows-DRI extension not available\n");
587b8e80941Smrg      return NULL;
588b8e80941Smrg   }
589b8e80941Smrg
590b8e80941Smrg   if (!XWindowsDRIQueryVersion(dpy, &major, &minor, &patch)) {
591b8e80941Smrg      ErrorMessageF("Fetching Windows-DRI extension version failed\n");
592b8e80941Smrg      return NULL;
593b8e80941Smrg   }
594b8e80941Smrg
595b8e80941Smrg   if (!windows_check_renderer()) {
596b8e80941Smrg      ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n");
597b8e80941Smrg      return NULL;
598b8e80941Smrg   }
599b8e80941Smrg
600b8e80941Smrg   pdpyp = malloc(sizeof *pdpyp);
601b8e80941Smrg   if (pdpyp == NULL)
602b8e80941Smrg      return NULL;
603b8e80941Smrg
604b8e80941Smrg   pdpyp->base.destroyDisplay = driwindowsDestroyDisplay;
605b8e80941Smrg   pdpyp->base.createScreen = driwindowsCreateScreen;
606b8e80941Smrg
607b8e80941Smrg   pdpyp->event_base = eventBase;
608b8e80941Smrg
609b8e80941Smrg   return &pdpyp->base;
610b8e80941Smrg}
611