1 //
2 // Copyright (c) 2002-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 // libEGL.cpp: Implements the exported EGL functions.
8
9 #include <exception>
10
11 #include "common/debug.h"
12 #include "common/version.h"
13 #include "libGLESv2/Context.h"
14 #include "libGLESv2/Texture.h"
15 #include "libGLESv2/main.h"
16 #include "libGLESv2/renderer/SwapChain.h"
17
18 #include "libEGL/main.h"
19 #include "libEGL/Display.h"
20 #include "libEGL/Surface.h"
21
validateDisplay(egl::Display * display)22 bool validateDisplay(egl::Display *display)
23 {
24 if (display == EGL_NO_DISPLAY)
25 {
26 return egl::error(EGL_BAD_DISPLAY, false);
27 }
28
29 if (!display->isInitialized())
30 {
31 return egl::error(EGL_NOT_INITIALIZED, false);
32 }
33
34 return true;
35 }
36
validateConfig(egl::Display * display,EGLConfig config)37 bool validateConfig(egl::Display *display, EGLConfig config)
38 {
39 if (!validateDisplay(display))
40 {
41 return false;
42 }
43
44 if (!display->isValidConfig(config))
45 {
46 return egl::error(EGL_BAD_CONFIG, false);
47 }
48
49 return true;
50 }
51
validateContext(egl::Display * display,gl::Context * context)52 bool validateContext(egl::Display *display, gl::Context *context)
53 {
54 if (!validateDisplay(display))
55 {
56 return false;
57 }
58
59 if (!display->isValidContext(context))
60 {
61 return egl::error(EGL_BAD_CONTEXT, false);
62 }
63
64 return true;
65 }
66
validateSurface(egl::Display * display,egl::Surface * surface)67 bool validateSurface(egl::Display *display, egl::Surface *surface)
68 {
69 if (!validateDisplay(display))
70 {
71 return false;
72 }
73
74 if (!display->isValidSurface(surface))
75 {
76 return egl::error(EGL_BAD_SURFACE, false);
77 }
78
79 return true;
80 }
81
82 extern "C"
83 {
eglGetError(void)84 EGLint __stdcall eglGetError(void)
85 {
86 EVENT("()");
87
88 EGLint error = egl::getCurrentError();
89
90 if (error != EGL_SUCCESS)
91 {
92 egl::setCurrentError(EGL_SUCCESS);
93 }
94
95 return error;
96 }
97
eglGetDisplay(EGLNativeDisplayType display_id)98 EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
99 {
100 EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
101
102 try
103 {
104 return egl::Display::getDisplay(display_id);
105 }
106 catch (...)
107 {
108 return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
109 }
110 }
111
eglInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)112 EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
113 {
114 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
115 dpy, major, minor);
116
117 try
118 {
119 if (dpy == EGL_NO_DISPLAY)
120 {
121 return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
122 }
123
124 egl::Display *display = static_cast<egl::Display*>(dpy);
125
126 if (!display->initialize())
127 {
128 return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
129 }
130
131 if (major) *major = 1;
132 if (minor) *minor = 4;
133
134 return egl::success(EGL_TRUE);
135 }
136 catch (...)
137 {
138 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
139 }
140 }
141
eglTerminate(EGLDisplay dpy)142 EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
143 {
144 EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
145
146 try
147 {
148 if (dpy == EGL_NO_DISPLAY)
149 {
150 return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
151 }
152
153 egl::Display *display = static_cast<egl::Display*>(dpy);
154
155 display->terminate();
156
157 return egl::success(EGL_TRUE);
158 }
159 catch (...)
160 {
161 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
162 }
163 }
164
eglQueryString(EGLDisplay dpy,EGLint name)165 const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
166 {
167 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
168
169 try
170 {
171 egl::Display *display = static_cast<egl::Display*>(dpy);
172
173 if (!validateDisplay(display))
174 {
175 return NULL;
176 }
177
178 switch (name)
179 {
180 case EGL_CLIENT_APIS:
181 return egl::success("OpenGL_ES");
182 case EGL_EXTENSIONS:
183 return egl::success(display->getExtensionString());
184 case EGL_VENDOR:
185 return egl::success(display->getVendorString());
186 case EGL_VERSION:
187 return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")");
188 }
189
190 return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
191 }
192 catch (...)
193 {
194 return egl::error(EGL_BAD_ALLOC, (const char*)NULL);
195 }
196 }
197
eglGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)198 EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
199 {
200 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
201 "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
202 dpy, configs, config_size, num_config);
203
204 try
205 {
206 egl::Display *display = static_cast<egl::Display*>(dpy);
207
208 if (!validateDisplay(display))
209 {
210 return EGL_FALSE;
211 }
212
213 if (!num_config)
214 {
215 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
216 }
217
218 const EGLint attribList[] = {EGL_NONE};
219
220 if (!display->getConfigs(configs, attribList, config_size, num_config))
221 {
222 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
223 }
224
225 return egl::success(EGL_TRUE);
226 }
227 catch (...)
228 {
229 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
230 }
231 }
232
eglChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)233 EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
234 {
235 EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
236 "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
237 dpy, attrib_list, configs, config_size, num_config);
238
239 try
240 {
241 egl::Display *display = static_cast<egl::Display*>(dpy);
242
243 if (!validateDisplay(display))
244 {
245 return EGL_FALSE;
246 }
247
248 if (!num_config)
249 {
250 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
251 }
252
253 const EGLint attribList[] = {EGL_NONE};
254
255 if (!attrib_list)
256 {
257 attrib_list = attribList;
258 }
259
260 display->getConfigs(configs, attrib_list, config_size, num_config);
261
262 return egl::success(EGL_TRUE);
263 }
264 catch (...)
265 {
266 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
267 }
268 }
269
eglGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)270 EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
271 {
272 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
273 dpy, config, attribute, value);
274
275 try
276 {
277 egl::Display *display = static_cast<egl::Display*>(dpy);
278
279 if (!validateConfig(display, config))
280 {
281 return EGL_FALSE;
282 }
283
284 if (!display->getConfigAttrib(config, attribute, value))
285 {
286 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
287 }
288
289 return egl::success(EGL_TRUE);
290 }
291 catch (...)
292 {
293 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
294 }
295 }
296
eglCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)297 EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
298 {
299 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
300 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
301
302 try
303 {
304 egl::Display *display = static_cast<egl::Display*>(dpy);
305
306 if (!validateConfig(display, config))
307 {
308 return EGL_NO_SURFACE;
309 }
310
311 HWND window = (HWND)win;
312
313 if (!IsWindow(window))
314 {
315 return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
316 }
317
318 return display->createWindowSurface(window, config, attrib_list);
319 }
320 catch (...)
321 {
322 return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
323 }
324 }
325
eglCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)326 EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
327 {
328 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
329 dpy, config, attrib_list);
330
331 try
332 {
333 egl::Display *display = static_cast<egl::Display*>(dpy);
334
335 if (!validateConfig(display, config))
336 {
337 return EGL_NO_SURFACE;
338 }
339
340 return display->createOffscreenSurface(config, NULL, attrib_list);
341 }
342 catch (...)
343 {
344 return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
345 }
346 }
347
eglCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)348 EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
349 {
350 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
351 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
352
353 try
354 {
355 egl::Display *display = static_cast<egl::Display*>(dpy);
356
357 if (!validateConfig(display, config))
358 {
359 return EGL_NO_SURFACE;
360 }
361
362 UNIMPLEMENTED(); // FIXME
363
364 return egl::success(EGL_NO_SURFACE);
365 }
366 catch (...)
367 {
368 return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
369 }
370 }
371
eglDestroySurface(EGLDisplay dpy,EGLSurface surface)372 EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
373 {
374 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
375
376 try
377 {
378 egl::Display *display = static_cast<egl::Display*>(dpy);
379 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
380
381 if (!validateSurface(display, eglSurface))
382 {
383 return EGL_FALSE;
384 }
385
386 if (surface == EGL_NO_SURFACE)
387 {
388 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
389 }
390
391 display->destroySurface((egl::Surface*)surface);
392
393 return egl::success(EGL_TRUE);
394 }
395 catch (...)
396 {
397 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
398 }
399 }
400
eglQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)401 EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
402 {
403 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
404 dpy, surface, attribute, value);
405
406 try
407 {
408 egl::Display *display = static_cast<egl::Display*>(dpy);
409 egl::Surface *eglSurface = (egl::Surface*)surface;
410
411 if (!validateSurface(display, eglSurface))
412 {
413 return EGL_FALSE;
414 }
415
416 if (surface == EGL_NO_SURFACE)
417 {
418 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
419 }
420
421 switch (attribute)
422 {
423 case EGL_VG_ALPHA_FORMAT:
424 UNIMPLEMENTED(); // FIXME
425 break;
426 case EGL_VG_COLORSPACE:
427 UNIMPLEMENTED(); // FIXME
428 break;
429 case EGL_CONFIG_ID:
430 *value = eglSurface->getConfigID();
431 break;
432 case EGL_HEIGHT:
433 *value = eglSurface->getHeight();
434 break;
435 case EGL_HORIZONTAL_RESOLUTION:
436 UNIMPLEMENTED(); // FIXME
437 break;
438 case EGL_LARGEST_PBUFFER:
439 UNIMPLEMENTED(); // FIXME
440 break;
441 case EGL_MIPMAP_TEXTURE:
442 UNIMPLEMENTED(); // FIXME
443 break;
444 case EGL_MIPMAP_LEVEL:
445 UNIMPLEMENTED(); // FIXME
446 break;
447 case EGL_MULTISAMPLE_RESOLVE:
448 UNIMPLEMENTED(); // FIXME
449 break;
450 case EGL_PIXEL_ASPECT_RATIO:
451 *value = eglSurface->getPixelAspectRatio();
452 break;
453 case EGL_RENDER_BUFFER:
454 *value = eglSurface->getRenderBuffer();
455 break;
456 case EGL_SWAP_BEHAVIOR:
457 *value = eglSurface->getSwapBehavior();
458 break;
459 case EGL_TEXTURE_FORMAT:
460 *value = eglSurface->getTextureFormat();
461 break;
462 case EGL_TEXTURE_TARGET:
463 *value = eglSurface->getTextureTarget();
464 break;
465 case EGL_VERTICAL_RESOLUTION:
466 UNIMPLEMENTED(); // FIXME
467 break;
468 case EGL_WIDTH:
469 *value = eglSurface->getWidth();
470 break;
471 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
472 *value = eglSurface->isPostSubBufferSupported();
473 break;
474 case EGL_FIXED_SIZE_ANGLE:
475 *value = eglSurface->isFixedSize();
476 break;
477 default:
478 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
479 }
480
481 return egl::success(EGL_TRUE);
482 }
483 catch (...)
484 {
485 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
486 }
487 }
488
eglQuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)489 EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
490 {
491 TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
492 dpy, surface, attribute, value);
493
494 try
495 {
496 egl::Display *display = static_cast<egl::Display*>(dpy);
497 egl::Surface *eglSurface = (egl::Surface*)surface;
498
499 if (!validateSurface(display, eglSurface))
500 {
501 return EGL_FALSE;
502 }
503
504 if (surface == EGL_NO_SURFACE)
505 {
506 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
507 }
508
509 switch (attribute)
510 {
511 case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
512 {
513 rx::SwapChain *swapchain = eglSurface->getSwapChain();
514 *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
515 }
516 break;
517 default:
518 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
519 }
520
521 return egl::success(EGL_TRUE);
522 }
523 catch (...)
524 {
525 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
526 }
527 }
528
eglBindAPI(EGLenum api)529 EGLBoolean __stdcall eglBindAPI(EGLenum api)
530 {
531 EVENT("(EGLenum api = 0x%X)", api);
532
533 try
534 {
535 switch (api)
536 {
537 case EGL_OPENGL_API:
538 case EGL_OPENVG_API:
539 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
540 case EGL_OPENGL_ES_API:
541 break;
542 default:
543 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
544 }
545
546 egl::setCurrentAPI(api);
547
548 return egl::success(EGL_TRUE);
549 }
550 catch (...)
551 {
552 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
553 }
554 }
555
eglQueryAPI(void)556 EGLenum __stdcall eglQueryAPI(void)
557 {
558 EVENT("()");
559
560 try
561 {
562 EGLenum API = egl::getCurrentAPI();
563
564 return egl::success(API);
565 }
566 catch (...)
567 {
568 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
569 }
570 }
571
eglWaitClient(void)572 EGLBoolean __stdcall eglWaitClient(void)
573 {
574 EVENT("()");
575
576 try
577 {
578 UNIMPLEMENTED(); // FIXME
579
580 return egl::success(0);
581 }
582 catch (...)
583 {
584 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
585 }
586 }
587
eglReleaseThread(void)588 EGLBoolean __stdcall eglReleaseThread(void)
589 {
590 EVENT("()");
591
592 try
593 {
594 eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
595
596 return egl::success(EGL_TRUE);
597 }
598 catch (...)
599 {
600 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
601 }
602 }
603
eglCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)604 EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
605 {
606 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
607 "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
608 dpy, buftype, buffer, config, attrib_list);
609
610 try
611 {
612 egl::Display *display = static_cast<egl::Display*>(dpy);
613
614 if (!validateConfig(display, config))
615 {
616 return EGL_NO_SURFACE;
617 }
618
619 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
620 {
621 return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
622 }
623
624 return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
625 }
626 catch (...)
627 {
628 return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
629 }
630 }
631
eglSurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)632 EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
633 {
634 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
635 dpy, surface, attribute, value);
636
637 try
638 {
639 egl::Display *display = static_cast<egl::Display*>(dpy);
640 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
641
642 if (!validateSurface(display, eglSurface))
643 {
644 return EGL_FALSE;
645 }
646
647 UNIMPLEMENTED(); // FIXME
648
649 return egl::success(EGL_TRUE);
650 }
651 catch (...)
652 {
653 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
654 }
655 }
656
eglBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)657 EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
658 {
659 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
660
661 try
662 {
663 egl::Display *display = static_cast<egl::Display*>(dpy);
664 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
665
666 if (!validateSurface(display, eglSurface))
667 {
668 return EGL_FALSE;
669 }
670
671 if (buffer != EGL_BACK_BUFFER)
672 {
673 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
674 }
675
676 if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
677 {
678 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
679 }
680
681 if (eglSurface->getBoundTexture())
682 {
683 return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
684 }
685
686 if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
687 {
688 return egl::error(EGL_BAD_MATCH, EGL_FALSE);
689 }
690
691 if (!glBindTexImage(eglSurface))
692 {
693 return egl::error(EGL_BAD_MATCH, EGL_FALSE);
694 }
695
696 return egl::success(EGL_TRUE);
697 }
698 catch (...)
699 {
700 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
701 }
702 }
703
eglReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)704 EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
705 {
706 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
707
708 try
709 {
710 egl::Display *display = static_cast<egl::Display*>(dpy);
711 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
712
713 if (!validateSurface(display, eglSurface))
714 {
715 return EGL_FALSE;
716 }
717
718 if (buffer != EGL_BACK_BUFFER)
719 {
720 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
721 }
722
723 if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
724 {
725 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
726 }
727
728 if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
729 {
730 return egl::error(EGL_BAD_MATCH, EGL_FALSE);
731 }
732
733 gl::Texture2D *texture = eglSurface->getBoundTexture();
734
735 if (texture)
736 {
737 texture->releaseTexImage();
738 }
739
740 return egl::success(EGL_TRUE);
741 }
742 catch (...)
743 {
744 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
745 }
746 }
747
eglSwapInterval(EGLDisplay dpy,EGLint interval)748 EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
749 {
750 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
751
752 try
753 {
754 egl::Display *display = static_cast<egl::Display*>(dpy);
755
756 if (!validateDisplay(display))
757 {
758 return EGL_FALSE;
759 }
760
761 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
762
763 if (draw_surface == NULL)
764 {
765 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
766 }
767
768 draw_surface->setSwapInterval(interval);
769
770 return egl::success(EGL_TRUE);
771 }
772 catch (...)
773 {
774 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
775 }
776 }
777
eglCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)778 EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
779 {
780 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
781 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
782
783 try
784 {
785 // Get the requested client version (default is 1) and check it is 2 or 3.
786 EGLint client_version = 1;
787 bool reset_notification = false;
788 bool robust_access = false;
789
790 if (attrib_list)
791 {
792 for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
793 {
794 switch (attribute[0])
795 {
796 case EGL_CONTEXT_CLIENT_VERSION:
797 client_version = attribute[1];
798 break;
799 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
800 if (attribute[1] == EGL_TRUE)
801 {
802 return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented
803 // robust_access = true;
804 }
805 else if (attribute[1] != EGL_FALSE)
806 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
807 break;
808 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
809 if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
810 reset_notification = true;
811 else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
812 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
813 break;
814 default:
815 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
816 }
817 }
818 }
819
820 if (client_version != 2 && client_version != 3)
821 {
822 return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
823 }
824
825 egl::Display *display = static_cast<egl::Display*>(dpy);
826
827 if (share_context)
828 {
829 gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
830
831 if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
832 {
833 return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
834 }
835
836 if (sharedGLContext->getClientVersion() != client_version)
837 {
838 return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
839 }
840
841 // Can not share contexts between displays
842 if (sharedGLContext->getRenderer() != display->getRenderer())
843 {
844 return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
845 }
846 }
847
848 if (!validateConfig(display, config))
849 {
850 return EGL_NO_CONTEXT;
851 }
852
853 return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
854 }
855 catch (...)
856 {
857 return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
858 }
859 }
860
eglDestroyContext(EGLDisplay dpy,EGLContext ctx)861 EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
862 {
863 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
864
865 try
866 {
867 egl::Display *display = static_cast<egl::Display*>(dpy);
868 gl::Context *context = static_cast<gl::Context*>(ctx);
869
870 if (!validateContext(display, context))
871 {
872 return EGL_FALSE;
873 }
874
875 if (ctx == EGL_NO_CONTEXT)
876 {
877 return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
878 }
879
880 display->destroyContext(context);
881
882 return egl::success(EGL_TRUE);
883 }
884 catch (...)
885 {
886 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
887 }
888 }
889
eglMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)890 EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
891 {
892 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
893 dpy, draw, read, ctx);
894
895 try
896 {
897 egl::Display *display = static_cast<egl::Display*>(dpy);
898 gl::Context *context = static_cast<gl::Context*>(ctx);
899
900 if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
901 {
902 return EGL_FALSE;
903 }
904
905 if (dpy != EGL_NO_DISPLAY)
906 {
907 rx::Renderer *renderer = display->getRenderer();
908 if (renderer->testDeviceLost(true))
909 {
910 return EGL_FALSE;
911 }
912
913 if (renderer->isDeviceLost())
914 {
915 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
916 }
917 }
918
919 if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
920 (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
921 {
922 return EGL_FALSE;
923 }
924
925 if (draw != read)
926 {
927 UNIMPLEMENTED(); // FIXME
928 }
929
930 egl::setCurrentDisplay(dpy);
931 egl::setCurrentDrawSurface(draw);
932 egl::setCurrentReadSurface(read);
933
934 glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
935
936 return egl::success(EGL_TRUE);
937 }
938 catch (...)
939 {
940 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
941 }
942 }
943
eglGetCurrentContext(void)944 EGLContext __stdcall eglGetCurrentContext(void)
945 {
946 EVENT("()");
947
948 try
949 {
950 EGLContext context = glGetCurrentContext();
951
952 return egl::success(context);
953 }
954 catch (...)
955 {
956 return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
957 }
958 }
959
eglGetCurrentSurface(EGLint readdraw)960 EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
961 {
962 EVENT("(EGLint readdraw = %d)", readdraw);
963
964 try
965 {
966 if (readdraw == EGL_READ)
967 {
968 EGLSurface read = egl::getCurrentReadSurface();
969 return egl::success(read);
970 }
971 else if (readdraw == EGL_DRAW)
972 {
973 EGLSurface draw = egl::getCurrentDrawSurface();
974 return egl::success(draw);
975 }
976 else
977 {
978 return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
979 }
980 }
981 catch (...)
982 {
983 return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
984 }
985 }
986
eglGetCurrentDisplay(void)987 EGLDisplay __stdcall eglGetCurrentDisplay(void)
988 {
989 EVENT("()");
990
991 try
992 {
993 EGLDisplay dpy = egl::getCurrentDisplay();
994
995 return egl::success(dpy);
996 }
997 catch (...)
998 {
999 return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
1000 }
1001 }
1002
eglQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)1003 EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1004 {
1005 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
1006 dpy, ctx, attribute, value);
1007
1008 try
1009 {
1010 egl::Display *display = static_cast<egl::Display*>(dpy);
1011 gl::Context *context = static_cast<gl::Context*>(ctx);
1012
1013 if (!validateContext(display, context))
1014 {
1015 return EGL_FALSE;
1016 }
1017
1018 UNIMPLEMENTED(); // FIXME
1019
1020 return egl::success(0);
1021 }
1022 catch (...)
1023 {
1024 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1025 }
1026 }
1027
eglWaitGL(void)1028 EGLBoolean __stdcall eglWaitGL(void)
1029 {
1030 EVENT("()");
1031
1032 try
1033 {
1034 UNIMPLEMENTED(); // FIXME
1035
1036 return egl::success(0);
1037 }
1038 catch (...)
1039 {
1040 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1041 }
1042 }
1043
eglWaitNative(EGLint engine)1044 EGLBoolean __stdcall eglWaitNative(EGLint engine)
1045 {
1046 EVENT("(EGLint engine = %d)", engine);
1047
1048 try
1049 {
1050 UNIMPLEMENTED(); // FIXME
1051
1052 return egl::success(0);
1053 }
1054 catch (...)
1055 {
1056 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1057 }
1058 }
1059
eglSwapBuffers(EGLDisplay dpy,EGLSurface surface)1060 EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1061 {
1062 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
1063
1064 try
1065 {
1066 egl::Display *display = static_cast<egl::Display*>(dpy);
1067 egl::Surface *eglSurface = (egl::Surface*)surface;
1068
1069 if (!validateSurface(display, eglSurface))
1070 {
1071 return EGL_FALSE;
1072 }
1073
1074 if (display->getRenderer()->isDeviceLost())
1075 {
1076 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1077 }
1078
1079 if (surface == EGL_NO_SURFACE)
1080 {
1081 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1082 }
1083
1084 if (eglSurface->swap())
1085 {
1086 return egl::success(EGL_TRUE);
1087 }
1088 }
1089 catch (...)
1090 {
1091 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1092 }
1093
1094 return EGL_FALSE;
1095 }
1096
eglCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)1097 EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1098 {
1099 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
1100
1101 try
1102 {
1103 egl::Display *display = static_cast<egl::Display*>(dpy);
1104 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1105
1106 if (!validateSurface(display, eglSurface))
1107 {
1108 return EGL_FALSE;
1109 }
1110
1111 if (display->getRenderer()->isDeviceLost())
1112 {
1113 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1114 }
1115
1116 UNIMPLEMENTED(); // FIXME
1117
1118 return egl::success(0);
1119 }
1120 catch (...)
1121 {
1122 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1123 }
1124 }
1125
eglPostSubBufferNV(EGLDisplay dpy,EGLSurface surface,EGLint x,EGLint y,EGLint width,EGLint height)1126 EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
1127 {
1128 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
1129
1130 try
1131 {
1132 if (x < 0 || y < 0 || width < 0 || height < 0)
1133 {
1134 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
1135 }
1136
1137 egl::Display *display = static_cast<egl::Display*>(dpy);
1138 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1139
1140 if (!validateSurface(display, eglSurface))
1141 {
1142 return EGL_FALSE;
1143 }
1144
1145 if (display->getRenderer()->isDeviceLost())
1146 {
1147 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1148 }
1149
1150 if (surface == EGL_NO_SURFACE)
1151 {
1152 return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1153 }
1154
1155 if (eglSurface->postSubBuffer(x, y, width, height))
1156 {
1157 return egl::success(EGL_TRUE);
1158 }
1159 }
1160 catch (...)
1161 {
1162 return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1163 }
1164
1165 return EGL_FALSE;
1166 }
1167
eglGetProcAddress(const char * procname)1168 __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
1169 {
1170 EVENT("(const char *procname = \"%s\")", procname);
1171
1172 try
1173 {
1174 struct Extension
1175 {
1176 const char *name;
1177 __eglMustCastToProperFunctionPointerType address;
1178 };
1179
1180 static const Extension eglExtensions[] =
1181 {
1182 {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
1183 {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
1184 {"", NULL},
1185 };
1186
1187 for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
1188 {
1189 if (strcmp(procname, eglExtensions[ext].name) == 0)
1190 {
1191 return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
1192 }
1193 }
1194
1195 return glGetProcAddress(procname);
1196 }
1197 catch (...)
1198 {
1199 return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
1200 }
1201 }
1202 }
1203