OSDN Git Service

Ignore EGL_SWAP_BEHAVIOR_PRESERVED_BIT on low API version
[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 "eglSync.h"
22 #include "egl_ftable.h"
23 #include <cutils/log.h>
24 #include "goldfish_sync.h"
25 #include "gralloc_cb.h"
26 #include "GLClientState.h"
27 #include "GLSharedGroup.h"
28 #include "eglContext.h"
29 #include "ClientAPIExts.h"
30 #include "EGLImage.h"
31 #include "ProcessPipe.h"
32
33 #include "GLEncoder.h"
34 #ifdef WITH_GLES2
35 #include "GL2Encoder.h"
36 #endif
37
38 #if PLATFORM_SDK_VERSION >= 16
39 #include <system/window.h>
40 #else // PLATFORM_SDK_VERSION >= 16
41 #include <private/ui/android_natives_priv.h>
42 #endif // PLATFORM_SDK_VERSION >= 16
43
44 #if PLATFORM_SDK_VERSION <= 16
45 #define queueBuffer_DEPRECATED queueBuffer
46 #define dequeueBuffer_DEPRECATED dequeueBuffer
47 #define cancelBuffer_DEPRECATED cancelBuffer
48 #endif // PLATFORM_SDK_VERSION <= 16
49
50 #define DEBUG_EGL 0
51
52 #if DEBUG_EGL
53 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
54 #else
55 #define DPRINT(...)
56 #endif
57
58 template<typename T>
59 static T setErrorFunc(GLint error, T returnValue) {
60     getEGLThreadInfo()->eglError = error;
61     return returnValue;
62 }
63
64 const char *  eglStrError(EGLint err)
65 {
66     switch (err){
67         case EGL_SUCCESS:           return "EGL_SUCCESS";
68         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
69         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
70         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
71         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
72         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
73         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
74         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
75         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
76         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
77         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
78         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
79         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
80         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
81         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
82         default: return "UNKNOWN";
83     }
84 }
85
86 #define LOG_EGL_ERRORS 1
87
88 #ifdef LOG_EGL_ERRORS
89
90 #define setErrorReturn(error, retVal)     \
91     {                                                \
92         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
93         return setErrorFunc(error, retVal);            \
94     }
95
96 #define RETURN_ERROR(ret,err)           \
97     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
98     getEGLThreadInfo()->eglError = err;    \
99     return ret;
100
101 #else //!LOG_EGL_ERRORS
102
103 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
104
105 #define RETURN_ERROR(ret,err)           \
106     getEGLThreadInfo()->eglError = err; \
107     return ret;
108
109 #endif //LOG_EGL_ERRORS
110
111 #define VALIDATE_CONFIG(cfg,ret) \
112     if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
113         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
114     }
115
116 #define VALIDATE_DISPLAY(dpy,ret) \
117     if ((dpy) != (EGLDisplay)&s_display) { \
118         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
119     }
120
121 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
122     VALIDATE_DISPLAY(dpy, ret)    \
123     if (!s_display.initialized()) {        \
124         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
125     }
126
127 #define DEFINE_HOST_CONNECTION \
128     HostConnection *hostCon = HostConnection::get(); \
129     ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
130
131 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
132     HostConnection *hostCon = HostConnection::get(); \
133     if (!hostCon) { \
134         ALOGE("egl: Failed to get host connection\n"); \
135         return ret; \
136     } \
137     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
138     if (!rcEnc) { \
139         ALOGE("egl: Failed to get renderControl encoder context\n"); \
140         return ret; \
141     }
142
143 #define VALIDATE_CONTEXT_RETURN(context,ret)  \
144     if (!(context)) {                         \
145         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
146     }
147
148 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
149     if ((surface) != EGL_NO_SURFACE) {    \
150         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
151         if (s->dpy != (EGLDisplay)&s_display)    \
152             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
153     }
154
155 // The one and only supported display object.
156 static eglDisplay s_display;
157
158 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
159     dpy(dpy),
160     config(config),
161     read(EGL_NO_SURFACE),
162     draw(EGL_NO_SURFACE),
163     shareCtx(shareCtx),
164     rcContext(0),
165     versionString(NULL),
166     vendorString(NULL),
167     rendererString(NULL),
168     shaderVersionString(NULL),
169     extensionString(NULL),
170     deletePending(0),
171     goldfishSyncFd(-1)
172 {
173     flags = 0;
174     version = 1;
175     clientState = new GLClientState();
176     if (shareCtx)
177         sharedGroup = shareCtx->getSharedGroup();
178     else
179         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
180     assert(dpy == (EGLDisplay)&s_display);
181     s_display.onCreateContext((EGLContext)this);
182 };
183
184 int EGLContext_t::getGoldfishSyncFd() {
185     if (goldfishSyncFd < 0) {
186         goldfishSyncFd = goldfish_sync_open();
187     }
188     return goldfishSyncFd;
189 }
190
191 EGLContext_t::~EGLContext_t()
192 {
193     if (goldfishSyncFd > 0) {
194         goldfish_sync_close(goldfishSyncFd);
195         goldfishSyncFd = -1;
196     }
197     assert(dpy == (EGLDisplay)&s_display);
198     s_display.onDestroyContext((EGLContext)this);
199     delete clientState;
200     delete [] versionString;
201     delete [] vendorString;
202     delete [] rendererString;
203     delete [] shaderVersionString;
204     delete [] extensionString;
205 }
206
207 // ----------------------------------------------------------------------------
208 //egl_surface_t
209
210 //we don't need to handle depth since it's handled when window created on the host
211
212 struct egl_surface_t {
213
214     EGLDisplay          dpy;
215     EGLConfig           config;
216
217
218     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
219     virtual     ~egl_surface_t();
220
221     virtual     void        setSwapInterval(int interval) = 0;
222     virtual     EGLBoolean  swapBuffers() = 0;
223
224     EGLint      getSwapBehavior() const;
225     uint32_t    getRcSurface()   { return rcSurface; }
226     EGLint      getSurfaceType() { return surfaceType; }
227
228     EGLint      getWidth(){ return width; }
229     EGLint      getHeight(){ return height; }
230     EGLint      getNativeWidth(){ return nativeWidth; }
231     EGLint      getNativeHeight(){ return nativeHeight; }
232     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
233     EGLint      getTextureFormat() { return texFormat; }
234     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
235     EGLint      getTextureTarget() { return texTarget; }
236
237 private:
238     //
239     //Surface attributes
240     //
241     EGLint      width;
242     EGLint      height;
243     EGLint      texFormat;
244     EGLint      texTarget;
245
246     // Width of the actual window being presented (not the EGL texture)
247     // Give it some default values.
248     int nativeWidth;
249     int nativeHeight;
250
251 protected:
252     void        setWidth(EGLint w)  { width = w;  }
253     void        setHeight(EGLint h) { height = h; }
254     void        setNativeWidth(int w)  { nativeWidth = w;  }
255     void        setNativeHeight(int h) { nativeHeight = h; }
256
257     EGLint      surfaceType;
258     uint32_t    rcSurface; //handle to surface created via remote control
259 };
260
261 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
262     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
263 {
264     width = 0;
265     height = 0;
266     // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
267     nativeWidth = 1;
268     nativeHeight = 1;
269     texFormat = EGL_NO_TEXTURE;
270     texTarget = EGL_NO_TEXTURE;
271     assert(dpy == (EGLDisplay)&s_display);
272     s_display.onCreateSurface((EGLSurface)this);
273 }
274
275 EGLint egl_surface_t::getSwapBehavior() const {
276     return EGL_BUFFER_PRESERVED;
277 }
278
279 egl_surface_t::~egl_surface_t()
280 {
281     assert(dpy == (EGLDisplay)&s_display);
282     s_display.onDestroySurface((EGLSurface)this);
283 }
284
285 // ----------------------------------------------------------------------------
286 // egl_window_surface_t
287
288 struct egl_window_surface_t : public egl_surface_t {
289     static egl_window_surface_t* create(
290             EGLDisplay dpy, EGLConfig config, EGLint surfType,
291             ANativeWindow* window);
292
293     virtual ~egl_window_surface_t();
294
295     virtual void       setSwapInterval(int interval);
296     virtual EGLBoolean swapBuffers();
297
298 private:
299     egl_window_surface_t(
300             EGLDisplay dpy, EGLConfig config, EGLint surfType,
301             ANativeWindow* window);
302     EGLBoolean init();
303
304     ANativeWindow*              nativeWindow;
305     android_native_buffer_t*    buffer;
306 };
307
308 egl_window_surface_t::egl_window_surface_t (
309         EGLDisplay dpy, EGLConfig config, EGLint surfType,
310         ANativeWindow* window)
311 :   egl_surface_t(dpy, config, surfType),
312     nativeWindow(window),
313     buffer(NULL)
314 {
315     // keep a reference on the window
316     nativeWindow->common.incRef(&nativeWindow->common);
317 }
318
319
320 EGLBoolean egl_window_surface_t::init()
321 {
322     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
323         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
324     }
325     setWidth(buffer->width);
326     setHeight(buffer->height);
327
328     int nativeWidth, nativeHeight;
329           nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
330           nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
331
332     setNativeWidth(nativeWidth);
333     setNativeHeight(nativeHeight);
334
335     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
336     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
337             getWidth(), getHeight());
338     if (!rcSurface) {
339         ALOGE("rcCreateWindowSurface returned 0");
340         return EGL_FALSE;
341     }
342     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
343             ((cb_handle_t*)(buffer->handle))->hostHandle);
344
345     return EGL_TRUE;
346 }
347
348 egl_window_surface_t* egl_window_surface_t::create(
349         EGLDisplay dpy, EGLConfig config, EGLint surfType,
350         ANativeWindow* window)
351 {
352     egl_window_surface_t* wnd = new egl_window_surface_t(
353             dpy, config, surfType, window);
354     if (wnd && !wnd->init()) {
355         delete wnd;
356         wnd = NULL;
357     }
358     return wnd;
359 }
360
361 egl_window_surface_t::~egl_window_surface_t() {
362     DEFINE_HOST_CONNECTION;
363     if (rcSurface && rcEnc) {
364         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
365     }
366     if (buffer) {
367         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
368     }
369     nativeWindow->common.decRef(&nativeWindow->common);
370 }
371
372 void egl_window_surface_t::setSwapInterval(int interval)
373 {
374     nativeWindow->setSwapInterval(nativeWindow, interval);
375 }
376
377 // createNativeSync() creates an OpenGL sync object on the host
378 // using rcCreateSyncKHR. If necessary, a native fence FD will
379 // also be created through the goldfish sync device.
380 // Returns a handle to the host-side FenceSync object.
381 static uint64_t createNativeSync(EGLenum type,
382                                  const EGLint* attrib_list,
383                                  int num_actual_attribs,
384                                  bool destroy_when_signaled,
385                                  int fd_in,
386                                  int* fd_out) {
387     DEFINE_HOST_CONNECTION;
388
389     uint64_t sync_handle;
390     uint64_t thread_handle;
391
392     EGLint* actual_attribs =
393         (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
394
395     rcEnc->rcCreateSyncKHR(rcEnc, type,
396                            actual_attribs,
397                            num_actual_attribs * sizeof(EGLint),
398                            destroy_when_signaled,
399                            &sync_handle,
400                            &thread_handle);
401
402     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
403         int queue_work_err =
404             goldfish_sync_queue_work(
405                     getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
406                     sync_handle,
407                     thread_handle,
408                     fd_out);
409
410         DPRINT("got native fence fd=%d queue_work_err=%d",
411                *fd_out, queue_work_err);
412     }
413
414     return sync_handle;
415 }
416
417 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
418 // that are needed by only this goldfish opengl driver,
419 // such as in swapBuffers().
420 // The guest will not see any of these, and these sync objects will be
421 // destroyed on the host when signaled.
422 // A native fence FD is possibly returned.
423 static void createGoldfishOpenGLNativeSync(int* fd_out) {
424     createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
425                      NULL /* empty attrib list */,
426                      0 /* 0 attrib count */,
427                      true /* destroy when signaled. this is host-only
428                              and there will only be one waiter */,
429                      -1 /* we want a new fd */,
430                      fd_out);
431 }
432
433 EGLBoolean egl_window_surface_t::swapBuffers()
434 {
435
436     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
437
438     // Follow up flushWindowColorBuffer with a fence command.
439     // When the fence command finishes,
440     // we're sure that the buffer on the host
441     // has been blitted.
442     //
443     // |presentFenceFd| guards the presentation of the
444     // current frame with a goldfish sync fence fd.
445     //
446     // When |presentFenceFd| is signaled, the recipient
447     // of the buffer that was sent through queueBuffer
448     // can be sure that the buffer is current.
449     //
450     // If we don't take care of this synchronization,
451     // an old frame can be processed by surfaceflinger,
452     // resulting in out of order frames.
453
454     int presentFenceFd = -1;
455
456 #if PLATFORM_SDK_VERSION <= 16
457     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
458     // equivalent to glFinish if no native sync
459     eglWaitClient();
460     nativeWindow->queueBuffer(nativeWindow, buffer);
461 #else
462     if (rcEnc->hasNativeSync()) {
463         rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
464         createGoldfishOpenGLNativeSync(&presentFenceFd);
465     } else {
466         rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
467         // equivalent to glFinish if no native sync
468         eglWaitClient();
469     }
470
471     DPRINT("queueBuffer with fence %d", presentFenceFd);
472     nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
473 #endif
474
475     DPRINT("calling dequeueBuffer...");
476
477 #if PLATFORM_SDK_VERSION <= 16
478     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
479         buffer = NULL;
480         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
481     }
482 #else
483     int acquireFenceFd = -1;
484     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
485         buffer = NULL;
486         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
487     }
488
489     DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
490
491     if (acquireFenceFd > 0) {
492         close(acquireFenceFd);
493     }
494 #endif
495
496     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
497             ((cb_handle_t *)(buffer->handle))->hostHandle);
498
499     setWidth(buffer->width);
500     setHeight(buffer->height);
501
502     return EGL_TRUE;
503 }
504
505 // ----------------------------------------------------------------------------
506 //egl_pbuffer_surface_t
507
508 struct egl_pbuffer_surface_t : public egl_surface_t {
509     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
510             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
511
512     virtual ~egl_pbuffer_surface_t();
513
514     virtual void       setSwapInterval(int interval) { (void)interval; }
515     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
516
517     uint32_t getRcColorBuffer() { return rcColorBuffer; }
518
519 private:
520     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
521             int32_t w, int32_t h);
522     EGLBoolean init(GLenum format);
523
524     uint32_t rcColorBuffer;
525 };
526
527 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
528         EGLint surfType, int32_t w, int32_t h)
529 :   egl_surface_t(dpy, config, surfType),
530     rcColorBuffer(0)
531 {
532     setWidth(w);
533     setHeight(h);
534 }
535
536 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
537 {
538     DEFINE_HOST_CONNECTION;
539     if (rcEnc) {
540         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
541         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
542     }
543 }
544
545 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
546 {
547     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
548
549     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
550             getWidth(), getHeight());
551     if (!rcSurface) {
552         ALOGE("rcCreateWindowSurface returned 0");
553         return EGL_FALSE;
554     }
555
556     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
557             pixelFormat);
558     if (!rcColorBuffer) {
559         ALOGE("rcCreateColorBuffer returned 0");
560         return EGL_FALSE;
561     }
562
563     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
564
565     return EGL_TRUE;
566 }
567
568 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
569         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
570         GLenum pixelFormat)
571 {
572     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
573             w, h);
574     if (pb && !pb->init(pixelFormat)) {
575         delete pb;
576         pb = NULL;
577     }
578     return pb;
579 }
580
581 static const char *getGLString(int glEnum)
582 {
583     EGLThreadInfo *tInfo = getEGLThreadInfo();
584     if (!tInfo || !tInfo->currentContext) {
585         return NULL;
586     }
587
588     const char** strPtr = NULL;
589
590 #define GL_VENDOR                         0x1F00
591 #define GL_RENDERER                       0x1F01
592 #define GL_VERSION                        0x1F02
593 #define GL_SHADING_LANGUAGE_VERSION       0x8B8C
594 #define GL_EXTENSIONS                     0x1F03
595
596     switch(glEnum) {
597         case GL_VERSION:
598             strPtr = &tInfo->currentContext->versionString;
599             break;
600         case GL_VENDOR:
601             strPtr = &tInfo->currentContext->vendorString;
602             break;
603         case GL_RENDERER:
604             strPtr = &tInfo->currentContext->rendererString;
605             break;
606         case GL_SHADING_LANGUAGE_VERSION:
607             strPtr = &tInfo->currentContext->shaderVersionString;
608             break;
609         case GL_EXTENSIONS:
610             strPtr = &tInfo->currentContext->extensionString;
611             break;
612     }
613
614     if (!strPtr) {
615         return NULL;
616     }
617
618     if (*strPtr != NULL) {
619         //
620         // string is already cached
621         //
622         return *strPtr;
623     }
624
625     //
626     // first query of that string - need to query host
627     //
628     DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
629     char *hostStr = NULL;
630     int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
631     if (n < 0) {
632         hostStr = new char[-n+1];
633         n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
634         if (n <= 0) {
635             delete [] hostStr;
636             hostStr = NULL;
637         }
638     }
639
640     //
641     // keep the string in the context and return its value
642     //
643     *strPtr = hostStr;
644     return hostStr;
645 }
646
647 // ----------------------------------------------------------------------------
648
649 static EGLClient_eglInterface s_eglIface = {
650     getThreadInfo: getEGLThreadInfo,
651     getGLString: getGLString
652 };
653
654 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
655 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
656 {
657     //
658     // we support only EGL_DEFAULT_DISPLAY.
659     //
660     if (display_id != EGL_DEFAULT_DISPLAY) {
661         return EGL_NO_DISPLAY;
662     }
663
664     return (EGLDisplay)&s_display;
665 }
666
667 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
668 {
669     VALIDATE_DISPLAY(dpy,EGL_FALSE);
670
671     if (!s_display.initialize(&s_eglIface)) {
672         return EGL_FALSE;
673     }
674     if (major!=NULL)
675         *major = s_display.getVersionMajor();
676     if (minor!=NULL)
677         *minor = s_display.getVersionMinor();
678     return EGL_TRUE;
679 }
680
681 EGLBoolean eglTerminate(EGLDisplay dpy)
682 {
683     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
684
685     s_display.terminate();
686     return EGL_TRUE;
687 }
688
689 EGLint eglGetError()
690 {
691     EGLint error = getEGLThreadInfo()->eglError;
692     getEGLThreadInfo()->eglError = EGL_SUCCESS;
693     return error;
694 }
695
696 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
697 {
698     // search in EGL function table
699     for (int i=0; i<egl_num_funcs; i++) {
700         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
701             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
702         }
703     }
704
705     // look in gles client api's extensions table
706     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
707
708     // Fail - function not found.
709     return NULL;
710 }
711
712 const char* eglQueryString(EGLDisplay dpy, EGLint name)
713 {
714     VALIDATE_DISPLAY_INIT(dpy, NULL);
715
716     return s_display.queryString(name);
717 }
718
719 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
720 {
721     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
722
723     if(!num_config) {
724         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
725     }
726
727     GLint numConfigs = s_display.getNumConfigs();
728     if (!configs) {
729         *num_config = numConfigs;
730         return EGL_TRUE;
731     }
732
733     EGLint i;
734     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
735         *configs++ = (EGLConfig)(uintptr_t)i;
736     }
737     *num_config = i;
738     return EGL_TRUE;
739 }
740
741 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
742 {
743     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
744
745     if (!num_config) {
746         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
747     }
748
749     int attribs_size = 0;
750     if (attrib_list) {
751         const EGLint * attrib_p = attrib_list;
752         while (attrib_p[0] != EGL_NONE) {
753             attribs_size += 2;
754             attrib_p += 2;
755         }
756         attribs_size++; //for the terminating EGL_NONE
757     }
758
759     // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
760     // while the host never supports it.
761     // We remove the bit here.
762     EGLint* local_attrib_list = NULL;
763     if (PLATFORM_SDK_VERSION <= 19) {
764         local_attrib_list = new EGLint[attribs_size];
765         memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
766         EGLint* local_attrib_p = local_attrib_list;
767         while (local_attrib_p[0] != EGL_NONE) {
768             if (local_attrib_p[0] == EGL_SURFACE_TYPE) {
769                 local_attrib_p[1] &= ~(EGLint)EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
770             }
771             local_attrib_p += 2;
772         }
773     }
774
775     uint32_t* tempConfigs[config_size];
776     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
777     *num_config = rcEnc->rcChooseConfig(rcEnc,
778             local_attrib_list ? local_attrib_list:(EGLint*)attrib_list,
779             attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
780
781     if (local_attrib_list) delete [] local_attrib_list;
782     if (*num_config <= 0) {
783         EGLint err = -(*num_config);
784         *num_config = 0;
785         switch (err) {
786             case EGL_BAD_ATTRIBUTE:
787                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
788             default:
789                 return EGL_FALSE;
790         }
791     }
792
793     if (configs!=NULL) {
794         EGLint i=0;
795         for (i=0;i<(*num_config);i++) {
796              *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
797         }
798     }
799
800     return EGL_TRUE;
801 }
802
803 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
804 {
805     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
806     VALIDATE_CONFIG(config, EGL_FALSE);
807
808     if (s_display.getConfigAttrib(config, attribute, value))
809     {
810         return EGL_TRUE;
811     }
812     else
813     {
814         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
815     }
816 }
817
818 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
819 {
820     (void)attrib_list;
821
822     VALIDATE_DISPLAY_INIT(dpy, NULL);
823     VALIDATE_CONFIG(config, EGL_FALSE);
824     if (win == 0) {
825         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
826     }
827
828     EGLint surfaceType;
829     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
830
831     if (!(surfaceType & EGL_WINDOW_BIT)) {
832         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
833     }
834
835     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
836         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
837     }
838
839     egl_surface_t* surface = egl_window_surface_t::create(
840             &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
841     if (!surface) {
842         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
843     }
844
845     return surface;
846 }
847
848 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
849 {
850     VALIDATE_DISPLAY_INIT(dpy, NULL);
851     VALIDATE_CONFIG(config, EGL_FALSE);
852
853     EGLint surfaceType;
854     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
855
856     if (!(surfaceType & EGL_PBUFFER_BIT)) {
857         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
858     }
859
860     int32_t w = 0;
861     int32_t h = 0;
862     EGLint texFormat = EGL_NO_TEXTURE;
863     EGLint texTarget = EGL_NO_TEXTURE;
864     while (attrib_list[0] != EGL_NONE) {
865         switch (attrib_list[0]) {
866             case EGL_WIDTH:
867                 w = attrib_list[1];
868                 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
869                 break;
870             case EGL_HEIGHT:
871                 h = attrib_list[1];
872                 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
873                 break;
874             case EGL_TEXTURE_FORMAT:
875                 texFormat = attrib_list[1];
876                 break;
877             case EGL_TEXTURE_TARGET:
878                 texTarget = attrib_list[1];
879                 break;
880             // the followings are not supported
881             case EGL_LARGEST_PBUFFER:
882             case EGL_MIPMAP_TEXTURE:
883             case EGL_VG_ALPHA_FORMAT:
884             case EGL_VG_COLORSPACE:
885                 break;
886             default:
887                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
888         };
889         attrib_list+=2;
890     }
891     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
892         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
893         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
894     }
895     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
896
897     GLenum pixelFormat;
898     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
899         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
900
901     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
902             EGL_PBUFFER_BIT, w, h, pixelFormat);
903     if (!surface) {
904         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
905     }
906
907     //setup attributes
908     surface->setTextureFormat(texFormat);
909     surface->setTextureTarget(texTarget);
910
911     return surface;
912 }
913
914 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
915 {
916     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
917     //     located on host. In order to support Pixmaps we should either punt
918     //     to s/w rendering -or- let the host render to a buffer that will be
919     //     copied back to guest at some sync point. None of those methods not
920     //     implemented and pixmaps are not used with OpenGL anyway ...
921     VALIDATE_CONFIG(config, EGL_FALSE);
922     (void)dpy;
923     (void)pixmap;
924     (void)attrib_list;
925     return EGL_NO_SURFACE;
926 }
927
928 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
929 {
930     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
931     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
932
933     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
934     delete surface;
935
936     return EGL_TRUE;
937 }
938
939 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
940 {
941     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
942     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
943
944     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
945
946     // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
947     // TODO: get the DPI from avd config
948     float fakeNativeDPI = 420.0;
949     float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
950     EGLBoolean ret = EGL_TRUE;
951     switch (attribute) {
952         case EGL_CONFIG_ID:
953             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
954             break;
955         case EGL_WIDTH:
956             *value = surface->getWidth();
957             break;
958         case EGL_HEIGHT:
959             *value = surface->getHeight();
960             break;
961         case EGL_TEXTURE_FORMAT:
962             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
963                 *value = surface->getTextureFormat();
964             }
965             break;
966         case EGL_TEXTURE_TARGET:
967             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
968                 *value = surface->getTextureTarget();
969             }
970             break;
971         case EGL_SWAP_BEHAVIOR:
972         {
973             EGLint surfaceType;
974             ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
975                     &surfaceType);
976             if (ret == EGL_TRUE) {
977                 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
978                     *value = EGL_BUFFER_PRESERVED;
979                 } else {
980                     *value = EGL_BUFFER_DESTROYED;
981                 }
982             }
983             break;
984         }
985         case EGL_LARGEST_PBUFFER:
986             // not modified for a window or pixmap surface
987             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
988             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
989             break;
990         case EGL_MIPMAP_TEXTURE:
991             // not modified for a window or pixmap surface
992             // and we ignore it when creating a PBuffer surface (default is 0)
993             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
994             break;
995         case EGL_MIPMAP_LEVEL:
996             // not modified for a window or pixmap surface
997             // and we ignore it when creating a PBuffer surface (default is 0)
998             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
999             break;
1000         case EGL_MULTISAMPLE_RESOLVE:
1001             // ignored when creating the surface, return default
1002             *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
1003             break;
1004         case EGL_HORIZONTAL_RESOLUTION:
1005             // pixel/mm * EGL_DISPLAY_SCALING
1006             // TODO: get the DPI from avd config
1007             currWidth = surface->getWidth();
1008             scaledResolution = currWidth / surface->getNativeWidth();
1009             effectiveSurfaceDPI =
1010                 scaledResolution * fakeNativeDPI * EGL_DISPLAY_SCALING;
1011             *value = (EGLint)(effectiveSurfaceDPI);
1012             break;
1013         case EGL_VERTICAL_RESOLUTION:
1014             // pixel/mm * EGL_DISPLAY_SCALING
1015             // TODO: get the real DPI from avd config
1016             currHeight = surface->getHeight();
1017             scaledResolution = currHeight / surface->getNativeHeight();
1018             effectiveSurfaceDPI =
1019                 scaledResolution * fakeNativeDPI * EGL_DISPLAY_SCALING;
1020             *value = (EGLint)(effectiveSurfaceDPI);
1021             break;
1022         case EGL_PIXEL_ASPECT_RATIO:
1023             // w / h * EGL_DISPLAY_SCALING
1024             // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
1025             *value = 1 * EGL_DISPLAY_SCALING;
1026             break;
1027         case EGL_RENDER_BUFFER:
1028             switch (surface->getSurfaceType()) {
1029                 case EGL_PBUFFER_BIT:
1030                     *value = EGL_BACK_BUFFER;
1031                     break;
1032                 case EGL_PIXMAP_BIT:
1033                     *value = EGL_SINGLE_BUFFER;
1034                     break;
1035                 case EGL_WINDOW_BIT:
1036                     // ignored when creating the surface, return default
1037                     *value = EGL_BACK_BUFFER;
1038                     break;
1039                 default:
1040                     ALOGE("eglQuerySurface %x unknown surface type %x",
1041                             attribute, surface->getSurfaceType());
1042                     ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1043                     break;
1044             }
1045             break;
1046         case EGL_VG_COLORSPACE:
1047             // ignored when creating the surface, return default
1048             *value = EGL_VG_COLORSPACE_sRGB;
1049             break;
1050         case EGL_VG_ALPHA_FORMAT:
1051             // ignored when creating the surface, return default
1052             *value = EGL_VG_ALPHA_FORMAT_NONPRE;
1053             break;
1054         //TODO: complete other attributes
1055         default:
1056             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
1057             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1058             break;
1059     }
1060
1061     return ret;
1062 }
1063
1064 EGLBoolean eglBindAPI(EGLenum api)
1065 {
1066     if (api != EGL_OPENGL_ES_API)
1067         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1068     return EGL_TRUE;
1069 }
1070
1071 EGLenum eglQueryAPI()
1072 {
1073     return EGL_OPENGL_ES_API;
1074 }
1075
1076 EGLBoolean eglWaitClient()
1077 {
1078     return eglWaitGL();
1079 }
1080
1081 EGLBoolean eglReleaseThread()
1082 {
1083     EGLThreadInfo *tInfo = getEGLThreadInfo();
1084     if (tInfo) {
1085         tInfo->eglError = EGL_SUCCESS;
1086         EGLContext_t* context = tInfo->currentContext;
1087         if (context) {
1088             // The following code is doing pretty much the same thing as
1089             // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1090             // with the only issue that we do not require a valid display here.
1091             DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1092             rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1093              if (context->version == 2) {
1094                 hostCon->gl2Encoder()->setClientState(NULL);
1095                 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
1096             }
1097             else {
1098                 hostCon->glEncoder()->setClientState(NULL);
1099                 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
1100             }
1101             context->flags &= ~EGLContext_t::IS_CURRENT;
1102
1103             if (context->deletePending) {
1104                 if (context->rcContext) {
1105                     rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1106                     context->rcContext = 0;
1107                 }
1108                 delete context;
1109             }
1110             tInfo->currentContext = 0;
1111         }
1112     }
1113     return EGL_TRUE;
1114 }
1115
1116 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1117 {
1118     //TODO
1119     (void)dpy;
1120     (void)buftype;
1121     (void)buffer;
1122     (void)config;
1123     (void)attrib_list;
1124     ALOGW("%s not implemented", __FUNCTION__);
1125     return 0;
1126 }
1127
1128 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1129 {
1130     // Right now we don't do anything when using host GPU.
1131     // This is purely just to pass the data through
1132     // without issuing a warning. We may benefit from validating the
1133     // display and surface for debug purposes.
1134     // TODO: Find cases where we actually need to do something.
1135     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1136     VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1137     if (surface == EGL_NO_SURFACE) {
1138         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1139     }
1140
1141     (void)value;
1142
1143     egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1144     switch (attribute) {
1145     case EGL_MIPMAP_LEVEL:
1146         return true;
1147         break;
1148     case EGL_MULTISAMPLE_RESOLVE:
1149     {
1150         if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1151             EGLint surface_type;
1152             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1153             if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1154                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1155             }
1156         }
1157         return true;
1158         break;
1159     }
1160     case EGL_SWAP_BEHAVIOR:
1161         if (value == EGL_BUFFER_PRESERVED) {
1162             EGLint surface_type;
1163             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1164             if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1165                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1166             }
1167         }
1168         return true;
1169         break;
1170     default:
1171         ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1172         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1173     }
1174     return false;
1175 }
1176
1177 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1178 {
1179     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1180     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1181     if (eglSurface == EGL_NO_SURFACE) {
1182         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1183     }
1184
1185     if (buffer != EGL_BACK_BUFFER) {
1186         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1187     }
1188
1189     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1190
1191     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1192         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1193     }
1194
1195     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1196         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1197     }
1198
1199     //It's now safe to cast to pbuffer surface
1200     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1201
1202     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1203     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1204
1205     return GL_TRUE;
1206 }
1207
1208 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1209 {
1210     //TODO
1211     (void)dpy;
1212     (void)surface;
1213     (void)buffer;
1214     ALOGW("%s not implemented", __FUNCTION__);
1215     return 0;
1216 }
1217
1218 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1219 {
1220     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1221     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1222
1223     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1224     if (!ctx) {
1225         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1226     }
1227     if (!ctx->draw) {
1228         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1229     }
1230     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1231     draw->setSwapInterval(interval);
1232
1233     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1234
1235     return EGL_TRUE;
1236 }
1237
1238 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1239 {
1240     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1241     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1242
1243     EGLint version = 1; //default
1244     while (attrib_list && attrib_list[0] != EGL_NONE) {
1245         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
1246             version = attrib_list[1];
1247         } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
1248             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1249         }
1250         attrib_list+=2;
1251     }
1252
1253     // Currently only support GLES1 and 2
1254     if (version != 1 && version != 2) {
1255         setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1256     }
1257
1258     uint32_t rcShareCtx = 0;
1259     EGLContext_t * shareCtx = NULL;
1260     if (share_context) {
1261         shareCtx = static_cast<EGLContext_t*>(share_context);
1262         rcShareCtx = shareCtx->rcContext;
1263         if (shareCtx->dpy != dpy)
1264             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1265     }
1266
1267     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1268     // We've created EGL context. Disconnecting
1269     // would be dangerous at this point.
1270     hostCon->setGrallocOnly(false);
1271
1272     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1273     if (!rcContext) {
1274         ALOGE("rcCreateContext returned 0");
1275         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1276     }
1277
1278     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1279     if (!context)
1280         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1281
1282     context->version = version;
1283     context->rcContext = rcContext;
1284
1285
1286     return context;
1287 }
1288
1289 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1290 {
1291     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1292     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1293
1294     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1295
1296     if (!context) return EGL_TRUE;
1297
1298     if (getEGLThreadInfo()->currentContext == context) {
1299         getEGLThreadInfo()->currentContext->deletePending = 1;
1300         return EGL_TRUE;
1301     }
1302
1303     if (context->rcContext) {
1304         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1305         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1306         context->rcContext = 0;
1307     }
1308
1309     delete context;
1310     return EGL_TRUE;
1311 }
1312
1313 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1314 {
1315     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1316     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1317     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1318
1319     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1320         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1321     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1322         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1323
1324     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1325     uint32_t ctxHandle = (context) ? context->rcContext : 0;
1326     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1327     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1328     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1329     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1330
1331     //
1332     // Nothing to do if no binding change has made
1333     //
1334     EGLThreadInfo *tInfo = getEGLThreadInfo();
1335
1336     if (tInfo->currentContext == context &&
1337         (context == NULL ||
1338         (context && context->draw == draw && context->read == read))) {
1339         return EGL_TRUE;
1340     }
1341
1342     if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1343         if (tInfo->currentContext != context) {
1344             EGLContext_t * contextToDelete = tInfo->currentContext;
1345             tInfo->currentContext = 0;
1346             eglDestroyContext(dpy, contextToDelete);
1347         }
1348     }
1349
1350     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1351         //context is current to another thread
1352         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1353     }
1354
1355     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1356     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1357         ALOGE("rcMakeCurrent returned EGL_FALSE");
1358         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1359     }
1360
1361     //Now make the local bind
1362     if (context) {
1363         // This is a nontrivial context.
1364         // The thread cannot be gralloc-only anymore.
1365         hostCon->setGrallocOnly(false);
1366         context->draw = draw;
1367         context->read = read;
1368         context->flags |= EGLContext_t::IS_CURRENT;
1369         //set the client state
1370         if (context->version == 2) {
1371             hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1372             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1373         }
1374         else {
1375             hostCon->glEncoder()->setClientState(context->getClientState());
1376             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1377         }
1378     }
1379     else if (tInfo->currentContext) {
1380         //release ClientState & SharedGroup
1381         if (tInfo->currentContext->version == 2) {
1382             hostCon->gl2Encoder()->setClientState(NULL);
1383             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1384         }
1385         else {
1386             hostCon->glEncoder()->setClientState(NULL);
1387             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1388         }
1389
1390     }
1391
1392     if (tInfo->currentContext)
1393         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1394
1395     //Now make current
1396     tInfo->currentContext = context;
1397
1398     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1399     if (tInfo->currentContext) {
1400         if (tInfo->currentContext->version == 2) {
1401             if (!hostCon->gl2Encoder()->isInitialized()) {
1402                 s_display.gles2_iface()->init();
1403                 hostCon->gl2Encoder()->setInitialized();
1404                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1405             }
1406         }
1407         else {
1408             if (!hostCon->glEncoder()->isInitialized()) {
1409                 s_display.gles_iface()->init();
1410                 hostCon->glEncoder()->setInitialized();
1411                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1412             }
1413         }
1414     }
1415
1416     return EGL_TRUE;
1417 }
1418
1419 EGLContext eglGetCurrentContext()
1420 {
1421     return getEGLThreadInfo()->currentContext;
1422 }
1423
1424 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1425 {
1426     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1427     if (!context)
1428         return EGL_NO_SURFACE; //not an error
1429
1430     switch (readdraw) {
1431         case EGL_READ:
1432             return context->read;
1433         case EGL_DRAW:
1434             return context->draw;
1435         default:
1436             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1437     }
1438 }
1439
1440 EGLDisplay eglGetCurrentDisplay()
1441 {
1442     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1443     if (!context)
1444         return EGL_NO_DISPLAY; //not an error
1445
1446     return context->dpy;
1447 }
1448
1449 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1450 {
1451     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1452     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1453
1454     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1455
1456     EGLBoolean ret = EGL_TRUE;
1457     switch (attribute) {
1458         case EGL_CONFIG_ID:
1459             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1460             break;
1461         case EGL_CONTEXT_CLIENT_TYPE:
1462             *value = EGL_OPENGL_ES_API;
1463             break;
1464         case EGL_CONTEXT_CLIENT_VERSION:
1465             *value = context->version;
1466             break;
1467         case EGL_RENDER_BUFFER:
1468             if (!context->draw)
1469                 *value = EGL_NONE;
1470             else
1471                 *value = EGL_BACK_BUFFER; //single buffer not supported
1472             break;
1473         default:
1474             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
1475             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1476             break;
1477     }
1478
1479     return ret;
1480 }
1481
1482 EGLBoolean eglWaitGL()
1483 {
1484     EGLThreadInfo *tInfo = getEGLThreadInfo();
1485     if (!tInfo || !tInfo->currentContext) {
1486         return EGL_FALSE;
1487     }
1488
1489     if (tInfo->currentContext->version == 2) {
1490         s_display.gles2_iface()->finish();
1491     }
1492     else {
1493         s_display.gles_iface()->finish();
1494     }
1495
1496     return EGL_TRUE;
1497 }
1498
1499 EGLBoolean eglWaitNative(EGLint engine)
1500 {
1501     (void)engine;
1502     return EGL_TRUE;
1503 }
1504
1505 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1506 {
1507     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1508     if (eglSurface == EGL_NO_SURFACE)
1509         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1510
1511     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1512
1513     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1514     if (d->dpy != dpy)
1515         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1516
1517     // post the surface
1518     d->swapBuffers();
1519
1520     hostCon->flush();
1521     return EGL_TRUE;
1522 }
1523
1524 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1525 {
1526     //TODO :later
1527     (void)dpy;
1528     (void)surface;
1529     (void)target;
1530     return 0;
1531 }
1532
1533 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1534 {
1535     //TODO later
1536     (void)display;
1537     (void)surface;
1538     (void)attrib_list;
1539     return 0;
1540 }
1541
1542 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1543 {
1544     //TODO later
1545     (void)display;
1546     (void)surface;
1547     return 0;
1548 }
1549
1550 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1551 {
1552     (void)attrib_list;
1553
1554     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1555
1556     if (target == EGL_NATIVE_BUFFER_ANDROID) {
1557         if (ctx != EGL_NO_CONTEXT) {
1558             setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1559         }
1560
1561         android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1562
1563         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1564             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1565
1566         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1567             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1568
1569         cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1570
1571         switch (cb->format) {
1572             case HAL_PIXEL_FORMAT_RGBA_8888:
1573             case HAL_PIXEL_FORMAT_RGBX_8888:
1574             case HAL_PIXEL_FORMAT_RGB_888:
1575             case HAL_PIXEL_FORMAT_RGB_565:
1576             case HAL_PIXEL_FORMAT_YV12:
1577             case HAL_PIXEL_FORMAT_BGRA_8888:
1578                 break;
1579             default:
1580                 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1581         }
1582
1583         native_buffer->common.incRef(&native_buffer->common);
1584
1585         EGLImage_t *image = new EGLImage_t();
1586         image->dpy = dpy;
1587         image->target = target;
1588         image->native_buffer = native_buffer;
1589
1590         return (EGLImageKHR)image;
1591     }
1592     else if (target == EGL_GL_TEXTURE_2D_KHR) {
1593         VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1594
1595         EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1596         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1597
1598         uint32_t ctxHandle = (context) ? context->rcContext : 0;
1599         GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1600         uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1601         EGLImage_t *image = new EGLImage_t();
1602         image->dpy = dpy;
1603         image->target = target;
1604         image->host_egl_image = img;
1605
1606         return (EGLImageKHR)image;
1607     }
1608     
1609     setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1610 }
1611
1612 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1613 {
1614     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1615     EGLImage_t *image = (EGLImage_t*)img;
1616
1617     if (!image || image->dpy != dpy) {
1618         RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1619     }
1620
1621     if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1622         android_native_buffer_t* native_buffer = image->native_buffer;
1623
1624         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1625             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1626
1627         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1628             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1629
1630         native_buffer->common.decRef(&native_buffer->common);
1631         delete image;
1632
1633         return EGL_TRUE;
1634     }
1635     else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1636         uint32_t host_egl_image = image->host_egl_image;
1637         delete image;
1638         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1639         return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1640     }
1641
1642     setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1643 }
1644
1645 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1646 #define MAX_EGL_SYNC_ATTRIBS 10
1647
1648 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1649         const EGLint *attrib_list)
1650 {
1651     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1652     DPRINT("type for eglCreateSyncKHR: 0x%x", type);
1653
1654     DEFINE_HOST_CONNECTION;
1655
1656     if ((type != EGL_SYNC_FENCE_KHR &&
1657          type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
1658         (type != EGL_SYNC_FENCE_KHR &&
1659          !rcEnc->hasNativeSync())) {
1660         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1661     }
1662
1663     EGLThreadInfo *tInfo = getEGLThreadInfo();
1664     if (!tInfo || !tInfo->currentContext) {
1665         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1666     }
1667
1668     int num_actual_attribs = 0;
1669
1670     // If attrib_list is not NULL,
1671     // ensure attrib_list contains (key, value) pairs
1672     // followed by a single EGL_NONE.
1673     // Also validate attribs.
1674     int inputFenceFd = -1;
1675     if (attrib_list) {
1676         for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
1677             if (attrib_list[i] == EGL_NONE) {
1678                 num_actual_attribs = i;
1679                 break;
1680             }
1681             if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
1682                 DPRINT("ERROR: attrib list without EGL_NONE");
1683                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1684             }
1685         }
1686
1687         // Validate and input attribs
1688         for (int i = 0; i < num_actual_attribs; i += 2) {
1689             if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
1690                 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
1691             }
1692             if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
1693                 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
1694             }
1695             if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
1696                 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
1697             }
1698             EGLint attrib_key = attrib_list[i];
1699             EGLint attrib_val = attrib_list[i + 1];
1700             if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
1701                 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
1702                     inputFenceFd = attrib_val;
1703                 }
1704             }
1705             DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
1706         }
1707     }
1708
1709     uint64_t sync_handle = 0;
1710     int newFenceFd = -1;
1711
1712     if (rcEnc->hasNativeSync()) {
1713         sync_handle =
1714             createNativeSync(type, attrib_list, num_actual_attribs,
1715                              false /* don't destroy when signaled on the host;
1716                                       let the guest clean this up,
1717                                       because the guest called eglCreateSyncKHR. */,
1718                              inputFenceFd,
1719                              &newFenceFd);
1720
1721     } else {
1722         // Just trigger a glFinish if the native sync on host
1723         // is unavailable.
1724         eglWaitClient();
1725     }
1726
1727     EGLSync_t* syncRes = new EGLSync_t(sync_handle);
1728
1729     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
1730         syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
1731
1732         if (inputFenceFd < 0) {
1733             syncRes->android_native_fence_fd = newFenceFd;
1734         } else {
1735             DPRINT("has input fence fd %d",
1736                     inputFenceFd);
1737             syncRes->android_native_fence_fd = inputFenceFd;
1738         }
1739     } else {
1740         syncRes->type = EGL_SYNC_FENCE_KHR;
1741         syncRes->android_native_fence_fd = -1;
1742         if (!rcEnc->hasNativeSync()) {
1743             syncRes->status = EGL_SIGNALED_KHR;
1744         }
1745     }
1746
1747     return (EGLSyncKHR)syncRes;
1748 }
1749
1750 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
1751 {
1752     (void)dpy;
1753
1754     if (!eglsync) {
1755         DPRINT("WARNING: null sync object")
1756         return EGL_TRUE;
1757     }
1758
1759     EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
1760
1761     if (sync && sync->android_native_fence_fd > 0) {
1762         close(sync->android_native_fence_fd);
1763         sync->android_native_fence_fd = -1;
1764     }
1765
1766     if (sync) {
1767         DEFINE_HOST_CONNECTION;
1768         if (rcEnc->hasNativeSync()) {
1769             rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
1770         }
1771         delete sync;
1772     }
1773
1774     return EGL_TRUE;
1775 }
1776
1777 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
1778         EGLTimeKHR timeout)
1779 {
1780     (void)dpy;
1781
1782     if (!eglsync) {
1783         DPRINT("WARNING: null sync object");
1784         return EGL_CONDITION_SATISFIED_KHR;
1785     }
1786
1787     EGLSync_t* sync = (EGLSync_t*)eglsync;
1788
1789     DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
1790            sync, sync->handle, flags, timeout);
1791
1792     DEFINE_HOST_CONNECTION;
1793
1794     EGLint retval;
1795     if (rcEnc->hasNativeSync()) {
1796         retval = rcEnc->rcClientWaitSyncKHR
1797             (rcEnc, sync->handle, flags, timeout);
1798     } else {
1799         retval = EGL_CONDITION_SATISFIED_KHR;
1800     }
1801     EGLint res_status;
1802     switch (sync->type) {
1803         case EGL_SYNC_FENCE_KHR:
1804             res_status = EGL_SIGNALED_KHR;
1805             break;
1806         case EGL_SYNC_NATIVE_FENCE_ANDROID:
1807             res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
1808             break;
1809         default:
1810             res_status = EGL_SIGNALED_KHR;
1811     }
1812     sync->status = res_status;
1813     return retval;
1814 }
1815
1816 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
1817         EGLint attribute, EGLint *value)
1818 {
1819     (void)dpy;
1820
1821     EGLSync_t* sync = (EGLSync_t*)eglsync;
1822
1823     switch (attribute) {
1824     case EGL_SYNC_TYPE_KHR:
1825         *value = sync->type;
1826         return EGL_TRUE;
1827     case EGL_SYNC_STATUS_KHR:
1828         *value = sync->status;
1829         return EGL_TRUE;
1830     case EGL_SYNC_CONDITION_KHR:
1831         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1832         return EGL_TRUE;
1833     default:
1834         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1835     }
1836 }
1837
1838 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
1839     (void)dpy;
1840
1841     DPRINT("call");
1842
1843     EGLSync_t* sync = (EGLSync_t*)eglsync;
1844     if (sync && sync->android_native_fence_fd > 0) {
1845         int res = dup(sync->android_native_fence_fd);
1846         return res;
1847     } else {
1848         return -1;
1849     }
1850 }
1851
1852 // TODO: Implement EGL_KHR_wait_sync
1853 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
1854     (void)dpy;
1855     (void)eglsync;
1856     (void)flags;
1857     return EGL_TRUE;
1858 }