1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2011 Morgan Armand <morgan.devel (at) gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <windows.h> 27 28 #define WGL_WGLEXT_PROTOTYPES 29 30 #include <GL/gl.h> 31 #include <GL/wglext.h> 32 33 #include "stw_icd.h" 34 #include "stw_context.h" 35 #include "stw_device.h" 36 #include "stw_ext_context.h" 37 38 #include "util/u_debug.h" 39 40 41 wglCreateContext_t wglCreateContext_func = 0; 42 wglDeleteContext_t wglDeleteContext_func = 0; 43 44 45 /** 46 * The implementation of this function is tricky. The OPENGL32.DLL library 47 * remaps the context IDs returned by our stw_create_context_attribs() 48 * function to different values returned to the caller of wglCreateContext(). 49 * That is, DHGLRC (driver) handles are not equivalent to HGLRC (public) 50 * handles. 51 * 52 * So we need to generate a new HGLRC ID here. We do that by calling 53 * the regular wglCreateContext() function. Then, we replace the newly- 54 * created stw_context with a new stw_context that reflects the arguments 55 * to this function. 56 */ 57 HGLRC WINAPI 58 wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) 59 { 60 HGLRC context; 61 62 int majorVersion = 1, minorVersion = 0, layerPlane = 0; 63 int contextFlags = 0x0; 64 int profileMask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; 65 int i; 66 BOOL done = FALSE; 67 const int contextFlagsAll = (WGL_CONTEXT_DEBUG_BIT_ARB | 68 WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); 69 70 /* parse attrib_list */ 71 if (attribList) { 72 for (i = 0; !done && attribList[i]; i++) { 73 switch (attribList[i]) { 74 case WGL_CONTEXT_MAJOR_VERSION_ARB: 75 majorVersion = attribList[++i]; 76 break; 77 case WGL_CONTEXT_MINOR_VERSION_ARB: 78 minorVersion = attribList[++i]; 79 break; 80 case WGL_CONTEXT_LAYER_PLANE_ARB: 81 layerPlane = attribList[++i]; 82 break; 83 case WGL_CONTEXT_FLAGS_ARB: 84 contextFlags = attribList[++i]; 85 break; 86 case WGL_CONTEXT_PROFILE_MASK_ARB: 87 profileMask = attribList[++i]; 88 break; 89 case 0: 90 /* end of list */ 91 done = TRUE; 92 break; 93 default: 94 /* bad attribute */ 95 SetLastError(ERROR_INVALID_PARAMETER); 96 return 0; 97 } 98 } 99 } 100 101 /* check contextFlags */ 102 if (contextFlags & ~contextFlagsAll) { 103 SetLastError(ERROR_INVALID_PARAMETER); 104 return NULL; 105 } 106 107 /* check profileMask */ 108 if (profileMask != WGL_CONTEXT_CORE_PROFILE_BIT_ARB && 109 profileMask != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB && 110 profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT) { 111 SetLastError(ERROR_INVALID_PROFILE_ARB); 112 return NULL; 113 } 114 115 /* check version (generate ERROR_INVALID_VERSION_ARB if bad) */ 116 if (majorVersion <= 0 || 117 minorVersion < 0 || 118 (profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT && 119 ((majorVersion == 1 && minorVersion > 5) || 120 (majorVersion == 2 && minorVersion > 1) || 121 (majorVersion == 3 && minorVersion > 3) || 122 (majorVersion == 4 && minorVersion > 5) || 123 majorVersion > 4)) || 124 (profileMask == WGL_CONTEXT_ES_PROFILE_BIT_EXT && 125 ((majorVersion == 1 && minorVersion > 1) || 126 (majorVersion == 2 && minorVersion > 0) || 127 (majorVersion == 3 && minorVersion > 1) || 128 majorVersion > 3))) { 129 SetLastError(ERROR_INVALID_VERSION_ARB); 130 return NULL; 131 } 132 133 if ((contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && 134 majorVersion < 3) { 135 SetLastError(ERROR_INVALID_VERSION_ARB); 136 return 0; 137 } 138 139 /* Get pointer to OPENGL32.DLL's wglCreate/DeleteContext() functions */ 140 if (!wglCreateContext_func || !wglDeleteContext_func) { 141 /* Get the OPENGL32.DLL library */ 142 HMODULE opengl_lib = GetModuleHandleA("opengl32.dll"); 143 if (!opengl_lib) { 144 _debug_printf("wgl: GetModuleHandleA(\"opengl32.dll\") failed\n"); 145 return 0; 146 } 147 148 /* Get pointer to wglCreateContext() function */ 149 wglCreateContext_func = (wglCreateContext_t) 150 GetProcAddress(opengl_lib, "wglCreateContext"); 151 if (!wglCreateContext_func) { 152 _debug_printf("wgl: failed to get wglCreateContext()\n"); 153 return 0; 154 } 155 156 /* Get pointer to wglDeleteContext() function */ 157 wglDeleteContext_func = (wglDeleteContext_t) 158 GetProcAddress(opengl_lib, "wglDeleteContext"); 159 if (!wglDeleteContext_func) { 160 _debug_printf("wgl: failed to get wglDeleteContext()\n"); 161 return 0; 162 } 163 } 164 165 /* Call wglCreateContext to get a valid context ID */ 166 context = wglCreateContext_func(hDC); 167 168 if (context) { 169 /* Now replace the context we just created with a new one that reflects 170 * the attributes passed to this function. 171 */ 172 DHGLRC dhglrc, c, share_dhglrc = 0; 173 174 /* Convert public HGLRC to driver DHGLRC */ 175 if (stw_dev && stw_dev->callbacks.wglCbGetDhglrc) { 176 dhglrc = stw_dev->callbacks.wglCbGetDhglrc(context); 177 if (hShareContext) 178 share_dhglrc = stw_dev->callbacks.wglCbGetDhglrc(hShareContext); 179 } 180 else { 181 /* not using ICD */ 182 dhglrc = (DHGLRC) context; 183 share_dhglrc = (DHGLRC) hShareContext; 184 } 185 186 c = stw_create_context_attribs(hDC, layerPlane, share_dhglrc, 187 majorVersion, minorVersion, 188 contextFlags, profileMask, 189 dhglrc); 190 if (!c) { 191 wglDeleteContext_func(context); 192 context = 0; 193 } 194 } 195 196 return context; 197 } 198