1 //
2 // Copyright 2016 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 // Thread.cpp : Defines the Thread class which represents a global EGL thread.
8
9 #include "libANGLE/Thread.h"
10
11 #include "libANGLE/Context.h"
12 #include "libANGLE/Debug.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/Error.h"
15
16 namespace angle
17 {
18 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
19 bool gUseAndroidOpenGLTlsSlot = false;
20 #endif
21
PthreadKeyDestructorCallback(void * ptr)22 void PthreadKeyDestructorCallback(void *ptr)
23 {
24 egl::Thread *thread = static_cast<egl::Thread *>(ptr);
25 ASSERT(thread);
26
27 egl::Display::EglDisplaySet displays = egl::Display::GetEglDisplaySet();
28 for (egl::Display *display : displays)
29 {
30 ASSERT(display);
31 // Perform necessary cleanup.
32 display->threadCleanup(thread);
33 }
34 }
35 } // namespace angle
36
37 namespace egl
38 {
39 namespace
40 {
41 Debug *sDebug = nullptr;
42 } // namespace
43
Thread()44 Thread::Thread()
45 : mLabel(nullptr),
46 mError(EGL_SUCCESS),
47 mAPI(EGL_OPENGL_ES_API),
48 mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
49 {}
50
setLabel(EGLLabelKHR label)51 void Thread::setLabel(EGLLabelKHR label)
52 {
53 mLabel = label;
54 }
55
getLabel() const56 EGLLabelKHR Thread::getLabel() const
57 {
58 return mLabel;
59 }
60
setSuccess()61 void Thread::setSuccess()
62 {
63 mError = EGL_SUCCESS;
64 }
65
setError(EGLint error,const char * command,const LabeledObject * object,const char * message)66 void Thread::setError(EGLint error,
67 const char *command,
68 const LabeledObject *object,
69 const char *message)
70 {
71 mError = error;
72 if (error != EGL_SUCCESS && message)
73 {
74 EnsureDebugAllocated();
75 sDebug->insertMessage(error, command, ErrorCodeToMessageType(error), getLabel(),
76 object ? object->getLabel() : nullptr, message);
77 }
78 }
79
setError(const Error & error,const char * command,const LabeledObject * object)80 void Thread::setError(const Error &error, const char *command, const LabeledObject *object)
81 {
82 mError = error.getCode();
83 if (error.isError() && !error.getMessage().empty())
84 {
85 EnsureDebugAllocated();
86 sDebug->insertMessage(error.getCode(), command, ErrorCodeToMessageType(error.getCode()),
87 getLabel(), object ? object->getLabel() : nullptr,
88 error.getMessage());
89 }
90 }
91
getError() const92 EGLint Thread::getError() const
93 {
94 return mError;
95 }
96
setAPI(EGLenum api)97 void Thread::setAPI(EGLenum api)
98 {
99 mAPI = api;
100 }
101
getAPI() const102 EGLenum Thread::getAPI() const
103 {
104 return mAPI;
105 }
106
setCurrent(gl::Context * context)107 void Thread::setCurrent(gl::Context *context)
108 {
109 mContext = context;
110 if (mContext)
111 {
112 ASSERT(mContext->getDisplay());
113 mContext->getDisplay()->addActiveThread(this);
114 }
115 }
116
getCurrentDrawSurface() const117 Surface *Thread::getCurrentDrawSurface() const
118 {
119 if (mContext)
120 {
121 return mContext->getCurrentDrawSurface();
122 }
123 return nullptr;
124 }
125
getCurrentReadSurface() const126 Surface *Thread::getCurrentReadSurface() const
127 {
128 if (mContext)
129 {
130 return mContext->getCurrentReadSurface();
131 }
132 return nullptr;
133 }
134
getContext() const135 gl::Context *Thread::getContext() const
136 {
137 return mContext;
138 }
139
getDisplay() const140 Display *Thread::getDisplay() const
141 {
142 if (mContext)
143 {
144 return mContext->getDisplay();
145 }
146 return nullptr;
147 }
148
EnsureDebugAllocated()149 void EnsureDebugAllocated()
150 {
151 // All EGL calls use a global lock, this is thread safe
152 if (sDebug == nullptr)
153 {
154 sDebug = new Debug();
155 }
156 }
157
DeallocateDebug()158 void DeallocateDebug()
159 {
160 SafeDelete(sDebug);
161 }
162
GetDebug()163 Debug *GetDebug()
164 {
165 EnsureDebugAllocated();
166 return sDebug;
167 }
168 } // namespace egl
169