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