Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libEGL / libEGL.cpp
1 //
2 // Copyright (c) 2002-2010 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
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
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
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
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 {
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
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(std::bad_alloc&)
107     {
108         return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
109     }
110 }
111
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(std::bad_alloc&)
137     {
138         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
139     }
140 }
141
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(std::bad_alloc&)
160     {
161         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
162     }
163 }
164
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(std::bad_alloc&)
193     {
194         return egl::error(EGL_BAD_ALLOC, (const char*)NULL);
195     }
196 }
197
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(std::bad_alloc&)
228     {
229         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
230     }
231 }
232
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(std::bad_alloc&)
265     {
266         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
267     }
268 }
269
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(std::bad_alloc&)
292     {
293         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
294     }
295 }
296
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(std::bad_alloc&)
321     {
322         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
323     }
324 }
325
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(std::bad_alloc&)
343     {
344         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
345     }
346 }
347
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(std::bad_alloc&)
367     {
368         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
369     }
370 }
371
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(std::bad_alloc&)
396     {
397         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
398     }
399 }
400
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             UNIMPLEMENTED();   // FIXME
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             UNIMPLEMENTED();   // FIXME
452             break;
453           case EGL_RENDER_BUFFER:
454             UNIMPLEMENTED();   // FIXME
455             break;
456           case EGL_SWAP_BEHAVIOR:
457             UNIMPLEMENTED();   // FIXME
458             break;
459           case EGL_TEXTURE_FORMAT:
460             UNIMPLEMENTED();   // FIXME
461             break;
462           case EGL_TEXTURE_TARGET:
463             UNIMPLEMENTED();   // FIXME
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(std::bad_alloc&)
484     {
485         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
486     }
487 }
488
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(std::bad_alloc&)
524     {
525         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
526     }
527 }
528
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(std::bad_alloc&)
551     {
552         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
553     }
554 }
555
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(std::bad_alloc&)
567     {
568         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
569     }
570 }
571
572 EGLBoolean __stdcall eglWaitClient(void)
573 {
574     EVENT("()");
575
576     try
577     {
578         UNIMPLEMENTED();   // FIXME
579
580         return egl::success(0);
581     }
582     catch(std::bad_alloc&)
583     {
584         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
585     }
586 }
587
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(std::bad_alloc&)
599     {
600         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
601     }
602 }
603
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(std::bad_alloc&)
627     {
628         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
629     }
630 }
631
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(std::bad_alloc&)
652     {
653         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
654     }
655 }
656
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(std::bad_alloc&)
699     {
700         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
701     }
702 }
703
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(std::bad_alloc&)
743     {
744         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
745     }
746 }
747
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(std::bad_alloc&)
773     {
774         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
775     }
776 }
777
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 two.
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)
821         {
822             return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
823         }
824
825         gl::Context *sharedContextPtr = (share_context != EGL_NO_CONTEXT ? static_cast<gl::Context*>(share_context) : NULL);
826
827         if (sharedContextPtr != NULL && sharedContextPtr->isResetNotificationEnabled() != reset_notification)
828         {
829             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
830         }
831
832         egl::Display *display = static_cast<egl::Display*>(dpy);
833
834         // Can not share contexts between displays
835         if (sharedContextPtr != NULL && sharedContextPtr->getRenderer() != display->getRenderer())
836         {
837             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
838         }
839
840         if (!validateConfig(display, config))
841         {
842             return EGL_NO_CONTEXT;
843         }
844
845         EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
846
847         if (context)
848             return egl::success(context);
849         else
850             return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
851     }
852     catch(std::bad_alloc&)
853     {
854         return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
855     }
856 }
857
858 EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
859 {
860     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
861
862     try
863     {
864         egl::Display *display = static_cast<egl::Display*>(dpy);
865         gl::Context *context = static_cast<gl::Context*>(ctx);
866
867         if (!validateContext(display, context))
868         {
869             return EGL_FALSE;
870         }
871
872         if (ctx == EGL_NO_CONTEXT)
873         {
874             return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
875         }
876
877         display->destroyContext(context);
878
879         return egl::success(EGL_TRUE);
880     }
881     catch(std::bad_alloc&)
882     {
883         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
884     }
885 }
886
887 EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
888 {
889     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
890           dpy, draw, read, ctx);
891
892     try
893     {
894         egl::Display *display = static_cast<egl::Display*>(dpy);
895         gl::Context *context = static_cast<gl::Context*>(ctx);
896
897         if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
898         {
899             return EGL_FALSE;
900         }
901
902         if (dpy != EGL_NO_DISPLAY)
903         {
904             rx::Renderer *renderer = display->getRenderer();
905             if (renderer->testDeviceLost(true))
906             {
907                 return EGL_FALSE;
908             }
909
910             if (renderer->isDeviceLost())
911             {
912                 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
913             }
914         }
915
916         if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
917             (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
918         {
919             return EGL_FALSE;
920         }
921
922         if (draw != read)
923         {
924             UNIMPLEMENTED();   // FIXME
925         }
926
927         egl::setCurrentDisplay(dpy);
928         egl::setCurrentDrawSurface(draw);
929         egl::setCurrentReadSurface(read);
930
931         glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
932
933         return egl::success(EGL_TRUE);
934     }
935     catch(std::bad_alloc&)
936     {
937         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
938     }
939 }
940
941 EGLContext __stdcall eglGetCurrentContext(void)
942 {
943     EVENT("()");
944
945     try
946     {
947         EGLContext context = glGetCurrentContext();
948
949         return egl::success(context);
950     }
951     catch(std::bad_alloc&)
952     {
953         return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
954     }
955 }
956
957 EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
958 {
959     EVENT("(EGLint readdraw = %d)", readdraw);
960
961     try
962     {
963         if (readdraw == EGL_READ)
964         {
965             EGLSurface read = egl::getCurrentReadSurface();
966             return egl::success(read);
967         }
968         else if (readdraw == EGL_DRAW)
969         {
970             EGLSurface draw = egl::getCurrentDrawSurface();
971             return egl::success(draw);
972         }
973         else
974         {
975             return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
976         }
977     }
978     catch(std::bad_alloc&)
979     {
980         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
981     }
982 }
983
984 EGLDisplay __stdcall eglGetCurrentDisplay(void)
985 {
986     EVENT("()");
987
988     try
989     {
990         EGLDisplay dpy = egl::getCurrentDisplay();
991
992         return egl::success(dpy);
993     }
994     catch(std::bad_alloc&)
995     {
996         return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
997     }
998 }
999
1000 EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1001 {
1002     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
1003           dpy, ctx, attribute, value);
1004
1005     try
1006     {
1007         egl::Display *display = static_cast<egl::Display*>(dpy);
1008         gl::Context *context = static_cast<gl::Context*>(ctx);
1009
1010         if (!validateContext(display, context))
1011         {
1012             return EGL_FALSE;
1013         }
1014
1015         UNIMPLEMENTED();   // FIXME
1016
1017         return egl::success(0);
1018     }
1019     catch(std::bad_alloc&)
1020     {
1021         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1022     }
1023 }
1024
1025 EGLBoolean __stdcall eglWaitGL(void)
1026 {
1027     EVENT("()");
1028
1029     try
1030     {
1031         UNIMPLEMENTED();   // FIXME
1032
1033         return egl::success(0);
1034     }
1035     catch(std::bad_alloc&)
1036     {
1037         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1038     }
1039 }
1040
1041 EGLBoolean __stdcall eglWaitNative(EGLint engine)
1042 {
1043     EVENT("(EGLint engine = %d)", engine);
1044
1045     try
1046     {
1047         UNIMPLEMENTED();   // FIXME
1048
1049         return egl::success(0);
1050     }
1051     catch(std::bad_alloc&)
1052     {
1053         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1054     }
1055 }
1056
1057 EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1058 {
1059     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
1060
1061     try
1062     {
1063         egl::Display *display = static_cast<egl::Display*>(dpy);
1064         egl::Surface *eglSurface = (egl::Surface*)surface;
1065
1066         if (!validateSurface(display, eglSurface))
1067         {
1068             return EGL_FALSE;
1069         }
1070
1071         if (display->getRenderer()->isDeviceLost())
1072         {
1073             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1074         }
1075
1076         if (surface == EGL_NO_SURFACE)
1077         {
1078             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1079         }
1080
1081         if (eglSurface->swap())
1082         {
1083             return egl::success(EGL_TRUE);
1084         }
1085     }
1086     catch(std::bad_alloc&)
1087     {
1088         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1089     }
1090
1091     return EGL_FALSE;
1092 }
1093
1094 EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1095 {
1096     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
1097
1098     try
1099     {
1100         egl::Display *display = static_cast<egl::Display*>(dpy);
1101         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1102
1103         if (!validateSurface(display, eglSurface))
1104         {
1105             return EGL_FALSE;
1106         }
1107
1108         if (display->getRenderer()->isDeviceLost())
1109         {
1110             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1111         }
1112
1113         UNIMPLEMENTED();   // FIXME
1114
1115         return egl::success(0);
1116     }
1117     catch(std::bad_alloc&)
1118     {
1119         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1120     }
1121 }
1122
1123 EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
1124 {
1125     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);
1126
1127     try
1128     {
1129         if (x < 0 || y < 0 || width < 0 || height < 0)
1130         {
1131             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
1132         }
1133
1134         egl::Display *display = static_cast<egl::Display*>(dpy);
1135         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1136
1137         if (!validateSurface(display, eglSurface))
1138         {
1139             return EGL_FALSE;
1140         }
1141
1142         if (display->getRenderer()->isDeviceLost())
1143         {
1144             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1145         }
1146
1147         if (surface == EGL_NO_SURFACE)
1148         {
1149             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1150         }
1151
1152         if (eglSurface->postSubBuffer(x, y, width, height))
1153         {
1154             return egl::success(EGL_TRUE);
1155         }
1156     }
1157     catch(std::bad_alloc&)
1158     {
1159         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1160     }
1161
1162     return EGL_FALSE;
1163 }
1164
1165 __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
1166 {
1167     EVENT("(const char *procname = \"%s\")", procname);
1168
1169     try
1170     {
1171         struct Extension
1172         {
1173             const char *name;
1174             __eglMustCastToProperFunctionPointerType address;
1175         };
1176
1177         static const Extension eglExtensions[] =
1178         {
1179             {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
1180             {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
1181             {"", NULL},
1182         };
1183
1184         for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
1185         {
1186             if (strcmp(procname, eglExtensions[ext].name) == 0)
1187             {
1188                 return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
1189             }
1190         }
1191
1192         return glGetProcAddress(procname);
1193     }
1194     catch(std::bad_alloc&)
1195     {
1196         return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
1197     }
1198 }
1199 }