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