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 14static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; 15 16namespace gl 17{ 18 19Current *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 40void DeallocateCurrent() 41{ 42 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); 43 SafeDelete(current); 44 SetTLSValue(currentTLS, NULL); 45} 46 47} 48 49extern "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 85namespace gl 86{ 87 88Current *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 97void 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 110Context *getContext() 111{ 112 Current *current = GetCurrentData(); 113 114 return current->context; 115} 116 117Context *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 136egl::Display *getDisplay() 137{ 138 Current *current = GetCurrentData(); 139 140 return current->display; 141} 142 143// Records an error code 144void 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