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