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