Home | History | Annotate | Download | only in libGL
      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