• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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