OSDN Git Service

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