blob: 755734819d096f45f5fca6710a1f2eac8eb6c27f [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.comfad16ed2012-10-17 18:24:01 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00009#include "libGLESv2/main.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
Geoff Lang44fa7592014-05-30 11:50:07 -040012#include "common/tls.h"
13
Kenneth Russell9d6d4982014-10-10 19:47:34 -070014static TLSIndex currentTLS = TLS_INVALID_INDEX;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015
Jamie Madill7a934372013-12-06 18:17:48 -050016namespace gl
17{
18
Kenneth Russell9d6d4982014-10-10 19:47:34 -070019// TODO(kbr): figure out how these are going to be managed on
20// non-Windows platforms. These routines would need to be exported
21// from ANGLE and called cooperatively when users create and destroy
22// threads -- or the initialization of the TLS index, and allocation
23// of thread-local data, will have to be done lazily. Will have to use
24// destructor function with pthread_create_key on POSIX platforms to
25// clean up thread-local data.
26
27// Call this exactly once at process startup.
28bool CreateThreadLocalIndex()
29{
30 currentTLS = CreateTLSIndex();
31 if (currentTLS == TLS_INVALID_INDEX)
32 {
33 return false;
34 }
35 return true;
36}
37
38// Call this exactly once at process shutdown.
39void DestroyThreadLocalIndex()
40{
41 DestroyTLSIndex(currentTLS);
42 currentTLS = TLS_INVALID_INDEX;
43}
44
45// Call this upon thread startup.
Jamie Madill7a934372013-12-06 18:17:48 -050046Current *AllocateCurrent()
47{
Kenneth Russell9d6d4982014-10-10 19:47:34 -070048 ASSERT(currentTLS != TLS_INVALID_INDEX);
49 if (currentTLS == TLS_INVALID_INDEX)
Jamie Madill7a934372013-12-06 18:17:48 -050050 {
Jamie Madill7a934372013-12-06 18:17:48 -050051 return NULL;
52 }
53
Geoff Lang44fa7592014-05-30 11:50:07 -040054 Current *current = new Current();
Jamie Madill7a934372013-12-06 18:17:48 -050055 current->context = NULL;
56 current->display = NULL;
57
Geoff Lang44fa7592014-05-30 11:50:07 -040058 if (!SetTLSValue(currentTLS, current))
59 {
60 ERR("Could not set thread local storage.");
61 return NULL;
62 }
63
Jamie Madill7a934372013-12-06 18:17:48 -050064 return current;
65}
66
Kenneth Russell9d6d4982014-10-10 19:47:34 -070067// Call this upon thread shutdown.
Jamie Madill7a934372013-12-06 18:17:48 -050068void DeallocateCurrent()
69{
Geoff Lang44fa7592014-05-30 11:50:07 -040070 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
71 SafeDelete(current);
72 SetTLSValue(currentTLS, NULL);
Jamie Madill7a934372013-12-06 18:17:48 -050073}
74
75}
76
Kenneth Russell9d6d4982014-10-10 19:47:34 -070077#ifdef ANGLE_PLATFORM_WINDOWS
daniel@transgaming.comfad16ed2012-10-17 18:24:01 +000078extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079{
80 switch (reason)
81 {
82 case DLL_PROCESS_ATTACH:
83 {
Kenneth Russell9d6d4982014-10-10 19:47:34 -070084 if (!gl::CreateThreadLocalIndex())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085 {
86 return FALSE;
87 }
Austin Kinross922a9fb2014-10-21 14:26:33 -070088
89#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
90 gl::InitializeDebugAnnotations();
91#endif
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 }
Geoff Lang44fa7592014-05-30 11:50:07 -040093 // Fall through to initialize index
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000094 case DLL_THREAD_ATTACH:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 {
Jamie Madill7a934372013-12-06 18:17:48 -050096 gl::AllocateCurrent();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000098 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099 case DLL_THREAD_DETACH:
100 {
Jamie Madill7a934372013-12-06 18:17:48 -0500101 gl::DeallocateCurrent();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000103 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104 case DLL_PROCESS_DETACH:
105 {
Jamie Madill7a934372013-12-06 18:17:48 -0500106 gl::DeallocateCurrent();
Kenneth Russell9d6d4982014-10-10 19:47:34 -0700107 gl::DestroyThreadLocalIndex();
Austin Kinross922a9fb2014-10-21 14:26:33 -0700108
109#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
110 gl::UninitializeDebugAnnotations();
111#endif
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000113 break;
114 default:
115 break;
116 }
117
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118 return TRUE;
119}
Kenneth Russell9d6d4982014-10-10 19:47:34 -0700120#endif
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121
122namespace gl
123{
Jamie Madill7a934372013-12-06 18:17:48 -0500124
125Current *GetCurrentData()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126{
Geoff Lang44fa7592014-05-30 11:50:07 -0400127 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
Jamie Madill7a934372013-12-06 18:17:48 -0500129 // ANGLE issue 488: when the dll is loaded after thread initialization,
130 // thread local storage (current) might not exist yet.
131 return (current ? current : AllocateCurrent());
132}
133
134void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
135{
136 Current *current = GetCurrentData();
137
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 current->context = context;
139 current->display = display;
140
141 if (context && display && surface)
142 {
daniel@transgaming.comad629872012-11-28 19:32:06 +0000143 context->makeCurrent(surface);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 }
145}
146
147Context *getContext()
148{
Jamie Madill7a934372013-12-06 18:17:48 -0500149 Current *current = GetCurrentData();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
151 return current->context;
152}
153
daniel@transgaming.com9d788502011-11-09 17:46:55 +0000154Context *getNonLostContext()
155{
156 Context *context = getContext();
Geoff Lang44fa7592014-05-30 11:50:07 -0400157
daniel@transgaming.com82b28912011-12-12 21:01:35 +0000158 if (context)
159 {
160 if (context->isContextLost())
161 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000162 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com82b28912011-12-12 21:01:35 +0000163 return NULL;
164 }
165 else
166 {
167 return context;
168 }
169 }
daniel@transgaming.com9d788502011-11-09 17:46:55 +0000170 return NULL;
171}
172
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000173egl::Display *getDisplay()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174{
Jamie Madill7a934372013-12-06 18:17:48 -0500175 Current *current = GetCurrentData();
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000176
177 return current->display;
178}
179
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180// Records an error code
181void error(GLenum errorCode)
182{
183 gl::Context *context = glGetCurrentContext();
Geoff Langda5777c2014-07-11 09:52:58 -0400184 context->recordError(Error(errorCode));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185
Geoff Langda5777c2014-07-11 09:52:58 -0400186 switch (errorCode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187 {
Geoff Langda5777c2014-07-11 09:52:58 -0400188 case GL_INVALID_ENUM:
189 TRACE("\t! Error generated: invalid enum\n");
190 break;
191 case GL_INVALID_VALUE:
192 TRACE("\t! Error generated: invalid value\n");
193 break;
194 case GL_INVALID_OPERATION:
195 TRACE("\t! Error generated: invalid operation\n");
196 break;
197 case GL_OUT_OF_MEMORY:
198 TRACE("\t! Error generated: out of memory\n");
199 break;
200 case GL_INVALID_FRAMEBUFFER_OPERATION:
201 TRACE("\t! Error generated: invalid framebuffer operation\n");
202 break;
203 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204 }
205}
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000206
207}