1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // main.cpp: DLL entry point and management of thread-local data.
16
17 #include "main.h"
18
19 #include "resource.h"
20 #include "Framebuffer.h"
21 #include "Surface.h"
22 #include "Common/Thread.hpp"
23 #include "common/debug.h"
24
25 static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
26
27 #if !defined(_MSC_VER)
28 #define CONSTRUCTOR __attribute__((constructor))
29 #define DESTRUCTOR __attribute__((destructor))
30 #else
31 #define CONSTRUCTOR
32 #define DESTRUCTOR
33 #endif
34
glAttachThread()35 static void glAttachThread()
36 {
37 TRACE("()");
38
39 gl::Current *current = new gl::Current;
40
41 if(current)
42 {
43 sw::Thread::setLocalStorage(currentTLS, current);
44
45 current->context = 0;
46 current->display = 0;
47 current->drawSurface = 0;
48 current->readSurface = 0;
49 }
50 }
51
glDetachThread()52 static void glDetachThread()
53 {
54 TRACE("()");
55
56 gl::Current *current = (gl::Current*)sw::Thread::getLocalStorage(currentTLS);
57
58 if(current)
59 {
60 delete current;
61 }
62 }
63
glAttachProcess()64 CONSTRUCTOR static bool glAttachProcess()
65 {
66 TRACE("()");
67
68 #if !(ANGLE_DISABLE_TRACE)
69 FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
70
71 if(debug)
72 {
73 fclose(debug);
74 debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase
75 fclose(debug);
76 }
77 #endif
78
79 currentTLS = sw::Thread::allocateLocalStorageKey();
80
81 if(currentTLS == TLS_OUT_OF_INDEXES)
82 {
83 return false;
84 }
85
86 glAttachThread();
87
88 return true;
89 }
90
glDetachProcess()91 DESTRUCTOR static void glDetachProcess()
92 {
93 TRACE("()");
94
95 glDetachThread();
96
97 sw::Thread::freeLocalStorageKey(currentTLS);
98 }
99
100 #if defined(_WIN32)
DebuggerWaitDialogProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)101 static INT_PTR CALLBACK DebuggerWaitDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
102 {
103 RECT rect;
104
105 switch(uMsg)
106 {
107 case WM_INITDIALOG:
108 GetWindowRect(GetDesktopWindow(), &rect);
109 SetWindowPos(hwnd, HWND_TOP, rect.right / 2, rect.bottom / 2, 0, 0, SWP_NOSIZE);
110 SetTimer(hwnd, 1, 100, NULL);
111 return TRUE;
112 case WM_COMMAND:
113 if(LOWORD(wParam) == IDCANCEL)
114 {
115 EndDialog(hwnd, 0);
116 }
117 break;
118 case WM_TIMER:
119 if(IsDebuggerPresent())
120 {
121 EndDialog(hwnd, 0);
122 }
123 }
124
125 return FALSE;
126 }
127
WaitForDebugger(HINSTANCE instance)128 static void WaitForDebugger(HINSTANCE instance)
129 {
130 if(!IsDebuggerPresent())
131 {
132 HRSRC dialog = FindResource(instance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG);
133 DLGTEMPLATE *dialogTemplate = (DLGTEMPLATE*)LoadResource(instance, dialog);
134 DialogBoxIndirect(instance, dialogTemplate, NULL, DebuggerWaitDialogProc);
135 }
136 }
137
DllMain(HINSTANCE instance,DWORD reason,LPVOID reserved)138 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
139 {
140 switch(reason)
141 {
142 case DLL_PROCESS_ATTACH:
143 #ifndef NDEBUG
144 WaitForDebugger(instance);
145 #endif
146 return glAttachProcess();
147 break;
148 case DLL_THREAD_ATTACH:
149 glAttachThread();
150 break;
151 case DLL_THREAD_DETACH:
152 glDetachThread();
153 break;
154 case DLL_PROCESS_DETACH:
155 glDetachProcess();
156 break;
157 default:
158 break;
159 }
160
161 return TRUE;
162 }
163 #endif
164
165 namespace gl
166 {
getCurrent(void)167 static gl::Current *getCurrent(void)
168 {
169 Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
170
171 if(!current)
172 {
173 glAttachThread();
174 }
175
176 return (Current*)sw::Thread::getLocalStorage(currentTLS);
177 }
178
makeCurrent(Context * context,Display * display,Surface * surface)179 void makeCurrent(Context *context, Display *display, Surface *surface)
180 {
181 Current *current = getCurrent();
182
183 current->context = context;
184 current->display = display;
185
186 if(context && display && surface)
187 {
188 context->makeCurrent(surface);
189 }
190 }
191
getContext()192 Context *getContext()
193 {
194 Current *current = getCurrent();
195
196 return current->context;
197 }
198
getDisplay()199 Display *getDisplay()
200 {
201 Current *current = getCurrent();
202
203 return current->display;
204 }
205
getDevice()206 Device *getDevice()
207 {
208 Context *context = getContext();
209
210 return context ? context->getDevice() : 0;
211 }
212
setCurrentDisplay(Display * dpy)213 void setCurrentDisplay(Display *dpy)
214 {
215 Current *current = getCurrent();
216
217 current->display = dpy;
218 }
219
setCurrentContext(gl::Context * ctx)220 void setCurrentContext(gl::Context *ctx)
221 {
222 Current *current = getCurrent();
223
224 current->context = ctx;
225 }
226
setCurrentDrawSurface(Surface * surface)227 void setCurrentDrawSurface(Surface *surface)
228 {
229 Current *current = getCurrent();
230
231 current->drawSurface = surface;
232 }
233
getCurrentDrawSurface()234 Surface *getCurrentDrawSurface()
235 {
236 Current *current = getCurrent();
237
238 return current->drawSurface;
239 }
240
setCurrentReadSurface(Surface * surface)241 void setCurrentReadSurface(Surface *surface)
242 {
243 Current *current = getCurrent();
244
245 current->readSurface = surface;
246 }
247
getCurrentReadSurface()248 Surface *getCurrentReadSurface()
249 {
250 Current *current = getCurrent();
251
252 return current->readSurface;
253 }
254 }
255
256 // Records an error code
error(GLenum errorCode)257 void error(GLenum errorCode)
258 {
259 gl::Context *context = gl::getContext();
260
261 if(context)
262 {
263 switch(errorCode)
264 {
265 case GL_INVALID_ENUM:
266 context->recordInvalidEnum();
267 TRACE("\t! Error generated: invalid enum\n");
268 break;
269 case GL_INVALID_VALUE:
270 context->recordInvalidValue();
271 TRACE("\t! Error generated: invalid value\n");
272 break;
273 case GL_INVALID_OPERATION:
274 context->recordInvalidOperation();
275 TRACE("\t! Error generated: invalid operation\n");
276 break;
277 case GL_OUT_OF_MEMORY:
278 context->recordOutOfMemory();
279 TRACE("\t! Error generated: out of memory\n");
280 break;
281 case GL_INVALID_FRAMEBUFFER_OPERATION:
282 context->recordInvalidFramebufferOperation();
283 TRACE("\t! Error generated: invalid framebuffer operation\n");
284 break;
285 default: UNREACHABLE(errorCode);
286 }
287 }
288 }
289