• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_egl.cpp : Implements the EGL entry points.
8 
9 #include "libGLESv2/entry_points_egl.h"
10 
11 #include "common/debug.h"
12 #include "common/utilities.h"
13 #include "common/version.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/EGLSync.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/Texture.h"
19 #include "libANGLE/Thread.h"
20 #include "libANGLE/entry_points_utils.h"
21 #include "libANGLE/queryutils.h"
22 #include "libANGLE/validationEGL.h"
23 #include "libGLESv2/global_state.h"
24 #include "libGLESv2/proc_table_egl.h"
25 
26 using namespace egl;
27 
28 namespace
29 {
30 
CompareProc(const ProcEntry & a,const char * b)31 bool CompareProc(const ProcEntry &a, const char *b)
32 {
33     return strcmp(a.first, b) < 0;
34 }
35 
ClipConfigs(const std::vector<const Config * > & filteredConfigs,EGLConfig * output_configs,EGLint config_size,EGLint * num_config)36 void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
37                  EGLConfig *output_configs,
38                  EGLint config_size,
39                  EGLint *num_config)
40 {
41     EGLint result_size = static_cast<EGLint>(filteredConfigs.size());
42     if (output_configs)
43     {
44         result_size = std::max(std::min(result_size, config_size), 0);
45         for (EGLint i = 0; i < result_size; i++)
46         {
47             output_configs[i] = const_cast<Config *>(filteredConfigs[i]);
48         }
49     }
50     *num_config = result_size;
51 }
52 }  // anonymous namespace
53 
54 extern "C" {
55 // EGL 1.0
EGL_GetError(void)56 EGLint EGLAPIENTRY EGL_GetError(void)
57 {
58     ANGLE_SCOPED_GLOBAL_LOCK();
59     EVENT(__FUNCTION__, "");
60     Thread *thread = egl::GetCurrentThread();
61 
62     EGLint error = thread->getError();
63     thread->setSuccess();
64     return error;
65 }
66 
EGL_GetDisplay(EGLNativeDisplayType display_id)67 EGLDisplay EGLAPIENTRY EGL_GetDisplay(EGLNativeDisplayType display_id)
68 {
69     ANGLE_SCOPED_GLOBAL_LOCK();
70     FUNC_EVENT("EGLNativeDisplayType display_id = 0x%016" PRIxPTR, (uintptr_t)display_id);
71 
72     return egl::Display::GetDisplayFromNativeDisplay(display_id, AttributeMap());
73 }
74 
EGL_Initialize(EGLDisplay dpy,EGLint * major,EGLint * minor)75 EGLBoolean EGLAPIENTRY EGL_Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
76 {
77     ANGLE_SCOPED_GLOBAL_LOCK();
78     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint *major = 0x%016" PRIxPTR
79                ", EGLint *minor = 0x%016" PRIxPTR,
80                (uintptr_t)dpy, (uintptr_t)major, (uintptr_t)minor);
81     Thread *thread = egl::GetCurrentThread();
82 
83     egl::Display *display = static_cast<egl::Display *>(dpy);
84     ANGLE_EGL_TRY_RETURN(thread, ValidateInitialize(display), "eglInitialize",
85                          GetDisplayIfValid(display), EGL_FALSE);
86 
87     ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display),
88                          EGL_FALSE);
89 
90     if (major)
91         *major = 1;
92     if (minor)
93         *minor = 4;
94 
95     thread->setSuccess();
96     return EGL_TRUE;
97 }
98 
EGL_Terminate(EGLDisplay dpy)99 EGLBoolean EGLAPIENTRY EGL_Terminate(EGLDisplay dpy)
100 {
101     ANGLE_SCOPED_GLOBAL_LOCK();
102     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR, (uintptr_t)dpy);
103     Thread *thread = egl::GetCurrentThread();
104 
105     egl::Display *display = static_cast<egl::Display *>(dpy);
106     ANGLE_EGL_TRY_RETURN(thread, ValidateTerminate(display), "eglTerminate",
107                          GetDisplayIfValid(display), EGL_FALSE);
108 
109     ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(thread, nullptr, nullptr, nullptr),
110                          "eglTerminate", GetDisplayIfValid(display), EGL_FALSE);
111     SetContextCurrent(thread, nullptr);
112     ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate",
113                          GetDisplayIfValid(display), EGL_FALSE);
114 
115     thread->setSuccess();
116     return EGL_TRUE;
117 }
118 
EGL_QueryString(EGLDisplay dpy,EGLint name)119 const char *EGLAPIENTRY EGL_QueryString(EGLDisplay dpy, EGLint name)
120 {
121     ANGLE_SCOPED_GLOBAL_LOCK();
122     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint name = %d", (uintptr_t)dpy, name);
123     Thread *thread = egl::GetCurrentThread();
124 
125     egl::Display *display = static_cast<egl::Display *>(dpy);
126     if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS))
127     {
128         ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglQueryString",
129                              GetDisplayIfValid(display), nullptr);
130     }
131 
132     const char *result;
133     switch (name)
134     {
135         case EGL_CLIENT_APIS:
136             result = "OpenGL_ES";
137             break;
138         case EGL_EXTENSIONS:
139             if (display == EGL_NO_DISPLAY)
140             {
141                 result = egl::Display::GetClientExtensionString().c_str();
142             }
143             else
144             {
145                 result = display->getExtensionString().c_str();
146             }
147             break;
148         case EGL_VENDOR:
149             result = display->getVendorString().c_str();
150             break;
151         case EGL_VERSION:
152             result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
153             break;
154         default:
155             thread->setError(EglBadParameter(), GetDebug(), "eglQueryString",
156                              GetDisplayIfValid(display));
157             return nullptr;
158     }
159 
160     thread->setSuccess();
161     return result;
162 }
163 
EGL_GetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)164 EGLBoolean EGLAPIENTRY EGL_GetConfigs(EGLDisplay dpy,
165                                       EGLConfig *configs,
166                                       EGLint config_size,
167                                       EGLint *num_config)
168 {
169     ANGLE_SCOPED_GLOBAL_LOCK();
170     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig *configs = 0x%016" PRIxPTR
171                ", "
172                "EGLint config_size = %d, EGLint *num_config = 0x%016" PRIxPTR,
173                (uintptr_t)dpy, (uintptr_t)configs, config_size, (uintptr_t)num_config);
174     Thread *thread = egl::GetCurrentThread();
175 
176     egl::Display *display = static_cast<egl::Display *>(dpy);
177 
178     ANGLE_EGL_TRY_RETURN(thread, ValidateGetConfigs(display, config_size, num_config),
179                          "eglGetConfigs", GetDisplayIfValid(display), EGL_FALSE);
180 
181     ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
182 
183     thread->setSuccess();
184     return EGL_TRUE;
185 }
186 
EGL_ChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)187 EGLBoolean EGLAPIENTRY EGL_ChooseConfig(EGLDisplay dpy,
188                                         const EGLint *attrib_list,
189                                         EGLConfig *configs,
190                                         EGLint config_size,
191                                         EGLint *num_config)
192 {
193     ANGLE_SCOPED_GLOBAL_LOCK();
194     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", const EGLint *attrib_list = 0x%016" PRIxPTR
195                ", "
196                "EGLConfig *configs = 0x%016" PRIxPTR
197                ", EGLint config_size = %d, EGLint *num_config = 0x%016" PRIxPTR,
198                (uintptr_t)dpy, (uintptr_t)attrib_list, (uintptr_t)configs, config_size,
199                (uintptr_t)num_config);
200     Thread *thread = egl::GetCurrentThread();
201 
202     egl::Display *display  = static_cast<egl::Display *>(dpy);
203     AttributeMap attribMap = AttributeMap::CreateFromIntArray(attrib_list);
204 
205     ANGLE_EGL_TRY_RETURN(thread, ValidateChooseConfig(display, attribMap, config_size, num_config),
206                          "eglChooseConfig", GetDisplayIfValid(display), EGL_FALSE);
207 
208     ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config);
209 
210     thread->setSuccess();
211     return EGL_TRUE;
212 }
213 
EGL_GetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)214 EGLBoolean EGLAPIENTRY EGL_GetConfigAttrib(EGLDisplay dpy,
215                                            EGLConfig config,
216                                            EGLint attribute,
217                                            EGLint *value)
218 {
219     ANGLE_SCOPED_GLOBAL_LOCK();
220     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
221                ", EGLint attribute = %d, EGLint "
222                "*value = 0x%016" PRIxPTR,
223                (uintptr_t)dpy, (uintptr_t)config, attribute, (uintptr_t)value);
224     Thread *thread = egl::GetCurrentThread();
225 
226     egl::Display *display = static_cast<egl::Display *>(dpy);
227     Config *configuration = static_cast<Config *>(config);
228 
229     ANGLE_EGL_TRY_RETURN(thread, ValidateGetConfigAttrib(display, configuration, attribute),
230                          "eglGetConfigAttrib", GetDisplayIfValid(display), EGL_FALSE);
231 
232     QueryConfigAttrib(configuration, attribute, value);
233 
234     thread->setSuccess();
235     return EGL_TRUE;
236 }
237 
EGL_CreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)238 EGLSurface EGLAPIENTRY EGL_CreateWindowSurface(EGLDisplay dpy,
239                                                EGLConfig config,
240                                                EGLNativeWindowType win,
241                                                const EGLint *attrib_list)
242 {
243     ANGLE_SCOPED_GLOBAL_LOCK();
244     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
245                ", EGLNativeWindowType win = 0x%016" PRIxPTR
246                ", "
247                "const EGLint *attrib_list = 0x%016" PRIxPTR,
248                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)win, (uintptr_t)attrib_list);
249     Thread *thread = egl::GetCurrentThread();
250 
251     egl::Display *display   = static_cast<egl::Display *>(dpy);
252     Config *configuration   = static_cast<Config *>(config);
253     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
254 
255     ANGLE_EGL_TRY_RETURN(thread,
256                          ValidateCreateWindowSurface(display, configuration, win, attributes),
257                          "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
258 
259     egl::Surface *surface = nullptr;
260     ANGLE_EGL_TRY_RETURN(thread,
261                          display->createWindowSurface(configuration, win, attributes, &surface),
262                          "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
263 
264     return static_cast<EGLSurface>(surface);
265 }
266 
EGL_CreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)267 EGLSurface EGLAPIENTRY EGL_CreatePbufferSurface(EGLDisplay dpy,
268                                                 EGLConfig config,
269                                                 const EGLint *attrib_list)
270 {
271     ANGLE_SCOPED_GLOBAL_LOCK();
272     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
273                ", const EGLint *attrib_list = "
274                "0x%016" PRIxPTR,
275                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list);
276     Thread *thread = egl::GetCurrentThread();
277 
278     egl::Display *display   = static_cast<egl::Display *>(dpy);
279     Config *configuration   = static_cast<Config *>(config);
280     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
281 
282     ANGLE_EGL_TRY_RETURN(thread, ValidateCreatePbufferSurface(display, configuration, attributes),
283                          "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
284 
285     egl::Surface *surface = nullptr;
286     ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface),
287                          "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
288 
289     return static_cast<EGLSurface>(surface);
290 }
291 
EGL_CreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)292 EGLSurface EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy,
293                                                EGLConfig config,
294                                                EGLNativePixmapType pixmap,
295                                                const EGLint *attrib_list)
296 {
297     ANGLE_SCOPED_GLOBAL_LOCK();
298     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
299                ", EGLNativePixmapType pixmap = "
300                "0x%016" PRIxPTR
301                ", "
302                "const EGLint *attrib_list = 0x%016" PRIxPTR,
303                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)pixmap, (uintptr_t)attrib_list);
304     Thread *thread = egl::GetCurrentThread();
305 
306     egl::Display *display = static_cast<egl::Display *>(dpy);
307     Config *configuration = static_cast<Config *>(config);
308 
309     ANGLE_EGL_TRY_RETURN(thread, ValidateConfig(display, configuration), "eglCreatePixmapSurface",
310                          GetDisplayIfValid(display), EGL_NO_SURFACE);
311 
312     UNIMPLEMENTED();  // FIXME
313 
314     thread->setSuccess();
315     return EGL_NO_SURFACE;
316 }
317 
EGL_DestroySurface(EGLDisplay dpy,EGLSurface surface)318 EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface)
319 {
320     ANGLE_SCOPED_GLOBAL_LOCK();
321     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR,
322                (uintptr_t)dpy, (uintptr_t)surface);
323     Thread *thread = egl::GetCurrentThread();
324 
325     egl::Display *display = static_cast<egl::Display *>(dpy);
326     Surface *eglSurface   = static_cast<Surface *>(surface);
327 
328     ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySurface(display, eglSurface, surface),
329                          "eglDestroySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
330 
331     ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface",
332                          GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
333 
334     thread->setSuccess();
335     return EGL_TRUE;
336 }
337 
EGL_QuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)338 EGLBoolean EGLAPIENTRY EGL_QuerySurface(EGLDisplay dpy,
339                                         EGLSurface surface,
340                                         EGLint attribute,
341                                         EGLint *value)
342 {
343     ANGLE_SCOPED_GLOBAL_LOCK();
344     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
345                ", EGLint attribute = %d, EGLint "
346                "*value = 0x%016" PRIxPTR,
347                (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value);
348     Thread *thread = egl::GetCurrentThread();
349 
350     const egl::Display *display = static_cast<const egl::Display *>(dpy);
351     const Surface *eglSurface   = static_cast<const Surface *>(surface);
352 
353     ANGLE_EGL_TRY_RETURN(thread, ValidateQuerySurface(display, eglSurface, attribute, value),
354                          "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
355 
356     QuerySurfaceAttrib(eglSurface, attribute, value);
357 
358     thread->setSuccess();
359     return EGL_TRUE;
360 }
361 
EGL_CreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)362 EGLContext EGLAPIENTRY EGL_CreateContext(EGLDisplay dpy,
363                                          EGLConfig config,
364                                          EGLContext share_context,
365                                          const EGLint *attrib_list)
366 {
367     ANGLE_SCOPED_GLOBAL_LOCK();
368     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
369                ", EGLContext share_context = %d, "
370                "const EGLint *attrib_list = 0x%016" PRIxPTR,
371                (uintptr_t)dpy, (uintptr_t)config, CID(dpy, share_context), (uintptr_t)attrib_list);
372     Thread *thread = egl::GetCurrentThread();
373 
374     egl::Display *display        = static_cast<egl::Display *>(dpy);
375     Config *configuration        = static_cast<Config *>(config);
376     gl::Context *sharedGLContext = static_cast<gl::Context *>(share_context);
377     AttributeMap attributes      = AttributeMap::CreateFromIntArray(attrib_list);
378 
379     ANGLE_EGL_TRY_RETURN(thread,
380                          ValidateCreateContext(display, configuration, sharedGLContext, attributes),
381                          "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT);
382 
383     gl::Context *context = nullptr;
384     ANGLE_EGL_TRY_RETURN(thread,
385                          display->createContext(configuration, sharedGLContext, thread->getAPI(),
386                                                 attributes, &context),
387                          "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT);
388 
389     thread->setSuccess();
390     return static_cast<EGLContext>(context);
391 }
392 
EGL_DestroyContext(EGLDisplay dpy,EGLContext ctx)393 EGLBoolean EGLAPIENTRY EGL_DestroyContext(EGLDisplay dpy, EGLContext ctx)
394 {
395     ANGLE_SCOPED_GLOBAL_LOCK();
396     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLContext ctx = %d", (uintptr_t)dpy,
397                CID(dpy, ctx));
398     Thread *thread = egl::GetCurrentThread();
399 
400     egl::Display *display = static_cast<egl::Display *>(dpy);
401     gl::Context *context  = static_cast<gl::Context *>(ctx);
402 
403     ANGLE_EGL_TRY_RETURN(thread, ValidateDestroyContext(display, context, ctx), "eglDestroyContext",
404                          GetContextIfValid(display, context), EGL_FALSE);
405 
406     bool contextWasCurrent = context == thread->getContext();
407 
408     ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext",
409                          GetContextIfValid(display, context), EGL_FALSE);
410 
411     if (contextWasCurrent)
412     {
413         SetContextCurrent(thread, nullptr);
414     }
415 
416     thread->setSuccess();
417     return EGL_TRUE;
418 }
419 
EGL_MakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)420 EGLBoolean EGLAPIENTRY EGL_MakeCurrent(EGLDisplay dpy,
421                                        EGLSurface draw,
422                                        EGLSurface read,
423                                        EGLContext ctx)
424 {
425     ANGLE_SCOPED_GLOBAL_LOCK();
426     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface draw = 0x%016" PRIxPTR
427                ", EGLSurface read = 0x%016" PRIxPTR
428                ", "
429                "EGLContext ctx = %d",
430                (uintptr_t)dpy, (uintptr_t)draw, (uintptr_t)read, CID(dpy, ctx));
431     Thread *thread = egl::GetCurrentThread();
432 
433     egl::Display *display = static_cast<egl::Display *>(dpy);
434     Surface *drawSurface  = static_cast<Surface *>(draw);
435     Surface *readSurface  = static_cast<Surface *>(read);
436     gl::Context *context  = static_cast<gl::Context *>(ctx);
437 
438     ANGLE_EGL_TRY_RETURN(thread, ValidateMakeCurrent(display, drawSurface, readSurface, context),
439                          "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
440 
441     Surface *previousDraw        = thread->getCurrentDrawSurface();
442     Surface *previousRead        = thread->getCurrentReadSurface();
443     gl::Context *previousContext = thread->getContext();
444 
445     // Only call makeCurrent if the context or surfaces have changed.
446     if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context)
447     {
448         ANGLE_EGL_TRY_RETURN(thread,
449                              display->makeCurrent(thread, drawSurface, readSurface, context),
450                              "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
451 
452         SetContextCurrent(thread, context);
453     }
454 
455     thread->setSuccess();
456     return EGL_TRUE;
457 }
458 
EGL_GetCurrentSurface(EGLint readdraw)459 EGLSurface EGLAPIENTRY EGL_GetCurrentSurface(EGLint readdraw)
460 {
461     ANGLE_SCOPED_GLOBAL_LOCK();
462     FUNC_EVENT("EGLint readdraw = %d", readdraw);
463     Thread *thread = egl::GetCurrentThread();
464 
465     if (readdraw == EGL_READ)
466     {
467         thread->setSuccess();
468         return thread->getCurrentReadSurface();
469     }
470     else if (readdraw == EGL_DRAW)
471     {
472         thread->setSuccess();
473         return thread->getCurrentDrawSurface();
474     }
475     else
476     {
477         thread->setError(EglBadParameter(), GetDebug(), "eglGetCurrentSurface", nullptr);
478         return EGL_NO_SURFACE;
479     }
480 }
481 
EGL_GetCurrentDisplay(void)482 EGLDisplay EGLAPIENTRY EGL_GetCurrentDisplay(void)
483 {
484     ANGLE_SCOPED_GLOBAL_LOCK();
485     EVENT(__FUNCTION__, "");
486     Thread *thread = egl::GetCurrentThread();
487 
488     thread->setSuccess();
489     if (thread->getContext() != nullptr)
490     {
491         return thread->getContext()->getDisplay();
492     }
493     return EGL_NO_DISPLAY;
494 }
495 
EGL_QueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)496 EGLBoolean EGLAPIENTRY EGL_QueryContext(EGLDisplay dpy,
497                                         EGLContext ctx,
498                                         EGLint attribute,
499                                         EGLint *value)
500 {
501     ANGLE_SCOPED_GLOBAL_LOCK();
502     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
503                ", EGLContext ctx = %d"
504                ", EGLint attribute = %d, EGLint *value "
505                "= 0x%016" PRIxPTR,
506                (uintptr_t)dpy, CID(dpy, ctx), attribute, (uintptr_t)value);
507     Thread *thread = egl::GetCurrentThread();
508 
509     egl::Display *display = static_cast<egl::Display *>(dpy);
510     gl::Context *context  = static_cast<gl::Context *>(ctx);
511 
512     ANGLE_EGL_TRY_RETURN(thread, ValidateQueryContext(display, context, attribute, value),
513                          "eglQueryContext", GetContextIfValid(display, context), EGL_FALSE);
514 
515     QueryContextAttrib(context, attribute, value);
516 
517     thread->setSuccess();
518     return EGL_TRUE;
519 }
520 
EGL_WaitGL(void)521 EGLBoolean EGLAPIENTRY EGL_WaitGL(void)
522 {
523     ANGLE_SCOPED_GLOBAL_LOCK();
524     EVENT(__FUNCTION__, "");
525     Thread *thread = egl::GetCurrentThread();
526 
527     egl::Display *display = thread->getDisplay();
528 
529     ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglWaitGL", GetDisplayIfValid(display),
530                          EGL_FALSE);
531 
532     // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
533     // OpenGL ES we can do the call directly.
534     ANGLE_EGL_TRY_RETURN(thread, display->waitClient(thread->getContext()), "eglWaitGL",
535                          GetDisplayIfValid(display), EGL_FALSE);
536 
537     thread->setSuccess();
538     return EGL_TRUE;
539 }
540 
EGL_WaitNative(EGLint engine)541 EGLBoolean EGLAPIENTRY EGL_WaitNative(EGLint engine)
542 {
543     ANGLE_SCOPED_GLOBAL_LOCK();
544     FUNC_EVENT("EGLint engine = %d", engine);
545     Thread *thread = egl::GetCurrentThread();
546 
547     egl::Display *display = thread->getDisplay();
548 
549     ANGLE_EGL_TRY_RETURN(thread, ValidateWaitNative(display, engine), "eglWaitNative",
550                          GetThreadIfValid(thread), EGL_FALSE);
551 
552     ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative",
553                          GetThreadIfValid(thread), EGL_FALSE);
554 
555     thread->setSuccess();
556     return EGL_TRUE;
557 }
558 
EGL_SwapBuffers(EGLDisplay dpy,EGLSurface surface)559 EGLBoolean EGLAPIENTRY EGL_SwapBuffers(EGLDisplay dpy, EGLSurface surface)
560 {
561     ANGLE_SCOPED_GLOBAL_LOCK();
562     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR,
563                (uintptr_t)dpy, (uintptr_t)surface);
564     Thread *thread = egl::GetCurrentThread();
565 
566     egl::Display *display = static_cast<egl::Display *>(dpy);
567     Surface *eglSurface   = (Surface *)surface;
568 
569     ANGLE_EGL_TRY_RETURN(thread, ValidateSwapBuffers(thread, display, eglSurface), "eglSwapBuffers",
570                          GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
571 
572     ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers",
573                          GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
574 
575     thread->setSuccess();
576     return EGL_TRUE;
577 }
578 
EGL_CopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)579 EGLBoolean EGLAPIENTRY EGL_CopyBuffers(EGLDisplay dpy,
580                                        EGLSurface surface,
581                                        EGLNativePixmapType target)
582 {
583     ANGLE_SCOPED_GLOBAL_LOCK();
584     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
585                ", EGLNativePixmapType target = "
586                "0x%016" PRIxPTR,
587                (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)target);
588     Thread *thread = egl::GetCurrentThread();
589 
590     egl::Display *display = static_cast<egl::Display *>(dpy);
591     Surface *eglSurface   = static_cast<Surface *>(surface);
592 
593     ANGLE_EGL_TRY_RETURN(thread, ValidateCopyBuffers(display, eglSurface), "eglCopyBuffers",
594                          GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
595 
596     UNIMPLEMENTED();  // FIXME
597 
598     thread->setSuccess();
599     return 0;
600 }
601 
602 // EGL 1.1
EGL_BindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)603 EGLBoolean EGLAPIENTRY EGL_BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
604 {
605     ANGLE_SCOPED_GLOBAL_LOCK();
606     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
607                ", EGLint buffer = %d",
608                (uintptr_t)dpy, (uintptr_t)surface, buffer);
609     Thread *thread = egl::GetCurrentThread();
610 
611     egl::Display *display      = static_cast<egl::Display *>(dpy);
612     Surface *eglSurface        = static_cast<Surface *>(surface);
613     gl::Context *context       = thread->getContext();
614     gl::Texture *textureObject = nullptr;
615 
616     ANGLE_EGL_TRY_RETURN(
617         thread, ValidateBindTexImage(display, eglSurface, surface, buffer, context, &textureObject),
618         "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
619 
620     if (context)
621     {
622         ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer),
623                              "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
624     }
625 
626     thread->setSuccess();
627     return EGL_TRUE;
628 }
629 
EGL_SurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)630 EGLBoolean EGLAPIENTRY EGL_SurfaceAttrib(EGLDisplay dpy,
631                                          EGLSurface surface,
632                                          EGLint attribute,
633                                          EGLint value)
634 {
635     ANGLE_SCOPED_GLOBAL_LOCK();
636     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
637                ", EGLint attribute = %d, EGLint "
638                "value = %d",
639                (uintptr_t)dpy, (uintptr_t)surface, attribute, value);
640     Thread *thread = egl::GetCurrentThread();
641 
642     egl::Display *display = static_cast<egl::Display *>(dpy);
643     Surface *eglSurface   = static_cast<Surface *>(surface);
644 
645     ANGLE_EGL_TRY_RETURN(thread, ValidateSurfaceAttrib(display, eglSurface, attribute, value),
646                          "eglSurfaceAttrib", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
647 
648     SetSurfaceAttrib(eglSurface, attribute, value);
649 
650     thread->setSuccess();
651     return EGL_TRUE;
652 }
653 
EGL_ReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)654 EGLBoolean EGLAPIENTRY EGL_ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
655 {
656     ANGLE_SCOPED_GLOBAL_LOCK();
657     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
658                ", EGLint buffer = %d",
659                (uintptr_t)dpy, (uintptr_t)surface, buffer);
660     Thread *thread = egl::GetCurrentThread();
661 
662     egl::Display *display = static_cast<egl::Display *>(dpy);
663     Surface *eglSurface   = static_cast<Surface *>(surface);
664 
665     ANGLE_EGL_TRY_RETURN(thread, ValidateReleaseTexImage(display, eglSurface, surface, buffer),
666                          "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
667 
668     gl::Texture *texture = eglSurface->getBoundTexture();
669 
670     if (texture)
671     {
672         ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer),
673                              "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface),
674                              EGL_FALSE);
675     }
676 
677     thread->setSuccess();
678     return EGL_TRUE;
679 }
680 
EGL_SwapInterval(EGLDisplay dpy,EGLint interval)681 EGLBoolean EGLAPIENTRY EGL_SwapInterval(EGLDisplay dpy, EGLint interval)
682 {
683     ANGLE_SCOPED_GLOBAL_LOCK();
684     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint interval = %d", (uintptr_t)dpy,
685                interval);
686     Thread *thread       = egl::GetCurrentThread();
687     gl::Context *context = thread->getContext();
688 
689     egl::Display *display = static_cast<egl::Display *>(dpy);
690     Surface *draw_surface = static_cast<Surface *>(thread->getCurrentDrawSurface());
691 
692     ANGLE_EGL_TRY_RETURN(thread, ValidateSwapInterval(display, draw_surface, context),
693                          "eglSwapInterval", GetDisplayIfValid(display), EGL_FALSE);
694 
695     const egl::Config *surfaceConfig = draw_surface->getConfig();
696     EGLint clampedInterval           = std::min(std::max(interval, surfaceConfig->minSwapInterval),
697                                       surfaceConfig->maxSwapInterval);
698 
699     draw_surface->setSwapInterval(clampedInterval);
700 
701     thread->setSuccess();
702     return EGL_TRUE;
703 }
704 
705 // EGL 1.2
EGL_BindAPI(EGLenum api)706 EGLBoolean EGLAPIENTRY EGL_BindAPI(EGLenum api)
707 {
708     ANGLE_SCOPED_GLOBAL_LOCK();
709     FUNC_EVENT("EGLenum api = 0x%X", api);
710     Thread *thread = egl::GetCurrentThread();
711 
712     ANGLE_EGL_TRY_RETURN(thread, ValidateBindAPI(api), "eglBindAPI", GetThreadIfValid(thread),
713                          EGL_FALSE);
714 
715     thread->setAPI(api);
716 
717     thread->setSuccess();
718     return EGL_TRUE;
719 }
720 
EGL_QueryAPI(void)721 EGLenum EGLAPIENTRY EGL_QueryAPI(void)
722 {
723     ANGLE_SCOPED_GLOBAL_LOCK();
724     EVENT(__FUNCTION__, "");
725     Thread *thread = egl::GetCurrentThread();
726 
727     EGLenum API = thread->getAPI();
728 
729     thread->setSuccess();
730     return API;
731 }
732 
EGL_CreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)733 EGLSurface EGLAPIENTRY EGL_CreatePbufferFromClientBuffer(EGLDisplay dpy,
734                                                          EGLenum buftype,
735                                                          EGLClientBuffer buffer,
736                                                          EGLConfig config,
737                                                          const EGLint *attrib_list)
738 {
739     ANGLE_SCOPED_GLOBAL_LOCK();
740     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
741                ", EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%016" PRIxPTR
742                ", "
743                "EGLConfig config = 0x%016" PRIxPTR ", const EGLint *attrib_list = 0x%016" PRIxPTR,
744                (uintptr_t)dpy, buftype, (uintptr_t)buffer, (uintptr_t)config,
745                (uintptr_t)attrib_list);
746     Thread *thread = egl::GetCurrentThread();
747 
748     egl::Display *display   = static_cast<egl::Display *>(dpy);
749     Config *configuration   = static_cast<Config *>(config);
750     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
751 
752     ANGLE_EGL_TRY_RETURN(
753         thread,
754         ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes),
755         "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display), EGL_NO_SURFACE);
756 
757     egl::Surface *surface = nullptr;
758     ANGLE_EGL_TRY_RETURN(thread,
759                          display->createPbufferFromClientBuffer(configuration, buftype, buffer,
760                                                                 attributes, &surface),
761                          "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display),
762                          EGL_NO_SURFACE);
763 
764     return static_cast<EGLSurface>(surface);
765 }
766 
EGL_ReleaseThread(void)767 EGLBoolean EGLAPIENTRY EGL_ReleaseThread(void)
768 {
769     ANGLE_SCOPED_GLOBAL_LOCK();
770     EVENT(__FUNCTION__, "");
771     Thread *thread = egl::GetCurrentThread();
772 
773     Surface *previousDraw         = thread->getCurrentDrawSurface();
774     Surface *previousRead         = thread->getCurrentReadSurface();
775     gl::Context *previousContext  = thread->getContext();
776     egl::Display *previousDisplay = thread->getDisplay();
777 
778     // Only call makeCurrent if the context or surfaces have changed.
779     if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE ||
780         previousContext != EGL_NO_CONTEXT)
781     {
782         if (previousDisplay != EGL_NO_DISPLAY)
783         {
784             ANGLE_EGL_TRY_RETURN(thread,
785                                  previousDisplay->makeCurrent(thread, nullptr, nullptr, nullptr),
786                                  "eglReleaseThread", nullptr, EGL_FALSE);
787         }
788 
789         SetContextCurrent(thread, nullptr);
790     }
791 
792     thread->setSuccess();
793     return EGL_TRUE;
794 }
795 
EGL_WaitClient(void)796 EGLBoolean EGLAPIENTRY EGL_WaitClient(void)
797 {
798     ANGLE_SCOPED_GLOBAL_LOCK();
799     EVENT(__FUNCTION__, "");
800     Thread *thread = egl::GetCurrentThread();
801 
802     egl::Display *display = thread->getDisplay();
803     gl::Context *context  = thread->getContext();
804 
805     ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglWaitClient",
806                          GetContextIfValid(display, context), EGL_FALSE);
807 
808     ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient",
809                          GetContextIfValid(display, context), EGL_FALSE);
810 
811     thread->setSuccess();
812     return EGL_TRUE;
813 }
814 
815 // EGL 1.4
EGL_GetCurrentContext(void)816 EGLContext EGLAPIENTRY EGL_GetCurrentContext(void)
817 {
818     ANGLE_SCOPED_GLOBAL_LOCK();
819     EVENT(__FUNCTION__, "");
820     Thread *thread = egl::GetCurrentThread();
821 
822     gl::Context *context = thread->getContext();
823 
824     thread->setSuccess();
825     return static_cast<EGLContext>(context);
826 }
827 
828 // EGL 1.5
EGL_CreateSync(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)829 EGLSync EGLAPIENTRY EGL_CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
830 {
831     ANGLE_SCOPED_GLOBAL_LOCK();
832     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
833                ", EGLenum type = 0x%X, const EGLint* attrib_list = 0x%016" PRIxPTR,
834                (uintptr_t)dpy, type, (uintptr_t)attrib_list);
835 
836     Thread *thread          = egl::GetCurrentThread();
837     egl::Display *display   = static_cast<egl::Display *>(dpy);
838     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
839 
840     gl::Context *currentContext  = thread->getContext();
841     egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
842 
843     ANGLE_EGL_TRY_RETURN(
844         thread, ValidateCreateSyncKHR(display, type, attributes, currentDisplay, currentContext),
845         "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
846 
847     egl::Sync *syncObject = nullptr;
848     ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
849                          "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
850 
851     thread->setSuccess();
852     return static_cast<EGLSync>(syncObject);
853 }
854 
EGL_DestroySync(EGLDisplay dpy,EGLSync sync)855 EGLBoolean EGLAPIENTRY EGL_DestroySync(EGLDisplay dpy, EGLSync sync)
856 {
857     ANGLE_SCOPED_GLOBAL_LOCK();
858     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR, (uintptr_t)dpy,
859                (uintptr_t)sync);
860 
861     Thread *thread        = egl::GetCurrentThread();
862     egl::Display *display = static_cast<egl::Display *>(dpy);
863     egl::Sync *syncObject = static_cast<Sync *>(sync);
864 
865     ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySync(display, syncObject), "eglDestroySync",
866                          GetDisplayIfValid(display), EGL_FALSE);
867 
868     display->destroySync(syncObject);
869 
870     thread->setSuccess();
871     return EGL_TRUE;
872 }
873 
EGL_ClientWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)874 EGLint EGLAPIENTRY EGL_ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
875 {
876     ANGLE_SCOPED_GLOBAL_LOCK();
877     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR
878                ", EGLint flags = 0x%X, EGLTime timeout = "
879                "%llu",
880                (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast<unsigned long long>(timeout));
881 
882     Thread *thread        = egl::GetCurrentThread();
883     egl::Display *display = static_cast<egl::Display *>(dpy);
884     egl::Sync *syncObject = static_cast<Sync *>(sync);
885 
886     ANGLE_EGL_TRY_RETURN(thread, ValidateClientWaitSync(display, syncObject, flags, timeout),
887                          "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
888 
889     gl::Context *currentContext = thread->getContext();
890     EGLint syncStatus           = EGL_FALSE;
891     ANGLE_EGL_TRY_RETURN(
892         thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus),
893         "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
894 
895     thread->setSuccess();
896     return syncStatus;
897 }
898 
EGL_GetSyncAttrib(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLAttrib * value)899 EGLBoolean EGLAPIENTRY EGL_GetSyncAttrib(EGLDisplay dpy,
900                                          EGLSync sync,
901                                          EGLint attribute,
902                                          EGLAttrib *value)
903 {
904     ANGLE_SCOPED_GLOBAL_LOCK();
905     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR
906                ", EGLint attribute = 0x%X, EGLAttrib "
907                "*value = 0x%016" PRIxPTR,
908                (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value);
909 
910     Thread *thread        = egl::GetCurrentThread();
911     egl::Display *display = static_cast<egl::Display *>(dpy);
912     egl::Sync *syncObject = static_cast<Sync *>(sync);
913 
914     ANGLE_EGL_TRY_RETURN(thread, ValidateGetSyncAttrib(display, syncObject, attribute, value),
915                          "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
916 
917     EGLint valueExt;
918     ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, &valueExt),
919                          "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
920     *value = valueExt;
921 
922     thread->setSuccess();
923     return EGL_TRUE;
924 }
925 
EGL_CreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attrib_list)926 EGLImage EGLAPIENTRY EGL_CreateImage(EGLDisplay dpy,
927                                      EGLContext ctx,
928                                      EGLenum target,
929                                      EGLClientBuffer buffer,
930                                      const EGLAttrib *attrib_list)
931 {
932     ANGLE_SCOPED_GLOBAL_LOCK();
933     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR
934                ", EGLContext ctx = %d"
935                ", EGLenum target = 0x%X, "
936                "EGLClientBuffer buffer = 0x%016" PRIxPTR
937                ", const EGLAttrib *attrib_list = 0x%016" PRIxPTR,
938                (uintptr_t)dpy, CID(dpy, ctx), target, (uintptr_t)buffer, (uintptr_t)attrib_list);
939     Thread *thread = egl::GetCurrentThread();
940 
941     egl::Display *display   = static_cast<egl::Display *>(dpy);
942     gl::Context *context    = static_cast<gl::Context *>(ctx);
943     AttributeMap attributes = AttributeMap::CreateFromIntArray((const EGLint *)attrib_list);
944 
945     Error error = ValidateCreateImage(display, context, target, buffer, attributes);
946     if (error.isError())
947     {
948         thread->setError(error, GetDebug(), "eglCreateImage", GetDisplayIfValid(display));
949         return EGL_NO_IMAGE;
950     }
951 
952     Image *image = nullptr;
953     error        = display->createImage(context, target, buffer, attributes, &image);
954     if (error.isError())
955     {
956         thread->setError(error, GetDebug(), "eglCreateImage", GetDisplayIfValid(display));
957         return EGL_NO_IMAGE;
958     }
959 
960     thread->setSuccess();
961     return static_cast<EGLImage>(image);
962 }
963 
EGL_DestroyImage(EGLDisplay dpy,EGLImage image)964 EGLBoolean EGLAPIENTRY EGL_DestroyImage(EGLDisplay dpy, EGLImage image)
965 {
966     ANGLE_SCOPED_GLOBAL_LOCK();
967     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLImage image = 0x%016" PRIxPTR,
968                (uintptr_t)dpy, (uintptr_t)image);
969     Thread *thread        = egl::GetCurrentThread();
970     egl::Display *display = static_cast<egl::Display *>(dpy);
971     Image *img            = static_cast<Image *>(image);
972 
973     Error error = ValidateDestroyImage(display, img);
974     if (error.isError())
975     {
976         thread->setError(error, GetDebug(), "eglDestroyImage", GetImageIfValid(display, img));
977         return EGL_FALSE;
978     }
979 
980     display->destroyImage(img);
981 
982     thread->setSuccess();
983     return EGL_TRUE;
984 }
985 
EGL_GetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)986 EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplay(EGLenum platform,
987                                               void *native_display,
988                                               const EGLAttrib *attrib_list)
989 {
990     ANGLE_SCOPED_GLOBAL_LOCK();
991     FUNC_EVENT("EGLenum platform = %d, void* native_display = 0x%016" PRIxPTR
992                ", const EGLint* attrib_list = "
993                "0x%016" PRIxPTR,
994                platform, (uintptr_t)native_display, (uintptr_t)attrib_list);
995     Thread *thread = egl::GetCurrentThread();
996 
997     ANGLE_EGL_TRY_RETURN(thread, ValidateGetPlatformDisplay(platform, native_display, attrib_list),
998                          "eglGetPlatformDisplay", GetThreadIfValid(thread), EGL_NO_DISPLAY);
999 
1000     const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list);
1001     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
1002     {
1003         return egl::Display::GetDisplayFromNativeDisplay(
1004             gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
1005     }
1006     else if (platform == EGL_PLATFORM_DEVICE_EXT)
1007     {
1008         Device *eglDevice = static_cast<Device *>(native_display);
1009         return egl::Display::GetDisplayFromDevice(eglDevice, attribMap);
1010     }
1011     else
1012     {
1013         UNREACHABLE();
1014         return EGL_NO_DISPLAY;
1015     }
1016 }
1017 
EGL_CreatePlatformWindowSurface(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLAttrib * attrib_list)1018 EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurface(EGLDisplay dpy,
1019                                                        EGLConfig config,
1020                                                        void *native_window,
1021                                                        const EGLAttrib *attrib_list)
1022 {
1023     ANGLE_SCOPED_GLOBAL_LOCK();
1024     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
1025                ", void* native_window = 0x%016" PRIxPTR
1026                ", "
1027                "const EGLint* attrib_list = 0x%016" PRIxPTR,
1028                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list);
1029     Thread *thread        = egl::GetCurrentThread();
1030     egl::Display *display = static_cast<egl::Display *>(dpy);
1031 
1032     UNIMPLEMENTED();
1033     thread->setError(EglBadDisplay() << "eglCreatePlatformWindowSurface unimplemented.", GetDebug(),
1034                      "eglCreatePlatformWindowSurface", GetDisplayIfValid(display));
1035     return EGL_NO_SURFACE;
1036 }
1037 
EGL_CreatePlatformPixmapSurface(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLAttrib * attrib_list)1038 EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy,
1039                                                        EGLConfig config,
1040                                                        void *native_pixmap,
1041                                                        const EGLAttrib *attrib_list)
1042 {
1043     ANGLE_SCOPED_GLOBAL_LOCK();
1044     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR
1045                ", void* native_pixmap = 0x%016" PRIxPTR
1046                ", "
1047                "const EGLint* attrib_list = 0x%016" PRIxPTR,
1048                (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list);
1049     Thread *thread        = egl::GetCurrentThread();
1050     egl::Display *display = static_cast<egl::Display *>(dpy);
1051 
1052     UNIMPLEMENTED();
1053     thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.", GetDebug(),
1054                      "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display));
1055     return EGL_NO_SURFACE;
1056 }
1057 
EGL_WaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags)1058 EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
1059 {
1060     ANGLE_SCOPED_GLOBAL_LOCK();
1061     FUNC_EVENT("EGLDisplay dpy =0x%016" PRIxPTR "p, EGLSync sync = 0x%016" PRIxPTR
1062                ", EGLint flags = 0x%X",
1063                (uintptr_t)dpy, (uintptr_t)sync, flags);
1064 
1065     Thread *thread        = egl::GetCurrentThread();
1066     egl::Display *display = static_cast<egl::Display *>(dpy);
1067     gl::Context *context  = thread->getContext();
1068     egl::Sync *syncObject = static_cast<Sync *>(sync);
1069 
1070     ANGLE_EGL_TRY_RETURN(thread, ValidateWaitSync(display, context, syncObject, flags),
1071                          "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
1072 
1073     gl::Context *currentContext = thread->getContext();
1074     ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
1075                          "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
1076 
1077     thread->setSuccess();
1078     return EGL_TRUE;
1079 }
1080 
EGL_GetProcAddress(const char * procname)1081 __eglMustCastToProperFunctionPointerType EGLAPIENTRY EGL_GetProcAddress(const char *procname)
1082 {
1083     ANGLE_SCOPED_GLOBAL_LOCK();
1084     FUNC_EVENT("const char *procname = \"%s\"", procname);
1085     Thread *thread = egl::GetCurrentThread();
1086 
1087     ProcEntry *entry =
1088         std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc);
1089 
1090     thread->setSuccess();
1091 
1092     if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0)
1093     {
1094         return nullptr;
1095     }
1096 
1097     return entry->second;
1098 }
1099 }  // extern "C"
1100