OSDN Git Service

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