1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // main.cpp: DLL entry point and management of thread-local data.
20 #include "Context.hpp"
21 #include "Surface.hpp"
24 #include "Common/Thread.hpp"
25 #include "Common/SharedLibrary.hpp"
26 #include "common/debug.h"
28 #include <EGL/eglext.h>
30 static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
32 #if !defined(_MSC_VER)
33 #define CONSTRUCTOR __attribute__((constructor))
34 #define DESTRUCTOR __attribute__((destructor))
42 void releaseCurrent(void *storage)
44 // This pthread destructor is called after the TLS is already reset to NULL,
45 // so we can't call EGL functions here to do the cleanup.
47 Current *current = (Current*)storage;
51 if(current->drawSurface)
53 current->drawSurface->release();
56 if(current->readSurface)
58 current->readSurface->release();
63 current->context->release();
70 Current *attachThread()
74 if(currentTLS == TLS_OUT_OF_INDEXES)
76 currentTLS = sw::Thread::allocateLocalStorageKey(releaseCurrent);
79 Current *current = (Current*)sw::Thread::allocateLocalStorage(currentTLS, sizeof(Current));
81 current->error = EGL_SUCCESS;
82 current->API = EGL_OPENGL_ES_API;
83 current->context = nullptr;
84 current->drawSurface = nullptr;
85 current->readSurface = nullptr;
94 eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
96 sw::Thread::freeLocalStorage(currentTLS);
99 CONSTRUCTOR void attachProcess()
103 #if !defined(ANGLE_DISABLE_TRACE) && defined(TRACE_OUTPUT_FILE)
104 FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
109 debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase
117 DESTRUCTOR void detachProcess()
122 sw::Thread::freeLocalStorageKey(currentTLS);
127 #ifdef DEBUGGER_WAIT_DIALOG
128 static INT_PTR CALLBACK DebuggerWaitDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
135 GetWindowRect(GetDesktopWindow(), &rect);
136 SetWindowPos(hwnd, HWND_TOP, rect.right / 2, rect.bottom / 2, 0, 0, SWP_NOSIZE);
137 SetTimer(hwnd, 1, 100, NULL);
140 if(LOWORD(wParam) == IDCANCEL)
146 if(IsDebuggerPresent())
155 static void WaitForDebugger(HINSTANCE instance)
157 if(!IsDebuggerPresent())
159 HRSRC dialog = FindResource(instance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG);
160 DLGTEMPLATE *dialogTemplate = (DLGTEMPLATE*)LoadResource(instance, dialog);
161 DialogBoxIndirect(instance, dialogTemplate, NULL, DebuggerWaitDialogProc);
166 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
170 case DLL_PROCESS_ATTACH:
171 #ifdef DEBUGGER_WAIT_DIALOG
172 WaitForDebugger(instance);
174 egl::attachProcess();
176 case DLL_THREAD_ATTACH:
179 case DLL_THREAD_DETACH:
182 case DLL_PROCESS_DETACH:
183 egl::detachProcess();
195 static Current *getCurrent(void)
197 Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
201 current = attachThread();
207 void setCurrentError(EGLint error)
209 Current *current = getCurrent();
211 current->error = error;
214 EGLint getCurrentError()
216 Current *current = getCurrent();
218 return current->error;
221 void setCurrentAPI(EGLenum API)
223 Current *current = getCurrent();
228 EGLenum getCurrentAPI()
230 Current *current = getCurrent();
235 void setCurrentContext(egl::Context *ctx)
237 Current *current = getCurrent();
246 current->context->release();
249 current->context = ctx;
252 NO_SANITIZE_FUNCTION egl::Context *getCurrentContext()
254 Current *current = getCurrent();
256 return current->context;
259 void setCurrentDrawSurface(egl::Surface *surface)
261 Current *current = getCurrent();
268 if(current->drawSurface)
270 current->drawSurface->release();
273 current->drawSurface = surface;
276 egl::Surface *getCurrentDrawSurface()
278 Current *current = getCurrent();
280 return current->drawSurface;
283 void setCurrentReadSurface(egl::Surface *surface)
285 Current *current = getCurrent();
292 if(current->readSurface)
294 current->readSurface->release();
297 current->readSurface = surface;
300 egl::Surface *getCurrentReadSurface()
302 Current *current = getCurrent();
304 return current->readSurface;
307 void error(EGLint errorCode)
309 egl::setCurrentError(errorCode);
311 if(errorCode != EGL_SUCCESS)
315 case EGL_NOT_INITIALIZED: TRACE("\t! Error generated: not initialized\n"); break;
316 case EGL_BAD_ACCESS: TRACE("\t! Error generated: bad access\n"); break;
317 case EGL_BAD_ALLOC: TRACE("\t! Error generated: bad alloc\n"); break;
318 case EGL_BAD_ATTRIBUTE: TRACE("\t! Error generated: bad attribute\n"); break;
319 case EGL_BAD_CONFIG: TRACE("\t! Error generated: bad config\n"); break;
320 case EGL_BAD_CONTEXT: TRACE("\t! Error generated: bad context\n"); break;
321 case EGL_BAD_CURRENT_SURFACE: TRACE("\t! Error generated: bad current surface\n"); break;
322 case EGL_BAD_DISPLAY: TRACE("\t! Error generated: bad display\n"); break;
323 case EGL_BAD_MATCH: TRACE("\t! Error generated: bad match\n"); break;
324 case EGL_BAD_NATIVE_PIXMAP: TRACE("\t! Error generated: bad native pixmap\n"); break;
325 case EGL_BAD_NATIVE_WINDOW: TRACE("\t! Error generated: bad native window\n"); break;
326 case EGL_BAD_PARAMETER: TRACE("\t! Error generated: bad parameter\n"); break;
327 case EGL_BAD_SURFACE: TRACE("\t! Error generated: bad surface\n"); break;
328 case EGL_CONTEXT_LOST: TRACE("\t! Error generated: context lost\n"); break;
329 default: TRACE("\t! Error generated: <0x%X>\n", errorCode); break;
337 EGLint GetError(void);
338 EGLDisplay GetDisplay(EGLNativeDisplayType display_id);
339 EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
340 EGLBoolean Terminate(EGLDisplay dpy);
341 const char *QueryString(EGLDisplay dpy, EGLint name);
342 EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
343 EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
344 EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
345 EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list);
346 EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
347 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
348 EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface);
349 EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
350 EGLBoolean BindAPI(EGLenum api);
351 EGLenum QueryAPI(void);
352 EGLBoolean WaitClient(void);
353 EGLBoolean ReleaseThread(void);
354 EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
355 EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
356 EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
357 EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
358 EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval);
359 EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
360 EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx);
361 EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
362 EGLContext GetCurrentContext(void);
363 EGLSurface GetCurrentSurface(EGLint readdraw);
364 EGLDisplay GetCurrentDisplay(void);
365 EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
366 EGLBoolean WaitGL(void);
367 EGLBoolean WaitNative(EGLint engine);
368 EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface);
369 EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
370 EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
371 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image);
372 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
373 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
374 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
375 EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
376 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
377 EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
378 EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
379 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname);
384 EGLAPI EGLint EGLAPIENTRY eglGetError(void)
386 return egl::GetError();
389 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
391 return egl::GetDisplay(display_id);
394 EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
396 return egl::Initialize(dpy, major, minor);
399 EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
401 return egl::Terminate(dpy);
404 EGLAPI const char *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
406 return egl::QueryString(dpy, name);
409 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
411 return egl::GetConfigs(dpy, configs, config_size, num_config);
414 EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
416 return egl::ChooseConfig(dpy, attrib_list, configs, config_size, num_config);
419 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
421 return egl::GetConfigAttrib(dpy, config, attribute, value);
424 EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
426 return egl::CreateWindowSurface(dpy, config, window, attrib_list);
429 EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
431 return egl::CreatePbufferSurface(dpy, config, attrib_list);
434 EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
436 return egl::CreatePixmapSurface(dpy, config, pixmap, attrib_list);
439 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
441 return egl::DestroySurface(dpy, surface);
444 EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
446 return egl::QuerySurface(dpy, surface, attribute, value);
449 EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
451 return egl::BindAPI(api);
454 EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void)
456 return egl::QueryAPI();
459 EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void)
461 return egl::WaitClient();
464 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void)
466 return egl::ReleaseThread();
469 EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
471 return egl::CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
474 EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
476 return egl::SurfaceAttrib(dpy, surface, attribute, value);
479 EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
481 return egl::BindTexImage(dpy, surface, buffer);
484 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
486 return egl::ReleaseTexImage(dpy, surface, buffer);
489 EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
491 return egl::SwapInterval(dpy, interval);
494 EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
496 return egl::CreateContext(dpy, config, share_context, attrib_list);
499 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
501 return egl::DestroyContext(dpy, ctx);
504 EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
506 return egl::MakeCurrent(dpy, draw, read, ctx);
509 EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void)
511 return egl::GetCurrentContext();
514 EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
516 return egl::GetCurrentSurface(readdraw);
519 EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
521 return egl::GetCurrentDisplay();
524 EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
526 return egl::QueryContext(dpy, ctx, attribute, value);
529 EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void)
531 return egl::WaitClient();
534 EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
536 return egl::WaitNative(engine);
539 EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
541 return egl::SwapBuffers(dpy, surface);
544 EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
546 return egl::CopyBuffers(dpy, surface, target);
549 EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
551 return egl::CreateImageKHR(dpy, ctx, target, buffer, attrib_list);
554 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
556 return egl::DestroyImageKHR(dpy, image);
559 EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
561 return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list);
564 EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
566 return egl::CreatePlatformWindowSurfaceEXT(dpy, config, native_window, attrib_list);
569 EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
571 return egl::CreatePlatformPixmapSurfaceEXT(dpy, config, native_pixmap, attrib_list);
574 EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
576 return egl::CreateSyncKHR(dpy, type, attrib_list);
579 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
581 return egl::DestroySyncKHR(dpy, sync);
584 EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
586 return egl::ClientWaitSyncKHR(dpy, sync, flags, timeout);
589 EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
591 return egl::GetSyncAttribKHR(dpy, sync, attribute, value);
594 EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
596 return egl::GetProcAddress(procname);
600 LibEGLexports::LibEGLexports()
602 this->eglGetError = egl::GetError;
603 this->eglGetDisplay = egl::GetDisplay;
604 this->eglInitialize = egl::Initialize;
605 this->eglTerminate = egl::Terminate;
606 this->eglQueryString = egl::QueryString;
607 this->eglGetConfigs = egl::GetConfigs;
608 this->eglChooseConfig = egl::ChooseConfig;
609 this->eglGetConfigAttrib = egl::GetConfigAttrib;
610 this->eglCreateWindowSurface = egl::CreateWindowSurface;
611 this->eglCreatePbufferSurface = egl::CreatePbufferSurface;
612 this->eglCreatePixmapSurface = egl::CreatePixmapSurface;
613 this->eglDestroySurface = egl::DestroySurface;
614 this->eglQuerySurface = egl::QuerySurface;
615 this->eglBindAPI = egl::BindAPI;
616 this->eglQueryAPI = egl::QueryAPI;
617 this->eglWaitClient = egl::WaitClient;
618 this->eglReleaseThread = egl::ReleaseThread;
619 this->eglCreatePbufferFromClientBuffer = egl::CreatePbufferFromClientBuffer;
620 this->eglSurfaceAttrib = egl::SurfaceAttrib;
621 this->eglBindTexImage = egl::BindTexImage;
622 this->eglReleaseTexImage = egl::ReleaseTexImage;
623 this->eglSwapInterval = egl::SwapInterval;
624 this->eglCreateContext = egl::CreateContext;
625 this->eglDestroyContext = egl::DestroyContext;
626 this->eglMakeCurrent = egl::MakeCurrent;
627 this->eglGetCurrentContext = egl::GetCurrentContext;
628 this->eglGetCurrentSurface = egl::GetCurrentSurface;
629 this->eglGetCurrentDisplay = egl::GetCurrentDisplay;
630 this->eglQueryContext = egl::QueryContext;
631 this->eglWaitGL = egl::WaitGL;
632 this->eglWaitNative = egl::WaitNative;
633 this->eglSwapBuffers = egl::SwapBuffers;
634 this->eglCopyBuffers = egl::CopyBuffers;
635 this->eglCreateImageKHR = egl::CreateImageKHR;
636 this->eglDestroyImageKHR = egl::DestroyImageKHR;
637 this->eglGetProcAddress = egl::GetProcAddress;
638 this->eglCreateSyncKHR = egl::CreateSyncKHR;
639 this->eglDestroySyncKHR = egl::DestroySyncKHR;
640 this->eglClientWaitSyncKHR = egl::ClientWaitSyncKHR;
641 this->eglGetSyncAttribKHR = egl::GetSyncAttribKHR;
643 this->clientGetCurrentContext = egl::getCurrentContext;
646 extern "C" EGLAPI LibEGLexports *libEGL_swiftshader()
648 static LibEGLexports libEGL;
652 LibGLES_CM libGLES_CM(getLibraryDirectoryFromSymbol((void*)libEGL_swiftshader));
653 LibGLESv2 libGLESv2(getLibraryDirectoryFromSymbol((void*)libEGL_swiftshader));