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