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