Upstream version 5.34.92.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 " 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           default:
475             return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
476         }
477
478         return egl::success(EGL_TRUE);
479     }
480     catch(std::bad_alloc&)
481     {
482         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
483     }
484 }
485
486 EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
487 {
488     TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
489           dpy, surface, attribute, value);
490
491     try
492     {
493         egl::Display *display = static_cast<egl::Display*>(dpy);
494         egl::Surface *eglSurface = (egl::Surface*)surface;
495
496         if (!validateSurface(display, eglSurface))
497         {
498             return EGL_FALSE;
499         }
500
501         if (surface == EGL_NO_SURFACE)
502         {
503             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
504         }
505
506         switch (attribute)
507         {
508           case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
509             {
510                 rx::SwapChain *swapchain = eglSurface->getSwapChain();
511                 *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
512             }
513             break;
514           default:
515             return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
516         }
517
518         return egl::success(EGL_TRUE);
519     }
520     catch(std::bad_alloc&)
521     {
522         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
523     }
524 }
525
526 EGLBoolean __stdcall eglBindAPI(EGLenum api)
527 {
528     EVENT("(EGLenum api = 0x%X)", api);
529
530     try
531     {
532         switch (api)
533         {
534           case EGL_OPENGL_API:
535           case EGL_OPENVG_API:
536             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
537           case EGL_OPENGL_ES_API:
538             break;
539           default:
540             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
541         }
542
543         egl::setCurrentAPI(api);
544
545         return egl::success(EGL_TRUE);
546     }
547     catch(std::bad_alloc&)
548     {
549         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
550     }
551 }
552
553 EGLenum __stdcall eglQueryAPI(void)
554 {
555     EVENT("()");
556
557     try
558     {
559         EGLenum API = egl::getCurrentAPI();
560
561         return egl::success(API);
562     }
563     catch(std::bad_alloc&)
564     {
565         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
566     }
567 }
568
569 EGLBoolean __stdcall eglWaitClient(void)
570 {
571     EVENT("()");
572
573     try
574     {
575         UNIMPLEMENTED();   // FIXME
576
577         return egl::success(0);
578     }
579     catch(std::bad_alloc&)
580     {
581         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
582     }
583 }
584
585 EGLBoolean __stdcall eglReleaseThread(void)
586 {
587     EVENT("()");
588
589     try
590     {
591         eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
592
593         return egl::success(EGL_TRUE);
594     }
595     catch(std::bad_alloc&)
596     {
597         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
598     }
599 }
600
601 EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
602 {
603     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
604           "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
605           dpy, buftype, buffer, config, attrib_list);
606
607     try
608     {
609         egl::Display *display = static_cast<egl::Display*>(dpy);
610
611         if (!validateConfig(display, config))
612         {
613             return EGL_NO_SURFACE;
614         }
615
616         if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
617         {
618             return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
619         }
620
621         return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
622     }
623     catch(std::bad_alloc&)
624     {
625         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
626     }
627 }
628
629 EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
630 {
631     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
632           dpy, surface, attribute, value);
633
634     try
635     {
636         egl::Display *display = static_cast<egl::Display*>(dpy);
637         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
638
639         if (!validateSurface(display, eglSurface))
640         {
641             return EGL_FALSE;
642         }
643
644         UNIMPLEMENTED();   // FIXME
645
646         return egl::success(EGL_TRUE);
647     }
648     catch(std::bad_alloc&)
649     {
650         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
651     }
652 }
653
654 EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
655 {
656     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
657
658     try
659     {
660         egl::Display *display = static_cast<egl::Display*>(dpy);
661         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
662
663         if (!validateSurface(display, eglSurface))
664         {
665             return EGL_FALSE;
666         }
667
668         if (buffer != EGL_BACK_BUFFER)
669         {
670             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
671         }
672
673         if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
674         {
675             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
676         }
677
678         if (eglSurface->getBoundTexture())
679         {
680             return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
681         }
682
683         if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
684         {
685             return egl::error(EGL_BAD_MATCH, EGL_FALSE);
686         }
687
688         if (!glBindTexImage(eglSurface))
689         {
690             return egl::error(EGL_BAD_MATCH, EGL_FALSE);
691         }
692
693         return egl::success(EGL_TRUE);
694     }
695     catch(std::bad_alloc&)
696     {
697         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
698     }
699 }
700
701 EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
702 {
703     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
704
705     try
706     {
707         egl::Display *display = static_cast<egl::Display*>(dpy);
708         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
709
710         if (!validateSurface(display, eglSurface))
711         {
712             return EGL_FALSE;
713         }
714
715         if (buffer != EGL_BACK_BUFFER)
716         {
717             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
718         }
719
720         if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
721         {
722             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
723         }
724
725         if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
726         {
727             return egl::error(EGL_BAD_MATCH, EGL_FALSE);
728         }
729
730         gl::Texture2D *texture = eglSurface->getBoundTexture();
731
732         if (texture)
733         {
734             texture->releaseTexImage();
735         }
736
737         return egl::success(EGL_TRUE);
738     }
739     catch(std::bad_alloc&)
740     {
741         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
742     }
743 }
744
745 EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
746 {
747     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
748
749     try
750     {
751         egl::Display *display = static_cast<egl::Display*>(dpy);
752
753         if (!validateDisplay(display))
754         {
755             return EGL_FALSE;
756         }
757
758         egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
759
760         if (draw_surface == NULL)
761         {
762             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
763         }
764         
765         draw_surface->setSwapInterval(interval);
766
767         return egl::success(EGL_TRUE);
768     }
769     catch(std::bad_alloc&)
770     {
771         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
772     }
773 }
774
775 EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
776 {
777     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
778           "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
779
780     try
781     {
782         // Get the requested client version (default is 1) and check it is two.
783         EGLint client_version = 1;
784         bool reset_notification = false;
785         bool robust_access = false;
786
787         if (attrib_list)
788         {
789             for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
790             {
791                 switch (attribute[0])
792                 {
793                   case EGL_CONTEXT_CLIENT_VERSION:
794                     client_version = attribute[1];
795                     break;
796                   case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
797                     if (attribute[1] == EGL_TRUE)
798                     {
799                         return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
800                         // robust_access = true;
801                     }
802                     else if (attribute[1] != EGL_FALSE)
803                         return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
804                     break;
805                   case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
806                     if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
807                         reset_notification = true;
808                     else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
809                         return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
810                     break;
811                   default:
812                     return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
813                 }
814             }
815         }
816
817         if (client_version != 2)
818         {
819             return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
820         }
821
822         gl::Context *sharedContextPtr = (share_context != EGL_NO_CONTEXT ? static_cast<gl::Context*>(share_context) : NULL);
823
824         if (sharedContextPtr != NULL && sharedContextPtr->isResetNotificationEnabled() != reset_notification)
825         {
826             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
827         }
828
829         egl::Display *display = static_cast<egl::Display*>(dpy);
830
831         // Can not share contexts between displays
832         if (sharedContextPtr != NULL && sharedContextPtr->getRenderer() != display->getRenderer())
833         {
834             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
835         }
836
837         if (!validateConfig(display, config))
838         {
839             return EGL_NO_CONTEXT;
840         }
841
842         EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
843
844         if (context)
845             return egl::success(context);
846         else
847             return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
848     }
849     catch(std::bad_alloc&)
850     {
851         return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
852     }
853 }
854
855 EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
856 {
857     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
858
859     try
860     {
861         egl::Display *display = static_cast<egl::Display*>(dpy);
862         gl::Context *context = static_cast<gl::Context*>(ctx);
863
864         if (!validateContext(display, context))
865         {
866             return EGL_FALSE;
867         }
868
869         if (ctx == EGL_NO_CONTEXT)
870         {
871             return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
872         }
873
874         display->destroyContext(context);
875
876         return egl::success(EGL_TRUE);
877     }
878     catch(std::bad_alloc&)
879     {
880         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
881     }
882 }
883
884 EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
885 {
886     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
887           dpy, draw, read, ctx);
888
889     try
890     {
891         egl::Display *display = static_cast<egl::Display*>(dpy);
892         gl::Context *context = static_cast<gl::Context*>(ctx);
893
894         if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
895         {
896             return EGL_FALSE;
897         }
898
899         if (dpy != EGL_NO_DISPLAY)
900         {
901             rx::Renderer *renderer = display->getRenderer();
902             if (renderer->testDeviceLost(true))
903             {
904                 return EGL_FALSE;
905             }
906
907             if (renderer->isDeviceLost())
908             {
909                 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
910             }
911         }
912
913         if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
914             (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
915         {
916             return EGL_FALSE;
917         }
918
919         if (draw != read)
920         {
921             UNIMPLEMENTED();   // FIXME
922         }
923
924         egl::setCurrentDisplay(dpy);
925         egl::setCurrentDrawSurface(draw);
926         egl::setCurrentReadSurface(read);
927
928         glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
929
930         return egl::success(EGL_TRUE);
931     }
932     catch(std::bad_alloc&)
933     {
934         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
935     }
936 }
937
938 EGLContext __stdcall eglGetCurrentContext(void)
939 {
940     EVENT("()");
941
942     try
943     {
944         EGLContext context = glGetCurrentContext();
945
946         return egl::success(context);
947     }
948     catch(std::bad_alloc&)
949     {
950         return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
951     }
952 }
953
954 EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
955 {
956     EVENT("(EGLint readdraw = %d)", readdraw);
957
958     try
959     {
960         if (readdraw == EGL_READ)
961         {
962             EGLSurface read = egl::getCurrentReadSurface();
963             return egl::success(read);
964         }
965         else if (readdraw == EGL_DRAW)
966         {
967             EGLSurface draw = egl::getCurrentDrawSurface();
968             return egl::success(draw);
969         }
970         else
971         {
972             return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
973         }
974     }
975     catch(std::bad_alloc&)
976     {
977         return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
978     }
979 }
980
981 EGLDisplay __stdcall eglGetCurrentDisplay(void)
982 {
983     EVENT("()");
984
985     try
986     {
987         EGLDisplay dpy = egl::getCurrentDisplay();
988
989         return egl::success(dpy);
990     }
991     catch(std::bad_alloc&)
992     {
993         return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
994     }
995 }
996
997 EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
998 {
999     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
1000           dpy, ctx, attribute, value);
1001
1002     try
1003     {
1004         egl::Display *display = static_cast<egl::Display*>(dpy);
1005         gl::Context *context = static_cast<gl::Context*>(ctx);
1006
1007         if (!validateContext(display, context))
1008         {
1009             return EGL_FALSE;
1010         }
1011
1012         UNIMPLEMENTED();   // FIXME
1013
1014         return egl::success(0);
1015     }
1016     catch(std::bad_alloc&)
1017     {
1018         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1019     }
1020 }
1021
1022 EGLBoolean __stdcall eglWaitGL(void)
1023 {
1024     EVENT("()");
1025
1026     try
1027     {
1028         UNIMPLEMENTED();   // FIXME
1029
1030         return egl::success(0);
1031     }
1032     catch(std::bad_alloc&)
1033     {
1034         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1035     }
1036 }
1037
1038 EGLBoolean __stdcall eglWaitNative(EGLint engine)
1039 {
1040     EVENT("(EGLint engine = %d)", engine);
1041
1042     try
1043     {
1044         UNIMPLEMENTED();   // FIXME
1045
1046         return egl::success(0);
1047     }
1048     catch(std::bad_alloc&)
1049     {
1050         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1051     }
1052 }
1053
1054 EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1055 {
1056     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
1057
1058     try
1059     {
1060         egl::Display *display = static_cast<egl::Display*>(dpy);
1061         egl::Surface *eglSurface = (egl::Surface*)surface;
1062
1063         if (!validateSurface(display, eglSurface))
1064         {
1065             return EGL_FALSE;
1066         }
1067
1068         if (display->getRenderer()->isDeviceLost())
1069         {
1070             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1071         }
1072
1073         if (surface == EGL_NO_SURFACE)
1074         {
1075             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1076         }
1077
1078         if (eglSurface->swap())
1079         {
1080             return egl::success(EGL_TRUE);
1081         }
1082     }
1083     catch(std::bad_alloc&)
1084     {
1085         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1086     }
1087
1088     return EGL_FALSE;
1089 }
1090
1091 EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1092 {
1093     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
1094
1095     try
1096     {
1097         egl::Display *display = static_cast<egl::Display*>(dpy);
1098         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1099
1100         if (!validateSurface(display, eglSurface))
1101         {
1102             return EGL_FALSE;
1103         }
1104
1105         if (display->getRenderer()->isDeviceLost())
1106         {
1107             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1108         }
1109
1110         UNIMPLEMENTED();   // FIXME
1111
1112         return egl::success(0);
1113     }
1114     catch(std::bad_alloc&)
1115     {
1116         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1117     }
1118 }
1119
1120 EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
1121 {
1122     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);
1123
1124     try
1125     {
1126         if (x < 0 || y < 0 || width < 0 || height < 0)
1127         {
1128             return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
1129         }
1130
1131         egl::Display *display = static_cast<egl::Display*>(dpy);
1132         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1133
1134         if (!validateSurface(display, eglSurface))
1135         {
1136             return EGL_FALSE;
1137         }
1138
1139         if (display->getRenderer()->isDeviceLost())
1140         {
1141             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
1142         }
1143
1144         if (surface == EGL_NO_SURFACE)
1145         {
1146             return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
1147         }
1148
1149         if (eglSurface->postSubBuffer(x, y, width, height))
1150         {
1151             return egl::success(EGL_TRUE);
1152         }
1153     }
1154     catch(std::bad_alloc&)
1155     {
1156         return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
1157     }
1158
1159     return EGL_FALSE;
1160 }
1161
1162 __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
1163 {
1164     EVENT("(const char *procname = \"%s\")", procname);
1165
1166     try
1167     {
1168         struct Extension
1169         {
1170             const char *name;
1171             __eglMustCastToProperFunctionPointerType address;
1172         };
1173
1174         static const Extension eglExtensions[] =
1175         {
1176             {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
1177             {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
1178             {"", NULL},
1179         };
1180
1181         for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
1182         {
1183             if (strcmp(procname, eglExtensions[ext].name) == 0)
1184             {
1185                 return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
1186             }
1187         }
1188
1189         return glGetProcAddress(procname);
1190     }
1191     catch(std::bad_alloc&)
1192     {
1193         return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
1194     }
1195 }
1196 }