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