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