1#include "precompiled.h"
2//
3// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// main.cpp: DLL entry point and management of thread-local data.
9
10#include "libGLESv2/main.h"
11
12#include "libGLESv2/Context.h"
13
14static DWORD currentTLS = TLS_OUT_OF_INDEXES;
15
16namespace gl
17{
18
19Current *AllocateCurrent()
20{
21    Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current));
22
23    if (!current)
24    {
25        ERR("Could not allocate thread local storage.");
26        return NULL;
27    }
28
29    ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
30    TlsSetValue(currentTLS, current);
31
32    current->context = NULL;
33    current->display = NULL;
34
35    return current;
36}
37
38void DeallocateCurrent()
39{
40    void *current = TlsGetValue(currentTLS);
41
42    if (current)
43    {
44        LocalFree((HLOCAL)current);
45    }
46}
47
48}
49
50extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
51{
52    switch (reason)
53    {
54      case DLL_PROCESS_ATTACH:
55        {
56            currentTLS = TlsAlloc();
57
58            if (currentTLS == TLS_OUT_OF_INDEXES)
59            {
60                return FALSE;
61            }
62        }
63        // Fall throught to initialize index
64      case DLL_THREAD_ATTACH:
65        {
66            gl::AllocateCurrent();
67        }
68        break;
69      case DLL_THREAD_DETACH:
70        {
71            gl::DeallocateCurrent();
72        }
73        break;
74      case DLL_PROCESS_DETACH:
75        {
76            gl::DeallocateCurrent();
77            TlsFree(currentTLS);
78        }
79        break;
80      default:
81        break;
82    }
83
84    return TRUE;
85}
86
87namespace gl
88{
89
90Current *GetCurrentData()
91{
92    Current *current = (Current*)TlsGetValue(currentTLS);
93
94    // ANGLE issue 488: when the dll is loaded after thread initialization,
95    // thread local storage (current) might not exist yet.
96    return (current ? current : AllocateCurrent());
97}
98
99void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
100{
101    Current *current = GetCurrentData();
102
103    current->context = context;
104    current->display = display;
105
106    if (context && display && surface)
107    {
108        context->makeCurrent(surface);
109    }
110}
111
112Context *getContext()
113{
114    Current *current = GetCurrentData();
115
116    return current->context;
117}
118
119Context *getNonLostContext()
120{
121    Context *context = getContext();
122
123    if (context)
124    {
125        if (context->isContextLost())
126        {
127            gl::error(GL_OUT_OF_MEMORY);
128            return NULL;
129        }
130        else
131        {
132            return context;
133        }
134    }
135    return NULL;
136}
137
138egl::Display *getDisplay()
139{
140    Current *current = GetCurrentData();
141
142    return current->display;
143}
144
145// Records an error code
146void error(GLenum errorCode)
147{
148    gl::Context *context = glGetCurrentContext();
149
150    if (context)
151    {
152        switch (errorCode)
153        {
154          case GL_INVALID_ENUM:
155            context->recordInvalidEnum();
156            TRACE("\t! Error generated: invalid enum\n");
157            break;
158          case GL_INVALID_VALUE:
159            context->recordInvalidValue();
160            TRACE("\t! Error generated: invalid value\n");
161            break;
162          case GL_INVALID_OPERATION:
163            context->recordInvalidOperation();
164            TRACE("\t! Error generated: invalid operation\n");
165            break;
166          case GL_OUT_OF_MEMORY:
167            context->recordOutOfMemory();
168            TRACE("\t! Error generated: out of memory\n");
169            break;
170          case GL_INVALID_FRAMEBUFFER_OPERATION:
171            context->recordInvalidFramebufferOperation();
172            TRACE("\t! Error generated: invalid framebuffer operation\n");
173            break;
174          default: UNREACHABLE();
175        }
176    }
177}
178
179}
180
181