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