1 // 2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // main.cpp: DLL entry point and management of thread-local data. 8 9 #include "libGLESv2/main.h" 10 #include "libGLESv2/Context.h" 11 12 #include "common/tls.h" 13 14 static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; 15 16 namespace gl 17 { 18 19 Current *AllocateCurrent() 20 { 21 ASSERT(currentTLS != TLS_OUT_OF_INDEXES); 22 if (currentTLS == TLS_OUT_OF_INDEXES) 23 { 24 return NULL; 25 } 26 27 Current *current = new Current(); 28 current->context = NULL; 29 current->display = NULL; 30 31 if (!SetTLSValue(currentTLS, current)) 32 { 33 ERR("Could not set thread local storage."); 34 return NULL; 35 } 36 37 return current; 38 } 39 40 void DeallocateCurrent() 41 { 42 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); 43 SafeDelete(current); 44 SetTLSValue(currentTLS, NULL); 45 } 46 47 } 48 49 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) 50 { 51 switch (reason) 52 { 53 case DLL_PROCESS_ATTACH: 54 { 55 currentTLS = CreateTLSIndex(); 56 if (currentTLS == TLS_OUT_OF_INDEXES) 57 { 58 return FALSE; 59 } 60 } 61 // Fall through to initialize index 62 case DLL_THREAD_ATTACH: 63 { 64 gl::AllocateCurrent(); 65 } 66 break; 67 case DLL_THREAD_DETACH: 68 { 69 gl::DeallocateCurrent(); 70 } 71 break; 72 case DLL_PROCESS_DETACH: 73 { 74 gl::DeallocateCurrent(); 75 DestroyTLSIndex(currentTLS); 76 } 77 break; 78 default: 79 break; 80 } 81 82 return TRUE; 83 } 84 85 namespace gl 86 { 87 88 Current *GetCurrentData() 89 { 90 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); 91 92 // ANGLE issue 488: when the dll is loaded after thread initialization, 93 // thread local storage (current) might not exist yet. 94 return (current ? current : AllocateCurrent()); 95 } 96 97 void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) 98 { 99 Current *current = GetCurrentData(); 100 101 current->context = context; 102 current->display = display; 103 104 if (context && display && surface) 105 { 106 context->makeCurrent(surface); 107 } 108 } 109 110 Context *getContext() 111 { 112 Current *current = GetCurrentData(); 113 114 return current->context; 115 } 116 117 Context *getNonLostContext() 118 { 119 Context *context = getContext(); 120 121 if (context) 122 { 123 if (context->isContextLost()) 124 { 125 gl::error(GL_OUT_OF_MEMORY); 126 return NULL; 127 } 128 else 129 { 130 return context; 131 } 132 } 133 return NULL; 134 } 135 136 egl::Display *getDisplay() 137 { 138 Current *current = GetCurrentData(); 139 140 return current->display; 141 } 142 143 // Records an error code 144 void error(GLenum errorCode) 145 { 146 gl::Context *context = glGetCurrentContext(); 147 context->recordError(Error(errorCode)); 148 149 switch (errorCode) 150 { 151 case GL_INVALID_ENUM: 152 TRACE("\t! Error generated: invalid enum\n"); 153 break; 154 case GL_INVALID_VALUE: 155 TRACE("\t! Error generated: invalid value\n"); 156 break; 157 case GL_INVALID_OPERATION: 158 TRACE("\t! Error generated: invalid operation\n"); 159 break; 160 case GL_OUT_OF_MEMORY: 161 TRACE("\t! Error generated: out of memory\n"); 162 break; 163 case GL_INVALID_FRAMEBUFFER_OPERATION: 164 TRACE("\t! Error generated: invalid framebuffer operation\n"); 165 break; 166 default: UNREACHABLE(); 167 } 168 } 169 170 } 171 172