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