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