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