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 "libEGL/main.h"
10
11#include "common/debug.h"
12#include "common/tls.h"
13
14static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
15
16namespace egl
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->error = EGL_SUCCESS;
29    current->API = EGL_OPENGL_ES_API;
30    current->display = EGL_NO_DISPLAY;
31    current->drawSurface = EGL_NO_SURFACE;
32    current->readSurface = EGL_NO_SURFACE;
33
34    if (!SetTLSValue(currentTLS, current))
35    {
36        ERR("Could not set thread local storage.");
37        return NULL;
38    }
39
40    return current;
41}
42
43void DeallocateCurrent()
44{
45    Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
46    SafeDelete(current);
47    SetTLSValue(currentTLS, NULL);
48}
49
50}
51
52extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
53{
54    switch (reason)
55    {
56      case DLL_PROCESS_ATTACH:
57        {
58#if defined(ANGLE_ENABLE_TRACE)
59            FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
60
61            if (debug)
62            {
63                fclose(debug);
64                debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase
65
66                if (debug)
67                {
68                    fclose(debug);
69                }
70            }
71#endif
72
73            currentTLS = CreateTLSIndex();
74            if (currentTLS == TLS_OUT_OF_INDEXES)
75            {
76                return FALSE;
77            }
78        }
79        // Fall through to initialize index
80      case DLL_THREAD_ATTACH:
81        {
82            egl::AllocateCurrent();
83        }
84        break;
85      case DLL_THREAD_DETACH:
86        {
87            egl::DeallocateCurrent();
88        }
89        break;
90      case DLL_PROCESS_DETACH:
91        {
92            egl::DeallocateCurrent();
93            DestroyTLSIndex(currentTLS);
94        }
95        break;
96      default:
97        break;
98    }
99
100    return TRUE;
101}
102
103namespace egl
104{
105
106Current *GetCurrentData()
107{
108    Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
109
110    // ANGLE issue 488: when the dll is loaded after thread initialization,
111    // thread local storage (current) might not exist yet.
112    return (current ? current : AllocateCurrent());
113}
114
115void setCurrentError(EGLint error)
116{
117    Current *current = GetCurrentData();
118
119    current->error = error;
120}
121
122EGLint getCurrentError()
123{
124    Current *current = GetCurrentData();
125
126    return current->error;
127}
128
129void setCurrentAPI(EGLenum API)
130{
131    Current *current = GetCurrentData();
132
133    current->API = API;
134}
135
136EGLenum getCurrentAPI()
137{
138    Current *current = GetCurrentData();
139
140    return current->API;
141}
142
143void setCurrentDisplay(EGLDisplay dpy)
144{
145    Current *current = GetCurrentData();
146
147    current->display = dpy;
148}
149
150EGLDisplay getCurrentDisplay()
151{
152    Current *current = GetCurrentData();
153
154    return current->display;
155}
156
157void setCurrentDrawSurface(EGLSurface surface)
158{
159    Current *current = GetCurrentData();
160
161    current->drawSurface = surface;
162}
163
164EGLSurface getCurrentDrawSurface()
165{
166    Current *current = GetCurrentData();
167
168    return current->drawSurface;
169}
170
171void setCurrentReadSurface(EGLSurface surface)
172{
173    Current *current = GetCurrentData();
174
175    current->readSurface = surface;
176}
177
178EGLSurface getCurrentReadSurface()
179{
180    Current *current = GetCurrentData();
181
182    return current->readSurface;
183}
184
185void error(EGLint errorCode)
186{
187    egl::setCurrentError(errorCode);
188}
189
190}
191