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