OSDN Git Service

Reference count the TLS objects.
[android-x86/external-swiftshader.git] / src / OpenGL / libEGL / main.cpp
1 // SwiftShader Software Renderer\r
2 //\r
3 // Copyright(c) 2005-2013 TransGaming Inc.\r
4 //\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,\r
6 // transcribed, stored in a retrieval system, translated into any human or computer\r
7 // language by any means, or disclosed to third parties without the explicit written\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express\r
9 // or implied, including but not limited to any patent rights, are granted to you.\r
10 //\r
11 \r
12 // main.cpp: DLL entry point and management of thread-local data.\r
13 \r
14 #include "main.h"\r
15 \r
16 #include "Context.hpp"\r
17 #include "Surface.h"\r
18 \r
19 #include "resource.h"\r
20 #include "Common/Thread.hpp"\r
21 #include "Common/SharedLibrary.hpp"\r
22 #include "common/debug.h"\r
23 \r
24 static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;\r
25 \r
26 #if !defined(_MSC_VER)\r
27 #define CONSTRUCTOR __attribute__((constructor))\r
28 #define DESTRUCTOR __attribute__((destructor))\r
29 #else\r
30 #define CONSTRUCTOR\r
31 #define DESTRUCTOR\r
32 #endif\r
33 \r
34 static void eglAttachThread()\r
35 {\r
36     TRACE("()");\r
37 \r
38     egl::Current *current = new egl::Current;\r
39 \r
40     if(current)\r
41     {\r
42         sw::Thread::setLocalStorage(currentTLS, current);\r
43 \r
44         current->error = EGL_SUCCESS;\r
45         current->API = EGL_OPENGL_ES_API;\r
46                 current->display = nullptr;\r
47                 current->context = nullptr;\r
48                 current->drawSurface = nullptr;\r
49         current->readSurface = nullptr;\r
50         }\r
51 }\r
52 \r
53 static void eglDetachThread()\r
54 {\r
55     TRACE("()");\r
56 \r
57         egl::Current *current = (egl::Current*)sw::Thread::getLocalStorage(currentTLS);\r
58 \r
59         if(current)\r
60         {\r
61         delete current;\r
62         }\r
63 }\r
64 \r
65 CONSTRUCTOR static bool eglAttachProcess()\r
66 {\r
67     TRACE("()");\r
68 \r
69         #if !defined(ANGLE_DISABLE_TRACE)\r
70         FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");\r
71 \r
72         if(debug)\r
73         {\r
74             fclose(debug);\r
75             debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase\r
76             fclose(debug);\r
77         }\r
78         #endif\r
79 \r
80     currentTLS = sw::Thread::allocateLocalStorageKey();\r
81 \r
82     if(currentTLS == TLS_OUT_OF_INDEXES)\r
83     {\r
84         return false;\r
85     }\r
86 \r
87         eglAttachThread();\r
88 \r
89         #if defined(_WIN32)\r
90         const char *libGLES_CM_lib[] = {"libGLES_CM.dll", "libGLES_CM_translator.dll"};\r
91         #elif defined(__ANDROID__)\r
92         const char *libGLES_CM_lib[] = {"/vendor/lib/egl/libGLESv1_CM_swiftshader.so"};\r
93         #elif defined(__LP64__)\r
94         const char *libGLES_CM_lib[] = {"lib64GLES_CM_translator.so", "libGLES_CM.so.1", "libGLES_CM.so"};\r
95         #else\r
96         const char *libGLES_CM_lib[] = {"libGLES_CM_translator.so", "libGLES_CM.so.1", "libGLES_CM.so"};\r
97         #endif\r
98 \r
99     libGLES_CM = loadLibrary(libGLES_CM_lib);\r
100     es1::createContext = (egl::Context *(*)(const egl::Config*, const egl::Context*))getProcAddress(libGLES_CM, "glCreateContext");\r
101     es1::getProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char*))getProcAddress(libGLES_CM, "glGetProcAddress");\r
102 \r
103         #if defined(_WIN32)\r
104         const char *libGLESv2_lib[] = {"libGLESv2.dll", "libGLES_V2_translator.dll"};\r
105         #elif defined(__ANDROID__)\r
106         const char *libGLESv2_lib[] = {"/vendor/lib/egl/libGLESv2_swiftshader.so"};\r
107         #elif defined(__LP64__)\r
108         const char *libGLESv2_lib[] = {"lib64GLES_V2_translator.so", "libGLESv2.so.2", "libGLESv2.so"};\r
109         #else\r
110         const char *libGLESv2_lib[] = {"libGLES_V2_translator.so", "libGLESv2.so.2", "libGLESv2.so"};\r
111         #endif\r
112 \r
113     libGLESv2 = loadLibrary(libGLESv2_lib);\r
114     es2::createContext = (egl::Context *(*)(const egl::Config*, const egl::Context*, EGLint))getProcAddress(libGLESv2, "glCreateContext");\r
115     es2::getProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char*))getProcAddress(libGLESv2, "glGetProcAddress");\r
116 \r
117         es::createBackBuffer = (egl::Image *(*)(int, int, const egl::Config*))getProcAddress(libGLES_CM, "createBackBuffer");\r
118         es::createDepthStencil = (egl::Image *(*)(unsigned int, unsigned int, sw::Format, int, bool))getProcAddress(libGLES_CM, "createDepthStencil");\r
119     es::createFrameBuffer = (sw::FrameBuffer *(*)(EGLNativeDisplayType, EGLNativeWindowType, int, int))getProcAddress(libGLES_CM, "createFrameBuffer");\r
120 \r
121         if(!es::createBackBuffer)\r
122         {\r
123                 es::createBackBuffer = (egl::Image *(*)(int, int, const egl::Config*))getProcAddress(libGLESv2, "createBackBuffer");\r
124                 es::createDepthStencil = (egl::Image *(*)(unsigned int, unsigned int, sw::Format, int, bool))getProcAddress(libGLESv2, "createDepthStencil");\r
125                 es::createFrameBuffer = (sw::FrameBuffer *(*)(EGLNativeDisplayType, EGLNativeWindowType, int, int))getProcAddress(libGLESv2, "createFrameBuffer");\r
126         }\r
127 \r
128         return libGLES_CM != 0 || libGLESv2 != 0;\r
129 }\r
130 \r
131 DESTRUCTOR static void eglDetachProcess()\r
132 {\r
133     TRACE("()");\r
134 \r
135         eglDetachThread();\r
136         sw::Thread::freeLocalStorageKey(currentTLS);\r
137         freeLibrary(libGLESv2);\r
138 }\r
139 \r
140 #if defined(_WIN32)\r
141 static INT_PTR CALLBACK DebuggerWaitDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
142 {\r
143         RECT rect;\r
144 \r
145     switch(uMsg)\r
146     {\r
147     case WM_INITDIALOG:\r
148                 GetWindowRect(GetDesktopWindow(), &rect);\r
149                 SetWindowPos(hwnd, HWND_TOP, rect.right / 2, rect.bottom / 2, 0, 0, SWP_NOSIZE);\r
150                 SetTimer(hwnd, 1, 100, NULL);\r
151                 return TRUE;\r
152     case WM_COMMAND:\r
153         if(LOWORD(wParam) == IDCANCEL)\r
154                 {\r
155                         EndDialog(hwnd, 0);\r
156                 }\r
157         break;\r
158     case WM_TIMER:\r
159                 if(IsDebuggerPresent())\r
160                 {\r
161                         EndDialog(hwnd, 0);\r
162                 }\r
163     }\r
164 \r
165     return FALSE;\r
166 }\r
167 \r
168 static void WaitForDebugger(HINSTANCE instance)\r
169 {\r
170     if(!IsDebuggerPresent())\r
171     {\r
172         HRSRC dialog = FindResource(instance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG);\r
173                 DLGTEMPLATE *dialogTemplate = (DLGTEMPLATE*)LoadResource(instance, dialog);\r
174                 DialogBoxIndirect(instance, dialogTemplate, NULL, DebuggerWaitDialogProc);\r
175     }\r
176 }\r
177 \r
178 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)\r
179 {\r
180     switch(reason)\r
181     {\r
182     case DLL_PROCESS_ATTACH:\r
183                 #ifndef NDEBUG\r
184                         WaitForDebugger(instance);\r
185                 #endif\r
186         return eglAttachProcess();\r
187         break;\r
188     case DLL_THREAD_ATTACH:\r
189         eglAttachThread();\r
190         break;\r
191     case DLL_THREAD_DETACH:\r
192         eglDetachThread();\r
193         break;\r
194     case DLL_PROCESS_DETACH:\r
195         eglDetachProcess();\r
196         break;\r
197     default:\r
198         break;\r
199     }\r
200 \r
201     return TRUE;\r
202 }\r
203 #endif\r
204 \r
205 namespace egl\r
206 {\r
207 static Current *eglGetCurrent(void)\r
208 {\r
209         Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);\r
210 \r
211         if(!current)\r
212         {\r
213                 eglAttachThread();\r
214         }\r
215 \r
216         return (Current*)sw::Thread::getLocalStorage(currentTLS);\r
217 }\r
218 \r
219 void setCurrentError(EGLint error)\r
220 {\r
221     Current *current = eglGetCurrent();\r
222 \r
223     current->error = error;\r
224 }\r
225 \r
226 EGLint getCurrentError()\r
227 {\r
228     Current *current = eglGetCurrent();\r
229 \r
230     return current->error;\r
231 }\r
232 \r
233 void setCurrentAPI(EGLenum API)\r
234 {\r
235     Current *current = eglGetCurrent();\r
236 \r
237     current->API = API;\r
238 }\r
239 \r
240 EGLenum getCurrentAPI()\r
241 {\r
242     Current *current = eglGetCurrent();\r
243 \r
244     return current->API;\r
245 }\r
246 \r
247 void setCurrentDisplay(egl::Display *dpy)\r
248 {\r
249     Current *current = eglGetCurrent();\r
250 \r
251     current->display = dpy;\r
252 }\r
253 \r
254 egl::Display *getCurrentDisplay()\r
255 {\r
256     Current *current = eglGetCurrent();\r
257 \r
258     return current->display;\r
259 }\r
260 \r
261 void setCurrentContext(egl::Context *ctx)\r
262 {\r
263     Current *current = eglGetCurrent();\r
264 \r
265         if(ctx)\r
266         {\r
267                 ctx->addRef();\r
268         }\r
269 \r
270         if(current->context)\r
271         {\r
272                 current->context->release();\r
273         }\r
274 \r
275     current->context = ctx;\r
276 }\r
277 \r
278 egl::Context *getCurrentContext()\r
279 {\r
280     Current *current = eglGetCurrent();\r
281 \r
282     return current->context;\r
283 }\r
284 \r
285 void setCurrentDrawSurface(egl::Surface *surface)\r
286 {\r
287     Current *current = eglGetCurrent();\r
288 \r
289         if(surface)\r
290         {\r
291                 surface->addRef();\r
292         }\r
293 \r
294         if(current->drawSurface)\r
295         {\r
296                 current->drawSurface->release();\r
297         }\r
298 \r
299     current->drawSurface = surface;\r
300 }\r
301 \r
302 egl::Surface *getCurrentDrawSurface()\r
303 {\r
304     Current *current = eglGetCurrent();\r
305 \r
306     return current->drawSurface;\r
307 }\r
308 \r
309 void setCurrentReadSurface(egl::Surface *surface)\r
310 {\r
311     Current *current = eglGetCurrent();\r
312 \r
313         if(surface)\r
314         {\r
315                 surface->addRef();\r
316         }\r
317 \r
318         if(current->readSurface)\r
319         {\r
320                 current->readSurface->release();\r
321         }\r
322 \r
323     current->readSurface = surface;\r
324 }\r
325 \r
326 egl::Surface *getCurrentReadSurface()\r
327 {\r
328     Current *current = eglGetCurrent();\r
329 \r
330     return current->readSurface;\r
331 }\r
332 }\r
333 \r
334 void error(EGLint errorCode)\r
335 {\r
336     egl::setCurrentError(errorCode);\r
337 \r
338         if(errorCode != EGL_SUCCESS)\r
339         {\r
340                 switch(errorCode)\r
341                 {\r
342                 case EGL_NOT_INITIALIZED:     TRACE("\t! Error generated: not initialized\n");     break;\r
343                 case EGL_BAD_ACCESS:          TRACE("\t! Error generated: bad access\n");          break;\r
344                 case EGL_BAD_ALLOC:           TRACE("\t! Error generated: bad alloc\n");           break;\r
345                 case EGL_BAD_ATTRIBUTE:       TRACE("\t! Error generated: bad attribute\n");       break;\r
346                 case EGL_BAD_CONFIG:          TRACE("\t! Error generated: bad config\n");          break;\r
347                 case EGL_BAD_CONTEXT:         TRACE("\t! Error generated: bad context\n");         break;\r
348                 case EGL_BAD_CURRENT_SURFACE: TRACE("\t! Error generated: bad current surface\n"); break;\r
349                 case EGL_BAD_DISPLAY:         TRACE("\t! Error generated: bad display\n");         break;\r
350                 case EGL_BAD_MATCH:           TRACE("\t! Error generated: bad match\n");           break;\r
351                 case EGL_BAD_NATIVE_PIXMAP:   TRACE("\t! Error generated: bad native pixmap\n");   break;\r
352                 case EGL_BAD_NATIVE_WINDOW:   TRACE("\t! Error generated: bad native window\n");   break;\r
353                 case EGL_BAD_PARAMETER:       TRACE("\t! Error generated: bad parameter\n");       break;\r
354                 case EGL_BAD_SURFACE:         TRACE("\t! Error generated: bad surface\n");         break;\r
355                 case EGL_CONTEXT_LOST:        TRACE("\t! Error generated: context lost\n");        break;\r
356                 default:                      TRACE("\t! Error generated: <0x%X>\n", errorCode);   break;\r
357                 }\r
358         }\r
359 }\r
360 \r
361 extern "C"\r
362 {\r
363 EGLContext clientGetCurrentContext()\r
364 {\r
365     return egl::getCurrentContext();\r
366 }\r
367 \r
368 EGLContext clientGetCurrentDisplay()\r
369 {\r
370     return egl::getCurrentDisplay();\r
371 }\r
372 }\r
373 \r
374 namespace es1\r
375 {\r
376         egl::Context *(*createContext)(const egl::Config *config, const egl::Context *shareContext) = 0;\r
377         __eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname) = 0;\r
378 }\r
379 \r
380 namespace es2\r
381 {\r
382         egl::Context *(*createContext)(const egl::Config *config, const egl::Context *shareContext, EGLint clientVersion) = 0;\r
383         __eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname) = 0;\r
384 }\r
385 \r
386 namespace es\r
387 {\r
388         egl::Image *(*createBackBuffer)(int width, int height, const egl::Config *config) = 0;\r
389         egl::Image *(*createDepthStencil)(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) = 0;\r
390         sw::FrameBuffer *(*createFrameBuffer)(EGLNativeDisplayType display, EGLNativeWindowType window, int width, int height) = 0;\r
391 }\r
392 \r
393 void *libGLES_CM = 0;   // Handle to the libGLES_CM module\r
394 void *libGLESv2 = 0;   // Handle to the libGLESv2 module\r