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