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 bool gUseAndroidOpenGLTlsSlot;
19 std::atomic_int gProcessCleanupRefCount(0);
20
ProcessCleanupCallback(void * ptr)21 void ProcessCleanupCallback(void *ptr)
22 {
23 egl::Thread *thread = static_cast<egl::Thread *>(ptr);
24 ASSERT(thread);
25
26 ASSERT(gProcessCleanupRefCount > 0);
27 if (--gProcessCleanupRefCount == 0)
28 {
29 egl::Display::EglDisplaySet displays = egl::Display::GetEglDisplaySet();
30 for (egl::Display *display : displays)
31 {
32 ASSERT(display);
33 (void)display->terminate(thread, egl::Display::TerminateReason::ProcessExit);
34 }
35 }
36 }
37 } // namespace angle
38
39 namespace egl
40 {
41 namespace
42 {
43 Debug *sDebug = nullptr;
44 } // namespace
45
Thread()46 Thread::Thread()
47 : mLabel(nullptr),
48 mError(EGL_SUCCESS),
49 mAPI(EGL_OPENGL_ES_API),
50 mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
51 {}
52
setLabel(EGLLabelKHR label)53 void Thread::setLabel(EGLLabelKHR label)
54 {
55 mLabel = label;
56 }
57
getLabel() const58 EGLLabelKHR Thread::getLabel() const
59 {
60 return mLabel;
61 }
62
setSuccess()63 void Thread::setSuccess()
64 {
65 mError = EGL_SUCCESS;
66 }
67
setError(EGLint error,const char * command,const LabeledObject * object,const char * message)68 void Thread::setError(EGLint error,
69 const char *command,
70 const LabeledObject *object,
71 const char *message)
72 {
73 mError = error;
74 if (error != EGL_SUCCESS && message)
75 {
76 EnsureDebugAllocated();
77 sDebug->insertMessage(error, command, ErrorCodeToMessageType(error), getLabel(),
78 object ? object->getLabel() : nullptr, message);
79 }
80 }
81
setError(const Error & error,const char * command,const LabeledObject * object)82 void Thread::setError(const Error &error, const char *command, const LabeledObject *object)
83 {
84 mError = error.getCode();
85 if (error.isError() && !error.getMessage().empty())
86 {
87 EnsureDebugAllocated();
88 sDebug->insertMessage(error.getCode(), command, ErrorCodeToMessageType(error.getCode()),
89 getLabel(), object ? object->getLabel() : nullptr,
90 error.getMessage());
91 }
92 }
93
getError() const94 EGLint Thread::getError() const
95 {
96 return mError;
97 }
98
setAPI(EGLenum api)99 void Thread::setAPI(EGLenum api)
100 {
101 mAPI = api;
102 }
103
getAPI() const104 EGLenum Thread::getAPI() const
105 {
106 return mAPI;
107 }
108
setCurrent(gl::Context * context)109 void Thread::setCurrent(gl::Context *context)
110 {
111 mContext = context;
112 }
113
getCurrentDrawSurface() const114 Surface *Thread::getCurrentDrawSurface() const
115 {
116 if (mContext)
117 {
118 return mContext->getCurrentDrawSurface();
119 }
120 return nullptr;
121 }
122
getCurrentReadSurface() const123 Surface *Thread::getCurrentReadSurface() const
124 {
125 if (mContext)
126 {
127 return mContext->getCurrentReadSurface();
128 }
129 return nullptr;
130 }
131
getContext() const132 gl::Context *Thread::getContext() const
133 {
134 return mContext;
135 }
136
getDisplay() const137 Display *Thread::getDisplay() const
138 {
139 if (mContext)
140 {
141 return mContext->getDisplay();
142 }
143 return nullptr;
144 }
145
EnsureDebugAllocated()146 void EnsureDebugAllocated()
147 {
148 // All EGL calls use a global lock, this is thread safe
149 if (sDebug == nullptr)
150 {
151 sDebug = new Debug();
152 }
153 }
154
DeallocateDebug()155 void DeallocateDebug()
156 {
157 SafeDelete(sDebug);
158 }
159
GetDebug()160 Debug *GetDebug()
161 {
162 EnsureDebugAllocated();
163 return sDebug;
164 }
165 } // namespace egl
166