OSDN Git Service

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