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