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