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