OSDN Git Service

Revert "Implementation of EGL_KHR_swap_buffers_with_damage."
[android-x86/external-swiftshader.git] / src / OpenGL / libEGL / libEGL.cpp
1 // SwiftShader Software Renderer\r
2 //\r
3 // Copyright(c) 2005-2012 TransGaming Inc.\r
4 //\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,\r
6 // transcribed, stored in a retrieval system, translated into any human or computer\r
7 // language by any means, or disclosed to third parties without the explicit written\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express\r
9 // or implied, including but not limited to any patent rights, are granted to you.\r
10 //\r
11 \r
12 // libEGL.cpp: Implements the exported EGL functions.\r
13 \r
14 #include "main.h"\r
15 #include "Display.h"\r
16 #include "Surface.h"\r
17 #include "Texture.hpp"\r
18 #include "Context.hpp"\r
19 #include "common/Image.hpp"\r
20 #include "common/debug.h"\r
21 #include "Common/Version.h"\r
22 \r
23 #if defined(__ANDROID__)\r
24 #include <system/window.h>\r
25 #endif\r
26 \r
27 #include <string.h>\r
28 \r
29 using namespace egl;\r
30 \r
31 static bool validateDisplay(egl::Display *display)\r
32 {\r
33         if(display == EGL_NO_DISPLAY)\r
34         {\r
35                 return error(EGL_BAD_DISPLAY, false);\r
36         }\r
37 \r
38         if(!display->isInitialized())\r
39         {\r
40                 return error(EGL_NOT_INITIALIZED, false);\r
41         }\r
42 \r
43         return true;\r
44 }\r
45 \r
46 static bool validateConfig(egl::Display *display, EGLConfig config)\r
47 {\r
48         if(!validateDisplay(display))\r
49         {\r
50                 return false;\r
51         }\r
52 \r
53         if(!display->isValidConfig(config))\r
54         {\r
55                 return error(EGL_BAD_CONFIG, false);\r
56         }\r
57 \r
58         return true;\r
59 }\r
60 \r
61 static bool validateContext(egl::Display *display, egl::Context *context)\r
62 {\r
63         if(!validateDisplay(display))\r
64         {\r
65                 return false;\r
66         }\r
67 \r
68         if(!display->isValidContext(context))\r
69         {\r
70                 return error(EGL_BAD_CONTEXT, false);\r
71         }\r
72 \r
73         return true;\r
74 }\r
75 \r
76 static bool validateSurface(egl::Display *display, egl::Surface *surface)\r
77 {\r
78         if(!validateDisplay(display))\r
79         {\r
80                 return false;\r
81         }\r
82 \r
83         if(!display->isValidSurface(surface))\r
84         {\r
85                 return error(EGL_BAD_SURFACE, false);\r
86         }\r
87 \r
88         return true;\r
89 }\r
90 \r
91 namespace egl\r
92 {\r
93 EGLint GetError(void)\r
94 {\r
95         TRACE("()");\r
96 \r
97         EGLint error = egl::getCurrentError();\r
98 \r
99         if(error != EGL_SUCCESS)\r
100         {\r
101                 egl::setCurrentError(EGL_SUCCESS);\r
102         }\r
103 \r
104         return error;\r
105 }\r
106 \r
107 EGLDisplay GetDisplay(EGLNativeDisplayType display_id)\r
108 {\r
109         TRACE("(EGLNativeDisplayType display_id = %p)", display_id);\r
110 \r
111         return egl::Display::getPlatformDisplay(EGL_UNKNOWN, display_id);\r
112 }\r
113 \r
114 EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)\r
115 {\r
116         TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",\r
117                   dpy, major, minor);\r
118 \r
119         if(dpy == EGL_NO_DISPLAY)\r
120         {\r
121                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
122         }\r
123 \r
124         egl::Display *display = static_cast<egl::Display*>(dpy);\r
125 \r
126         if(!display->initialize())\r
127         {\r
128                 return error(EGL_NOT_INITIALIZED, EGL_FALSE);\r
129         }\r
130 \r
131         if(major) *major = 1;\r
132         if(minor) *minor = 4;\r
133 \r
134         return success(EGL_TRUE);\r
135 }\r
136 \r
137 EGLBoolean Terminate(EGLDisplay dpy)\r
138 {\r
139         TRACE("(EGLDisplay dpy = %p)", dpy);\r
140 \r
141         if(dpy == EGL_NO_DISPLAY)\r
142         {\r
143                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
144         }\r
145 \r
146         egl::Display *display = static_cast<egl::Display*>(dpy);\r
147 \r
148         display->terminate();\r
149 \r
150         return success(EGL_TRUE);\r
151 }\r
152 \r
153 const char *QueryString(EGLDisplay dpy, EGLint name)\r
154 {\r
155         TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);\r
156 \r
157         if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)\r
158         {\r
159                 return success("EGL_KHR_platform_gbm "\r
160                                "EGL_KHR_platform_x11 "\r
161                                "EGL_EXT_client_extensions "\r
162                                "EGL_EXT_platform_base");\r
163         }\r
164 \r
165         egl::Display *display = static_cast<egl::Display*>(dpy);\r
166 \r
167         if(!validateDisplay(display))\r
168         {\r
169                 return NULL;\r
170         }\r
171 \r
172         switch(name)\r
173         {\r
174         case EGL_CLIENT_APIS:\r
175                 return success("OpenGL_ES");\r
176         case EGL_EXTENSIONS:\r
177                 return success("EGL_KHR_gl_texture_2D_image "\r
178                                "EGL_KHR_gl_texture_cubemap_image "\r
179                                "EGL_KHR_gl_renderbuffer_image "\r
180                                "EGL_KHR_fence_sync "\r
181                                "EGL_KHR_image_base "\r
182                                "EGL_ANDROID_framebuffer_target "\r
183                                "EGL_ANDROID_recordable");\r
184         case EGL_VENDOR:\r
185                 return success("TransGaming Inc.");\r
186         case EGL_VERSION:\r
187                 return success("1.4 SwiftShader " VERSION_STRING);\r
188         }\r
189 \r
190         return error(EGL_BAD_PARAMETER, (const char*)NULL);\r
191 }\r
192 \r
193 EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)\r
194 {\r
195         TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "\r
196                   "EGLint config_size = %d, EGLint *num_config = %p)",\r
197                   dpy, configs, config_size, num_config);\r
198 \r
199         egl::Display *display = static_cast<egl::Display*>(dpy);\r
200 \r
201         if(!validateDisplay(display))\r
202         {\r
203                 return EGL_FALSE;\r
204         }\r
205 \r
206         if(!num_config)\r
207         {\r
208                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
209         }\r
210 \r
211         const EGLint attribList[] = {EGL_NONE};\r
212 \r
213         if(!display->getConfigs(configs, attribList, config_size, num_config))\r
214         {\r
215                 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
216         }\r
217 \r
218         return success(EGL_TRUE);\r
219 }\r
220 \r
221 EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)\r
222 {\r
223         TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "\r
224                   "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",\r
225                   dpy, attrib_list, configs, config_size, num_config);\r
226 \r
227         egl::Display *display = static_cast<egl::Display*>(dpy);\r
228 \r
229         if(!validateDisplay(display))\r
230         {\r
231                 return EGL_FALSE;\r
232         }\r
233 \r
234         if(!num_config)\r
235         {\r
236                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
237         }\r
238 \r
239         const EGLint attribList[] = {EGL_NONE};\r
240 \r
241         if(!attrib_list)\r
242         {\r
243                 attrib_list = attribList;\r
244         }\r
245 \r
246         if(!display->getConfigs(configs, attrib_list, config_size, num_config))\r
247         {\r
248                 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
249         }\r
250 \r
251         return success(EGL_TRUE);\r
252 }\r
253 \r
254 EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)\r
255 {\r
256         TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",\r
257                   dpy, config, attribute, value);\r
258 \r
259         egl::Display *display = static_cast<egl::Display*>(dpy);\r
260 \r
261         if(!validateConfig(display, config))\r
262         {\r
263                 return EGL_FALSE;\r
264         }\r
265 \r
266         if(!display->getConfigAttrib(config, attribute, value))\r
267         {\r
268                 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
269         }\r
270 \r
271         return success(EGL_TRUE);\r
272 }\r
273 \r
274 EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)\r
275 {\r
276         TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, "\r
277                   "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);\r
278 \r
279         egl::Display *display = static_cast<egl::Display*>(dpy);\r
280 \r
281         if(!validateConfig(display, config))\r
282         {\r
283                 return EGL_NO_SURFACE;\r
284         }\r
285 \r
286         if(!display->isValidWindow(window))\r
287         {\r
288                 return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);\r
289         }\r
290 \r
291         return display->createWindowSurface(window, config, attrib_list);\r
292 }\r
293 \r
294 EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)\r
295 {\r
296         TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",\r
297                   dpy, config, attrib_list);\r
298 \r
299         egl::Display *display = static_cast<egl::Display*>(dpy);\r
300 \r
301         if(!validateConfig(display, config))\r
302         {\r
303                 return EGL_NO_SURFACE;\r
304         }\r
305 \r
306         return display->createPBufferSurface(config, attrib_list);\r
307 }\r
308 \r
309 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)\r
310 {\r
311         TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "\r
312                   "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);\r
313 \r
314         egl::Display *display = static_cast<egl::Display*>(dpy);\r
315 \r
316         if(!validateConfig(display, config))\r
317         {\r
318                 return EGL_NO_SURFACE;\r
319         }\r
320 \r
321         UNIMPLEMENTED();   // FIXME\r
322 \r
323         return success(EGL_NO_SURFACE);\r
324 }\r
325 \r
326 EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)\r
327 {\r
328         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);\r
329 \r
330         egl::Display *display = static_cast<egl::Display*>(dpy);\r
331         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
332 \r
333         if(!validateSurface(display, eglSurface))\r
334         {\r
335                 return EGL_FALSE;\r
336         }\r
337 \r
338         if(surface == EGL_NO_SURFACE)\r
339         {\r
340                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
341         }\r
342 \r
343         display->destroySurface((egl::Surface*)surface);\r
344 \r
345         return success(EGL_TRUE);\r
346 }\r
347 \r
348 EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)\r
349 {\r
350         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",\r
351                   dpy, surface, attribute, value);\r
352 \r
353         egl::Display *display = static_cast<egl::Display*>(dpy);\r
354         egl::Surface *eglSurface = (egl::Surface*)surface;\r
355 \r
356         if(!validateSurface(display, eglSurface))\r
357         {\r
358                 return EGL_FALSE;\r
359         }\r
360 \r
361         if(surface == EGL_NO_SURFACE)\r
362         {\r
363                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
364         }\r
365 \r
366         switch(attribute)\r
367         {\r
368         case EGL_VG_ALPHA_FORMAT:\r
369                 UNIMPLEMENTED();   // FIXME\r
370                 break;\r
371         case EGL_VG_COLORSPACE:\r
372                 UNIMPLEMENTED();   // FIXME\r
373                 break;\r
374         case EGL_CONFIG_ID:\r
375                 *value = eglSurface->getConfigID();\r
376                 break;\r
377         case EGL_HEIGHT:\r
378                 *value = eglSurface->getHeight();\r
379                 break;\r
380         case EGL_HORIZONTAL_RESOLUTION:\r
381                 UNIMPLEMENTED();   // FIXME\r
382                 break;\r
383         case EGL_LARGEST_PBUFFER:\r
384                 if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.\r
385                 {\r
386                         *value = eglSurface->getLargestPBuffer();       \r
387                 }\r
388                 break;\r
389         case EGL_MIPMAP_TEXTURE:\r
390                 UNIMPLEMENTED();   // FIXME\r
391                 break;\r
392         case EGL_MIPMAP_LEVEL:\r
393                 UNIMPLEMENTED();   // FIXME\r
394                 break;\r
395         case EGL_MULTISAMPLE_RESOLVE:\r
396                 UNIMPLEMENTED();   // FIXME\r
397                 break;\r
398         case EGL_PIXEL_ASPECT_RATIO:\r
399                 *value = eglSurface->getPixelAspectRatio();\r
400                 break;\r
401         case EGL_RENDER_BUFFER:\r
402                 *value = eglSurface->getRenderBuffer();\r
403                 break;\r
404         case EGL_SWAP_BEHAVIOR:\r
405                 *value = eglSurface->getSwapBehavior();\r
406                 break;\r
407         case EGL_TEXTURE_FORMAT:\r
408                 *value = eglSurface->getTextureFormat();\r
409                 break;\r
410         case EGL_TEXTURE_TARGET:\r
411                 *value = eglSurface->getTextureTarget();\r
412                 break;\r
413         case EGL_VERTICAL_RESOLUTION:\r
414                 UNIMPLEMENTED();   // FIXME\r
415                 break;\r
416         case EGL_WIDTH:\r
417                 *value = eglSurface->getWidth();\r
418                 break;\r
419         default:\r
420                 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
421         }\r
422 \r
423         return success(EGL_TRUE);\r
424 }\r
425 \r
426 EGLBoolean BindAPI(EGLenum api)\r
427 {\r
428         TRACE("(EGLenum api = 0x%X)", api);\r
429 \r
430         switch(api)\r
431         {\r
432         case EGL_OPENGL_API:\r
433         case EGL_OPENVG_API:\r
434                 return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation\r
435         case EGL_OPENGL_ES_API:\r
436                 break;\r
437         default:\r
438                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
439         }\r
440 \r
441         egl::setCurrentAPI(api);\r
442 \r
443         return success(EGL_TRUE);\r
444 }\r
445 \r
446 EGLenum QueryAPI(void)\r
447 {\r
448         TRACE("()");\r
449 \r
450         EGLenum API = egl::getCurrentAPI();\r
451 \r
452         return success(API);\r
453 }\r
454 \r
455 EGLBoolean WaitClient(void)\r
456 {\r
457         TRACE("()");\r
458 \r
459         UNIMPLEMENTED();   // FIXME\r
460 \r
461         return success(EGL_FALSE);\r
462 }\r
463 \r
464 EGLBoolean ReleaseThread(void)\r
465 {\r
466         TRACE("()");\r
467 \r
468         eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);\r
469 \r
470         return success(EGL_TRUE);\r
471 }\r
472 \r
473 EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)\r
474 {\r
475         TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "\r
476                   "EGLConfig config = %p, const EGLint *attrib_list = %p)",\r
477                   dpy, buftype, buffer, config, attrib_list);\r
478 \r
479         UNIMPLEMENTED();\r
480 \r
481         return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);\r
482 }\r
483 \r
484 EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)\r
485 {\r
486         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",\r
487                   dpy, surface, attribute, value);\r
488 \r
489         egl::Display *display = static_cast<egl::Display*>(dpy);\r
490         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
491 \r
492         if(!validateSurface(display, eglSurface))\r
493         {\r
494                 return EGL_FALSE;\r
495         }\r
496 \r
497         switch(attribute)\r
498         {\r
499         case EGL_SWAP_BEHAVIOR:\r
500                 if(value == EGL_BUFFER_PRESERVED)\r
501                 {\r
502                         if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))\r
503                         {\r
504                                 return error(EGL_BAD_MATCH, EGL_FALSE);\r
505                         }\r
506                 }\r
507                 else if(value != EGL_BUFFER_DESTROYED)\r
508                 {\r
509                         return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
510                 }\r
511                 eglSurface->setSwapBehavior(value);\r
512                 break;\r
513         default:\r
514                 UNIMPLEMENTED();   // FIXME\r
515         }\r
516 \r
517         return success(EGL_TRUE);\r
518 }\r
519 \r
520 EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)\r
521 {\r
522         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);\r
523 \r
524         egl::Display *display = static_cast<egl::Display*>(dpy);\r
525         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
526 \r
527         if(!validateSurface(display, eglSurface))\r
528         {\r
529                 return EGL_FALSE;\r
530         }\r
531 \r
532         if(buffer != EGL_BACK_BUFFER)\r
533         {\r
534                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
535         }\r
536 \r
537         if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())\r
538         {\r
539                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
540         }\r
541 \r
542         if(eglSurface->getBoundTexture())\r
543         {\r
544                 return error(EGL_BAD_ACCESS, EGL_FALSE);\r
545         }\r
546 \r
547         if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)\r
548         {\r
549                 return error(EGL_BAD_MATCH, EGL_FALSE);\r
550         }\r
551 \r
552         egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());\r
553 \r
554         if(context)\r
555         {\r
556                 context->bindTexImage(eglSurface);\r
557         }\r
558 \r
559         return success(EGL_TRUE);\r
560 }\r
561 \r
562 EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)\r
563 {\r
564         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);\r
565 \r
566         egl::Display *display = static_cast<egl::Display*>(dpy);\r
567         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
568 \r
569         if(!validateSurface(display, eglSurface))\r
570         {\r
571                 return EGL_FALSE;\r
572         }\r
573 \r
574         if(buffer != EGL_BACK_BUFFER)\r
575         {\r
576                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
577         }\r
578 \r
579         if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())\r
580         {\r
581                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
582         }\r
583 \r
584         if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)\r
585         {\r
586                 return error(EGL_BAD_MATCH, EGL_FALSE);\r
587         }\r
588 \r
589         egl::Texture *texture = eglSurface->getBoundTexture();\r
590 \r
591         if(texture)\r
592         {\r
593                 texture->releaseTexImage();\r
594         }\r
595 \r
596         return success(EGL_TRUE);\r
597 }\r
598 \r
599 EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)\r
600 {\r
601         TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);\r
602 \r
603         egl::Display *display = static_cast<egl::Display*>(dpy);\r
604 \r
605         if(!validateDisplay(display))\r
606         {\r
607                 return EGL_FALSE;\r
608         }\r
609 \r
610         egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());\r
611 \r
612         if(draw_surface == NULL)\r
613         {\r
614                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
615         }\r
616 \r
617         draw_surface->setSwapInterval(interval);\r
618 \r
619         return success(EGL_TRUE);\r
620 }\r
621 \r
622 EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)\r
623 {\r
624         TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "\r
625                   "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);\r
626 \r
627         EGLint clientVersion = 1;\r
628         if(attrib_list)\r
629         {\r
630                 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)\r
631                 {\r
632                         if(attribute[0] == EGL_CONTEXT_CLIENT_VERSION)\r
633                         {\r
634                                 clientVersion = attribute[1];\r
635                         }\r
636                         else\r
637                         {\r
638                                 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);\r
639                         }\r
640                 }\r
641         }\r
642 \r
643         egl::Display *display = static_cast<egl::Display*>(dpy);\r
644         egl::Context *shareContext = static_cast<egl::Context*>(share_context);\r
645 \r
646         if(!validateConfig(display, config))\r
647         {\r
648                 return EGL_NO_CONTEXT;\r
649         }\r
650 \r
651         if(shareContext && shareContext->getClientVersion() != clientVersion)\r
652         {\r
653                 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);\r
654         }\r
655 \r
656         return display->createContext(config, shareContext, clientVersion);\r
657 }\r
658 \r
659 EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)\r
660 {\r
661         TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);\r
662 \r
663         egl::Display *display = static_cast<egl::Display*>(dpy);\r
664         egl::Context *context = static_cast<egl::Context*>(ctx);\r
665 \r
666         if(!validateContext(display, context))\r
667         {\r
668                 return EGL_FALSE;\r
669         }\r
670 \r
671         if(ctx == EGL_NO_CONTEXT)\r
672         {\r
673                 return error(EGL_BAD_CONTEXT, EGL_FALSE);\r
674         }\r
675 \r
676         display->destroyContext(context);\r
677 \r
678         return success(EGL_TRUE);\r
679 }\r
680 \r
681 EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)\r
682 {\r
683         TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",\r
684                   dpy, draw, read, ctx);\r
685 \r
686         egl::Display *display = static_cast<egl::Display*>(dpy);\r
687         egl::Context *context = static_cast<egl::Context*>(ctx);\r
688         egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);\r
689         egl::Surface *readSurface = static_cast<egl::Surface*>(read);\r
690 \r
691         if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)\r
692         {\r
693                 if(!validateDisplay(display))\r
694                 {\r
695                         return EGL_FALSE;\r
696                 }\r
697         }\r
698 \r
699         if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))\r
700         {\r
701                 return error(EGL_BAD_MATCH, EGL_FALSE);\r
702         }\r
703 \r
704         if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))\r
705         {\r
706                 return EGL_FALSE;\r
707         }\r
708 \r
709         if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||\r
710            (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))\r
711         {\r
712                 return EGL_FALSE;\r
713         }\r
714 \r
715         if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))\r
716         {\r
717                 return error(EGL_BAD_MATCH, EGL_FALSE);\r
718         }\r
719 \r
720         if(draw != read)\r
721         {\r
722                 UNIMPLEMENTED();   // FIXME\r
723         }\r
724 \r
725         egl::setCurrentDisplay(display);\r
726         egl::setCurrentDrawSurface(drawSurface);\r
727         egl::setCurrentReadSurface(readSurface);\r
728         egl::setCurrentContext(context);\r
729 \r
730         if(context)\r
731         {\r
732                 context->makeCurrent(drawSurface);\r
733         }\r
734 \r
735         return success(EGL_TRUE);\r
736 }\r
737 \r
738 EGLContext GetCurrentContext(void)\r
739 {\r
740         TRACE("()");\r
741 \r
742         EGLContext context = egl::getCurrentContext();\r
743 \r
744         return success(context);\r
745 }\r
746 \r
747 EGLSurface GetCurrentSurface(EGLint readdraw)\r
748 {\r
749         TRACE("(EGLint readdraw = %d)", readdraw);\r
750 \r
751         if(readdraw == EGL_READ)\r
752         {\r
753                 EGLSurface read = egl::getCurrentReadSurface();\r
754                 return success(read);\r
755         }\r
756         else if(readdraw == EGL_DRAW)\r
757         {\r
758                 EGLSurface draw = egl::getCurrentDrawSurface();\r
759                 return success(draw);\r
760         }\r
761         else\r
762         {\r
763                 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);\r
764         }\r
765 }\r
766 \r
767 EGLDisplay GetCurrentDisplay(void)\r
768 {\r
769         TRACE("()");\r
770 \r
771         EGLDisplay dpy = egl::getCurrentDisplay();\r
772 \r
773         return success(dpy);\r
774 }\r
775 \r
776 EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)\r
777 {\r
778         TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",\r
779                   dpy, ctx, attribute, value);\r
780 \r
781         egl::Display *display = static_cast<egl::Display*>(dpy);\r
782         egl::Context *context = static_cast<egl::Context*>(ctx);\r
783 \r
784         if(!validateContext(display, context))\r
785         {\r
786                 return EGL_FALSE;\r
787         }\r
788 \r
789         UNIMPLEMENTED();   // FIXME\r
790 \r
791         return success(0);\r
792 }\r
793 \r
794 EGLBoolean WaitGL(void)\r
795 {\r
796         TRACE("()");\r
797 \r
798         UNIMPLEMENTED();   // FIXME\r
799 \r
800         return success(EGL_FALSE);\r
801 }\r
802 \r
803 EGLBoolean WaitNative(EGLint engine)\r
804 {\r
805         TRACE("(EGLint engine = %d)", engine);\r
806 \r
807         UNIMPLEMENTED();   // FIXME\r
808 \r
809         return success(EGL_FALSE);\r
810 }\r
811 \r
812 EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)\r
813 {\r
814         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);\r
815 \r
816         egl::Display *display = static_cast<egl::Display*>(dpy);\r
817         egl::Surface *eglSurface = (egl::Surface*)surface;\r
818 \r
819         if(!validateSurface(display, eglSurface))\r
820         {\r
821                 return EGL_FALSE;\r
822         }\r
823 \r
824         if(surface == EGL_NO_SURFACE)\r
825         {\r
826                 return error(EGL_BAD_SURFACE, EGL_FALSE);\r
827         }\r
828 \r
829         eglSurface->swap();\r
830 \r
831         return success(EGL_TRUE);\r
832 }\r
833 \r
834 EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)\r
835 {\r
836         TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);\r
837 \r
838         egl::Display *display = static_cast<egl::Display*>(dpy);\r
839         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
840 \r
841         if(!validateSurface(display, eglSurface))\r
842         {\r
843                 return EGL_FALSE;\r
844         }\r
845 \r
846         UNIMPLEMENTED();   // FIXME\r
847 \r
848         return success(EGL_FALSE);\r
849 }\r
850 \r
851 EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)\r
852 {\r
853         TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);\r
854 \r
855         egl::Display *display = static_cast<egl::Display*>(dpy);\r
856         egl::Context *context = static_cast<egl::Context*>(ctx);\r
857 \r
858         if(!validateDisplay(display))\r
859         {\r
860                 return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);\r
861         }\r
862 \r
863         if(context != EGL_NO_CONTEXT && !display->isValidContext(context))\r
864         {\r
865                 return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);\r
866         }\r
867 \r
868         EGLenum imagePreserved = EGL_FALSE;\r
869         GLuint textureLevel = 0;\r
870         if(attrib_list)\r
871         {\r
872                 for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)\r
873                 {\r
874                         if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)\r
875                         {\r
876                                 imagePreserved = attribute[1];\r
877                         }\r
878                         else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)\r
879                         {\r
880                                 textureLevel = attribute[1];\r
881                         }\r
882                         else\r
883                         {\r
884                                 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);\r
885                         }\r
886                 }\r
887         }\r
888 \r
889         GLuint name = reinterpret_cast<intptr_t>(buffer);\r
890 \r
891         if(name == 0)\r
892         {\r
893                 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);\r
894         }\r
895 \r
896         #if defined(__ANDROID__)\r
897                 if(target == EGL_NATIVE_BUFFER_ANDROID)\r
898                 {\r
899                         return new AndroidNativeImage(reinterpret_cast<ANativeWindowBuffer*>(name));\r
900                 }\r
901         #endif\r
902 \r
903         EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);\r
904 \r
905         if(validationResult != EGL_SUCCESS)\r
906         {\r
907                 return error(validationResult, EGL_NO_IMAGE_KHR);\r
908         }\r
909 \r
910         egl::Image *image = context->createSharedImage(target, name, textureLevel);\r
911 \r
912         if(!image)\r
913         {\r
914                 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);\r
915         }\r
916 \r
917         if(image->getDepth() > 1)\r
918         {\r
919                 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);\r
920         }\r
921 \r
922         return success((EGLImageKHR)image);\r
923 }\r
924 \r
925 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)\r
926 {\r
927         TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);\r
928 \r
929         egl::Display *display = static_cast<egl::Display*>(dpy);\r
930 \r
931         if(!validateDisplay(display))\r
932         {\r
933                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
934         }\r
935 \r
936         if(!image)\r
937         {\r
938                 return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
939         }\r
940 \r
941         egl::Image *glImage = static_cast<egl::Image*>(image);\r
942         glImage->destroyShared();\r
943 \r
944         return success(EGL_TRUE);\r
945 }\r
946 \r
947 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)\r
948 {\r
949         TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);\r
950 \r
951         return egl::Display::getPlatformDisplay(platform, (EGLNativeDisplayType)native_display);\r
952 }\r
953 \r
954 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)\r
955 {\r
956         return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list);\r
957 }\r
958 \r
959 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)\r
960 {\r
961         return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);\r
962 }\r
963 \r
964 class FenceSync\r
965 {\r
966 public:\r
967         explicit FenceSync(Context *context) : context(context)\r
968         {\r
969                 status = EGL_UNSIGNALED_KHR;\r
970                 context->addRef();\r
971         }\r
972 \r
973         ~FenceSync()\r
974         {\r
975                 context->release();\r
976                 context = nullptr;\r
977         }\r
978 \r
979         void wait() const { return context->finish(); }\r
980         void signal() { status = EGL_SIGNALED_KHR; }\r
981         bool isSignaled() const { return status == EGL_SIGNALED_KHR; }\r
982 \r
983 private:\r
984         EGLint status;\r
985         Context *context;\r
986 };\r
987 \r
988 EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)\r
989 {\r
990         TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);\r
991 \r
992         egl::Display *display = static_cast<egl::Display*>(dpy);\r
993 \r
994         if(!validateDisplay(display))\r
995         {\r
996                 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);\r
997         }\r
998 \r
999         if(type != EGL_SYNC_FENCE_KHR)\r
1000         {\r
1001                 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);\r
1002         }\r
1003 \r
1004         if(attrib_list && attrib_list[0] != EGL_NONE)\r
1005         {\r
1006                 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);\r
1007         }\r
1008 \r
1009         egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());\r
1010 \r
1011         if(!validateContext(display, context))\r
1012         {\r
1013                 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);\r
1014         }\r
1015 \r
1016         return new FenceSync(context);\r
1017 }\r
1018 \r
1019 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)\r
1020 {\r
1021         TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);\r
1022 \r
1023         egl::Display *display = static_cast<egl::Display*>(dpy);\r
1024         FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
1025 \r
1026         if(!validateDisplay(display))\r
1027         {\r
1028                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
1029         }\r
1030 \r
1031         delete eglSync;\r
1032 \r
1033         return EGL_TRUE;\r
1034 }\r
1035 \r
1036 EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)\r
1037 {\r
1038         TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);\r
1039 \r
1040         egl::Display *display = static_cast<egl::Display*>(dpy);\r
1041         FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
1042 \r
1043         if(!validateDisplay(display))\r
1044         {\r
1045                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
1046         }\r
1047 \r
1048         (void)flags;\r
1049         (void)timeout;\r
1050 \r
1051         if(!eglSync->isSignaled())\r
1052         {\r
1053                 eglSync->wait();\r
1054                 eglSync->signal();\r
1055         }\r
1056 \r
1057         return EGL_CONDITION_SATISFIED_KHR;\r
1058 }\r
1059 \r
1060 EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)\r
1061 {\r
1062         TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);\r
1063 \r
1064         egl::Display *display = static_cast<egl::Display*>(dpy);\r
1065 \r
1066         if(!validateDisplay(display))\r
1067         {\r
1068                 return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
1069         }\r
1070 \r
1071         FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
1072 \r
1073         switch(attribute)\r
1074         {\r
1075         case EGL_SYNC_TYPE_KHR:\r
1076                 *value = EGL_SYNC_FENCE_KHR;\r
1077                 return EGL_TRUE;\r
1078         case EGL_SYNC_STATUS_KHR:\r
1079                 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;\r
1080                 return EGL_TRUE;\r
1081         case EGL_SYNC_CONDITION_KHR:\r
1082                 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;\r
1083                 return EGL_TRUE;\r
1084         default:\r
1085                 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
1086         }\r
1087 }\r
1088 \r
1089 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)\r
1090 {\r
1091         TRACE("(const char *procname = \"%s\")", procname);\r
1092 \r
1093         struct Extension\r
1094         {\r
1095                 const char *name;\r
1096                 __eglMustCastToProperFunctionPointerType address;\r
1097         };\r
1098 \r
1099         static const Extension eglExtensions[] =\r
1100         {\r
1101                 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}\r
1102 \r
1103                 EXTENSION(eglCreateImageKHR),\r
1104                 EXTENSION(eglDestroyImageKHR),\r
1105                 EXTENSION(eglGetPlatformDisplayEXT),\r
1106                 EXTENSION(eglCreatePlatformWindowSurfaceEXT),\r
1107                 EXTENSION(eglCreatePlatformPixmapSurfaceEXT),\r
1108                 EXTENSION(eglCreateSyncKHR),\r
1109                 EXTENSION(eglDestroySyncKHR),\r
1110                 EXTENSION(eglClientWaitSyncKHR),\r
1111                 EXTENSION(eglGetSyncAttribKHR),\r
1112 \r
1113                 #undef EXTENSION\r
1114         };\r
1115 \r
1116         for(int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)\r
1117         {\r
1118                 if(strcmp(procname, eglExtensions[ext].name) == 0)\r
1119                 {\r
1120                         return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;\r
1121                 }\r
1122         }\r
1123 \r
1124         if(libGLESv2)\r
1125         {\r
1126                 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);\r
1127                 if(proc) return proc;\r
1128         }\r
1129 \r
1130         if(libGLES_CM)\r
1131         {\r
1132                 __eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);\r
1133                 if(proc) return proc;\r
1134         }\r
1135 \r
1136         return NULL;\r
1137 }\r
1138 }\r