OSDN Git Service

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