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