blob: 2135d8b10e7521eca6bfc780502840e591ad702a [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 }
88 }
Geoff Lang44fa7592014-05-30 11:50:07 -040089 // Fall through to initialize index
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000090 case DLL_THREAD_ATTACH:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091 {
Jamie Madill7a934372013-12-06 18:17:48 -050092 gl::AllocateCurrent();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000094 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 case DLL_THREAD_DETACH:
96 {
Jamie Madill7a934372013-12-06 18:17:48 -050097 gl::DeallocateCurrent();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000099 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100 case DLL_PROCESS_DETACH:
101 {
Jamie Madill7a934372013-12-06 18:17:48 -0500102 gl::DeallocateCurrent();
Kenneth Russell9d6d4982014-10-10 19:47:34 -0700103 gl::DestroyThreadLocalIndex();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104 }
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000105 break;
106 default:
107 break;
108 }
109
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 return TRUE;
111}
Kenneth Russell9d6d4982014-10-10 19:47:34 -0700112#endif
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
114namespace gl
115{
Jamie Madill7a934372013-12-06 18:17:48 -0500116
117Current *GetCurrentData()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118{
Geoff Lang44fa7592014-05-30 11:50:07 -0400119 Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
Jamie Madill7a934372013-12-06 18:17:48 -0500121 // ANGLE issue 488: when the dll is loaded after thread initialization,
122 // thread local storage (current) might not exist yet.
123 return (current ? current : AllocateCurrent());
124}
125
126void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
127{
128 Current *current = GetCurrentData();
129
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130 current->context = context;
131 current->display = display;
132
133 if (context && display && surface)
134 {
daniel@transgaming.comad629872012-11-28 19:32:06 +0000135 context->makeCurrent(surface);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 }
137}
138
139Context *getContext()
140{
Jamie Madill7a934372013-12-06 18:17:48 -0500141 Current *current = GetCurrentData();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
143 return current->context;
144}
145
daniel@transgaming.com9d788502011-11-09 17:46:55 +0000146Context *getNonLostContext()
147{
148 Context *context = getContext();
Geoff Lang44fa7592014-05-30 11:50:07 -0400149
daniel@transgaming.com82b28912011-12-12 21:01:35 +0000150 if (context)
151 {
152 if (context->isContextLost())
153 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000154 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com82b28912011-12-12 21:01:35 +0000155 return NULL;
156 }
157 else
158 {
159 return context;
160 }
161 }
daniel@transgaming.com9d788502011-11-09 17:46:55 +0000162 return NULL;
163}
164
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000165egl::Display *getDisplay()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166{
Jamie Madill7a934372013-12-06 18:17:48 -0500167 Current *current = GetCurrentData();
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000168
169 return current->display;
170}
171
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172// Records an error code
173void error(GLenum errorCode)
174{
175 gl::Context *context = glGetCurrentContext();
Geoff Langda5777c2014-07-11 09:52:58 -0400176 context->recordError(Error(errorCode));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177
Geoff Langda5777c2014-07-11 09:52:58 -0400178 switch (errorCode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179 {
Geoff Langda5777c2014-07-11 09:52:58 -0400180 case GL_INVALID_ENUM:
181 TRACE("\t! Error generated: invalid enum\n");
182 break;
183 case GL_INVALID_VALUE:
184 TRACE("\t! Error generated: invalid value\n");
185 break;
186 case GL_INVALID_OPERATION:
187 TRACE("\t! Error generated: invalid operation\n");
188 break;
189 case GL_OUT_OF_MEMORY:
190 TRACE("\t! Error generated: out of memory\n");
191 break;
192 case GL_INVALID_FRAMEBUFFER_OPERATION:
193 TRACE("\t! Error generated: invalid framebuffer operation\n");
194 break;
195 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196 }
197}
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000198
199}