OSDN Git Service

Add DEBUG_EGL / DPRINT macros for debug logging EGL.
[android-x86/device-generic-goldfish-opengl.git] / system / egl / egl.cpp
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <assert.h>
18 #include "HostConnection.h"
19 #include "ThreadInfo.h"
20 #include "eglDisplay.h"
21 #include "egl_ftable.h"
22 #include <cutils/log.h>
23 #include "goldfish_sync.h"
24 #include "gralloc_cb.h"
25 #include "GLClientState.h"
26 #include "GLSharedGroup.h"
27 #include "eglContext.h"
28 #include "ClientAPIExts.h"
29 #include "EGLImage.h"
30
31 #include "GLEncoder.h"
32 #ifdef WITH_GLES2
33 #include "GL2Encoder.h"
34 #endif
35
36 #if PLATFORM_SDK_VERSION >= 16
37 #include <system/window.h>
38 #else // PLATFORM_SDK_VERSION >= 16
39 #include <private/ui/android_natives_priv.h>
40 #endif // PLATFORM_SDK_VERSION >= 16
41
42 #if PLATFORM_SDK_VERSION <= 16
43 #define queueBuffer_DEPRECATED queueBuffer
44 #define dequeueBuffer_DEPRECATED dequeueBuffer
45 #define cancelBuffer_DEPRECATED cancelBuffer
46 #endif // PLATFORM_SDK_VERSION <= 16
47
48 #define DEBUG_EGL 0
49
50 #if DEBUG_EGL
51 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
52 #else
53 #define DPRINT(...)
54 #endif
55
56 template<typename T>
57 static T setErrorFunc(GLint error, T returnValue) {
58     getEGLThreadInfo()->eglError = error;
59     return returnValue;
60 }
61
62 const char *  eglStrError(EGLint err)
63 {
64     switch (err){
65         case EGL_SUCCESS:           return "EGL_SUCCESS";
66         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
67         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
68         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
69         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
70         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
71         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
72         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
73         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
74         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
75         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
76         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
77         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
78         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
79         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
80         default: return "UNKNOWN";
81     }
82 }
83
84 #define LOG_EGL_ERRORS 1
85
86 #ifdef LOG_EGL_ERRORS
87
88 #define setErrorReturn(error, retVal)     \
89     {                                                \
90         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
91         return setErrorFunc(error, retVal);            \
92     }
93
94 #define RETURN_ERROR(ret,err)           \
95     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
96     getEGLThreadInfo()->eglError = err;    \
97     return ret;
98
99 #else //!LOG_EGL_ERRORS
100
101 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
102
103 #define RETURN_ERROR(ret,err)           \
104     getEGLThreadInfo()->eglError = err; \
105     return ret;
106
107 #endif //LOG_EGL_ERRORS
108
109 #define VALIDATE_CONFIG(cfg,ret) \
110     if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
111         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
112     }
113
114 #define VALIDATE_DISPLAY(dpy,ret) \
115     if ((dpy) != (EGLDisplay)&s_display) { \
116         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
117     }
118
119 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
120     VALIDATE_DISPLAY(dpy, ret)    \
121     if (!s_display.initialized()) {        \
122         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
123     }
124
125 #define DEFINE_HOST_CONNECTION \
126     HostConnection *hostCon = HostConnection::get(); \
127     ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
128
129 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
130     HostConnection *hostCon = HostConnection::get(); \
131     if (!hostCon) { \
132         ALOGE("egl: Failed to get host connection\n"); \
133         return ret; \
134     } \
135     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
136     if (!rcEnc) { \
137         ALOGE("egl: Failed to get renderControl encoder context\n"); \
138         return ret; \
139     }
140
141 #define VALIDATE_CONTEXT_RETURN(context,ret)  \
142     if (!(context)) {                         \
143         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
144     }
145
146 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
147     if ((surface) != EGL_NO_SURFACE) {    \
148         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
149         if (s->dpy != (EGLDisplay)&s_display)    \
150             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
151     }
152
153 // The one and only supported display object.
154 static eglDisplay s_display;
155
156 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
157     dpy(dpy),
158     config(config),
159     read(EGL_NO_SURFACE),
160     draw(EGL_NO_SURFACE),
161     shareCtx(shareCtx),
162     rcContext(0),
163     versionString(NULL),
164     vendorString(NULL),
165     rendererString(NULL),
166     shaderVersionString(NULL),
167     extensionString(NULL),
168     deletePending(0),
169     goldfishSyncFd(-1)
170 {
171     flags = 0;
172     version = 1;
173     clientState = new GLClientState();
174     if (shareCtx)
175         sharedGroup = shareCtx->getSharedGroup();
176     else
177         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
178     assert(dpy == (EGLDisplay)&s_display);
179     s_display.onCreateContext((EGLContext)this);
180 };
181
182 int EGLContext_t::getGoldfishSyncFd() {
183     if (goldfishSyncFd < 0) {
184         goldfishSyncFd = goldfish_sync_open();
185     }
186     return goldfishSyncFd;
187 }
188
189 EGLContext_t::~EGLContext_t()
190 {
191     assert(dpy == (EGLDisplay)&s_display);
192     s_display.onDestroyContext((EGLContext)this);
193     delete clientState;
194     delete [] versionString;
195     delete [] vendorString;
196     delete [] rendererString;
197     delete [] shaderVersionString;
198     delete [] extensionString;
199 }
200
201 // ----------------------------------------------------------------------------
202 //egl_surface_t
203
204 //we don't need to handle depth since it's handled when window created on the host
205
206 struct egl_surface_t {
207
208     EGLDisplay          dpy;
209     EGLConfig           config;
210
211
212     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
213     virtual     ~egl_surface_t();
214
215     virtual     void        setSwapInterval(int interval) = 0;
216     virtual     EGLBoolean  swapBuffers() = 0;
217
218     EGLint      getSwapBehavior() const;
219     uint32_t    getRcSurface()   { return rcSurface; }
220     EGLint      getSurfaceType() { return surfaceType; }
221
222     EGLint      getWidth(){ return width; }
223     EGLint      getHeight(){ return height; }
224     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
225     EGLint      getTextureFormat() { return texFormat; }
226     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
227     EGLint      getTextureTarget() { return texTarget; }
228
229 private:
230     //
231     //Surface attributes
232     //
233     EGLint      width;
234     EGLint      height;
235     EGLint      texFormat;
236     EGLint      texTarget;
237
238 protected:
239     void        setWidth(EGLint w)  { width = w;  }
240     void        setHeight(EGLint h) { height = h; }
241
242     EGLint      surfaceType;
243     uint32_t    rcSurface; //handle to surface created via remote control
244 };
245
246 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
247     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
248 {
249     width = 0;
250     height = 0;
251     texFormat = EGL_NO_TEXTURE;
252     texTarget = EGL_NO_TEXTURE;
253     assert(dpy == (EGLDisplay)&s_display);
254     s_display.onCreateSurface((EGLSurface)this);
255 }
256
257 EGLint egl_surface_t::getSwapBehavior() const {
258     return EGL_BUFFER_PRESERVED;
259 }
260
261 egl_surface_t::~egl_surface_t()
262 {
263     assert(dpy == (EGLDisplay)&s_display);
264     s_display.onDestroySurface((EGLSurface)this);
265 }
266
267 // ----------------------------------------------------------------------------
268 // egl_window_surface_t
269
270 struct egl_window_surface_t : public egl_surface_t {
271     static egl_window_surface_t* create(
272             EGLDisplay dpy, EGLConfig config, EGLint surfType,
273             ANativeWindow* window);
274
275     virtual ~egl_window_surface_t();
276
277     virtual void       setSwapInterval(int interval);
278     virtual EGLBoolean swapBuffers();
279
280 private:
281     egl_window_surface_t(
282             EGLDisplay dpy, EGLConfig config, EGLint surfType,
283             ANativeWindow* window);
284     EGLBoolean init();
285
286     ANativeWindow*              nativeWindow;
287     android_native_buffer_t*    buffer;
288 };
289
290 egl_window_surface_t::egl_window_surface_t (
291         EGLDisplay dpy, EGLConfig config, EGLint surfType,
292         ANativeWindow* window)
293 :   egl_surface_t(dpy, config, surfType),
294     nativeWindow(window),
295     buffer(NULL)
296 {
297     // keep a reference on the window
298     nativeWindow->common.incRef(&nativeWindow->common);
299 }
300
301
302 EGLBoolean egl_window_surface_t::init()
303 {
304     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
305         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
306     }
307     setWidth(buffer->width);
308     setHeight(buffer->height);
309
310     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
311     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
312             getWidth(), getHeight());
313     if (!rcSurface) {
314         ALOGE("rcCreateWindowSurface returned 0");
315         return EGL_FALSE;
316     }
317     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
318             ((cb_handle_t*)(buffer->handle))->hostHandle);
319
320     return EGL_TRUE;
321 }
322
323 egl_window_surface_t* egl_window_surface_t::create(
324         EGLDisplay dpy, EGLConfig config, EGLint surfType,
325         ANativeWindow* window)
326 {
327     egl_window_surface_t* wnd = new egl_window_surface_t(
328             dpy, config, surfType, window);
329     if (wnd && !wnd->init()) {
330         delete wnd;
331         wnd = NULL;
332     }
333     return wnd;
334 }
335
336 egl_window_surface_t::~egl_window_surface_t() {
337     DEFINE_HOST_CONNECTION;
338     if (rcSurface && rcEnc) {
339         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
340     }
341     if (buffer) {
342         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
343     }
344     nativeWindow->common.decRef(&nativeWindow->common);
345 }
346
347 void egl_window_surface_t::setSwapInterval(int interval)
348 {
349     nativeWindow->setSwapInterval(nativeWindow, interval);
350 }
351
352 EGLBoolean egl_window_surface_t::swapBuffers()
353 {
354     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
355
356     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
357
358     nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
359     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
360         buffer = NULL;
361         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
362     }
363
364     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
365             ((cb_handle_t *)(buffer->handle))->hostHandle);
366
367     setWidth(buffer->width);
368     setHeight(buffer->height);
369
370     return EGL_TRUE;
371 }
372
373 // ----------------------------------------------------------------------------
374 //egl_pbuffer_surface_t
375
376 struct egl_pbuffer_surface_t : public egl_surface_t {
377     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
378             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
379
380     virtual ~egl_pbuffer_surface_t();
381
382     virtual void       setSwapInterval(int interval) { (void)interval; }
383     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
384
385     uint32_t getRcColorBuffer() { return rcColorBuffer; }
386
387 private:
388     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
389             int32_t w, int32_t h);
390     EGLBoolean init(GLenum format);
391
392     uint32_t rcColorBuffer;
393 };
394
395 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
396         EGLint surfType, int32_t w, int32_t h)
397 :   egl_surface_t(dpy, config, surfType),
398     rcColorBuffer(0)
399 {
400     setWidth(w);
401     setHeight(h);
402 }
403
404 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
405 {
406     DEFINE_HOST_CONNECTION;
407     if (rcEnc) {
408         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
409         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
410     }
411 }
412
413 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
414 {
415     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
416
417     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
418             getWidth(), getHeight());
419     if (!rcSurface) {
420         ALOGE("rcCreateWindowSurface returned 0");
421         return EGL_FALSE;
422     }
423
424     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
425             pixelFormat);
426     if (!rcColorBuffer) {
427         ALOGE("rcCreateColorBuffer returned 0");
428         return EGL_FALSE;
429     }
430
431     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
432
433     return EGL_TRUE;
434 }
435
436 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
437         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
438         GLenum pixelFormat)
439 {
440     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
441             w, h);
442     if (pb && !pb->init(pixelFormat)) {
443         delete pb;
444         pb = NULL;
445     }
446     return pb;
447 }
448
449 static const char *getGLString(int glEnum)
450 {
451     EGLThreadInfo *tInfo = getEGLThreadInfo();
452     if (!tInfo || !tInfo->currentContext) {
453         return NULL;
454     }
455
456     const char** strPtr = NULL;
457
458 #define GL_VENDOR                         0x1F00
459 #define GL_RENDERER                       0x1F01
460 #define GL_VERSION                        0x1F02
461 #define GL_SHADING_LANGUAGE_VERSION       0x8B8C
462 #define GL_EXTENSIONS                     0x1F03
463
464     switch(glEnum) {
465         case GL_VERSION:
466             strPtr = &tInfo->currentContext->versionString;
467             break;
468         case GL_VENDOR:
469             strPtr = &tInfo->currentContext->vendorString;
470             break;
471         case GL_RENDERER:
472             strPtr = &tInfo->currentContext->rendererString;
473             break;
474         case GL_SHADING_LANGUAGE_VERSION:
475             strPtr = &tInfo->currentContext->shaderVersionString;
476             break;
477         case GL_EXTENSIONS:
478             strPtr = &tInfo->currentContext->extensionString;
479             break;
480     }
481
482     if (!strPtr) {
483         return NULL;
484     }
485
486     if (*strPtr != NULL) {
487         //
488         // string is already cached
489         //
490         return *strPtr;
491     }
492
493     //
494     // first query of that string - need to query host
495     //
496     DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
497     char *hostStr = NULL;
498     int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
499     if (n < 0) {
500         hostStr = new char[-n+1];
501         n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
502         if (n <= 0) {
503             delete [] hostStr;
504             hostStr = NULL;
505         }
506     }
507
508     //
509     // keep the string in the context and return its value
510     //
511     *strPtr = hostStr;
512     return hostStr;
513 }
514
515 // ----------------------------------------------------------------------------
516
517 static EGLClient_eglInterface s_eglIface = {
518     getThreadInfo: getEGLThreadInfo,
519     getGLString: getGLString
520 };
521
522 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
523 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
524 {
525     //
526     // we support only EGL_DEFAULT_DISPLAY.
527     //
528     if (display_id != EGL_DEFAULT_DISPLAY) {
529         return EGL_NO_DISPLAY;
530     }
531
532     return (EGLDisplay)&s_display;
533 }
534
535 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
536 {
537     VALIDATE_DISPLAY(dpy,EGL_FALSE);
538
539     if (!s_display.initialize(&s_eglIface)) {
540         return EGL_FALSE;
541     }
542     if (major!=NULL)
543         *major = s_display.getVersionMajor();
544     if (minor!=NULL)
545         *minor = s_display.getVersionMinor();
546     return EGL_TRUE;
547 }
548
549 EGLBoolean eglTerminate(EGLDisplay dpy)
550 {
551     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
552
553     s_display.terminate();
554     return EGL_TRUE;
555 }
556
557 EGLint eglGetError()
558 {
559     EGLint error = getEGLThreadInfo()->eglError;
560     getEGLThreadInfo()->eglError = EGL_SUCCESS;
561     return error;
562 }
563
564 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
565 {
566     // search in EGL function table
567     for (int i=0; i<egl_num_funcs; i++) {
568         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
569             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
570         }
571     }
572
573     // look in gles client api's extensions table
574     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
575
576     // Fail - function not found.
577     return NULL;
578 }
579
580 const char* eglQueryString(EGLDisplay dpy, EGLint name)
581 {
582     VALIDATE_DISPLAY_INIT(dpy, NULL);
583
584     return s_display.queryString(name);
585 }
586
587 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
588 {
589     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
590
591     if(!num_config) {
592         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
593     }
594
595     GLint numConfigs = s_display.getNumConfigs();
596     if (!configs) {
597         *num_config = numConfigs;
598         return EGL_TRUE;
599     }
600
601     EGLint i;
602     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
603         *configs++ = (EGLConfig)(uintptr_t)i;
604     }
605     *num_config = i;
606     return EGL_TRUE;
607 }
608
609 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
610 {
611     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
612
613     int attribs_size = 0;
614     if (attrib_list) {
615         const EGLint * attrib_p = attrib_list;
616         while (attrib_p[0] != EGL_NONE) {
617             attribs_size += 2;
618             attrib_p += 2;
619         }
620         attribs_size++; //for the terminating EGL_NONE
621     }
622
623     uint32_t* tempConfigs[config_size];
624     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
625     *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
626     if (configs!=NULL) {
627         EGLint i=0;
628         for (i=0;i<(*num_config);i++) {
629              *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
630         }
631     }
632
633     if (*num_config <= 0)
634         return EGL_FALSE;
635     return EGL_TRUE;
636 }
637
638 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
639 {
640     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
641     VALIDATE_CONFIG(config, EGL_FALSE);
642
643     if (s_display.getConfigAttrib(config, attribute, value))
644     {
645         return EGL_TRUE;
646     }
647     else
648     {
649         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
650     }
651 }
652
653 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
654 {
655     (void)attrib_list;
656
657     VALIDATE_DISPLAY_INIT(dpy, NULL);
658     VALIDATE_CONFIG(config, EGL_FALSE);
659     if (win == 0) {
660         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
661     }
662
663     EGLint surfaceType;
664     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
665
666     if (!(surfaceType & EGL_WINDOW_BIT)) {
667         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
668     }
669
670     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
671         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
672     }
673
674     egl_surface_t* surface = egl_window_surface_t::create(
675             &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
676     if (!surface) {
677         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
678     }
679
680     return surface;
681 }
682
683 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
684 {
685     VALIDATE_DISPLAY_INIT(dpy, NULL);
686     VALIDATE_CONFIG(config, EGL_FALSE);
687
688     EGLint surfaceType;
689     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
690
691     if (!(surfaceType & EGL_PBUFFER_BIT)) {
692         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
693     }
694
695     int32_t w = 0;
696     int32_t h = 0;
697     EGLint texFormat = EGL_NO_TEXTURE;
698     EGLint texTarget = EGL_NO_TEXTURE;
699     while (attrib_list[0] != EGL_NONE) {
700         switch (attrib_list[0]) {
701             case EGL_WIDTH:
702                 w = attrib_list[1];
703                 break;
704             case EGL_HEIGHT:
705                 h = attrib_list[1];
706                 break;
707             case EGL_TEXTURE_FORMAT:
708                 texFormat = attrib_list[1];
709                 break;
710             case EGL_TEXTURE_TARGET:
711                 texTarget = attrib_list[1];
712                 break;
713             default:
714                 break;
715         };
716         attrib_list+=2;
717     }
718     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
719         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
720         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
721     }
722     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
723
724     GLenum pixelFormat;
725     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
726         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
727
728     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
729             EGL_PBUFFER_BIT, w, h, pixelFormat);
730     if (!surface) {
731         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
732     }
733
734     //setup attributes
735     surface->setTextureFormat(texFormat);
736     surface->setTextureTarget(texTarget);
737
738     return surface;
739 }
740
741 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
742 {
743     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
744     //     located on host. In order to support Pixmaps we should either punt
745     //     to s/w rendering -or- let the host render to a buffer that will be
746     //     copied back to guest at some sync point. None of those methods not
747     //     implemented and pixmaps are not used with OpenGL anyway ...
748     (void)dpy;
749     (void)config;
750     (void)pixmap;
751     (void)attrib_list;
752     return EGL_NO_SURFACE;
753 }
754
755 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
756 {
757     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
758     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
759
760     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
761     delete surface;
762
763     return EGL_TRUE;
764 }
765
766 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
767 {
768     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
769     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
770
771     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
772     EGLBoolean ret = EGL_TRUE;
773     switch (attribute) {
774         case EGL_CONFIG_ID:
775             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
776             break;
777         case EGL_WIDTH:
778             *value = surface->getWidth();
779             break;
780         case EGL_HEIGHT:
781             *value = surface->getHeight();
782             break;
783         case EGL_TEXTURE_FORMAT:
784             *value = surface->getTextureFormat();
785             break;
786         case EGL_TEXTURE_TARGET:
787             *value = surface->getTextureTarget();
788             break;
789         case EGL_SWAP_BEHAVIOR:
790             *value = surface->getSwapBehavior();
791             break;
792         case EGL_LARGEST_PBUFFER:
793             // not modified for a window or pixmap surface
794             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
795             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
796             break;
797         case EGL_MIPMAP_LEVEL:
798             // not modified for a window or pixmap surface
799             // and we ignore it when creating a PBuffer surface (default is 0)
800             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
801             break;
802         case EGL_MULTISAMPLE_RESOLVE:
803             // ignored when creating the surface, return default
804             *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
805             break;
806         //TODO: complete other attributes
807         default:
808             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
809             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
810             break;
811     }
812
813     return ret;
814 }
815
816 EGLBoolean eglBindAPI(EGLenum api)
817 {
818     if (api != EGL_OPENGL_ES_API)
819         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
820     return EGL_TRUE;
821 }
822
823 EGLenum eglQueryAPI()
824 {
825     return EGL_OPENGL_ES_API;
826 }
827
828 EGLBoolean eglWaitClient()
829 {
830     return eglWaitGL();
831 }
832
833 EGLBoolean eglReleaseThread()
834 {
835     EGLThreadInfo *tInfo = getEGLThreadInfo();
836     if (tInfo) {
837         tInfo->eglError = EGL_SUCCESS;
838         EGLContext_t* context = tInfo->currentContext;
839         if (context) {
840             // The following code is doing pretty much the same thing as
841             // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
842             // with the only issue that we do not require a valid display here.
843             DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
844             rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
845              if (context->version == 2) {
846                 hostCon->gl2Encoder()->setClientState(NULL);
847                 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
848             }
849             else {
850                 hostCon->glEncoder()->setClientState(NULL);
851                 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
852             }
853             context->flags &= ~EGLContext_t::IS_CURRENT;
854
855             if (context->deletePending) {
856                 if (context->rcContext) {
857                     rcEnc->rcDestroyContext(rcEnc, context->rcContext);
858                     context->rcContext = 0;
859                 }
860                 delete context;
861             }
862             tInfo->currentContext = 0;
863         }
864     }
865     return EGL_TRUE;
866 }
867
868 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
869 {
870     //TODO
871     (void)dpy;
872     (void)buftype;
873     (void)buffer;
874     (void)config;
875     (void)attrib_list;
876     ALOGW("%s not implemented", __FUNCTION__);
877     return 0;
878 }
879
880 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
881 {
882     // Right now we don't do anything when using host GPU.
883     // This is purely just to pass the data through
884     // without issuing a warning. We may benefit from validating the
885     // display and surface for debug purposes.
886     // TODO: Find cases where we actually need to do something.
887     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
888     VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
889     if (surface == EGL_NO_SURFACE) {
890         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
891     }
892
893     (void)value;
894
895     switch (attribute) {
896     case EGL_MIPMAP_LEVEL:
897     case EGL_MULTISAMPLE_RESOLVE:
898     case EGL_SWAP_BEHAVIOR:
899         return true;
900         break;
901     default:
902         ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
903     }
904     return false;
905 }
906
907 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
908 {
909     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
910     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
911     if (eglSurface == EGL_NO_SURFACE) {
912         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
913     }
914
915     if (buffer != EGL_BACK_BUFFER) {
916         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
917     }
918
919     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
920
921     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
922         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
923     }
924
925     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
926         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
927     }
928
929     //It's now safe to cast to pbuffer surface
930     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
931
932     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
933     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
934
935     return GL_TRUE;
936 }
937
938 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
939 {
940     //TODO
941     (void)dpy;
942     (void)surface;
943     (void)buffer;
944     ALOGW("%s not implemented", __FUNCTION__);
945     return 0;
946 }
947
948 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
949 {
950     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
951     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
952
953     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
954     if (!ctx) {
955         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
956     }
957     if (!ctx->draw) {
958         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
959     }
960     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
961     draw->setSwapInterval(interval);
962
963     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
964
965     return EGL_TRUE;
966 }
967
968 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
969 {
970     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
971     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
972
973     EGLint version = 1; //default
974     while (attrib_list && attrib_list[0] != EGL_NONE) {
975         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
976             version = attrib_list[1];
977         } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
978             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
979         }
980         attrib_list+=2;
981     }
982
983     // Currently only support GLES1 and 2
984     if (version != 1 && version != 2) {
985         setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
986     }
987
988     uint32_t rcShareCtx = 0;
989     EGLContext_t * shareCtx = NULL;
990     if (share_context) {
991         shareCtx = static_cast<EGLContext_t*>(share_context);
992         rcShareCtx = shareCtx->rcContext;
993         if (shareCtx->dpy != dpy)
994             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
995     }
996
997     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
998     // We've created EGL context. Disconnecting
999     // would be dangerous at this point.
1000     hostCon->setGrallocOnly(false);
1001
1002     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1003     if (!rcContext) {
1004         ALOGE("rcCreateContext returned 0");
1005         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1006     }
1007
1008     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1009     if (!context)
1010         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1011
1012     context->version = version;
1013     context->rcContext = rcContext;
1014
1015
1016     return context;
1017 }
1018
1019 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1020 {
1021     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1022     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1023
1024     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1025
1026     if (!context) return EGL_TRUE;
1027
1028     if (getEGLThreadInfo()->currentContext == context) {
1029         getEGLThreadInfo()->currentContext->deletePending = 1;
1030         return EGL_TRUE;
1031     }
1032
1033     if (context->rcContext) {
1034         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1035         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1036         context->rcContext = 0;
1037     }
1038
1039     delete context;
1040     return EGL_TRUE;
1041 }
1042
1043 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1044 {
1045     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1046     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1047     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1048
1049     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1050         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1051     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1052         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1053
1054     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1055     uint32_t ctxHandle = (context) ? context->rcContext : 0;
1056     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1057     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1058     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1059     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1060
1061     //
1062     // Nothing to do if no binding change has made
1063     //
1064     EGLThreadInfo *tInfo = getEGLThreadInfo();
1065
1066     if (tInfo->currentContext == context &&
1067         (context == NULL ||
1068         (context && context->draw == draw && context->read == read))) {
1069         return EGL_TRUE;
1070     }
1071
1072     if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1073         if (tInfo->currentContext != context) {
1074             EGLContext_t * contextToDelete = tInfo->currentContext;
1075             tInfo->currentContext = 0;
1076             eglDestroyContext(dpy, contextToDelete);
1077         }
1078     }
1079
1080     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1081         //context is current to another thread
1082         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1083     }
1084
1085     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1086     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1087         ALOGE("rcMakeCurrent returned EGL_FALSE");
1088         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1089     }
1090
1091     //Now make the local bind
1092     if (context) {
1093         // This is a nontrivial context.
1094         // The thread cannot be gralloc-only anymore.
1095         hostCon->setGrallocOnly(false);
1096         context->draw = draw;
1097         context->read = read;
1098         context->flags |= EGLContext_t::IS_CURRENT;
1099         //set the client state
1100         if (context->version == 2) {
1101             hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1102             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1103         }
1104         else {
1105             hostCon->glEncoder()->setClientState(context->getClientState());
1106             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1107         }
1108     }
1109     else if (tInfo->currentContext) {
1110         //release ClientState & SharedGroup
1111         if (tInfo->currentContext->version == 2) {
1112             hostCon->gl2Encoder()->setClientState(NULL);
1113             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1114         }
1115         else {
1116             hostCon->glEncoder()->setClientState(NULL);
1117             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1118         }
1119
1120     }
1121
1122     if (tInfo->currentContext)
1123         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1124
1125     //Now make current
1126     tInfo->currentContext = context;
1127
1128     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1129     if (tInfo->currentContext) {
1130         if (tInfo->currentContext->version == 2) {
1131             if (!hostCon->gl2Encoder()->isInitialized()) {
1132                 s_display.gles2_iface()->init();
1133                 hostCon->gl2Encoder()->setInitialized();
1134                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1135             }
1136         }
1137         else {
1138             if (!hostCon->glEncoder()->isInitialized()) {
1139                 s_display.gles_iface()->init();
1140                 hostCon->glEncoder()->setInitialized();
1141                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1142             }
1143         }
1144     }
1145
1146     return EGL_TRUE;
1147 }
1148
1149 EGLContext eglGetCurrentContext()
1150 {
1151     return getEGLThreadInfo()->currentContext;
1152 }
1153
1154 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1155 {
1156     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1157     if (!context)
1158         return EGL_NO_SURFACE; //not an error
1159
1160     switch (readdraw) {
1161         case EGL_READ:
1162             return context->read;
1163         case EGL_DRAW:
1164             return context->draw;
1165         default:
1166             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1167     }
1168 }
1169
1170 EGLDisplay eglGetCurrentDisplay()
1171 {
1172     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1173     if (!context)
1174         return EGL_NO_DISPLAY; //not an error
1175
1176     return context->dpy;
1177 }
1178
1179 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1180 {
1181     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1182     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1183
1184     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1185
1186     EGLBoolean ret = EGL_TRUE;
1187     switch (attribute) {
1188         case EGL_CONFIG_ID:
1189             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1190             break;
1191         case EGL_CONTEXT_CLIENT_TYPE:
1192             *value = EGL_OPENGL_ES_API;
1193             break;
1194         case EGL_CONTEXT_CLIENT_VERSION:
1195             *value = context->version;
1196             break;
1197         case EGL_RENDER_BUFFER:
1198             if (!context->draw)
1199                 *value = EGL_NONE;
1200             else
1201                 *value = EGL_BACK_BUFFER; //single buffer not supported
1202             break;
1203         default:
1204             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
1205             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1206             break;
1207     }
1208
1209     return ret;
1210 }
1211
1212 EGLBoolean eglWaitGL()
1213 {
1214     EGLThreadInfo *tInfo = getEGLThreadInfo();
1215     if (!tInfo || !tInfo->currentContext) {
1216         return EGL_FALSE;
1217     }
1218
1219     if (tInfo->currentContext->version == 2) {
1220         s_display.gles2_iface()->finish();
1221     }
1222     else {
1223         s_display.gles_iface()->finish();
1224     }
1225
1226     return EGL_TRUE;
1227 }
1228
1229 EGLBoolean eglWaitNative(EGLint engine)
1230 {
1231     (void)engine;
1232     return EGL_TRUE;
1233 }
1234
1235 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1236 {
1237     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1238     if (eglSurface == EGL_NO_SURFACE)
1239         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1240
1241     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1242
1243     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1244     if (d->dpy != dpy)
1245         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1246
1247     // post the surface
1248     d->swapBuffers();
1249
1250     hostCon->flush();
1251     return EGL_TRUE;
1252 }
1253
1254 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1255 {
1256     //TODO :later
1257     (void)dpy;
1258     (void)surface;
1259     (void)target;
1260     return 0;
1261 }
1262
1263 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1264 {
1265     //TODO later
1266     (void)display;
1267     (void)surface;
1268     (void)attrib_list;
1269     return 0;
1270 }
1271
1272 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1273 {
1274     //TODO later
1275     (void)display;
1276     (void)surface;
1277     return 0;
1278 }
1279
1280 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1281 {
1282     (void)attrib_list;
1283
1284     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1285
1286     if (target == EGL_NATIVE_BUFFER_ANDROID) {
1287         if (ctx != EGL_NO_CONTEXT) {
1288             setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1289         }
1290
1291         android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1292
1293         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1294             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1295
1296         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1297             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1298
1299         cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1300
1301         switch (cb->format) {
1302             case HAL_PIXEL_FORMAT_RGBA_8888:
1303             case HAL_PIXEL_FORMAT_RGBX_8888:
1304             case HAL_PIXEL_FORMAT_RGB_888:
1305             case HAL_PIXEL_FORMAT_RGB_565:
1306             case HAL_PIXEL_FORMAT_BGRA_8888:
1307                 break;
1308             default:
1309                 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1310         }
1311
1312         native_buffer->common.incRef(&native_buffer->common);
1313
1314         EGLImage_t *image = new EGLImage_t();
1315         image->dpy = dpy;
1316         image->target = target;
1317         image->native_buffer = native_buffer;
1318
1319         return (EGLImageKHR)image;
1320     }
1321     else if (target == EGL_GL_TEXTURE_2D_KHR) {
1322         VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1323
1324         EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1325         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1326
1327         uint32_t ctxHandle = (context) ? context->rcContext : 0;
1328         GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1329         uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1330         EGLImage_t *image = new EGLImage_t();
1331         image->dpy = dpy;
1332         image->target = target;
1333         image->host_egl_image = img;
1334
1335         return (EGLImageKHR)image;
1336     }
1337     
1338     setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1339 }
1340
1341 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1342 {
1343     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1344     EGLImage_t *image = (EGLImage_t*)img;
1345
1346     if (!image || image->dpy != dpy) {
1347         RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1348     }
1349
1350     if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1351         android_native_buffer_t* native_buffer = image->native_buffer;
1352
1353         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1354             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1355
1356         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1357             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1358
1359         native_buffer->common.decRef(&native_buffer->common);
1360         delete image;
1361
1362         return EGL_TRUE;
1363     }
1364     else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1365         uint32_t host_egl_image = image->host_egl_image;
1366         delete image;
1367         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1368         return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1369     }
1370
1371     setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1372 }
1373
1374 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1375
1376 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1377         const EGLint *attrib_list)
1378 {
1379     // TODO: This implementation could be faster. We should require the host EGL
1380     // to support KHR_fence_sync, or at least pipe the fence command to the host
1381     // and wait for it (probably involving a glFinish on the host) in
1382     // eglClientWaitSyncKHR.
1383
1384     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1385
1386     if (type != EGL_SYNC_FENCE_KHR ||
1387             (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1388         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1389     }
1390
1391     EGLThreadInfo *tInfo = getEGLThreadInfo();
1392     if (!tInfo || !tInfo->currentContext) {
1393         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1394     }
1395
1396     if (tInfo->currentContext->version == 2) {
1397         s_display.gles2_iface()->finish();
1398     } else {
1399         s_display.gles_iface()->finish();
1400     }
1401
1402     return FENCE_SYNC_HANDLE;
1403 }
1404
1405 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1406 {
1407     (void)dpy;
1408
1409     if (sync != FENCE_SYNC_HANDLE) {
1410         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1411     }
1412
1413     return EGL_TRUE;
1414 }
1415
1416 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1417         EGLTimeKHR timeout)
1418 {
1419     (void)dpy;
1420     (void)flags;
1421     (void)timeout;
1422
1423     if (sync != FENCE_SYNC_HANDLE) {
1424         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1425     }
1426
1427     return EGL_CONDITION_SATISFIED_KHR;
1428 }
1429
1430 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1431         EGLint attribute, EGLint *value)
1432 {
1433     (void)dpy;
1434
1435     if (sync != FENCE_SYNC_HANDLE) {
1436         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1437     }
1438
1439     switch (attribute) {
1440     case EGL_SYNC_TYPE_KHR:
1441         *value = EGL_SYNC_FENCE_KHR;
1442         return EGL_TRUE;
1443     case EGL_SYNC_STATUS_KHR:
1444         *value = EGL_SIGNALED_KHR;
1445         return EGL_TRUE;
1446     case EGL_SYNC_CONDITION_KHR:
1447         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1448         return EGL_TRUE;
1449     default:
1450         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1451     }
1452 }