1 //
2 // Copyright 2014 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 // entry_points_ext.cpp : Implements the EGL extension entry points.
8 
9 #include "libGLESv2/entry_points_egl_ext.h"
10 
11 #include "common/debug.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Device.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/EGLSync.h"
16 #include "libANGLE/Stream.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/Thread.h"
19 #include "libANGLE/entry_points_utils.h"
20 #include "libANGLE/queryutils.h"
21 #include "libANGLE/validationEGL.h"
22 #include "libGLESv2/global_state.h"
23 
24 using namespace egl;
25 
26 extern "C" {
27 
28 // EGL_ANGLE_query_surface_pointer
EGL_QuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)29 EGLBoolean EGLAPIENTRY EGL_QuerySurfacePointerANGLE(EGLDisplay dpy,
30                                                     EGLSurface surface,
31                                                     EGLint attribute,
32                                                     void **value)
33 {
34     ANGLE_SCOPED_GLOBAL_LOCK();
35     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
36                ", EGLint attribute = %d, void "
37                "**value = 0x%016" PRIxPTR,
38                (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value);
39     Thread *thread = egl::GetCurrentThread();
40 
41     egl::Display *display = static_cast<egl::Display *>(dpy);
42     Surface *eglSurface   = static_cast<Surface *>(surface);
43 
44     Error error = ValidateSurface(display, eglSurface);
45     if (error.isError())
46     {
47         thread->setError(error, GetDebug(), "eglQuerySurfacePointerANGLE",
48                          GetSurfaceIfValid(display, eglSurface));
49         return EGL_FALSE;
50     }
51 
52     if (!display->getExtensions().querySurfacePointer)
53     {
54         thread->setSuccess();
55         return EGL_FALSE;
56     }
57 
58     if (surface == EGL_NO_SURFACE)
59     {
60         thread->setError(EglBadSurface(), GetDebug(), "eglQuerySurfacePointerANGLE",
61                          GetSurfaceIfValid(display, eglSurface));
62         return EGL_FALSE;
63     }
64 
65     // validate the attribute parameter
66     switch (attribute)
67     {
68         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
69             if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
70             {
71                 thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
72                                  GetSurfaceIfValid(display, eglSurface));
73                 return EGL_FALSE;
74             }
75             break;
76         case EGL_DXGI_KEYED_MUTEX_ANGLE:
77             if (!display->getExtensions().keyedMutex)
78             {
79                 thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
80                                  GetSurfaceIfValid(display, eglSurface));
81                 return EGL_FALSE;
82             }
83             break;
84         default:
85             thread->setError(EglBadAttribute(), GetDebug(), "eglQuerySurfacePointerANGLE",
86                              GetSurfaceIfValid(display, eglSurface));
87             return EGL_FALSE;
88     }
89     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurfacePointerANGLE",
90                          GetDisplayIfValid(display), EGL_FALSE);
91     error = eglSurface->querySurfacePointerANGLE(attribute, value);
92     if (error.isError())
93     {
94         thread->setError(error, GetDebug(), "eglQuerySurfacePointerANGLE",
95                          GetSurfaceIfValid(display, eglSurface));
96         return EGL_FALSE;
97     }
98 
99     thread->setSuccess();
100     return EGL_TRUE;
101 }
102 
103 // EGL_NV_post_sub_buffer
EGL_PostSubBufferNV(EGLDisplay dpy,EGLSurface surface,EGLint x,EGLint y,EGLint width,EGLint height)104 EGLBoolean EGLAPIENTRY EGL_PostSubBufferNV(EGLDisplay dpy,
105                                            EGLSurface surface,
106                                            EGLint x,
107                                            EGLint y,
108                                            EGLint width,
109                                            EGLint height)
110 {
111     ANGLE_SCOPED_GLOBAL_LOCK();
112     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
113                ", EGLint x = %d, EGLint y = %d, "
114                "EGLint width = %d, EGLint height = %d",
115                (uintptr_t)dpy, (uintptr_t)surface, x, y, width, height);
116     Thread *thread        = egl::GetCurrentThread();
117     egl::Display *display = static_cast<egl::Display *>(dpy);
118     Surface *eglSurface   = static_cast<Surface *>(surface);
119 
120     if (x < 0 || y < 0 || width < 0 || height < 0)
121     {
122         thread->setError(EglBadParameter(), GetDebug(), "eglPostSubBufferNV",
123                          GetSurfaceIfValid(display, eglSurface));
124         return EGL_FALSE;
125     }
126 
127     Error error = ValidateSurface(display, eglSurface);
128     if (error.isError())
129     {
130         thread->setError(error, GetDebug(), "eglPostSubBufferNV",
131                          GetSurfaceIfValid(display, eglSurface));
132         return EGL_FALSE;
133     }
134 
135     if (display->testDeviceLost())
136     {
137         thread->setError(EglContextLost(), GetDebug(), "eglPostSubBufferNV",
138                          GetSurfaceIfValid(display, eglSurface));
139         return EGL_FALSE;
140     }
141 
142     if (surface == EGL_NO_SURFACE)
143     {
144         thread->setError(EglBadSurface(), GetDebug(), "eglPostSubBufferNV",
145                          GetSurfaceIfValid(display, eglSurface));
146         return EGL_FALSE;
147     }
148 
149     if (!display->getExtensions().postSubBuffer)
150     {
151         // Spec is not clear about how this should be handled.
152         thread->setSuccess();
153         return EGL_TRUE;
154     }
155     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglPostSubBufferNV",
156                          GetDisplayIfValid(display), EGL_FALSE);
157     // TODO(jmadill): Validate Surface is bound to the thread.
158     error = eglSurface->postSubBuffer(thread->getContext(), x, y, width, height);
159     if (error.isError())
160     {
161         thread->setError(error, GetDebug(), "eglPostSubBufferNV",
162                          GetSurfaceIfValid(display, eglSurface));
163         return EGL_FALSE;
164     }
165 
166     thread->setSuccess();
167     return EGL_TRUE;
168 }
169 
170 // EGL_EXT_platform_base
EGL_GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)171 EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplayEXT(EGLenum platform,
172                                                  void *native_display,
173                                                  const EGLint *attrib_list)
174 {
175     ANGLE_SCOPED_GLOBAL_LOCK();
176     FUNC_EVENT("EGLenum platform = %d, void* native_display = 0x%016" PRIxPTR
177                ", const EGLint* attrib_list = "
178                "0x%016" PRIxPTR,
179                platform, (uintptr_t)native_display, (uintptr_t)attrib_list);
180     Thread *thread = egl::GetCurrentThread();
181 
182     Error err = ValidateGetPlatformDisplayEXT(platform, native_display, attrib_list);
183     thread->setError(err, GetDebug(), "eglGetPlatformDisplayEXT", GetThreadIfValid(thread));
184     if (err.isError())
185     {
186         return EGL_NO_DISPLAY;
187     }
188 
189     const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
190     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
191     {
192         return egl::Display::GetDisplayFromNativeDisplay(
193             gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
194     }
195     else if (platform == EGL_PLATFORM_DEVICE_EXT)
196     {
197         Device *eglDevice = static_cast<Device *>(native_display);
198         return egl::Display::GetDisplayFromDevice(eglDevice, attribMap);
199     }
200     else
201     {
202         UNREACHABLE();
203         return EGL_NO_DISPLAY;
204     }
205 }
206 
EGL_CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)207 EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,
208                                                           EGLConfig config,
209                                                           void *native_window,
210                                                           const EGLint *attrib_list)
211 {
212     ANGLE_SCOPED_GLOBAL_LOCK();
213     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
214                ", void *native_window = 0x%016" PRIxPTR
215                ", "
216                "const EGLint *attrib_list = 0x%016" PRIxPTR,
217                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list);
218     Thread *thread = egl::GetCurrentThread();
219 
220     egl::Display *display   = static_cast<egl::Display *>(dpy);
221     Config *configuration   = static_cast<Config *>(config);
222     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
223 
224     ANGLE_EGL_TRY_RETURN(
225         thread,
226         ValidateCreatePlatformWindowSurfaceEXT(display, configuration, native_window, attributes),
227         "eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
228     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurfaceEXT",
229                          GetDisplayIfValid(display), EGL_NO_SURFACE);
230     thread->setError(EglBadDisplay() << "CreatePlatformWindowSurfaceEXT unimplemented.", GetDebug(),
231                      "eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display));
232     return EGL_NO_SURFACE;
233 }
234 
EGL_CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)235 EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,
236                                                           EGLConfig config,
237                                                           void *native_pixmap,
238                                                           const EGLint *attrib_list)
239 {
240     ANGLE_SCOPED_GLOBAL_LOCK();
241     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
242                ", void *native_pixmap = 0x%016" PRIxPTR
243                ", "
244                "const EGLint *attrib_list = 0x%016" PRIxPTR,
245                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list);
246     Thread *thread = egl::GetCurrentThread();
247 
248     egl::Display *display   = static_cast<egl::Display *>(dpy);
249     Config *configuration   = static_cast<Config *>(config);
250     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
251 
252     ANGLE_EGL_TRY_RETURN(
253         thread,
254         ValidateCreatePlatformPixmapSurfaceEXT(display, configuration, native_pixmap, attributes),
255         "eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
256     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurfaceEXT",
257                          GetDisplayIfValid(display), EGL_NO_SURFACE);
258     thread->setError(EglBadDisplay() << "CreatePlatformPixmapSurfaceEXT unimplemented.", GetDebug(),
259                      "eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display));
260     return EGL_NO_SURFACE;
261 }
262 
263 // EGL_EXT_device_query
EGL_QueryDeviceAttribEXT(EGLDeviceEXT device,EGLint attribute,EGLAttrib * value)264 EGLBoolean EGLAPIENTRY EGL_QueryDeviceAttribEXT(EGLDeviceEXT device,
265                                                 EGLint attribute,
266                                                 EGLAttrib *value)
267 {
268     ANGLE_SCOPED_GLOBAL_LOCK();
269     FUNC_EVENT("EGLDeviceEXT device = 0x%016" PRIxPTR
270                ", EGLint attribute = %d, EGLAttrib *value = 0x%016" PRIxPTR,
271                (uintptr_t)device, attribute, (uintptr_t)value);
272     Thread *thread = egl::GetCurrentThread();
273 
274     Device *dev = static_cast<Device *>(device);
275 
276     Error error = ValidateDevice(dev);
277     if (error.isError())
278     {
279         thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
280         return EGL_FALSE;
281     }
282     egl::Display *owningDisplay = dev->getOwningDisplay();
283     if (owningDisplay)
284     {
285         ANGLE_EGL_TRY_RETURN(thread, owningDisplay->prepareForCall(), "eglQueryDeviceAttribEXT",
286                              GetDisplayIfValid(owningDisplay), EGL_FALSE);
287     }
288     // If the device was created by (and is owned by) a display, and that display doesn't support
289     // device querying, then this call should fail
290     if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
291     {
292         thread->setError(EglBadAccess() << "Device wasn't created using eglCreateDeviceANGLE, "
293                                            "and the egl::Display that created it doesn't support "
294                                            "device querying",
295                          GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
296         return EGL_FALSE;
297     }
298 
299     // validate the attribute parameter
300     switch (attribute)
301     {
302         case EGL_D3D11_DEVICE_ANGLE:
303         case EGL_D3D9_DEVICE_ANGLE:
304             if (!dev->getExtensions().deviceD3D || dev->getType() != attribute)
305             {
306                 thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
307                                  GetDeviceIfValid(dev));
308                 return EGL_FALSE;
309             }
310             error = dev->getAttribute(attribute, value);
311             break;
312         case EGL_EAGL_CONTEXT_ANGLE:
313             if (!dev->getExtensions().deviceEAGL)
314             {
315                 thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
316                                  GetDeviceIfValid(dev));
317                 return EGL_FALSE;
318             }
319             error = dev->getAttribute(attribute, value);
320             break;
321         case EGL_CGL_CONTEXT_ANGLE:
322         case EGL_CGL_PIXEL_FORMAT_ANGLE:
323             if (!dev->getExtensions().deviceCGL)
324             {
325                 thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
326                                  GetDeviceIfValid(dev));
327                 return EGL_FALSE;
328             }
329             error = dev->getAttribute(attribute, value);
330             break;
331         default:
332             thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
333                              GetDeviceIfValid(dev));
334             return EGL_FALSE;
335     }
336 
337     if (error.isError())
338     {
339         thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
340         return EGL_FALSE;
341     }
342     thread->setSuccess();
343     return EGL_TRUE;
344 }
345 
346 // EGL_EXT_device_query
EGL_QueryDeviceStringEXT(EGLDeviceEXT device,EGLint name)347 const char *EGLAPIENTRY EGL_QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
348 {
349     ANGLE_SCOPED_GLOBAL_LOCK();
350     FUNC_EVENT("EGLDeviceEXT device = 0x%016" PRIxPTR ", EGLint name = %d", (uintptr_t)device,
351                name);
352     Thread *thread = egl::GetCurrentThread();
353 
354     Device *dev = static_cast<Device *>(device);
355 
356     Error error = ValidateDevice(dev);
357     if (error.isError())
358     {
359         thread->setError(error, GetDebug(), "eglQueryDeviceStringEXT", GetDeviceIfValid(dev));
360         return EGL_FALSE;
361     }
362     egl::Display *owningDisplay = dev->getOwningDisplay();
363     ANGLE_EGL_TRY_RETURN(thread, owningDisplay->prepareForCall(), "eglQueryDeviceStringEXT",
364                          GetDisplayIfValid(owningDisplay), EGL_FALSE);
365     const char *result;
366     switch (name)
367     {
368         case EGL_EXTENSIONS:
369             result = dev->getExtensionString().c_str();
370             break;
371         default:
372             thread->setError(EglBadDevice(), GetDebug(), "eglQueryDeviceStringEXT",
373                              GetDeviceIfValid(dev));
374             return nullptr;
375     }
376 
377     thread->setSuccess();
378     return result;
379 }
380 
381 // EGL_EXT_device_query
EGL_QueryDisplayAttribEXT(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)382 EGLBoolean EGLAPIENTRY EGL_QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
383 {
384     ANGLE_SCOPED_GLOBAL_LOCK();
385     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
386                ", EGLint attribute = %d, EGLAttrib *value = 0x%016" PRIxPTR,
387                (uintptr_t)dpy, attribute, (uintptr_t)value);
388 
389     egl::Display *display = static_cast<egl::Display *>(dpy);
390     Thread *thread        = egl::GetCurrentThread();
391 
392     ANGLE_EGL_TRY_RETURN(thread, ValidateQueryDisplayAttribEXT(display, attribute),
393                          "eglQueryDisplayAttribEXT", GetDisplayIfValid(display), EGL_FALSE);
394     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryDisplayAttribEXT",
395                          GetDisplayIfValid(display), EGL_FALSE);
396     *value = display->queryAttrib(attribute);
397     thread->setSuccess();
398     return EGL_TRUE;
399 }
400 
401 // EGL_ANGLE_feature_control
EGL_QueryDisplayAttribANGLE(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)402 EGLBoolean EGLAPIENTRY EGL_QueryDisplayAttribANGLE(EGLDisplay dpy,
403                                                    EGLint attribute,
404                                                    EGLAttrib *value)
405 {
406     ANGLE_SCOPED_GLOBAL_LOCK();
407     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
408                ", EGLint attribute = %d, EGLAttrib *value = 0x%016" PRIxPTR,
409                (uintptr_t)dpy, attribute, (uintptr_t)value);
410 
411     egl::Display *display = static_cast<egl::Display *>(dpy);
412     Thread *thread        = egl::GetCurrentThread();
413 
414     ANGLE_EGL_TRY_RETURN(thread, ValidateQueryDisplayAttribANGLE(display, attribute),
415                          "eglQueryDisplayAttribANGLE", GetDisplayIfValid(display), EGL_FALSE);
416     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryDisplayAttribANGLE",
417                          GetDisplayIfValid(display), EGL_FALSE);
418     *value = display->queryAttrib(attribute);
419     thread->setSuccess();
420     return EGL_TRUE;
421 }
422 
EGL_CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)423 ANGLE_EXPORT EGLImageKHR EGLAPIENTRY EGL_CreateImageKHR(EGLDisplay dpy,
424                                                         EGLContext ctx,
425                                                         EGLenum target,
426                                                         EGLClientBuffer buffer,
427                                                         const EGLint *attrib_list)
428 {
429     ANGLE_SCOPED_GLOBAL_LOCK();
430     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
431                ", EGLContext ctx = %d"
432                ", EGLenum target = 0x%X, "
433                "EGLClientBuffer buffer = 0x%016" PRIxPTR
434                ", const EGLAttrib *attrib_list = 0x%016" PRIxPTR,
435                (uintptr_t)dpy, CID(dpy, ctx), target, (uintptr_t)buffer, (uintptr_t)attrib_list);
436     Thread *thread = egl::GetCurrentThread();
437 
438     egl::Display *display   = static_cast<egl::Display *>(dpy);
439     gl::Context *context    = static_cast<gl::Context *>(ctx);
440     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
441 
442     Error error = ValidateCreateImageKHR(display, context, target, buffer, attributes);
443     if (error.isError())
444     {
445         thread->setError(error, GetDebug(), "eglCreateImageKHR", GetDisplayIfValid(display));
446         return EGL_NO_IMAGE;
447     }
448     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImageKHR",
449                          GetDisplayIfValid(display), EGL_NO_IMAGE);
450     Image *image = nullptr;
451     error        = display->createImage(context, target, buffer, attributes, &image);
452     if (error.isError())
453     {
454         thread->setError(error, GetDebug(), "eglCreateImageKHR", GetDisplayIfValid(display));
455         return EGL_NO_IMAGE;
456     }
457 
458     thread->setSuccess();
459     return static_cast<EGLImage>(image);
460 }
461 
EGL_DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)462 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
463 {
464     ANGLE_SCOPED_GLOBAL_LOCK();
465     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLImage image = 0x%016" PRIxPTR,
466                (uintptr_t)dpy, (uintptr_t)image);
467     Thread *thread = egl::GetCurrentThread();
468 
469     egl::Display *display = static_cast<egl::Display *>(dpy);
470     Image *img            = static_cast<Image *>(image);
471 
472     Error error = ValidateDestroyImageKHR(display, img);
473     if (error.isError())
474     {
475         thread->setError(error, GetDebug(), "eglDestroyImageKHR", GetImageIfValid(display, img));
476         return EGL_FALSE;
477     }
478     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImageKHR",
479                          GetDisplayIfValid(display), EGL_FALSE);
480     display->destroyImage(img);
481 
482     thread->setSuccess();
483     return EGL_TRUE;
484 }
485 
EGL_CreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)486 ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY EGL_CreateDeviceANGLE(EGLint device_type,
487                                                             void *native_device,
488                                                             const EGLAttrib *attrib_list)
489 {
490     ANGLE_SCOPED_GLOBAL_LOCK();
491     FUNC_EVENT("EGLint device_type = %d, void* native_device = 0x%016" PRIxPTR
492                ", const EGLAttrib* attrib_list = "
493                "0x%016" PRIxPTR,
494                device_type, (uintptr_t)native_device, (uintptr_t)attrib_list);
495     Thread *thread = egl::GetCurrentThread();
496 
497     Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
498     if (error.isError())
499     {
500         thread->setError(error, GetDebug(), "eglCreateDeviceANGLE", GetThreadIfValid(thread));
501         return EGL_NO_DEVICE_EXT;
502     }
503 
504     Device *device = nullptr;
505     error          = Device::CreateDevice(device_type, native_device, &device);
506     if (error.isError())
507     {
508         ASSERT(device == nullptr);
509         thread->setError(error, GetDebug(), "eglCreateDeviceANGLE", GetThreadIfValid(thread));
510         return EGL_NO_DEVICE_EXT;
511     }
512 
513     thread->setSuccess();
514     return device;
515 }
516 
EGL_ReleaseDeviceANGLE(EGLDeviceEXT device)517 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_ReleaseDeviceANGLE(EGLDeviceEXT device)
518 {
519     ANGLE_SCOPED_GLOBAL_LOCK();
520     FUNC_EVENT("EGLDeviceEXT device = 0x%016" PRIxPTR, (uintptr_t)device);
521     Thread *thread = egl::GetCurrentThread();
522 
523     Device *dev = static_cast<Device *>(device);
524 
525     Error error = ValidateReleaseDeviceANGLE(dev);
526     if (error.isError())
527     {
528         thread->setError(error, GetDebug(), "eglReleaseDeviceANGLE", GetDeviceIfValid(dev));
529         return EGL_FALSE;
530     }
531 
532     SafeDelete(dev);
533 
534     thread->setSuccess();
535     return EGL_TRUE;
536 }
537 
538 // EGL_KHR_stream
EGL_CreateStreamKHR(EGLDisplay dpy,const EGLint * attrib_list)539 EGLStreamKHR EGLAPIENTRY EGL_CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
540 {
541     ANGLE_SCOPED_GLOBAL_LOCK();
542     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", const EGLAttrib* attrib_list = 0x%016" PRIxPTR,
543                (uintptr_t)dpy, (uintptr_t)attrib_list);
544     Thread *thread = egl::GetCurrentThread();
545 
546     egl::Display *display   = static_cast<egl::Display *>(dpy);
547     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
548 
549     Error error = ValidateCreateStreamKHR(display, attributes);
550     if (error.isError())
551     {
552         thread->setError(error, GetDebug(), "eglCreateStreamKHR", GetDisplayIfValid(display));
553         return EGL_NO_STREAM_KHR;
554     }
555     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateStreamKHR",
556                          GetDisplayIfValid(display), EGL_NO_STREAM_KHR);
557     Stream *stream;
558     error = display->createStream(attributes, &stream);
559     if (error.isError())
560     {
561         thread->setError(error, GetDebug(), "eglCreateStreamKHR", GetDisplayIfValid(display));
562         return EGL_NO_STREAM_KHR;
563     }
564 
565     thread->setSuccess();
566     return static_cast<EGLStreamKHR>(stream);
567 }
568 
EGL_DestroyStreamKHR(EGLDisplay dpy,EGLStreamKHR stream)569 EGLBoolean EGLAPIENTRY EGL_DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
570 {
571     ANGLE_SCOPED_GLOBAL_LOCK();
572     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR = 0x%016" PRIxPTR, (uintptr_t)dpy,
573                (uintptr_t)stream);
574     Thread *thread = egl::GetCurrentThread();
575 
576     egl::Display *display = static_cast<egl::Display *>(dpy);
577     Stream *streamObject  = static_cast<Stream *>(stream);
578 
579     Error error = ValidateDestroyStreamKHR(display, streamObject);
580     if (error.isError())
581     {
582         thread->setError(error, GetDebug(), "eglDestroyStreamKHR",
583                          GetStreamIfValid(display, streamObject));
584         return EGL_FALSE;
585     }
586     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyStreamKHR",
587                          GetDisplayIfValid(display), EGL_FALSE);
588     display->destroyStream(streamObject);
589 
590     thread->setSuccess();
591     return EGL_TRUE;
592 }
593 
EGL_StreamAttribKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint value)594 EGLBoolean EGLAPIENTRY EGL_StreamAttribKHR(EGLDisplay dpy,
595                                            EGLStreamKHR stream,
596                                            EGLenum attribute,
597                                            EGLint value)
598 {
599     ANGLE_SCOPED_GLOBAL_LOCK();
600     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
601                ", EGLenum attribute = 0x%X, "
602                "EGLint value = 0x%X",
603                (uintptr_t)dpy, (uintptr_t)stream, attribute, value);
604     Thread *thread = egl::GetCurrentThread();
605 
606     egl::Display *display = static_cast<egl::Display *>(dpy);
607     Stream *streamObject  = static_cast<Stream *>(stream);
608 
609     Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
610     if (error.isError())
611     {
612         thread->setError(error, GetDebug(), "eglStreamAttribKHR",
613                          GetStreamIfValid(display, streamObject));
614         return EGL_FALSE;
615     }
616     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamAttribKHR",
617                          GetDisplayIfValid(display), EGL_FALSE);
618     switch (attribute)
619     {
620         case EGL_CONSUMER_LATENCY_USEC_KHR:
621             streamObject->setConsumerLatency(value);
622             break;
623         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
624             streamObject->setConsumerAcquireTimeout(value);
625             break;
626         default:
627             UNREACHABLE();
628     }
629 
630     thread->setSuccess();
631     return EGL_TRUE;
632 }
633 
EGL_QueryStreamKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)634 EGLBoolean EGLAPIENTRY EGL_QueryStreamKHR(EGLDisplay dpy,
635                                           EGLStreamKHR stream,
636                                           EGLenum attribute,
637                                           EGLint *value)
638 {
639     ANGLE_SCOPED_GLOBAL_LOCK();
640     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
641                ", EGLenum attribute = 0x%X, "
642                "EGLint value = 0x%016" PRIxPTR,
643                (uintptr_t)dpy, (uintptr_t)stream, attribute, (uintptr_t)value);
644     Thread *thread = egl::GetCurrentThread();
645 
646     egl::Display *display = static_cast<egl::Display *>(dpy);
647     Stream *streamObject  = static_cast<Stream *>(stream);
648 
649     Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
650     if (error.isError())
651     {
652         thread->setError(error, GetDebug(), "eglQueryStreamKHR",
653                          GetStreamIfValid(display, streamObject));
654         return EGL_FALSE;
655     }
656     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStreamKHR",
657                          GetDisplayIfValid(display), EGL_FALSE);
658     switch (attribute)
659     {
660         case EGL_STREAM_STATE_KHR:
661             *value = streamObject->getState();
662             break;
663         case EGL_CONSUMER_LATENCY_USEC_KHR:
664             *value = streamObject->getConsumerLatency();
665             break;
666         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
667             *value = streamObject->getConsumerAcquireTimeout();
668             break;
669         default:
670             UNREACHABLE();
671     }
672 
673     thread->setSuccess();
674     return EGL_TRUE;
675 }
676 
EGL_QueryStreamu64KHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLuint64KHR * value)677 EGLBoolean EGLAPIENTRY EGL_QueryStreamu64KHR(EGLDisplay dpy,
678                                              EGLStreamKHR stream,
679                                              EGLenum attribute,
680                                              EGLuint64KHR *value)
681 {
682     ANGLE_SCOPED_GLOBAL_LOCK();
683     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
684                ", EGLenum attribute = 0x%X, "
685                "EGLuint64KHR value = 0x%016" PRIxPTR,
686                (uintptr_t)dpy, (uintptr_t)stream, attribute, (uintptr_t)value);
687     Thread *thread = egl::GetCurrentThread();
688 
689     egl::Display *display = static_cast<egl::Display *>(dpy);
690     Stream *streamObject  = static_cast<Stream *>(stream);
691 
692     Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
693     if (error.isError())
694     {
695         thread->setError(error, GetDebug(), "eglQueryStreamu64KHR",
696                          GetStreamIfValid(display, streamObject));
697         return EGL_FALSE;
698     }
699     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStreamu64KHR",
700                          GetDisplayIfValid(display), EGL_FALSE);
701     switch (attribute)
702     {
703         case EGL_PRODUCER_FRAME_KHR:
704             *value = streamObject->getProducerFrame();
705             break;
706         case EGL_CONSUMER_FRAME_KHR:
707             *value = streamObject->getConsumerFrame();
708             break;
709         default:
710             UNREACHABLE();
711     }
712 
713     thread->setSuccess();
714     return EGL_TRUE;
715 }
716 
EGL_StreamConsumerGLTextureExternalKHR(EGLDisplay dpy,EGLStreamKHR stream)717 EGLBoolean EGLAPIENTRY EGL_StreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
718 {
719     ANGLE_SCOPED_GLOBAL_LOCK();
720     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR = 0x%016" PRIxPTR, (uintptr_t)dpy,
721                (uintptr_t)stream);
722     Thread *thread = egl::GetCurrentThread();
723 
724     egl::Display *display = static_cast<egl::Display *>(dpy);
725     Stream *streamObject  = static_cast<Stream *>(stream);
726     gl::Context *context  = gl::GetValidGlobalContext();
727 
728     Error error = ValidateStreamConsumerGLTextureExternalKHR(display, context, streamObject);
729     if (error.isError())
730     {
731         thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalKHR",
732                          GetStreamIfValid(display, streamObject));
733         return EGL_FALSE;
734     }
735     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerGLTextureExternalKHR",
736                          GetDisplayIfValid(display), EGL_FALSE);
737     error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
738     if (error.isError())
739     {
740         thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalKHR",
741                          GetStreamIfValid(display, streamObject));
742         return EGL_FALSE;
743     }
744 
745     thread->setSuccess();
746     return EGL_TRUE;
747 }
748 
EGL_StreamConsumerAcquireKHR(EGLDisplay dpy,EGLStreamKHR stream)749 EGLBoolean EGLAPIENTRY EGL_StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
750 {
751     ANGLE_SCOPED_GLOBAL_LOCK();
752     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR = 0x%016" PRIxPTR, (uintptr_t)dpy,
753                (uintptr_t)stream);
754     Thread *thread = egl::GetCurrentThread();
755 
756     egl::Display *display = static_cast<egl::Display *>(dpy);
757     Stream *streamObject  = static_cast<Stream *>(stream);
758     gl::Context *context  = gl::GetValidGlobalContext();
759 
760     Error error = ValidateStreamConsumerAcquireKHR(display, context, streamObject);
761     if (error.isError())
762     {
763         thread->setError(error, GetDebug(), "eglStreamConsumerAcquireKHR",
764                          GetStreamIfValid(display, streamObject));
765         return EGL_FALSE;
766     }
767     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerAcquireKHR",
768                          GetDisplayIfValid(display), EGL_FALSE);
769     error = streamObject->consumerAcquire(context);
770     if (error.isError())
771     {
772         thread->setError(error, GetDebug(), "eglStreamConsumerAcquireKHR",
773                          GetStreamIfValid(display, streamObject));
774         return EGL_FALSE;
775     }
776 
777     thread->setSuccess();
778     return EGL_TRUE;
779 }
780 
EGL_StreamConsumerReleaseKHR(EGLDisplay dpy,EGLStreamKHR stream)781 EGLBoolean EGLAPIENTRY EGL_StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
782 {
783     ANGLE_SCOPED_GLOBAL_LOCK();
784     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR = 0x%016" PRIxPTR, (uintptr_t)dpy,
785                (uintptr_t)stream);
786     Thread *thread = egl::GetCurrentThread();
787 
788     egl::Display *display = static_cast<egl::Display *>(dpy);
789     Stream *streamObject  = static_cast<Stream *>(stream);
790     gl::Context *context  = gl::GetValidGlobalContext();
791 
792     Error error = ValidateStreamConsumerReleaseKHR(display, context, streamObject);
793     if (error.isError())
794     {
795         thread->setError(error, GetDebug(), "eglSStreamConsumerReleaseKHR",
796                          GetStreamIfValid(display, streamObject));
797         return EGL_FALSE;
798     }
799     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerReleaseKHR",
800                          GetDisplayIfValid(display), EGL_FALSE);
801     error = streamObject->consumerRelease(context);
802     if (error.isError())
803     {
804         thread->setError(error, GetDebug(), "eglStreamConsumerReleaseKHR",
805                          GetStreamIfValid(display, streamObject));
806         return EGL_FALSE;
807     }
808 
809     thread->setSuccess();
810     return EGL_TRUE;
811 }
812 
EGL_StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)813 EGLBoolean EGLAPIENTRY EGL_StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
814                                                                     EGLStreamKHR stream,
815                                                                     const EGLAttrib *attrib_list)
816 {
817     ANGLE_SCOPED_GLOBAL_LOCK();
818     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
819                ", EGLAttrib attrib_list = 0x%016" PRIxPTR "",
820                (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list);
821     Thread *thread = egl::GetCurrentThread();
822 
823     egl::Display *display   = static_cast<egl::Display *>(dpy);
824     Stream *streamObject    = static_cast<Stream *>(stream);
825     gl::Context *context    = gl::GetValidGlobalContext();
826     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
827 
828     Error error = ValidateStreamConsumerGLTextureExternalAttribsNV(display, context, streamObject,
829                                                                    attributes);
830     if (error.isError())
831     {
832         thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalAttribsNV",
833                          GetStreamIfValid(display, streamObject));
834         return EGL_FALSE;
835     }
836     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(),
837                          "eglStreamConsumerGLTextureExternalAttribsNV", GetDisplayIfValid(display),
838                          EGL_FALSE);
839     error = streamObject->createConsumerGLTextureExternal(attributes, context);
840     if (error.isError())
841     {
842         thread->setError(error, GetDebug(), "eglStreamConsumerGLTextureExternalAttribsNV",
843                          GetStreamIfValid(display, streamObject));
844         return EGL_FALSE;
845     }
846 
847     thread->setSuccess();
848     return EGL_TRUE;
849 }
850 
EGL_CreateStreamProducerD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)851 EGLBoolean EGLAPIENTRY EGL_CreateStreamProducerD3DTextureANGLE(EGLDisplay dpy,
852                                                                EGLStreamKHR stream,
853                                                                const EGLAttrib *attrib_list)
854 {
855     ANGLE_SCOPED_GLOBAL_LOCK();
856     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
857                ", EGLAttrib attrib_list = 0x%016" PRIxPTR "",
858                (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)attrib_list);
859     Thread *thread = egl::GetCurrentThread();
860 
861     egl::Display *display   = static_cast<egl::Display *>(dpy);
862     Stream *streamObject    = static_cast<Stream *>(stream);
863     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
864 
865     Error error = ValidateCreateStreamProducerD3DTextureANGLE(display, streamObject, attributes);
866     if (error.isError())
867     {
868         thread->setError(error, GetDebug(), "eglCreateStreamProducerD3DTextureANGLE",
869                          GetStreamIfValid(display, streamObject));
870         return EGL_FALSE;
871     }
872     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(),
873                          "eglCreateStreamProducerD3DTextureANGLE", GetDisplayIfValid(display),
874                          EGL_FALSE);
875     error = streamObject->createProducerD3D11Texture(attributes);
876     if (error.isError())
877     {
878         thread->setError(error, GetDebug(), "eglCreateStreamProducerD3DTextureANGLE",
879                          GetStreamIfValid(display, streamObject));
880         return EGL_FALSE;
881     }
882 
883     thread->setSuccess();
884     return EGL_TRUE;
885 }
886 
EGL_StreamPostD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)887 EGLBoolean EGLAPIENTRY EGL_StreamPostD3DTextureANGLE(EGLDisplay dpy,
888                                                      EGLStreamKHR stream,
889                                                      void *texture,
890                                                      const EGLAttrib *attrib_list)
891 {
892     ANGLE_SCOPED_GLOBAL_LOCK();
893     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLStreamKHR stream = 0x%016" PRIxPTR
894                ", void* texture = 0x%016" PRIxPTR
895                ", "
896                "EGLAttrib attrib_list = 0x%016" PRIxPTR "",
897                (uintptr_t)dpy, (uintptr_t)stream, (uintptr_t)texture, (uintptr_t)attrib_list);
898     Thread *thread = egl::GetCurrentThread();
899 
900     egl::Display *display   = static_cast<egl::Display *>(dpy);
901     Stream *streamObject    = static_cast<Stream *>(stream);
902     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
903 
904     Error error = ValidateStreamPostD3DTextureANGLE(display, streamObject, texture, attributes);
905     if (error.isError())
906     {
907         thread->setError(error, GetDebug(), "eglStreamPostD3DTextureANGLE",
908                          GetStreamIfValid(display, streamObject));
909         return EGL_FALSE;
910     }
911     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamPostD3DTextureANGLE",
912                          GetDisplayIfValid(display), EGL_FALSE);
913     error = streamObject->postD3D11Texture(texture, attributes);
914     if (error.isError())
915     {
916         thread->setError(error, GetDebug(), "eglStreamPostD3DTextureANGLE",
917                          GetStreamIfValid(display, streamObject));
918         return EGL_FALSE;
919     }
920 
921     thread->setSuccess();
922     return EGL_TRUE;
923 }
924 
925 // EGL_KHR_fence_sync
EGL_CreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)926 ANGLE_EXPORT EGLSync EGLAPIENTRY EGL_CreateSyncKHR(EGLDisplay dpy,
927                                                    EGLenum type,
928                                                    const EGLint *attrib_list)
929 {
930     ANGLE_SCOPED_GLOBAL_LOCK();
931     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
932                ", EGLenum type = 0x%X, const EGLint* attrib_list = 0x%016" PRIxPTR,
933                (uintptr_t)dpy, type, (uintptr_t)attrib_list);
934 
935     Thread *thread          = egl::GetCurrentThread();
936     egl::Display *display   = static_cast<egl::Display *>(dpy);
937     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
938 
939     gl::Context *currentContext  = thread->getContext();
940     egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
941 
942     ANGLE_EGL_TRY_RETURN(
943         thread, ValidateCreateSyncKHR(display, type, attributes, currentDisplay, currentContext),
944         "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
945     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync",
946                          GetDisplayIfValid(display), EGL_NO_SYNC);
947     egl::Sync *syncObject = nullptr;
948     ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
949                          "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
950 
951     thread->setSuccess();
952     return static_cast<EGLSync>(syncObject);
953 }
954 
EGL_DestroySyncKHR(EGLDisplay dpy,EGLSync sync)955 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_DestroySyncKHR(EGLDisplay dpy, EGLSync sync)
956 {
957     ANGLE_SCOPED_GLOBAL_LOCK();
958     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR, (uintptr_t)dpy,
959                (uintptr_t)sync);
960 
961     Thread *thread        = egl::GetCurrentThread();
962     egl::Display *display = static_cast<egl::Display *>(dpy);
963     egl::Sync *syncObject = static_cast<Sync *>(sync);
964 
965     ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySync(display, syncObject), "eglDestroySync",
966                          GetDisplayIfValid(display), EGL_FALSE);
967     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync",
968                          GetDisplayIfValid(display), EGL_FALSE);
969     display->destroySync(syncObject);
970 
971     thread->setSuccess();
972     return EGL_TRUE;
973 }
974 
EGL_ClientWaitSyncKHR(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)975 ANGLE_EXPORT EGLint EGLAPIENTRY EGL_ClientWaitSyncKHR(EGLDisplay dpy,
976                                                       EGLSync sync,
977                                                       EGLint flags,
978                                                       EGLTime timeout)
979 {
980     ANGLE_SCOPED_GLOBAL_LOCK();
981     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR
982                ", EGLint flags = 0x%X, EGLTime timeout = "
983                "%llu",
984                (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast<unsigned long long>(timeout));
985 
986     Thread *thread        = egl::GetCurrentThread();
987     egl::Display *display = static_cast<egl::Display *>(dpy);
988     egl::Sync *syncObject = static_cast<Sync *>(sync);
989 
990     ANGLE_EGL_TRY_RETURN(thread, ValidateClientWaitSync(display, syncObject, flags, timeout),
991                          "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
992     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync",
993                          GetDisplayIfValid(display), EGL_FALSE);
994     gl::Context *currentContext = thread->getContext();
995     EGLint syncStatus           = EGL_FALSE;
996     ANGLE_EGL_TRY_RETURN(
997         thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus),
998         "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
999 
1000     thread->setSuccess();
1001     return syncStatus;
1002 }
1003 
EGL_GetSyncAttribKHR(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLint * value)1004 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetSyncAttribKHR(EGLDisplay dpy,
1005                                                          EGLSync sync,
1006                                                          EGLint attribute,
1007                                                          EGLint *value)
1008 {
1009     ANGLE_SCOPED_GLOBAL_LOCK();
1010     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR
1011                ", EGLint attribute = 0x%X, EGLAttrib "
1012                "*value = 0x%016" PRIxPTR,
1013                (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value);
1014 
1015     Thread *thread        = egl::GetCurrentThread();
1016     egl::Display *display = static_cast<egl::Display *>(dpy);
1017     egl::Sync *syncObject = static_cast<Sync *>(sync);
1018 
1019     ANGLE_EGL_TRY_RETURN(thread, ValidateGetSyncAttribKHR(display, syncObject, attribute, value),
1020                          "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
1021     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetSyncAttrib",
1022                          GetDisplayIfValid(display), EGL_FALSE);
1023     ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, value),
1024                          "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
1025 
1026     thread->setSuccess();
1027     return EGL_TRUE;
1028 }
1029 
1030 // EGL_KHR_wait_sync
EGL_WaitSyncKHR(EGLDisplay dpy,EGLSync sync,EGLint flags)1031 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_WaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
1032 {
1033     ANGLE_SCOPED_GLOBAL_LOCK();
1034     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR "p, EGLSync sync = 0x%016" PRIxPTR
1035                ", EGLint flags = 0x%X",
1036                (uintptr_t)dpy, (uintptr_t)sync, flags);
1037 
1038     Thread *thread        = egl::GetCurrentThread();
1039     egl::Display *display = static_cast<egl::Display *>(dpy);
1040     gl::Context *context  = thread->getContext();
1041     egl::Sync *syncObject = static_cast<Sync *>(sync);
1042 
1043     ANGLE_EGL_TRY_RETURN(thread, ValidateWaitSync(display, context, syncObject, flags),
1044                          "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
1045     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync",
1046                          GetDisplayIfValid(display), EGL_FALSE);
1047     gl::Context *currentContext = thread->getContext();
1048     ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
1049                          "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
1050 
1051     thread->setSuccess();
1052     return EGL_TRUE;
1053 }
1054 
EGL_GetMscRateANGLE(EGLDisplay dpy,EGLSurface surface,EGLint * numerator,EGLint * denominator)1055 EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy,
1056                                            EGLSurface surface,
1057                                            EGLint *numerator,
1058                                            EGLint *denominator)
1059 {
1060     ANGLE_SCOPED_GLOBAL_LOCK();
1061     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1062                ", EGLint* numerator = 0x%016" PRIxPTR
1063                ", "
1064                "EGLint* denomintor = 0x%016" PRIxPTR "",
1065                (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)numerator, (uintptr_t)denominator);
1066     Thread *thread = egl::GetCurrentThread();
1067 
1068     egl::Display *display = static_cast<egl::Display *>(dpy);
1069     Surface *eglSurface   = static_cast<Surface *>(surface);
1070 
1071     Error error = ValidateGetMscRateANGLE(display, eglSurface, numerator, denominator);
1072     if (error.isError())
1073     {
1074         thread->setError(error, GetDebug(), "eglGetMscRateANGLE",
1075                          GetSurfaceIfValid(display, eglSurface));
1076         return EGL_FALSE;
1077     }
1078     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetMscRateANGLE",
1079                          GetDisplayIfValid(display), EGL_FALSE);
1080     error = eglSurface->getMscRate(numerator, denominator);
1081     if (error.isError())
1082     {
1083         thread->setError(error, GetDebug(), "eglGetMscRateANGLE",
1084                          GetSurfaceIfValid(display, eglSurface));
1085         return EGL_FALSE;
1086     }
1087 
1088     thread->setSuccess();
1089     return EGL_TRUE;
1090 }
1091 
EGL_GetSyncValuesCHROMIUM(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)1092 EGLBoolean EGLAPIENTRY EGL_GetSyncValuesCHROMIUM(EGLDisplay dpy,
1093                                                  EGLSurface surface,
1094                                                  EGLuint64KHR *ust,
1095                                                  EGLuint64KHR *msc,
1096                                                  EGLuint64KHR *sbc)
1097 {
1098     ANGLE_SCOPED_GLOBAL_LOCK();
1099     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1100                ", EGLuint64KHR* ust = 0x%016" PRIxPTR
1101                ", "
1102                "EGLuint64KHR* msc = 0x%016" PRIxPTR ", EGLuint64KHR* sbc = 0x%016" PRIxPTR "",
1103                (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)ust, (uintptr_t)msc, (uintptr_t)sbc);
1104     Thread *thread = egl::GetCurrentThread();
1105 
1106     egl::Display *display = static_cast<egl::Display *>(dpy);
1107     Surface *eglSurface   = static_cast<Surface *>(surface);
1108 
1109     Error error = ValidateGetSyncValuesCHROMIUM(display, eglSurface, ust, msc, sbc);
1110     if (error.isError())
1111     {
1112         thread->setError(error, GetDebug(), "eglGetSyncValuesCHROMIUM",
1113                          GetSurfaceIfValid(display, eglSurface));
1114         return EGL_FALSE;
1115     }
1116     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetSyncValuesCHROMIUM",
1117                          GetDisplayIfValid(display), EGL_FALSE);
1118     error = eglSurface->getSyncValues(ust, msc, sbc);
1119     if (error.isError())
1120     {
1121         thread->setError(error, GetDebug(), "eglGetSyncValuesCHROMIUM",
1122                          GetSurfaceIfValid(display, eglSurface));
1123         return EGL_FALSE;
1124     }
1125 
1126     thread->setSuccess();
1127     return EGL_TRUE;
1128 }
1129 
EGL_SwapBuffersWithDamageKHR(EGLDisplay dpy,EGLSurface surface,EGLint * rects,EGLint n_rects)1130 EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithDamageKHR(EGLDisplay dpy,
1131                                                     EGLSurface surface,
1132                                                     EGLint *rects,
1133                                                     EGLint n_rects)
1134 {
1135     ANGLE_SCOPED_GLOBAL_LOCK();
1136     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1137                ", EGLint *rects = 0x%016" PRIxPTR
1138                ", EGLint "
1139                "n_rects = %d",
1140                (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)rects, n_rects);
1141     Thread *thread = egl::GetCurrentThread();
1142 
1143     egl::Display *display = static_cast<egl::Display *>(dpy);
1144     Surface *eglSurface   = static_cast<Surface *>(surface);
1145 
1146     Error error = ValidateSwapBuffersWithDamageKHR(display, eglSurface, rects, n_rects);
1147     if (error.isError())
1148     {
1149         thread->setError(error, GetDebug(), "eglSwapBuffersWithDamageEXT",
1150                          GetSurfaceIfValid(display, eglSurface));
1151         return EGL_FALSE;
1152     }
1153     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffersWithDamageEXT",
1154                          GetDisplayIfValid(display), EGL_FALSE);
1155     error = eglSurface->swapWithDamage(thread->getContext(), rects, n_rects);
1156     if (error.isError())
1157     {
1158         thread->setError(error, GetDebug(), "eglSwapBuffersWithDamageEXT",
1159                          GetSurfaceIfValid(display, eglSurface));
1160         return EGL_FALSE;
1161     }
1162 
1163     thread->setSuccess();
1164     return EGL_TRUE;
1165 }
1166 
EGL_PresentationTimeANDROID(EGLDisplay dpy,EGLSurface surface,EGLnsecsANDROID time)1167 EGLBoolean EGLAPIENTRY EGL_PresentationTimeANDROID(EGLDisplay dpy,
1168                                                    EGLSurface surface,
1169                                                    EGLnsecsANDROID time)
1170 {
1171     ANGLE_SCOPED_GLOBAL_LOCK();
1172     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1173                ", EGLnsecsANDROID time = %llu",
1174                (uintptr_t)dpy, (uintptr_t)surface, static_cast<unsigned long long>(time));
1175     Thread *thread = egl::GetCurrentThread();
1176 
1177     egl::Display *display = static_cast<egl::Display *>(dpy);
1178     Surface *eglSurface   = static_cast<Surface *>(surface);
1179 
1180     ANGLE_EGL_TRY_RETURN(thread, ValidatePresentationTimeANDROID(display, eglSurface, time),
1181                          "eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
1182                          EGL_FALSE);
1183     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglPresentationTimeANDROID",
1184                          GetDisplayIfValid(display), EGL_FALSE);
1185     ANGLE_EGL_TRY_RETURN(thread, eglSurface->setPresentationTime(time),
1186                          "eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
1187                          EGL_FALSE);
1188 
1189     return EGL_TRUE;
1190 }
1191 
EGL_SetBlobCacheFuncsANDROID(EGLDisplay dpy,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)1192 ANGLE_EXPORT void EGLAPIENTRY EGL_SetBlobCacheFuncsANDROID(EGLDisplay dpy,
1193                                                            EGLSetBlobFuncANDROID set,
1194                                                            EGLGetBlobFuncANDROID get)
1195 {
1196     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSetBlobFuncANDROID set = 0x%016" PRIxPTR
1197                ", EGLGetBlobFuncANDROID get "
1198                "= 0x%016" PRIxPTR,
1199                (uintptr_t)dpy, (uintptr_t)set, (uintptr_t)get);
1200     Thread *thread = egl::GetCurrentThread();
1201 
1202     egl::Display *display = static_cast<egl::Display *>(dpy);
1203 
1204     ANGLE_EGL_TRY(thread, ValidateSetBlobCacheANDROID(display, set, get),
1205                   "eglSetBlobCacheFuncsANDROID", GetDisplayIfValid(display));
1206     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglSetBlobCacheFuncsANDROID",
1207                   GetDisplayIfValid(display));
1208     thread->setSuccess();
1209     display->setBlobCacheFuncs(set, get);
1210 }
1211 
EGL_ProgramCacheGetAttribANGLE(EGLDisplay dpy,EGLenum attrib)1212 EGLint EGLAPIENTRY EGL_ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib)
1213 {
1214     ANGLE_SCOPED_GLOBAL_LOCK();
1215     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLenum attrib = 0x%X", (uintptr_t)dpy, attrib);
1216 
1217     egl::Display *display = static_cast<egl::Display *>(dpy);
1218     Thread *thread        = egl::GetCurrentThread();
1219 
1220     ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib),
1221                          "eglProgramCacheGetAttribANGLE", GetDisplayIfValid(display), 0);
1222     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglProgramCacheGetAttribANGLE",
1223                          GetDisplayIfValid(display), 0);
1224     thread->setSuccess();
1225     return display->programCacheGetAttrib(attrib);
1226 }
1227 
EGL_ProgramCacheQueryANGLE(EGLDisplay dpy,EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)1228 void EGLAPIENTRY EGL_ProgramCacheQueryANGLE(EGLDisplay dpy,
1229                                             EGLint index,
1230                                             void *key,
1231                                             EGLint *keysize,
1232                                             void *binary,
1233                                             EGLint *binarysize)
1234 {
1235     ANGLE_SCOPED_GLOBAL_LOCK();
1236     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint index = %d, void *key = 0x%016" PRIxPTR
1237                ", EGLint *keysize = "
1238                "0x%016" PRIxPTR ", void *binary = 0x%016" PRIxPTR ", EGLint *size = 0x%016" PRIxPTR,
1239                (uintptr_t)dpy, index, (uintptr_t)key, (uintptr_t)keysize, (uintptr_t)binary,
1240                (uintptr_t)binarysize);
1241 
1242     egl::Display *display = static_cast<egl::Display *>(dpy);
1243     Thread *thread        = egl::GetCurrentThread();
1244 
1245     ANGLE_EGL_TRY(thread,
1246                   ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize),
1247                   "eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
1248     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglProgramCacheQueryANGLE",
1249                   GetDisplayIfValid(display));
1250     ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize),
1251                   "eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
1252 
1253     thread->setSuccess();
1254 }
1255 
EGL_ProgramCachePopulateANGLE(EGLDisplay dpy,const void * key,EGLint keysize,const void * binary,EGLint binarysize)1256 void EGLAPIENTRY EGL_ProgramCachePopulateANGLE(EGLDisplay dpy,
1257                                                const void *key,
1258                                                EGLint keysize,
1259                                                const void *binary,
1260                                                EGLint binarysize)
1261 {
1262     ANGLE_SCOPED_GLOBAL_LOCK();
1263     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", void *key = 0x%016" PRIxPTR
1264                ", EGLint keysize = %d, void *binary = "
1265                "0x%016" PRIxPTR ", EGLint size = %d",
1266                (uintptr_t)dpy, (uintptr_t)key, keysize, (uintptr_t)binary, binarysize);
1267 
1268     egl::Display *display = static_cast<egl::Display *>(dpy);
1269     Thread *thread        = egl::GetCurrentThread();
1270 
1271     ANGLE_EGL_TRY(thread,
1272                   ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize),
1273                   "eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
1274     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglProgramCachePopulateANGLE",
1275                   GetDisplayIfValid(display));
1276     ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize),
1277                   "eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
1278 
1279     thread->setSuccess();
1280 }
1281 
EGL_ProgramCacheResizeANGLE(EGLDisplay dpy,EGLint limit,EGLenum mode)1282 EGLint EGLAPIENTRY EGL_ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode)
1283 {
1284     ANGLE_SCOPED_GLOBAL_LOCK();
1285     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint limit = %d, EGLenum mode = 0x%X",
1286                (uintptr_t)dpy, limit, mode);
1287 
1288     egl::Display *display = static_cast<egl::Display *>(dpy);
1289     Thread *thread        = egl::GetCurrentThread();
1290 
1291     ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode),
1292                          "eglProgramCacheResizeANGLE", GetDisplayIfValid(display), 0);
1293     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglProgramCacheResizeANGLE",
1294                          GetDisplayIfValid(display), 0);
1295     thread->setSuccess();
1296     return display->programCacheResize(limit, mode);
1297 }
1298 
EGL_DebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attrib_list)1299 EGLint EGLAPIENTRY EGL_DebugMessageControlKHR(EGLDEBUGPROCKHR callback,
1300                                               const EGLAttrib *attrib_list)
1301 {
1302     ANGLE_SCOPED_GLOBAL_LOCK();
1303     FUNC_EVENT("EGLDEBUGPROCKHR callback = 0x%016" PRIxPTR
1304                ", EGLAttrib attrib_list = 0x%016" PRIxPTR,
1305                (uintptr_t)callback, (uintptr_t)attrib_list);
1306 
1307     Thread *thread = egl::GetCurrentThread();
1308 
1309     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
1310 
1311     Error error = ValidateDebugMessageControlKHR(callback, attributes);
1312     if (error.isError())
1313     {
1314         thread->setError(error, GetDebug(), "eglDebugMessageControlKHR", nullptr);
1315         return error.getCode();
1316     }
1317 
1318     Debug *debug = GetDebug();
1319     debug->setCallback(callback, attributes);
1320 
1321     thread->setSuccess();
1322     return EGL_SUCCESS;
1323 }
1324 
EGL_QueryDebugKHR(EGLint attribute,EGLAttrib * value)1325 EGLBoolean EGLAPIENTRY EGL_QueryDebugKHR(EGLint attribute, EGLAttrib *value)
1326 {
1327     ANGLE_SCOPED_GLOBAL_LOCK();
1328     FUNC_EVENT("EGLint attribute = 0x%X, EGLAttrib* value = 0x%016" PRIxPTR, attribute,
1329                (uintptr_t)value);
1330 
1331     Thread *thread = egl::GetCurrentThread();
1332 
1333     Error error = ValidateQueryDebugKHR(attribute, value);
1334     if (error.isError())
1335     {
1336         thread->setError(error, GetDebug(), "eglQueryDebugKHR", nullptr);
1337         return EGL_FALSE;
1338     }
1339 
1340     Debug *debug = GetDebug();
1341     switch (attribute)
1342     {
1343         case EGL_DEBUG_MSG_CRITICAL_KHR:
1344         case EGL_DEBUG_MSG_ERROR_KHR:
1345         case EGL_DEBUG_MSG_WARN_KHR:
1346         case EGL_DEBUG_MSG_INFO_KHR:
1347             *value = debug->isMessageTypeEnabled(FromEGLenum<MessageType>(attribute)) ? EGL_TRUE
1348                                                                                       : EGL_FALSE;
1349             break;
1350         case EGL_DEBUG_CALLBACK_KHR:
1351             *value = reinterpret_cast<EGLAttrib>(debug->getCallback());
1352             break;
1353 
1354         default:
1355             UNREACHABLE();
1356     }
1357 
1358     thread->setSuccess();
1359     return EGL_TRUE;
1360 }
1361 
EGL_LabelObjectKHR(EGLDisplay dpy,EGLenum objectType,EGLObjectKHR object,EGLLabelKHR label)1362 EGLint EGLAPIENTRY EGL_LabelObjectKHR(EGLDisplay dpy,
1363                                       EGLenum objectType,
1364                                       EGLObjectKHR object,
1365                                       EGLLabelKHR label)
1366 {
1367     ANGLE_SCOPED_GLOBAL_LOCK();
1368     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
1369                ", EGLenum objectType = 0x%X, EGLObjectKHR object = 0x%016" PRIxPTR
1370                ", "
1371                "EGLLabelKHR label = 0x%016" PRIxPTR,
1372                (uintptr_t)dpy, objectType, (uintptr_t)object, (uintptr_t)label);
1373 
1374     egl::Display *display = static_cast<egl::Display *>(dpy);
1375     Thread *thread        = egl::GetCurrentThread();
1376 
1377     ObjectType objectTypePacked = FromEGLenum<ObjectType>(objectType);
1378     Error error = ValidateLabelObjectKHR(thread, display, objectTypePacked, object, label);
1379     if (error.isError())
1380     {
1381         thread->setError(error, GetDebug(), "eglLabelObjectKHR",
1382                          GetLabeledObjectIfValid(thread, display, objectTypePacked, object));
1383         return error.getCode();
1384     }
1385     if (display)
1386     {
1387         error = display->prepareForCall();
1388         if (error.isError())
1389         {
1390             thread->setError(error, GetDebug(), "eglLabelObjectKHR", GetDisplayIfValid(display));
1391             return error.getCode();
1392         }
1393     }
1394     LabeledObject *labeledObject =
1395         GetLabeledObjectIfValid(thread, display, objectTypePacked, object);
1396     ASSERT(labeledObject != nullptr);
1397     labeledObject->setLabel(label);
1398 
1399     thread->setSuccess();
1400     return EGL_SUCCESS;
1401 }
1402 
EGL_GetCompositorTimingSupportedANDROID(EGLDisplay dpy,EGLSurface surface,EGLint name)1403 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetCompositorTimingSupportedANDROID(EGLDisplay dpy,
1404                                                                             EGLSurface surface,
1405                                                                             EGLint name)
1406 {
1407     ANGLE_SCOPED_GLOBAL_LOCK();
1408     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1409                ", EGLint name = 0x%X",
1410                (uintptr_t)dpy, (uintptr_t)surface, name);
1411 
1412     egl::Display *display = static_cast<egl::Display *>(dpy);
1413     Surface *eglSurface   = static_cast<Surface *>(surface);
1414     Thread *thread        = egl::GetCurrentThread();
1415 
1416     CompositorTiming nameInternal = FromEGLenum<CompositorTiming>(name);
1417 
1418     ANGLE_EGL_TRY_RETURN(
1419         thread, ValidateGetCompositorTimingSupportedANDROID(display, eglSurface, nameInternal),
1420         "eglQueryTimestampSupportedANDROID", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
1421 
1422     thread->setSuccess();
1423     return eglSurface->getSupportedCompositorTimings().test(nameInternal);
1424 }
1425 
EGL_GetCompositorTimingANDROID(EGLDisplay dpy,EGLSurface surface,EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values)1426 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetCompositorTimingANDROID(EGLDisplay dpy,
1427                                                                    EGLSurface surface,
1428                                                                    EGLint numTimestamps,
1429                                                                    const EGLint *names,
1430                                                                    EGLnsecsANDROID *values)
1431 {
1432     ANGLE_SCOPED_GLOBAL_LOCK();
1433     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1434                ", EGLint numTimestamps = %d, const EGLint *names = 0x%016" PRIxPTR
1435                ", EGLnsecsANDROID *values = 0x%016" PRIxPTR,
1436                (uintptr_t)dpy, (uintptr_t)surface, numTimestamps, (uintptr_t)names,
1437                (uintptr_t)values);
1438 
1439     egl::Display *display = static_cast<egl::Display *>(dpy);
1440     Surface *eglSurface   = static_cast<Surface *>(surface);
1441     Thread *thread        = egl::GetCurrentThread();
1442 
1443     ANGLE_EGL_TRY_RETURN(
1444         thread,
1445         ValidateGetCompositorTimingANDROID(display, eglSurface, numTimestamps, names, values),
1446         "eglGetCompositorTimingANDROIDD", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
1447     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetCompositorTimingANDROIDD",
1448                          GetDisplayIfValid(display), EGL_FALSE);
1449     ANGLE_EGL_TRY_RETURN(thread, eglSurface->getCompositorTiming(numTimestamps, names, values),
1450                          "eglGetCompositorTimingANDROIDD", GetSurfaceIfValid(display, eglSurface),
1451                          EGL_FALSE);
1452 
1453     thread->setSuccess();
1454     return EGL_TRUE;
1455 }
1456 
EGL_GetNextFrameIdANDROID(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR * frameId)1457 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetNextFrameIdANDROID(EGLDisplay dpy,
1458                                                               EGLSurface surface,
1459                                                               EGLuint64KHR *frameId)
1460 {
1461     ANGLE_SCOPED_GLOBAL_LOCK();
1462     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1463                ", EGLuint64KHR *frameId = 0x%016" PRIxPTR,
1464                (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)frameId);
1465 
1466     egl::Display *display = static_cast<egl::Display *>(dpy);
1467     Surface *eglSurface   = static_cast<Surface *>(surface);
1468     Thread *thread        = egl::GetCurrentThread();
1469 
1470     ANGLE_EGL_TRY_RETURN(thread, ValidateGetNextFrameIdANDROID(display, eglSurface, frameId),
1471                          "eglGetNextFrameIdANDROID", GetSurfaceIfValid(display, eglSurface),
1472                          EGL_FALSE);
1473     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetNextFrameIdANDROID",
1474                          GetDisplayIfValid(display), EGL_FALSE);
1475     ANGLE_EGL_TRY_RETURN(thread, eglSurface->getNextFrameId(frameId), "eglGetNextFrameIdANDROID",
1476                          GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
1477 
1478     thread->setSuccess();
1479     return EGL_TRUE;
1480 }
1481 
EGL_GetFrameTimestampSupportedANDROID(EGLDisplay dpy,EGLSurface surface,EGLint timestamp)1482 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetFrameTimestampSupportedANDROID(EGLDisplay dpy,
1483                                                                           EGLSurface surface,
1484                                                                           EGLint timestamp)
1485 {
1486     ANGLE_SCOPED_GLOBAL_LOCK();
1487     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1488                ", EGLint timestamp = 0x%X",
1489                (uintptr_t)dpy, (uintptr_t)surface, timestamp);
1490 
1491     egl::Display *display = static_cast<egl::Display *>(dpy);
1492     Surface *eglSurface   = static_cast<Surface *>(surface);
1493     Thread *thread        = egl::GetCurrentThread();
1494 
1495     Timestamp timestampInternal = FromEGLenum<Timestamp>(timestamp);
1496 
1497     ANGLE_EGL_TRY_RETURN(
1498         thread, ValidateGetFrameTimestampSupportedANDROID(display, eglSurface, timestampInternal),
1499         "eglQueryTimestampSupportedANDROID", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
1500     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryTimestampSupportedANDROID",
1501                          GetDisplayIfValid(display), EGL_FALSE);
1502     thread->setSuccess();
1503     return eglSurface->getSupportedTimestamps().test(timestampInternal);
1504 }
1505 
EGL_GetFrameTimestampsANDROID(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values)1506 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetFrameTimestampsANDROID(EGLDisplay dpy,
1507                                                                   EGLSurface surface,
1508                                                                   EGLuint64KHR frameId,
1509                                                                   EGLint numTimestamps,
1510                                                                   const EGLint *timestamps,
1511                                                                   EGLnsecsANDROID *values)
1512 {
1513     ANGLE_SCOPED_GLOBAL_LOCK();
1514     FUNC_EVENT(
1515         "EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1516         ", EGLuint64KHR frameId = %llu, EGLint numTimestamps = %d, const EGLint *timestamps = "
1517         "0x%016" PRIxPTR ", EGLnsecsANDROID *values = 0x%016" PRIxPTR,
1518         (uintptr_t)dpy, (uintptr_t)surface, (unsigned long long)frameId, numTimestamps,
1519         (uintptr_t)timestamps, (uintptr_t)values);
1520 
1521     egl::Display *display = static_cast<egl::Display *>(dpy);
1522     Surface *eglSurface   = static_cast<Surface *>(surface);
1523     Thread *thread        = egl::GetCurrentThread();
1524 
1525     ANGLE_EGL_TRY_RETURN(thread,
1526                          ValidateGetFrameTimestampsANDROID(display, eglSurface, frameId,
1527                                                            numTimestamps, timestamps, values),
1528                          "eglGetFrameTimestampsANDROID", GetSurfaceIfValid(display, eglSurface),
1529                          EGL_FALSE);
1530     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetFrameTimestampsANDROID",
1531                          GetDisplayIfValid(display), EGL_FALSE);
1532     ANGLE_EGL_TRY_RETURN(
1533         thread, eglSurface->getFrameTimestamps(frameId, numTimestamps, timestamps, values),
1534         "eglGetFrameTimestampsANDROID", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
1535 
1536     thread->setSuccess();
1537     return EGL_TRUE;
1538 }
1539 
1540 // EGL_ANGLE_feature_control
EGL_QueryStringiANGLE(EGLDisplay dpy,EGLint name,EGLint index)1541 ANGLE_EXPORT const char *EGLAPIENTRY EGL_QueryStringiANGLE(EGLDisplay dpy,
1542                                                            EGLint name,
1543                                                            EGLint index)
1544 {
1545     ANGLE_SCOPED_GLOBAL_LOCK();
1546     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint name = %d, EGLint index = %d",
1547                (uintptr_t)dpy, name, index);
1548 
1549     egl::Display *display = static_cast<egl::Display *>(dpy);
1550     Thread *thread        = egl::GetCurrentThread();
1551 
1552     ANGLE_EGL_TRY_RETURN(thread, ValidateQueryStringiANGLE(display, name, index),
1553                          "eglQueryStringiANGLE", GetDisplayIfValid(display), nullptr);
1554     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStringiANGLE",
1555                          GetDisplayIfValid(display), nullptr);
1556     thread->setSuccess();
1557     return display->queryStringi(name, index);
1558 }
1559 
EGL_GetNativeClientBufferANDROID(const struct AHardwareBuffer * buffer)1560 EGLClientBuffer EGLAPIENTRY EGL_GetNativeClientBufferANDROID(const struct AHardwareBuffer *buffer)
1561 {
1562     ANGLE_SCOPED_GLOBAL_LOCK();
1563     FUNC_EVENT("const struct AHardwareBuffer *buffer = 0x%016" PRIxPTR, (uintptr_t)buffer);
1564 
1565     Thread *thread = egl::GetCurrentThread();
1566 
1567     ANGLE_EGL_TRY_RETURN(thread, ValidateGetNativeClientBufferANDROID(buffer),
1568                          "eglGetNativeClientBufferANDROID", nullptr, nullptr);
1569 
1570     thread->setSuccess();
1571     return egl::Display::GetNativeClientBuffer(buffer);
1572 }
1573 
EGL_CreateNativeClientBufferANDROID(const EGLint * attrib_list)1574 EGLClientBuffer EGLAPIENTRY EGL_CreateNativeClientBufferANDROID(const EGLint *attrib_list)
1575 {
1576     ANGLE_SCOPED_GLOBAL_LOCK();
1577     FUNC_EVENT("const EGLint *attrib_list = 0x%016" PRIxPTR, (uintptr_t)attrib_list);
1578 
1579     Thread *thread = egl::GetCurrentThread();
1580     ANGLE_EGL_TRY_RETURN(thread,
1581                          (attrib_list == nullptr || attrib_list[0] == EGL_NONE)
1582                              ? egl::EglBadParameter() << "invalid attribute list."
1583                              : NoError(),
1584                          "eglCreateNativeClientBufferANDROID", nullptr, nullptr);
1585 
1586     const AttributeMap &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
1587     ANGLE_EGL_TRY_RETURN(thread, ValidateCreateNativeClientBufferANDROID(attribMap),
1588                          "eglCreateNativeClientBufferANDROID", nullptr, nullptr);
1589 
1590     EGLClientBuffer eglClientBuffer = nullptr;
1591     ANGLE_EGL_TRY_RETURN(thread,
1592                          egl::Display::CreateNativeClientBuffer(attribMap, &eglClientBuffer),
1593                          "eglCreateNativeClientBufferANDROID", nullptr, nullptr);
1594 
1595     thread->setSuccess();
1596     return eglClientBuffer;
1597 }
1598 
EGL_DupNativeFenceFDANDROID(EGLDisplay dpy,EGLSyncKHR sync)1599 EGLint EGLAPIENTRY EGL_DupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1600 {
1601     ANGLE_SCOPED_GLOBAL_LOCK();
1602     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSyncKHR sync = 0x%016" PRIxPTR,
1603                (uintptr_t)dpy, (uintptr_t)sync);
1604 
1605     egl::Display *display = static_cast<egl::Display *>(dpy);
1606     Sync *syncObject      = static_cast<Sync *>(sync);
1607     Thread *thread        = egl::GetCurrentThread();
1608 
1609     ANGLE_EGL_TRY_RETURN(thread, ValidateDupNativeFenceFDANDROID(display, syncObject),
1610                          "eglDupNativeFenceFDANDROID", GetSyncIfValid(display, syncObject),
1611                          EGL_NO_NATIVE_FENCE_FD_ANDROID);
1612     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDupNativeFenceFDANDROID",
1613                          GetDisplayIfValid(display), EGL_NO_NATIVE_FENCE_FD_ANDROID);
1614     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1615     ANGLE_EGL_TRY_RETURN(thread, syncObject->dupNativeFenceFD(display, &result),
1616                          "eglDupNativeFenceFDANDROID", GetSyncIfValid(display, syncObject),
1617                          EGL_NO_NATIVE_FENCE_FD_ANDROID);
1618 
1619     thread->setSuccess();
1620     return result;
1621 }
1622 
EGL_SwapBuffersWithFrameTokenANGLE(EGLDisplay dpy,EGLSurface surface,EGLFrameTokenANGLE frametoken)1623 EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithFrameTokenANGLE(EGLDisplay dpy,
1624                                                           EGLSurface surface,
1625                                                           EGLFrameTokenANGLE frametoken)
1626 {
1627     ANGLE_SCOPED_GLOBAL_LOCK();
1628     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
1629                ", EGLFrameTokenANGLE frametoken = 0x%llX",
1630                (uintptr_t)dpy, (uintptr_t)surface, (unsigned long long)frametoken);
1631 
1632     egl::Display *display    = static_cast<egl::Display *>(dpy);
1633     egl::Surface *eglSurface = static_cast<egl::Surface *>(surface);
1634     Thread *thread           = egl::GetCurrentThread();
1635 
1636     ANGLE_EGL_TRY_RETURN(
1637         thread, ValidateSwapBuffersWithFrameTokenANGLE(display, eglSurface, frametoken),
1638         "eglSwapBuffersWithFrameTokenANGLE", GetDisplayIfValid(display), EGL_FALSE);
1639     ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffersWithFrameTokenANGLE",
1640                          GetDisplayIfValid(display), EGL_FALSE);
1641     ANGLE_EGL_TRY_RETURN(thread, eglSurface->swapWithFrameToken(thread->getContext(), frametoken),
1642                          "eglSwapBuffersWithFrameTokenANGLE", GetDisplayIfValid(display),
1643                          EGL_FALSE);
1644 
1645     thread->setSuccess();
1646     return EGL_TRUE;
1647 }
1648 
EGL_ReleaseHighPowerGPUANGLE(EGLDisplay dpy,EGLContext ctx)1649 void EGLAPIENTRY EGL_ReleaseHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx)
1650 {
1651     ANGLE_SCOPED_GLOBAL_LOCK();
1652     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLContext ctx = 0x%016" PRIxPTR,
1653                (uintptr_t)dpy, (uintptr_t)ctx);
1654     Thread *thread = egl::GetCurrentThread();
1655 
1656     egl::Display *display = static_cast<egl::Display *>(dpy);
1657     gl::Context *context  = static_cast<gl::Context *>(ctx);
1658 
1659     ANGLE_EGL_TRY(thread, ValidateContext(display, context), "eglReleaseHighPowerGPUANGLE",
1660                   GetDisplayIfValid(display));
1661     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglReleaseHighPowerGPUANGLE",
1662                   GetDisplayIfValid(display));
1663     ANGLE_EGL_TRY(thread, context->releaseHighPowerGPU(), "eglReleaseHighPowerGPUANGLE",
1664                   GetDisplayIfValid(display));
1665 
1666     thread->setSuccess();
1667 }
1668 
EGL_ReacquireHighPowerGPUANGLE(EGLDisplay dpy,EGLContext ctx)1669 void EGLAPIENTRY EGL_ReacquireHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx)
1670 {
1671     ANGLE_SCOPED_GLOBAL_LOCK();
1672     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLContext ctx = 0x%016" PRIxPTR,
1673                (uintptr_t)dpy, (uintptr_t)ctx);
1674     Thread *thread = egl::GetCurrentThread();
1675 
1676     egl::Display *display = static_cast<egl::Display *>(dpy);
1677     gl::Context *context  = static_cast<gl::Context *>(ctx);
1678 
1679     ANGLE_EGL_TRY(thread, ValidateContext(display, context), "eglReacquireHighPowerGPUANGLE",
1680                   GetDisplayIfValid(display));
1681     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglReacquireHighPowerGPUANGLE",
1682                   GetDisplayIfValid(display));
1683     ANGLE_EGL_TRY(thread, context->reacquireHighPowerGPU(), "eglReacquireHighPowerGPUANGLE",
1684                   GetDisplayIfValid(display));
1685 
1686     thread->setSuccess();
1687 }
1688 
EGL_HandleGPUSwitchANGLE(EGLDisplay dpy)1689 void EGLAPIENTRY EGL_HandleGPUSwitchANGLE(EGLDisplay dpy)
1690 {
1691     ANGLE_SCOPED_GLOBAL_LOCK();
1692     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR, (uintptr_t)dpy);
1693     Thread *thread = egl::GetCurrentThread();
1694 
1695     egl::Display *display = static_cast<egl::Display *>(dpy);
1696 
1697     ANGLE_EGL_TRY(thread, ValidateDisplay(display), "eglHandleGPUSwitchANGLE",
1698                   GetDisplayIfValid(display));
1699     ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglHandleGPUSwitchANGLE",
1700                   GetDisplayIfValid(display));
1701     ANGLE_EGL_TRY(thread, display->handleGPUSwitch(), "eglHandleGPUSwitchANGLE",
1702                   GetDisplayIfValid(display));
1703 
1704     thread->setSuccess();
1705 }
1706 
1707 // EGL_KHR_reusable_sync
EGL_SignalSyncKHR(EGLDisplay dpy,EGLSync sync,EGLenum mode)1708 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_SignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
1709 {
1710     ANGLE_SCOPED_GLOBAL_LOCK();
1711     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR
1712                ", EGLint mode = 0x%X",
1713                (uintptr_t)dpy, (uintptr_t)sync, mode);
1714 
1715     Thread *thread        = egl::GetCurrentThread();
1716     egl::Display *display = static_cast<egl::Display *>(dpy);
1717     egl::Sync *syncObject = static_cast<Sync *>(sync);
1718 
1719     ANGLE_EGL_TRY_RETURN(thread, ValidateSignalSyncKHR(display, syncObject, mode),
1720                          "eglSignalSyncKHR", GetSyncIfValid(display, syncObject), EGL_FALSE);
1721 
1722     gl::Context *currentContext = thread->getContext();
1723     ANGLE_EGL_TRY_RETURN(thread, syncObject->signal(display, currentContext, mode),
1724                          "eglSignalSyncKHR", GetSyncIfValid(display, syncObject), EGL_FALSE);
1725 
1726     thread->setSuccess();
1727     return EGL_TRUE;
1728 }
1729 
1730 }  // extern "C"
1731