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