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