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