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 35 static void glAttachThread() 36 { 37 TRACE("()"); 38 39 gl::Current *current = (gl::Current*)sw::Thread::allocateLocalStorage(currentTLS, sizeof(gl::Current)); 40 41 if(current) 42 { 43 current->context = nullptr; 44 current->display = nullptr; 45 current->drawSurface = nullptr; 46 current->readSurface = nullptr; 47 } 48 } 49 50 static void glDetachThread() 51 { 52 TRACE("()"); 53 54 wglMakeCurrent(NULL, NULL); 55 56 sw::Thread::freeLocalStorage(currentTLS); 57 } 58 59 CONSTRUCTOR static bool glAttachProcess() 60 { 61 TRACE("()"); 62 63 #if !(ANGLE_DISABLE_TRACE) 64 FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); 65 66 if(debug) 67 { 68 fclose(debug); 69 debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase 70 fclose(debug); 71 } 72 #endif 73 74 currentTLS = sw::Thread::allocateLocalStorageKey(); 75 76 if(currentTLS == TLS_OUT_OF_INDEXES) 77 { 78 return false; 79 } 80 81 glAttachThread(); 82 83 return true; 84 } 85 86 DESTRUCTOR static void glDetachProcess() 87 { 88 TRACE("()"); 89 90 glDetachThread(); 91 92 sw::Thread::freeLocalStorageKey(currentTLS); 93 } 94 95 #if defined(_WIN32) 96 static INT_PTR CALLBACK DebuggerWaitDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 97 { 98 RECT rect; 99 100 switch(uMsg) 101 { 102 case WM_INITDIALOG: 103 GetWindowRect(GetDesktopWindow(), &rect); 104 SetWindowPos(hwnd, HWND_TOP, rect.right / 2, rect.bottom / 2, 0, 0, SWP_NOSIZE); 105 SetTimer(hwnd, 1, 100, NULL); 106 return TRUE; 107 case WM_COMMAND: 108 if(LOWORD(wParam) == IDCANCEL) 109 { 110 EndDialog(hwnd, 0); 111 } 112 break; 113 case WM_TIMER: 114 if(IsDebuggerPresent()) 115 { 116 EndDialog(hwnd, 0); 117 } 118 } 119 120 return FALSE; 121 } 122 123 static void WaitForDebugger(HINSTANCE instance) 124 { 125 if(!IsDebuggerPresent()) 126 { 127 HRSRC dialog = FindResource(instance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG); 128 DLGTEMPLATE *dialogTemplate = (DLGTEMPLATE*)LoadResource(instance, dialog); 129 DialogBoxIndirect(instance, dialogTemplate, NULL, DebuggerWaitDialogProc); 130 } 131 } 132 133 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) 134 { 135 switch(reason) 136 { 137 case DLL_PROCESS_ATTACH: 138 #ifndef NDEBUG 139 WaitForDebugger(instance); 140 #endif 141 return glAttachProcess(); 142 break; 143 case DLL_THREAD_ATTACH: 144 glAttachThread(); 145 break; 146 case DLL_THREAD_DETACH: 147 glDetachThread(); 148 break; 149 case DLL_PROCESS_DETACH: 150 glDetachProcess(); 151 break; 152 default: 153 break; 154 } 155 156 return TRUE; 157 } 158 #endif 159 160 namespace gl 161 { 162 static gl::Current *getCurrent(void) 163 { 164 Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS); 165 166 if(!current) 167 { 168 glAttachThread(); 169 } 170 171 return (Current*)sw::Thread::getLocalStorage(currentTLS); 172 } 173 174 void makeCurrent(Context *context, Display *display, Surface *surface) 175 { 176 Current *current = getCurrent(); 177 178 current->context = context; 179 current->display = display; 180 181 if(context && display && surface) 182 { 183 context->makeCurrent(surface); 184 } 185 } 186 187 Context *getContext() 188 { 189 Current *current = getCurrent(); 190 191 return current->context; 192 } 193 194 Display *getDisplay() 195 { 196 Current *current = getCurrent(); 197 198 return current->display; 199 } 200 201 Device *getDevice() 202 { 203 Context *context = getContext(); 204 205 return context ? context->getDevice() : nullptr; 206 } 207 208 void setCurrentDisplay(Display *dpy) 209 { 210 Current *current = getCurrent(); 211 212 current->display = dpy; 213 } 214 215 void setCurrentContext(gl::Context *ctx) 216 { 217 Current *current = getCurrent(); 218 219 current->context = ctx; 220 } 221 222 void setCurrentDrawSurface(Surface *surface) 223 { 224 Current *current = getCurrent(); 225 226 current->drawSurface = surface; 227 } 228 229 Surface *getCurrentDrawSurface() 230 { 231 Current *current = getCurrent(); 232 233 return current->drawSurface; 234 } 235 236 void setCurrentReadSurface(Surface *surface) 237 { 238 Current *current = getCurrent(); 239 240 current->readSurface = surface; 241 } 242 243 Surface *getCurrentReadSurface() 244 { 245 Current *current = getCurrent(); 246 247 return current->readSurface; 248 } 249 } 250 251 // Records an error code 252 void error(GLenum errorCode) 253 { 254 gl::Context *context = gl::getContext(); 255 256 if(context) 257 { 258 switch(errorCode) 259 { 260 case GL_INVALID_ENUM: 261 context->recordInvalidEnum(); 262 TRACE("\t! Error generated: invalid enum\n"); 263 break; 264 case GL_INVALID_VALUE: 265 context->recordInvalidValue(); 266 TRACE("\t! Error generated: invalid value\n"); 267 break; 268 case GL_INVALID_OPERATION: 269 context->recordInvalidOperation(); 270 TRACE("\t! Error generated: invalid operation\n"); 271 break; 272 case GL_OUT_OF_MEMORY: 273 context->recordOutOfMemory(); 274 TRACE("\t! Error generated: out of memory\n"); 275 break; 276 case GL_INVALID_FRAMEBUFFER_OPERATION: 277 context->recordInvalidFramebufferOperation(); 278 TRACE("\t! Error generated: invalid framebuffer operation\n"); 279 break; 280 default: UNREACHABLE(errorCode); 281 } 282 } 283 } 284