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