1/* 2 * Copyright © 2013 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <assert.h> 25#include <string.h> 26#include <stdio.h> 27 28#include "dispatch_common.h" 29 30static bool first_context_current = false; 31static bool already_switched_to_dispatch_table = false; 32 33/** 34 * If we can determine the WGL extension support from the current 35 * context, then return that, otherwise give the answer that will just 36 * send us on to get_proc_address(). 37 */ 38bool 39epoxy_conservative_has_wgl_extension(const char *ext) 40{ 41 HDC hdc = wglGetCurrentDC(); 42 43 if (!hdc) 44 return true; 45 46 return epoxy_has_wgl_extension(hdc, ext); 47} 48 49bool 50epoxy_has_wgl_extension(HDC hdc, const char *ext) 51 { 52 PFNWGLGETEXTENSIONSSTRINGARBPROC getext; 53 54 getext = (void *)wglGetProcAddress("wglGetExtensionsStringARB"); 55 if (!getext) { 56 fputs("Implementation unexpectedly missing " 57 "WGL_ARB_extensions_string. Probably a libepoxy bug.\n", 58 stderr); 59 return false; 60 } 61 62 return epoxy_extension_in_string(getext(hdc), ext); 63} 64 65/** 66 * Does the work necessary to update the win32 per-thread dispatch 67 * tables when wglMakeCurrent() is called. 68 * 69 * Right now, we use global function pointers until the second 70 * MakeCurrent occurs, at which point we switch to dispatch tables. 71 * This could be improved in the future to track a resolved dispatch 72 * table per context and reuse it when the context is made current 73 * again. 74 */ 75void 76epoxy_handle_external_wglMakeCurrent(void) 77{ 78 if (!first_context_current) { 79 first_context_current = true; 80 } else { 81 if (!already_switched_to_dispatch_table) { 82 already_switched_to_dispatch_table = true; 83 gl_switch_to_dispatch_table(); 84 wgl_switch_to_dispatch_table(); 85 } 86 87 gl_init_dispatch_table(); 88 wgl_init_dispatch_table(); 89 } 90} 91 92/** 93 * This global symbol is apparently looked up by Windows when loading 94 * a DLL, but it doesn't declare the prototype. 95 */ 96BOOL WINAPI 97DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved); 98 99BOOL WINAPI 100DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) 101{ 102 void *data; 103 104 switch (reason) { 105 case DLL_PROCESS_ATTACH: 106 gl_tls_index = TlsAlloc(); 107 if (gl_tls_index == TLS_OUT_OF_INDEXES) 108 return FALSE; 109 wgl_tls_index = TlsAlloc(); 110 if (wgl_tls_index == TLS_OUT_OF_INDEXES) 111 return FALSE; 112 113 first_context_current = false; 114 115 /* FALLTHROUGH */ 116 117 case DLL_THREAD_ATTACH: 118 data = LocalAlloc(LPTR, gl_tls_size); 119 TlsSetValue(gl_tls_index, data); 120 121 data = LocalAlloc(LPTR, wgl_tls_size); 122 TlsSetValue(wgl_tls_index, data); 123 124 break; 125 126 case DLL_THREAD_DETACH: 127 case DLL_PROCESS_DETACH: 128 data = TlsGetValue(gl_tls_index); 129 LocalFree(data); 130 131 data = TlsGetValue(wgl_tls_index); 132 LocalFree(data); 133 134 if (reason == DLL_PROCESS_DETACH) { 135 TlsFree(gl_tls_index); 136 TlsFree(wgl_tls_index); 137 } 138 break; 139 } 140 141 return TRUE; 142} 143 144WRAPPER_VISIBILITY (BOOL) 145WRAPPER(epoxy_wglMakeCurrent)(HDC hdc, HGLRC hglrc) 146{ 147 BOOL ret = epoxy_wglMakeCurrent_unwrapped(hdc, hglrc); 148 149 epoxy_handle_external_wglMakeCurrent(); 150 151 return ret; 152} 153 154 155WRAPPER_VISIBILITY (BOOL) 156WRAPPER(epoxy_wglMakeContextCurrentARB)(HDC hDrawDC, 157 HDC hReadDC, 158 HGLRC hglrc) 159{ 160 BOOL ret = epoxy_wglMakeContextCurrentARB_unwrapped(hDrawDC, hReadDC, 161 hglrc); 162 163 epoxy_handle_external_wglMakeCurrent(); 164 165 return ret; 166} 167 168 169WRAPPER_VISIBILITY (BOOL) 170WRAPPER(epoxy_wglMakeContextCurrentEXT)(HDC hDrawDC, 171 HDC hReadDC, 172 HGLRC hglrc) 173{ 174 BOOL ret = epoxy_wglMakeContextCurrentEXT_unwrapped(hDrawDC, hReadDC, 175 hglrc); 176 177 epoxy_handle_external_wglMakeCurrent(); 178 179 return ret; 180} 181 182 183WRAPPER_VISIBILITY (BOOL) 184WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc) 185{ 186 BOOL ret = epoxy_wglMakeAssociatedContextCurrentAMD_unwrapped(hglrc); 187 188 epoxy_handle_external_wglMakeCurrent(); 189 190 return ret; 191} 192 193PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped; 194PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped; 195PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped; 196PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped; 197