1 //
2 // Copyright 2020 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 // egl_stubs.cpp: Stubs for EGL entry points.
7 //
8
9 #include "libGLESv2/egl_stubs_autogen.h"
10
11 #include "common/angle_version.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/EGLSync.h"
15 #include "libANGLE/Surface.h"
16 #include "libANGLE/Thread.h"
17 #include "libANGLE/queryutils.h"
18 #include "libANGLE/validationEGL.h"
19 #include "libGLESv2/global_state.h"
20 #include "libGLESv2/proc_table_egl.h"
21
22 namespace egl
23 {
24 namespace
25 {
26
CompareProc(const ProcEntry & a,const char * b)27 bool CompareProc(const ProcEntry &a, const char *b)
28 {
29 return strcmp(a.first, b) < 0;
30 }
31
ClipConfigs(const std::vector<const Config * > & filteredConfigs,EGLConfig * outputConfigs,EGLint configSize,EGLint * numConfigs)32 void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
33 EGLConfig *outputConfigs,
34 EGLint configSize,
35 EGLint *numConfigs)
36 {
37 EGLint resultSize = static_cast<EGLint>(filteredConfigs.size());
38 if (outputConfigs)
39 {
40 resultSize = std::max(std::min(resultSize, configSize), 0);
41 for (EGLint i = 0; i < resultSize; i++)
42 {
43 outputConfigs[i] = const_cast<Config *>(filteredConfigs[i]);
44 }
45 }
46 *numConfigs = resultSize;
47 }
48 } // anonymous namespace
49
BindAPI(Thread * thread,EGLenum api)50 EGLBoolean BindAPI(Thread *thread, EGLenum api)
51 {
52 thread->setAPI(api);
53
54 thread->setSuccess();
55 return EGL_TRUE;
56 }
57
BindTexImage(Thread * thread,Display * display,Surface * eglSurface,EGLint buffer)58 EGLBoolean BindTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer)
59 {
60 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglBindTexImage",
61 GetDisplayIfValid(display), EGL_FALSE);
62
63 gl::Context *context = thread->getContext();
64 if (context)
65 {
66 gl::TextureType type =
67 egl_gl::EGLTextureTargetToTextureType(eglSurface->getTextureTarget());
68 gl::Texture *textureObject = context->getTextureByType(type);
69 ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer),
70 "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
71 }
72
73 thread->setSuccess();
74 return EGL_TRUE;
75 }
76
ChooseConfig(Thread * thread,Display * display,const AttributeMap & attribMap,EGLConfig * configs,EGLint config_size,EGLint * num_config)77 EGLBoolean ChooseConfig(Thread *thread,
78 Display *display,
79 const AttributeMap &attribMap,
80 EGLConfig *configs,
81 EGLint config_size,
82 EGLint *num_config)
83 {
84 ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config);
85
86 thread->setSuccess();
87 return EGL_TRUE;
88 }
89
ClientWaitSync(Thread * thread,Display * display,Sync * syncObject,EGLint flags,EGLTime timeout)90 EGLint ClientWaitSync(Thread *thread,
91 Display *display,
92 Sync *syncObject,
93 EGLint flags,
94 EGLTime timeout)
95 {
96 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync",
97 GetDisplayIfValid(display), EGL_FALSE);
98 gl::Context *currentContext = thread->getContext();
99 EGLint syncStatus = EGL_FALSE;
100 ANGLE_EGL_TRY_RETURN(
101 thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus),
102 "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
103
104 thread->setSuccess();
105 return syncStatus;
106 }
107
CopyBuffers(Thread * thread,Display * display,Surface * eglSurface,EGLNativePixmapType target)108 EGLBoolean CopyBuffers(Thread *thread,
109 Display *display,
110 Surface *eglSurface,
111 EGLNativePixmapType target)
112 {
113 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCopyBuffers",
114 GetDisplayIfValid(display), EGL_FALSE);
115 UNIMPLEMENTED(); // FIXME
116
117 thread->setSuccess();
118 return 0;
119 }
120
CreateContext(Thread * thread,Display * display,Config * configuration,gl::Context * sharedGLContext,const AttributeMap & attributes)121 EGLContext CreateContext(Thread *thread,
122 Display *display,
123 Config *configuration,
124 gl::Context *sharedGLContext,
125 const AttributeMap &attributes)
126 {
127 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateContext",
128 GetDisplayIfValid(display), EGL_NO_CONTEXT);
129 gl::Context *context = nullptr;
130 ANGLE_EGL_TRY_RETURN(thread,
131 display->createContext(configuration, sharedGLContext, thread->getAPI(),
132 attributes, &context),
133 "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT);
134
135 thread->setSuccess();
136 return static_cast<EGLContext>(context);
137 }
138
CreateImage(Thread * thread,Display * display,gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)139 EGLImage CreateImage(Thread *thread,
140 Display *display,
141 gl::Context *context,
142 EGLenum target,
143 EGLClientBuffer buffer,
144 const AttributeMap &attributes)
145 {
146 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImage",
147 GetDisplayIfValid(display), EGL_FALSE);
148
149 Image *image = nullptr;
150 Error error = display->createImage(context, target, buffer, attributes, &image);
151 if (error.isError())
152 {
153 thread->setError(error, "eglCreateImage", GetDisplayIfValid(display));
154 return EGL_NO_IMAGE;
155 }
156
157 thread->setSuccess();
158 return static_cast<EGLImage>(image);
159 }
160
CreatePbufferFromClientBuffer(Thread * thread,Display * display,EGLenum buftype,EGLClientBuffer buffer,Config * configuration,const AttributeMap & attributes)161 EGLSurface CreatePbufferFromClientBuffer(Thread *thread,
162 Display *display,
163 EGLenum buftype,
164 EGLClientBuffer buffer,
165 Config *configuration,
166 const AttributeMap &attributes)
167 {
168 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferFromClientBuffer",
169 GetDisplayIfValid(display), EGL_NO_SURFACE);
170 Surface *surface = nullptr;
171 ANGLE_EGL_TRY_RETURN(thread,
172 display->createPbufferFromClientBuffer(configuration, buftype, buffer,
173 attributes, &surface),
174 "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display),
175 EGL_NO_SURFACE);
176
177 return static_cast<EGLSurface>(surface);
178 }
179
CreatePbufferSurface(Thread * thread,Display * display,Config * configuration,const AttributeMap & attributes)180 EGLSurface CreatePbufferSurface(Thread *thread,
181 Display *display,
182 Config *configuration,
183 const AttributeMap &attributes)
184 {
185 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferSurface",
186 GetDisplayIfValid(display), EGL_NO_SURFACE);
187 Surface *surface = nullptr;
188 ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface),
189 "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
190
191 return static_cast<EGLSurface>(surface);
192 }
193
CreatePixmapSurface(Thread * thread,Display * display,Config * configuration,EGLNativePixmapType pixmap,const AttributeMap & attributes)194 EGLSurface CreatePixmapSurface(Thread *thread,
195 Display *display,
196 Config *configuration,
197 EGLNativePixmapType pixmap,
198 const AttributeMap &attributes)
199 {
200 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePixmapSurface",
201 GetDisplayIfValid(display), EGL_NO_SURFACE);
202 Surface *surface = nullptr;
203 ANGLE_EGL_TRY_RETURN(thread,
204 display->createPixmapSurface(configuration, pixmap, attributes, &surface),
205 "eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
206
207 thread->setSuccess();
208 return static_cast<EGLSurface>(surface);
209 }
210
CreatePlatformPixmapSurface(Thread * thread,Display * display,Config * configuration,void * pixmap,const AttributeMap & attributes)211 EGLSurface CreatePlatformPixmapSurface(Thread *thread,
212 Display *display,
213 Config *configuration,
214 void *pixmap,
215 const AttributeMap &attributes)
216 {
217 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurface",
218 GetDisplayIfValid(display), EGL_NO_SURFACE);
219 Surface *surface = nullptr;
220 EGLNativePixmapType nativePixmap = reinterpret_cast<EGLNativePixmapType>(pixmap);
221 ANGLE_EGL_TRY_RETURN(
222 thread, display->createPixmapSurface(configuration, nativePixmap, attributes, &surface),
223 "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
224
225 thread->setSuccess();
226 return static_cast<EGLSurface>(surface);
227 }
228
CreatePlatformWindowSurface(Thread * thread,Display * display,Config * configuration,void * win,const AttributeMap & attributes)229 EGLSurface CreatePlatformWindowSurface(Thread *thread,
230 Display *display,
231 Config *configuration,
232 void *win,
233 const AttributeMap &attributes)
234 {
235 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurface",
236 GetDisplayIfValid(display), EGL_NO_SURFACE);
237 Surface *surface = nullptr;
238 EGLNativeWindowType nativeWindow = reinterpret_cast<EGLNativeWindowType>(win);
239 ANGLE_EGL_TRY_RETURN(
240 thread, display->createWindowSurface(configuration, nativeWindow, attributes, &surface),
241 "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
242
243 return static_cast<EGLSurface>(surface);
244 }
245
CreateSync(Thread * thread,Display * display,EGLenum type,const AttributeMap & attributes)246 EGLSync CreateSync(Thread *thread, Display *display, EGLenum type, const AttributeMap &attributes)
247 {
248 gl::Context *currentContext = thread->getContext();
249
250 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync",
251 GetDisplayIfValid(display), EGL_FALSE);
252 Sync *syncObject = nullptr;
253 ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
254 "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
255
256 thread->setSuccess();
257 return static_cast<EGLSync>(syncObject);
258 }
259
CreateWindowSurface(Thread * thread,Display * display,Config * configuration,EGLNativeWindowType win,const AttributeMap & attributes)260 EGLSurface CreateWindowSurface(Thread *thread,
261 Display *display,
262 Config *configuration,
263 EGLNativeWindowType win,
264 const AttributeMap &attributes)
265 {
266 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface",
267 GetDisplayIfValid(display), EGL_NO_SURFACE);
268
269 Surface *surface = nullptr;
270 ANGLE_EGL_TRY_RETURN(thread,
271 display->createWindowSurface(configuration, win, attributes, &surface),
272 "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
273
274 return static_cast<EGLSurface>(surface);
275 }
276
DestroyContext(Thread * thread,Display * display,gl::Context * context)277 EGLBoolean DestroyContext(Thread *thread, Display *display, gl::Context *context)
278 {
279 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyContext",
280 GetDisplayIfValid(display), EGL_FALSE);
281
282 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
283
284 ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext",
285 GetContextIfValid(display, context), EGL_FALSE);
286 thread->setSuccess();
287 return EGL_TRUE;
288 }
289
DestroyImage(Thread * thread,Display * display,Image * img)290 EGLBoolean DestroyImage(Thread *thread, Display *display, Image *img)
291 {
292 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImage",
293 GetDisplayIfValid(display), EGL_FALSE);
294 display->destroyImage(img);
295
296 thread->setSuccess();
297 return EGL_TRUE;
298 }
299
DestroySurface(Thread * thread,Display * display,Surface * eglSurface)300 EGLBoolean DestroySurface(Thread *thread, Display *display, Surface *eglSurface)
301 {
302 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySurface",
303 GetDisplayIfValid(display), EGL_FALSE);
304 ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface",
305 GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
306
307 thread->setSuccess();
308 return EGL_TRUE;
309 }
310
DestroySync(Thread * thread,Display * display,Sync * syncObject)311 EGLBoolean DestroySync(Thread *thread, Display *display, Sync *syncObject)
312 {
313 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync",
314 GetDisplayIfValid(display), EGL_FALSE);
315 display->destroySync(syncObject);
316
317 thread->setSuccess();
318 return EGL_TRUE;
319 }
320
GetConfigAttrib(Thread * thread,Display * display,Config * configuration,EGLint attribute,EGLint * value)321 EGLBoolean GetConfigAttrib(Thread *thread,
322 Display *display,
323 Config *configuration,
324 EGLint attribute,
325 EGLint *value)
326 {
327 QueryConfigAttrib(configuration, attribute, value);
328
329 thread->setSuccess();
330 return EGL_TRUE;
331 }
332
GetConfigs(Thread * thread,Display * display,EGLConfig * configs,EGLint config_size,EGLint * num_config)333 EGLBoolean GetConfigs(Thread *thread,
334 Display *display,
335 EGLConfig *configs,
336 EGLint config_size,
337 EGLint *num_config)
338 {
339 ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
340
341 thread->setSuccess();
342 return EGL_TRUE;
343 }
344
GetCurrentContext(Thread * thread)345 EGLContext GetCurrentContext(Thread *thread)
346 {
347 gl::Context *context = thread->getContext();
348
349 thread->setSuccess();
350 return static_cast<EGLContext>(context);
351 }
352
GetCurrentDisplay(Thread * thread)353 EGLDisplay GetCurrentDisplay(Thread *thread)
354 {
355 thread->setSuccess();
356 if (thread->getContext() != nullptr)
357 {
358 return thread->getContext()->getDisplay();
359 }
360 return EGL_NO_DISPLAY;
361 }
362
GetCurrentSurface(Thread * thread,EGLint readdraw)363 EGLSurface GetCurrentSurface(Thread *thread, EGLint readdraw)
364 {
365 if (readdraw == EGL_READ)
366 {
367 thread->setSuccess();
368 return thread->getCurrentReadSurface();
369 }
370 else if (readdraw == EGL_DRAW)
371 {
372 thread->setSuccess();
373 return thread->getCurrentDrawSurface();
374 }
375 else
376 {
377 thread->setError(EglBadParameter(), "eglGetCurrentSurface", nullptr);
378 return EGL_NO_SURFACE;
379 }
380 }
381
GetDisplay(Thread * thread,EGLNativeDisplayType display_id)382 EGLDisplay GetDisplay(Thread *thread, EGLNativeDisplayType display_id)
383 {
384 return Display::GetDisplayFromNativeDisplay(display_id, AttributeMap());
385 }
386
GetError(Thread * thread)387 EGLint GetError(Thread *thread)
388 {
389 EGLint error = thread->getError();
390 thread->setSuccess();
391 return error;
392 }
393
GetPlatformDisplay(Thread * thread,EGLenum platform,void * native_display,const AttributeMap & attribMap)394 EGLDisplay GetPlatformDisplay(Thread *thread,
395 EGLenum platform,
396 void *native_display,
397 const AttributeMap &attribMap)
398 {
399 if (platform == EGL_PLATFORM_ANGLE_ANGLE)
400 {
401 return Display::GetDisplayFromNativeDisplay(
402 gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
403 }
404 else if (platform == EGL_PLATFORM_DEVICE_EXT)
405 {
406 Device *eglDevice = static_cast<Device *>(native_display);
407 return Display::GetDisplayFromDevice(eglDevice, attribMap);
408 }
409 else
410 {
411 UNREACHABLE();
412 return EGL_NO_DISPLAY;
413 }
414 }
415
GetProcAddress(Thread * thread,const char * procname)416 __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname)
417 {
418 const ProcEntry *entry =
419 std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc);
420
421 thread->setSuccess();
422
423 if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0)
424 {
425 return nullptr;
426 }
427
428 return entry->second;
429 }
430
GetSyncAttrib(Thread * thread,Display * display,Sync * syncObject,EGLint attribute,EGLAttrib * value)431 EGLBoolean GetSyncAttrib(Thread *thread,
432 Display *display,
433 Sync *syncObject,
434 EGLint attribute,
435 EGLAttrib *value)
436 {
437 EGLint valueExt;
438 ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, &valueExt),
439 "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
440 *value = valueExt;
441
442 thread->setSuccess();
443 return EGL_TRUE;
444 }
445
Initialize(Thread * thread,Display * display,EGLint * major,EGLint * minor)446 EGLBoolean Initialize(Thread *thread, Display *display, EGLint *major, EGLint *minor)
447 {
448 ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display),
449 EGL_FALSE);
450
451 if (major)
452 *major = 1;
453 if (minor)
454 *minor = 5;
455
456 thread->setSuccess();
457 return EGL_TRUE;
458 }
459
MakeCurrent(Thread * thread,Display * display,Surface * drawSurface,Surface * readSurface,gl::Context * context)460 EGLBoolean MakeCurrent(Thread *thread,
461 Display *display,
462 Surface *drawSurface,
463 Surface *readSurface,
464 gl::Context *context)
465 {
466 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglMakeCurrent",
467 GetDisplayIfValid(display), EGL_FALSE);
468 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
469
470 Surface *previousDraw = thread->getCurrentDrawSurface();
471 Surface *previousRead = thread->getCurrentReadSurface();
472 gl::Context *previousContext = thread->getContext();
473
474 // Only call makeCurrent if the context or surfaces have changed.
475 if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context)
476 {
477 ANGLE_EGL_TRY_RETURN(
478 thread,
479 display->makeCurrent(thread, previousContext, drawSurface, readSurface, context),
480 "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
481 }
482
483 thread->setSuccess();
484 return EGL_TRUE;
485 }
486
QueryAPI(Thread * thread)487 EGLenum QueryAPI(Thread *thread)
488 {
489 EGLenum API = thread->getAPI();
490
491 thread->setSuccess();
492 return API;
493 }
494
QueryContext(Thread * thread,Display * display,gl::Context * context,EGLint attribute,EGLint * value)495 EGLBoolean QueryContext(Thread *thread,
496 Display *display,
497 gl::Context *context,
498 EGLint attribute,
499 EGLint *value)
500 {
501 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryContext",
502 GetDisplayIfValid(display), EGL_FALSE);
503 QueryContextAttrib(context, attribute, value);
504
505 thread->setSuccess();
506 return EGL_TRUE;
507 }
508
QueryString(Thread * thread,Display * display,EGLint name)509 const char *QueryString(Thread *thread, Display *display, EGLint name)
510 {
511 if (display)
512 {
513 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryString",
514 GetDisplayIfValid(display), nullptr);
515 }
516
517 const char *result = nullptr;
518 switch (name)
519 {
520 case EGL_CLIENT_APIS:
521 result = "OpenGL_ES";
522 break;
523 case EGL_EXTENSIONS:
524 if (display == EGL_NO_DISPLAY)
525 {
526 result = Display::GetClientExtensionString().c_str();
527 }
528 else
529 {
530 result = display->getExtensionString().c_str();
531 }
532 break;
533 case EGL_VENDOR:
534 result = display->getVendorString().c_str();
535 break;
536 case EGL_VERSION:
537 result = "1.5 (ANGLE " ANGLE_VERSION_STRING ")";
538 break;
539 default:
540 UNREACHABLE();
541 break;
542 }
543
544 thread->setSuccess();
545 return result;
546 }
547
QuerySurface(Thread * thread,Display * display,Surface * eglSurface,EGLint attribute,EGLint * value)548 EGLBoolean QuerySurface(Thread *thread,
549 Display *display,
550 Surface *eglSurface,
551 EGLint attribute,
552 EGLint *value)
553 {
554 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface",
555 GetDisplayIfValid(display), EGL_FALSE);
556 ANGLE_EGL_TRY_RETURN(
557 thread, QuerySurfaceAttrib(display, thread->getContext(), eglSurface, attribute, value),
558 "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
559
560 thread->setSuccess();
561 return EGL_TRUE;
562 }
563
ReleaseTexImage(Thread * thread,Display * display,Surface * eglSurface,EGLint buffer)564 EGLBoolean ReleaseTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer)
565 {
566 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage",
567 GetDisplayIfValid(display), EGL_FALSE);
568 gl::Texture *texture = eglSurface->getBoundTexture();
569
570 if (texture)
571 {
572 ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer),
573 "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface),
574 EGL_FALSE);
575 }
576
577 thread->setSuccess();
578 return EGL_TRUE;
579 }
580
ReleaseThread(Thread * thread)581 EGLBoolean ReleaseThread(Thread *thread)
582 {
583 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
584
585 Surface *previousDraw = thread->getCurrentDrawSurface();
586 Surface *previousRead = thread->getCurrentReadSurface();
587 gl::Context *previousContext = thread->getContext();
588 Display *previousDisplay = thread->getDisplay();
589
590 if (previousDisplay != EGL_NO_DISPLAY)
591 {
592 ANGLE_EGL_TRY_RETURN(thread, previousDisplay->prepareForCall(), "eglReleaseThread",
593 GetDisplayIfValid(previousDisplay), EGL_FALSE);
594 // Only call makeCurrent if the context or surfaces have changed.
595 if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE ||
596 previousContext != EGL_NO_CONTEXT)
597 {
598 ANGLE_EGL_TRY_RETURN(
599 thread,
600 previousDisplay->makeCurrent(thread, previousContext, nullptr, nullptr, nullptr),
601 "eglReleaseThread", nullptr, EGL_FALSE);
602 }
603 ANGLE_EGL_TRY_RETURN(thread, previousDisplay->releaseThread(), "eglReleaseThread",
604 GetDisplayIfValid(previousDisplay), EGL_FALSE);
605 }
606
607 thread->setSuccess();
608 return EGL_TRUE;
609 }
610
SurfaceAttrib(Thread * thread,Display * display,Surface * eglSurface,EGLint attribute,EGLint value)611 EGLBoolean SurfaceAttrib(Thread *thread,
612 Display *display,
613 Surface *eglSurface,
614 EGLint attribute,
615 EGLint value)
616 {
617 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSurfaceAttrib",
618 GetDisplayIfValid(display), EGL_FALSE);
619 SetSurfaceAttrib(eglSurface, attribute, value);
620
621 thread->setSuccess();
622 return EGL_TRUE;
623 }
624
SwapBuffers(Thread * thread,Display * display,Surface * eglSurface)625 EGLBoolean SwapBuffers(Thread *thread, Display *display, Surface *eglSurface)
626 {
627 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffers",
628 GetDisplayIfValid(display), EGL_FALSE);
629
630 ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers",
631 GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
632
633 thread->setSuccess();
634 return EGL_TRUE;
635 }
636
SwapInterval(Thread * thread,Display * display,EGLint interval)637 EGLBoolean SwapInterval(Thread *thread, Display *display, EGLint interval)
638 {
639 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapInterval",
640 GetDisplayIfValid(display), EGL_FALSE);
641
642 Surface *drawSurface = static_cast<Surface *>(thread->getCurrentDrawSurface());
643 const Config *surfaceConfig = drawSurface->getConfig();
644 EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval),
645 surfaceConfig->maxSwapInterval);
646
647 drawSurface->setSwapInterval(clampedInterval);
648
649 thread->setSuccess();
650 return EGL_TRUE;
651 }
652
Terminate(Thread * thread,Display * display)653 EGLBoolean Terminate(Thread *thread, Display *display)
654 {
655 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglTerminate",
656 GetDisplayIfValid(display), EGL_FALSE);
657
658 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
659
660 ANGLE_EGL_TRY_RETURN(
661 thread, display->makeCurrent(thread, thread->getContext(), nullptr, nullptr, nullptr),
662 "eglTerminate", GetDisplayIfValid(display), EGL_FALSE);
663 ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate",
664 GetDisplayIfValid(display), EGL_FALSE);
665
666 thread->setSuccess();
667 return EGL_TRUE;
668 }
669
WaitClient(Thread * thread)670 EGLBoolean WaitClient(Thread *thread)
671 {
672 Display *display = thread->getDisplay();
673 if (display == nullptr)
674 {
675 // EGL spec says this about eglWaitClient -
676 // If there is no current context for the current rendering API,
677 // the function has no effect but still returns EGL_TRUE.
678 return EGL_TRUE;
679 }
680
681 gl::Context *context = thread->getContext();
682
683 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitClient",
684 GetDisplayIfValid(display), EGL_FALSE);
685 ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient",
686 GetContextIfValid(display, context), EGL_FALSE);
687
688 thread->setSuccess();
689 return EGL_TRUE;
690 }
691
WaitGL(Thread * thread)692 EGLBoolean WaitGL(Thread *thread)
693 {
694 Display *display = thread->getDisplay();
695 if (display == nullptr)
696 {
697 // EGL spec says this about eglWaitGL -
698 // eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
699 return EGL_TRUE;
700 }
701
702 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitGL", GetDisplayIfValid(display),
703 EGL_FALSE);
704
705 // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
706 // OpenGL ES we can do the call directly.
707 ANGLE_EGL_TRY_RETURN(thread, display->waitClient(thread->getContext()), "eglWaitGL",
708 GetDisplayIfValid(display), EGL_FALSE);
709
710 thread->setSuccess();
711 return EGL_TRUE;
712 }
713
WaitNative(Thread * thread,EGLint engine)714 EGLBoolean WaitNative(Thread *thread, EGLint engine)
715 {
716 Display *display = thread->getDisplay();
717 if (display == nullptr)
718 {
719 // EGL spec says this about eglWaitNative -
720 // eglWaitNative is ignored if there is no current EGL rendering context.
721 return EGL_TRUE;
722 }
723
724 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitNative",
725 GetDisplayIfValid(display), EGL_FALSE);
726 ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative",
727 GetThreadIfValid(thread), EGL_FALSE);
728
729 thread->setSuccess();
730 return EGL_TRUE;
731 }
732
WaitSync(Thread * thread,Display * display,Sync * syncObject,EGLint flags)733 EGLBoolean WaitSync(Thread *thread, Display *display, Sync *syncObject, EGLint flags)
734 {
735 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync",
736 GetDisplayIfValid(display), EGL_FALSE);
737 gl::Context *currentContext = thread->getContext();
738 ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
739 "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
740
741 thread->setSuccess();
742 return EGL_TRUE;
743 }
744 } // namespace egl
745