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