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
30 static bool first_context_current = false;
31 static 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 */
38 bool
epoxy_conservative_has_wgl_extension(const char * ext)39 epoxy_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
49 bool
epoxy_has_wgl_extension(HDC hdc,const char * ext)50 epoxy_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 */
75 void
epoxy_handle_external_wglMakeCurrent(void)76 epoxy_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 */
96 BOOL WINAPI
97 DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved);
98
99 BOOL WINAPI
DllMain(HINSTANCE dll,DWORD reason,LPVOID reserved)100 DllMain(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
144 WRAPPER_VISIBILITY (BOOL)
WRAPPER(epoxy_wglMakeCurrent)145 WRAPPER(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
155 WRAPPER_VISIBILITY (BOOL)
WRAPPER(epoxy_wglMakeContextCurrentARB)156 WRAPPER(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
169 WRAPPER_VISIBILITY (BOOL)
WRAPPER(epoxy_wglMakeContextCurrentEXT)170 WRAPPER(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
183 WRAPPER_VISIBILITY (BOOL)
WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)184 WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc)
185 {
186 BOOL ret = epoxy_wglMakeAssociatedContextCurrentAMD_unwrapped(hglrc);
187
188 epoxy_handle_external_wglMakeCurrent();
189
190 return ret;
191 }
192
193 PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped;
194 PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped;
195 PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped;
196 PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped;
197