| #include "precompiled.h" | |
| // | |
| // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| // main.cpp: DLL entry point and management of thread-local data. | |
| #include "libGLESv2/main.h" | |
| #include "libGLESv2/Context.h" | |
| #include "common/tls.h" | |
| static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; | |
| namespace gl | |
| { | |
| Current *AllocateCurrent() | |
| { | |
| ASSERT(currentTLS != TLS_OUT_OF_INDEXES); | |
| if (currentTLS == TLS_OUT_OF_INDEXES) | |
| { | |
| return NULL; | |
| } | |
| Current *current = new Current(); | |
| current->context = NULL; | |
| current->display = NULL; | |
| if (!SetTLSValue(currentTLS, current)) | |
| { | |
| ERR("Could not set thread local storage."); | |
| return NULL; | |
| } | |
| return current; | |
| } | |
| void DeallocateCurrent() | |
| { | |
| Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); | |
| SafeDelete(current); | |
| SetTLSValue(currentTLS, NULL); | |
| } | |
| } | |
| extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) | |
| { | |
| switch (reason) | |
| { | |
| case DLL_PROCESS_ATTACH: | |
| { | |
| currentTLS = CreateTLSIndex(); | |
| if (currentTLS == TLS_OUT_OF_INDEXES) | |
| { | |
| return FALSE; | |
| } | |
| } | |
| // Fall through to initialize index | |
| case DLL_THREAD_ATTACH: | |
| { | |
| gl::AllocateCurrent(); | |
| } | |
| break; | |
| case DLL_THREAD_DETACH: | |
| { | |
| gl::DeallocateCurrent(); | |
| } | |
| break; | |
| case DLL_PROCESS_DETACH: | |
| { | |
| gl::DeallocateCurrent(); | |
| DestroyTLSIndex(currentTLS); | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return TRUE; | |
| } | |
| namespace gl | |
| { | |
| Current *GetCurrentData() | |
| { | |
| Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); | |
| // ANGLE issue 488: when the dll is loaded after thread initialization, | |
| // thread local storage (current) might not exist yet. | |
| return (current ? current : AllocateCurrent()); | |
| } | |
| void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) | |
| { | |
| Current *current = GetCurrentData(); | |
| current->context = context; | |
| current->display = display; | |
| if (context && display && surface) | |
| { | |
| context->makeCurrent(surface); | |
| } | |
| } | |
| Context *getContext() | |
| { | |
| Current *current = GetCurrentData(); | |
| return current->context; | |
| } | |
| Context *getNonLostContext() | |
| { | |
| Context *context = getContext(); | |
| if (context) | |
| { | |
| if (context->isContextLost()) | |
| { | |
| gl::error(GL_OUT_OF_MEMORY); | |
| return NULL; | |
| } | |
| else | |
| { | |
| return context; | |
| } | |
| } | |
| return NULL; | |
| } | |
| egl::Display *getDisplay() | |
| { | |
| Current *current = GetCurrentData(); | |
| return current->display; | |
| } | |
| // Records an error code | |
| void error(GLenum errorCode) | |
| { | |
| gl::Context *context = glGetCurrentContext(); | |
| if (context) | |
| { | |
| switch (errorCode) | |
| { | |
| case GL_INVALID_ENUM: | |
| context->recordInvalidEnum(); | |
| TRACE("\t! Error generated: invalid enum\n"); | |
| break; | |
| case GL_INVALID_VALUE: | |
| context->recordInvalidValue(); | |
| TRACE("\t! Error generated: invalid value\n"); | |
| break; | |
| case GL_INVALID_OPERATION: | |
| context->recordInvalidOperation(); | |
| TRACE("\t! Error generated: invalid operation\n"); | |
| break; | |
| case GL_OUT_OF_MEMORY: | |
| context->recordOutOfMemory(); | |
| TRACE("\t! Error generated: out of memory\n"); | |
| break; | |
| case GL_INVALID_FRAMEBUFFER_OPERATION: | |
| context->recordInvalidFramebufferOperation(); | |
| TRACE("\t! Error generated: invalid framebuffer operation\n"); | |
| break; | |
| default: UNREACHABLE(); | |
| } | |
| } | |
| } | |
| } | |