1 #include "libeglcurrent.h"
2
3 #include "glvnd_pthread.h"
4 #include "lkdhash.h"
5
6 static void OnDispatchThreadDestroyed(__GLdispatchThreadState *state);
7 static void OnThreadDestroyed(void *data);
8
9 static __EGLThreadAPIState *CreateThreadState(void);
10 static void DestroyThreadState(__EGLThreadAPIState *threadState);
11
12 /**
13 * A list of current __EGLdispatchThreadState structures. This is used so that we can
14 * clean up at process termination or after a fork.
15 */
16 static struct glvnd_list currentAPIStateList;
17 static struct glvnd_list currentThreadStateList;
18 static glvnd_mutex_t currentStateListMutex = PTHREAD_MUTEX_INITIALIZER;
19 static glvnd_key_t threadStateKey;
20
__eglQueryAPI(void)21 EGLenum __eglQueryAPI(void)
22 {
23 __EGLThreadAPIState *state = __eglGetCurrentThreadAPIState(EGL_FALSE);
24 if (state != NULL) {
25 return state->currentClientApi;
26 } else {
27 // FIXME: If none of the vendor libraries support GLES, then this
28 // should be EGL_NONE.
29 return EGL_OPENGL_ES_API;
30 }
31 }
32
__eglGetCurrentVendor(void)33 __EGLvendorInfo *__eglGetCurrentVendor(void)
34 {
35 __EGLdispatchThreadState *state = __eglGetCurrentAPIState();
36 if (state != NULL) {
37 return state->currentVendor;
38 } else {
39 return NULL;
40 }
41 }
42
__eglGetCurrentContext(void)43 EGLContext __eglGetCurrentContext(void)
44 {
45 __EGLdispatchThreadState *state = __eglGetCurrentAPIState();
46 if (state != NULL) {
47 return state->currentContext;
48 } else {
49 return EGL_NO_CONTEXT;
50 }
51 }
52
__eglGetCurrentDisplay(void)53 EGLDisplay __eglGetCurrentDisplay(void)
54 {
55 __EGLdispatchThreadState *state = __eglGetCurrentAPIState();
56 if (state != NULL && state->currentDisplay != NULL) {
57 return state->currentDisplay->dpy;
58 } else {
59 return EGL_NO_DISPLAY;
60 }
61 }
62
__eglGetCurrentSurface(EGLint readDraw)63 EGLSurface __eglGetCurrentSurface(EGLint readDraw)
64 {
65 __EGLdispatchThreadState *state = __eglGetCurrentAPIState();
66 if (state != NULL) {
67 if (readDraw == EGL_DRAW) {
68 return state->currentDraw;
69 } else if (readDraw == EGL_READ) {
70 return state->currentRead;
71 } else {
72 return EGL_NO_SURFACE;
73 }
74 } else {
75 return EGL_NO_SURFACE;
76 }
77 }
78
__eglCurrentInit(void)79 void __eglCurrentInit(void)
80 {
81 glvnd_list_init(¤tAPIStateList);
82 glvnd_list_init(¤tThreadStateList);
83 __glvndPthreadFuncs.key_create(&threadStateKey, OnThreadDestroyed);
84 }
85
__eglCurrentTeardown(EGLBoolean doReset)86 void __eglCurrentTeardown(EGLBoolean doReset)
87 {
88 while (!glvnd_list_is_empty(¤tAPIStateList)) {
89 __EGLdispatchThreadState *apiState = glvnd_list_first_entry(
90 ¤tAPIStateList, __EGLdispatchThreadState, entry);
91 __eglDestroyAPIState(apiState);
92 }
93
94 while (!glvnd_list_is_empty(¤tThreadStateList)) {
95 __EGLThreadAPIState *threadState = glvnd_list_first_entry(
96 ¤tThreadStateList, __EGLThreadAPIState, entry);
97 DestroyThreadState(threadState);
98 }
99
100 if (doReset) {
101 __glvndPthreadFuncs.mutex_init(¤tStateListMutex, NULL);
102 }
103 }
104
CreateThreadState(void)105 __EGLThreadAPIState *CreateThreadState(void)
106 {
107 __EGLThreadAPIState *threadState = calloc(1, sizeof(__EGLThreadAPIState));
108 if (threadState == NULL) {
109 return NULL;
110 }
111
112 threadState->lastError = EGL_SUCCESS;
113 threadState->lastVendor = NULL;
114
115 // TODO: If no vendor library supports GLES, then we should initialize this
116 // to EGL_NONE.
117 threadState->currentClientApi = EGL_OPENGL_ES_API;
118
119 __glvndPthreadFuncs.mutex_lock(¤tStateListMutex);
120 glvnd_list_add(&threadState->entry, ¤tThreadStateList);
121 __glvndPthreadFuncs.mutex_unlock(¤tStateListMutex);
122
123 __glvndPthreadFuncs.setspecific(threadStateKey, threadState);
124 return threadState;
125 }
126
__eglGetCurrentThreadAPIState(EGLBoolean create)127 __EGLThreadAPIState *__eglGetCurrentThreadAPIState(EGLBoolean create)
128 {
129 __EGLThreadAPIState *threadState = (__EGLThreadAPIState *) __glvndPthreadFuncs.getspecific(threadStateKey);
130 if (threadState == NULL && create) {
131 threadState = CreateThreadState();
132 }
133 return threadState;
134 }
135
DestroyThreadState(__EGLThreadAPIState * threadState)136 void DestroyThreadState(__EGLThreadAPIState *threadState)
137 {
138 if (threadState != NULL) {
139 __glvndPthreadFuncs.mutex_lock(¤tStateListMutex);
140 glvnd_list_del(&threadState->entry);
141 __glvndPthreadFuncs.mutex_unlock(¤tStateListMutex);
142
143 free(threadState);
144 }
145 }
146
__eglDestroyCurrentThreadAPIState(void)147 void __eglDestroyCurrentThreadAPIState(void)
148 {
149 __EGLThreadAPIState *threadState = __glvndPthreadFuncs.getspecific(threadStateKey);
150 if (threadState != NULL) {
151 __glvndPthreadFuncs.setspecific(threadStateKey, NULL);
152 DestroyThreadState(threadState);
153 }
154 }
155
OnThreadDestroyed(void * data)156 void OnThreadDestroyed(void *data)
157 {
158 __EGLThreadAPIState *threadState = (__EGLThreadAPIState *) data;
159 DestroyThreadState(threadState);
160 }
161
__eglCreateAPIState(void)162 __EGLdispatchThreadState *__eglCreateAPIState(void)
163 {
164 __EGLdispatchThreadState *apiState = calloc(1, sizeof(__EGLdispatchThreadState));
165 if (apiState == NULL) {
166 return NULL;
167 }
168
169 apiState->glas.tag = GLDISPATCH_API_EGL;
170 apiState->glas.threadDestroyedCallback = OnDispatchThreadDestroyed;
171
172 apiState->currentDisplay = NULL;
173 apiState->currentDraw = EGL_NO_SURFACE;
174 apiState->currentRead = EGL_NO_SURFACE;
175 apiState->currentContext = EGL_NO_CONTEXT;
176 apiState->currentVendor = NULL;
177
178 __glvndPthreadFuncs.mutex_lock(¤tStateListMutex);
179 glvnd_list_add(&apiState->entry, ¤tAPIStateList);
180 __glvndPthreadFuncs.mutex_unlock(¤tStateListMutex);
181
182 return apiState;
183 }
184
__eglDestroyAPIState(__EGLdispatchThreadState * apiState)185 void __eglDestroyAPIState(__EGLdispatchThreadState *apiState)
186 {
187 if (apiState != NULL) {
188 __glvndPthreadFuncs.mutex_lock(¤tStateListMutex);
189 glvnd_list_del(&apiState->entry);
190 __glvndPthreadFuncs.mutex_unlock(¤tStateListMutex);
191
192 free(apiState);
193 }
194 }
195
OnDispatchThreadDestroyed(__GLdispatchThreadState * state)196 void OnDispatchThreadDestroyed(__GLdispatchThreadState *state)
197 {
198 __EGLdispatchThreadState *eglState = (__EGLdispatchThreadState *) state;
199 __eglDestroyAPIState(eglState);
200 }
201
202