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