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