2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "HostConnection.h"
19 #include "ThreadInfo.h"
20 #include "eglDisplay.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"
32 #include "ProcessPipe.h"
34 #include "GLEncoder.h"
36 #include "GL2Encoder.h"
39 #if PLATFORM_SDK_VERSION >= 16
40 #include <system/window.h>
41 #else // PLATFORM_SDK_VERSION >= 16
42 #include <private/ui/android_natives_priv.h>
43 #endif // PLATFORM_SDK_VERSION >= 16
45 #if PLATFORM_SDK_VERSION <= 16
46 #define queueBuffer_DEPRECATED queueBuffer
47 #define dequeueBuffer_DEPRECATED dequeueBuffer
48 #define cancelBuffer_DEPRECATED cancelBuffer
49 #endif // PLATFORM_SDK_VERSION <= 16
54 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
60 static T setErrorFunc(GLint error, T returnValue) {
61 getEGLThreadInfo()->eglError = error;
65 const char * eglStrError(EGLint err)
68 case EGL_SUCCESS: return "EGL_SUCCESS";
69 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
70 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
71 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
72 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
73 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
74 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
75 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
76 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
77 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
78 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
79 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
80 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
81 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
82 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
83 default: return "UNKNOWN";
87 #define LOG_EGL_ERRORS 1
91 #define setErrorReturn(error, retVal) \
93 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
94 return setErrorFunc(error, retVal); \
97 #define RETURN_ERROR(ret,err) \
98 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
99 getEGLThreadInfo()->eglError = err; \
102 #else //!LOG_EGL_ERRORS
104 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
106 #define RETURN_ERROR(ret,err) \
107 getEGLThreadInfo()->eglError = err; \
110 #endif //LOG_EGL_ERRORS
112 #define VALIDATE_CONFIG(cfg,ret) \
113 if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
114 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
117 #define VALIDATE_DISPLAY(dpy,ret) \
118 if ((dpy) != (EGLDisplay)&s_display) { \
119 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
122 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
123 VALIDATE_DISPLAY(dpy, ret) \
124 if (!s_display.initialized()) { \
125 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
128 #define DEFINE_HOST_CONNECTION \
129 HostConnection *hostCon = HostConnection::get(); \
130 ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
132 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
133 HostConnection *hostCon = HostConnection::get(); \
135 ALOGE("egl: Failed to get host connection\n"); \
138 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
140 ALOGE("egl: Failed to get renderControl encoder context\n"); \
144 #define VALIDATE_CONTEXT_RETURN(context,ret) \
146 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
149 #define VALIDATE_SURFACE_RETURN(surface, ret) \
150 if ((surface) != EGL_NO_SURFACE) { \
151 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
152 if (s->dpy != (EGLDisplay)&s_display) \
153 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
156 // The one and only supported display object.
157 static eglDisplay s_display;
159 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
162 read(EGL_NO_SURFACE),
163 draw(EGL_NO_SURFACE),
168 rendererString(NULL),
169 shaderVersionString(NULL),
170 extensionString(NULL),
176 clientState = new GLClientState();
178 sharedGroup = shareCtx->getSharedGroup();
180 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
181 assert(dpy == (EGLDisplay)&s_display);
182 s_display.onCreateContext((EGLContext)this);
185 int EGLContext_t::getGoldfishSyncFd() {
186 if (goldfishSyncFd < 0) {
187 goldfishSyncFd = goldfish_sync_open();
189 return goldfishSyncFd;
192 EGLContext_t::~EGLContext_t()
194 if (goldfishSyncFd > 0) {
195 goldfish_sync_close(goldfishSyncFd);
198 assert(dpy == (EGLDisplay)&s_display);
199 s_display.onDestroyContext((EGLContext)this);
201 delete [] versionString;
202 delete [] vendorString;
203 delete [] rendererString;
204 delete [] shaderVersionString;
205 delete [] extensionString;
208 // ----------------------------------------------------------------------------
211 //we don't need to handle depth since it's handled when window created on the host
213 struct egl_surface_t {
219 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
220 virtual ~egl_surface_t();
222 virtual void setSwapInterval(int interval) = 0;
223 virtual EGLBoolean swapBuffers() = 0;
225 EGLint getSwapBehavior() const;
226 uint32_t getRcSurface() { return rcSurface; }
227 EGLint getSurfaceType() { return surfaceType; }
229 EGLint getWidth(){ return width; }
230 EGLint getHeight(){ return height; }
231 EGLint getNativeWidth(){ return nativeWidth; }
232 EGLint getNativeHeight(){ return nativeHeight; }
233 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
234 EGLint getTextureFormat() { return texFormat; }
235 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
236 EGLint getTextureTarget() { return texTarget; }
247 // Width of the actual window being presented (not the EGL texture)
248 // Give it some default values.
253 void setWidth(EGLint w) { width = w; }
254 void setHeight(EGLint h) { height = h; }
255 void setNativeWidth(int w) { nativeWidth = w; }
256 void setNativeHeight(int h) { nativeHeight = h; }
259 uint32_t rcSurface; //handle to surface created via remote control
262 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
263 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
267 // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
270 texFormat = EGL_NO_TEXTURE;
271 texTarget = EGL_NO_TEXTURE;
272 assert(dpy == (EGLDisplay)&s_display);
273 s_display.onCreateSurface((EGLSurface)this);
276 EGLint egl_surface_t::getSwapBehavior() const {
277 return EGL_BUFFER_PRESERVED;
280 egl_surface_t::~egl_surface_t()
282 assert(dpy == (EGLDisplay)&s_display);
283 s_display.onDestroySurface((EGLSurface)this);
286 // ----------------------------------------------------------------------------
287 // egl_window_surface_t
289 struct egl_window_surface_t : public egl_surface_t {
290 static egl_window_surface_t* create(
291 EGLDisplay dpy, EGLConfig config, EGLint surfType,
292 ANativeWindow* window);
294 virtual ~egl_window_surface_t();
296 virtual void setSwapInterval(int interval);
297 virtual EGLBoolean swapBuffers();
300 egl_window_surface_t(
301 EGLDisplay dpy, EGLConfig config, EGLint surfType,
302 ANativeWindow* window);
305 ANativeWindow* nativeWindow;
306 android_native_buffer_t* buffer;
309 egl_window_surface_t::egl_window_surface_t (
310 EGLDisplay dpy, EGLConfig config, EGLint surfType,
311 ANativeWindow* window)
312 : egl_surface_t(dpy, config, surfType),
313 nativeWindow(window),
316 // keep a reference on the window
317 nativeWindow->common.incRef(&nativeWindow->common);
321 EGLBoolean egl_window_surface_t::init()
323 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
324 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
326 setWidth(buffer->width);
327 setHeight(buffer->height);
329 int nativeWidth, nativeHeight;
330 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
331 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
333 setNativeWidth(nativeWidth);
334 setNativeHeight(nativeHeight);
336 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
337 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
338 getWidth(), getHeight());
340 ALOGE("rcCreateWindowSurface returned 0");
343 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
344 ((cb_handle_t*)(buffer->handle))->hostHandle);
349 egl_window_surface_t* egl_window_surface_t::create(
350 EGLDisplay dpy, EGLConfig config, EGLint surfType,
351 ANativeWindow* window)
353 egl_window_surface_t* wnd = new egl_window_surface_t(
354 dpy, config, surfType, window);
355 if (wnd && !wnd->init()) {
362 egl_window_surface_t::~egl_window_surface_t() {
363 DEFINE_HOST_CONNECTION;
364 if (rcSurface && rcEnc) {
365 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
368 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
370 nativeWindow->common.decRef(&nativeWindow->common);
373 void egl_window_surface_t::setSwapInterval(int interval)
375 nativeWindow->setSwapInterval(nativeWindow, interval);
378 // createNativeSync() creates an OpenGL sync object on the host
379 // using rcCreateSyncKHR. If necessary, a native fence FD will
380 // also be created through the goldfish sync device.
381 // Returns a handle to the host-side FenceSync object.
382 static uint64_t createNativeSync(EGLenum type,
383 const EGLint* attrib_list,
384 int num_actual_attribs,
385 bool destroy_when_signaled,
388 DEFINE_HOST_CONNECTION;
390 uint64_t sync_handle;
391 uint64_t thread_handle;
393 EGLint* actual_attribs =
394 (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
396 rcEnc->rcCreateSyncKHR(rcEnc, type,
398 num_actual_attribs * sizeof(EGLint),
399 destroy_when_signaled,
403 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
405 goldfish_sync_queue_work(
406 getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
411 DPRINT("got native fence fd=%d queue_work_err=%d",
412 *fd_out, queue_work_err);
418 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
419 // that are needed by only this goldfish opengl driver,
420 // such as in swapBuffers().
421 // The guest will not see any of these, and these sync objects will be
422 // destroyed on the host when signaled.
423 // A native fence FD is possibly returned.
424 static void createGoldfishOpenGLNativeSync(int* fd_out) {
425 createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
426 NULL /* empty attrib list */,
427 0 /* 0 attrib count */,
428 true /* destroy when signaled. this is host-only
429 and there will only be one waiter */,
430 -1 /* we want a new fd */,
434 EGLBoolean egl_window_surface_t::swapBuffers()
437 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
439 // Follow up flushWindowColorBuffer with a fence command.
440 // When the fence command finishes,
441 // we're sure that the buffer on the host
444 // |presentFenceFd| guards the presentation of the
445 // current frame with a goldfish sync fence fd.
447 // When |presentFenceFd| is signaled, the recipient
448 // of the buffer that was sent through queueBuffer
449 // can be sure that the buffer is current.
451 // If we don't take care of this synchronization,
452 // an old frame can be processed by surfaceflinger,
453 // resulting in out of order frames.
455 int presentFenceFd = -1;
457 if (buffer == NULL) {
458 ALOGE("egl_window_surface_t::swapBuffers called with NULL buffer");
459 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
462 #if PLATFORM_SDK_VERSION <= 16
463 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
464 // equivalent to glFinish if no native sync
466 nativeWindow->queueBuffer(nativeWindow, buffer);
468 if (rcEnc->hasNativeSync()) {
469 rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
470 createGoldfishOpenGLNativeSync(&presentFenceFd);
472 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
473 // equivalent to glFinish if no native sync
477 DPRINT("queueBuffer with fence %d", presentFenceFd);
478 nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
481 DPRINT("calling dequeueBuffer...");
483 #if PLATFORM_SDK_VERSION <= 16
484 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
486 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
489 int acquireFenceFd = -1;
490 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
492 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
495 DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
497 if (acquireFenceFd > 0) {
498 close(acquireFenceFd);
502 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
503 ((cb_handle_t *)(buffer->handle))->hostHandle);
505 setWidth(buffer->width);
506 setHeight(buffer->height);
511 // ----------------------------------------------------------------------------
512 //egl_pbuffer_surface_t
514 struct egl_pbuffer_surface_t : public egl_surface_t {
515 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
516 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
518 virtual ~egl_pbuffer_surface_t();
520 virtual void setSwapInterval(int interval) { (void)interval; }
521 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
523 uint32_t getRcColorBuffer() { return rcColorBuffer; }
526 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
527 int32_t w, int32_t h);
528 EGLBoolean init(GLenum format);
530 uint32_t rcColorBuffer;
533 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
534 EGLint surfType, int32_t w, int32_t h)
535 : egl_surface_t(dpy, config, surfType),
542 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
544 DEFINE_HOST_CONNECTION;
546 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
547 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
551 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
553 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
555 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
556 getWidth(), getHeight());
558 ALOGE("rcCreateWindowSurface returned 0");
562 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
563 if (!rcColorBuffer) {
564 ALOGE("rcCreateColorBuffer returned 0");
568 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
573 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
574 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
577 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
579 if (pb && !pb->init(pixelFormat)) {
586 static const char *getGLString(int glEnum)
588 EGLThreadInfo *tInfo = getEGLThreadInfo();
589 if (!tInfo || !tInfo->currentContext) {
593 const char** strPtr = NULL;
595 #define GL_VENDOR 0x1F00
596 #define GL_RENDERER 0x1F01
597 #define GL_VERSION 0x1F02
598 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
599 #define GL_EXTENSIONS 0x1F03
603 strPtr = &tInfo->currentContext->versionString;
606 strPtr = &tInfo->currentContext->vendorString;
609 strPtr = &tInfo->currentContext->rendererString;
611 case GL_SHADING_LANGUAGE_VERSION:
612 strPtr = &tInfo->currentContext->shaderVersionString;
615 strPtr = &tInfo->currentContext->extensionString;
623 if (*strPtr != NULL) {
625 // string is already cached
631 // first query of that string - need to query host
633 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
634 char *hostStr = NULL;
635 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
637 hostStr = new char[-n+1];
638 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
646 // keep the string in the context and return its value
652 // ----------------------------------------------------------------------------
654 static EGLClient_eglInterface s_eglIface = {
655 getThreadInfo: getEGLThreadInfo,
656 getGLString: getGLString
659 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
660 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
663 // we support only EGL_DEFAULT_DISPLAY.
665 if (display_id != EGL_DEFAULT_DISPLAY) {
666 return EGL_NO_DISPLAY;
669 return (EGLDisplay)&s_display;
672 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
674 VALIDATE_DISPLAY(dpy,EGL_FALSE);
676 if (!s_display.initialize(&s_eglIface)) {
680 *major = s_display.getVersionMajor();
682 *minor = s_display.getVersionMinor();
686 EGLBoolean eglTerminate(EGLDisplay dpy)
688 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
690 s_display.terminate();
696 EGLint error = getEGLThreadInfo()->eglError;
697 getEGLThreadInfo()->eglError = EGL_SUCCESS;
701 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
703 // search in EGL function table
704 for (int i=0; i<egl_num_funcs; i++) {
705 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
706 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
710 // look in gles client api's extensions table
711 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
713 // Fail - function not found.
717 const char* eglQueryString(EGLDisplay dpy, EGLint name)
719 VALIDATE_DISPLAY_INIT(dpy, NULL);
721 return s_display.queryString(name);
724 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
726 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
729 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
732 GLint numConfigs = s_display.getNumConfigs();
734 *num_config = numConfigs;
739 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
740 *configs++ = (EGLConfig)(uintptr_t)i;
746 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
748 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
751 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
754 int attribs_size = 0;
756 const EGLint * attrib_p = attrib_list;
757 while (attrib_p[0] != EGL_NONE) {
761 attribs_size++; //for the terminating EGL_NONE
764 // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
765 // while the host never supports it.
766 // We remove the bit here.
767 EGLint* local_attrib_list = NULL;
768 if (PLATFORM_SDK_VERSION <= 19) {
769 local_attrib_list = new EGLint[attribs_size];
770 memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
771 EGLint* local_attrib_p = local_attrib_list;
772 while (local_attrib_p[0] != EGL_NONE) {
773 if (local_attrib_p[0] == EGL_SURFACE_TYPE) {
774 local_attrib_p[1] &= ~(EGLint)EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
780 uint32_t* tempConfigs[config_size];
781 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
782 *num_config = rcEnc->rcChooseConfig(rcEnc,
783 local_attrib_list ? local_attrib_list:(EGLint*)attrib_list,
784 attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
786 if (local_attrib_list) delete [] local_attrib_list;
787 if (*num_config <= 0) {
788 EGLint err = -(*num_config);
791 case EGL_BAD_ATTRIBUTE:
792 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
800 for (i=0;i<(*num_config);i++) {
801 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
808 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
810 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
811 VALIDATE_CONFIG(config, EGL_FALSE);
813 if (s_display.getConfigAttrib(config, attribute, value))
819 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
823 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
827 VALIDATE_DISPLAY_INIT(dpy, NULL);
828 VALIDATE_CONFIG(config, EGL_FALSE);
830 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
834 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
836 if (!(surfaceType & EGL_WINDOW_BIT)) {
837 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
840 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
841 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
844 egl_surface_t* surface = egl_window_surface_t::create(
845 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
847 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
853 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
855 VALIDATE_DISPLAY_INIT(dpy, NULL);
856 VALIDATE_CONFIG(config, EGL_FALSE);
859 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
861 if (!(surfaceType & EGL_PBUFFER_BIT)) {
862 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
867 EGLint texFormat = EGL_NO_TEXTURE;
868 EGLint texTarget = EGL_NO_TEXTURE;
869 while (attrib_list[0] != EGL_NONE) {
870 switch (attrib_list[0]) {
873 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
877 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
879 case EGL_TEXTURE_FORMAT:
880 texFormat = attrib_list[1];
882 case EGL_TEXTURE_TARGET:
883 texTarget = attrib_list[1];
885 // the followings are not supported
886 case EGL_LARGEST_PBUFFER:
887 case EGL_MIPMAP_TEXTURE:
888 case EGL_VG_ALPHA_FORMAT:
889 case EGL_VG_COLORSPACE:
892 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
896 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
897 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
898 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
900 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
903 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
904 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
906 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
907 EGL_PBUFFER_BIT, w, h, pixelFormat);
909 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
913 surface->setTextureFormat(texFormat);
914 surface->setTextureTarget(texTarget);
919 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
921 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
922 // located on host. In order to support Pixmaps we should either punt
923 // to s/w rendering -or- let the host render to a buffer that will be
924 // copied back to guest at some sync point. None of those methods not
925 // implemented and pixmaps are not used with OpenGL anyway ...
926 VALIDATE_CONFIG(config, EGL_FALSE);
930 return EGL_NO_SURFACE;
933 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
935 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
936 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
938 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
944 static float s_getNativeDpi() {
945 float nativeDPI = 560.0f;
946 const char* dpiPropName = "qemu.sf.lcd_density";
947 char dpiProp[PROPERTY_VALUE_MAX];
948 if (property_get(dpiPropName, dpiProp, NULL) > 0) {
949 nativeDPI = atof(dpiProp);
954 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
956 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
957 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
959 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
961 // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
962 float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
963 EGLBoolean ret = EGL_TRUE;
966 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
969 *value = surface->getWidth();
972 *value = surface->getHeight();
974 case EGL_TEXTURE_FORMAT:
975 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
976 *value = surface->getTextureFormat();
979 case EGL_TEXTURE_TARGET:
980 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
981 *value = surface->getTextureTarget();
984 case EGL_SWAP_BEHAVIOR:
987 ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
989 if (ret == EGL_TRUE) {
990 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
991 *value = EGL_BUFFER_PRESERVED;
993 *value = EGL_BUFFER_DESTROYED;
998 case EGL_LARGEST_PBUFFER:
999 // not modified for a window or pixmap surface
1000 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
1001 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
1003 case EGL_MIPMAP_TEXTURE:
1004 // not modified for a window or pixmap surface
1005 // and we ignore it when creating a PBuffer surface (default is 0)
1006 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
1008 case EGL_MIPMAP_LEVEL:
1009 // not modified for a window or pixmap surface
1010 // and we ignore it when creating a PBuffer surface (default is 0)
1011 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
1013 case EGL_MULTISAMPLE_RESOLVE:
1014 // ignored when creating the surface, return default
1015 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
1017 case EGL_HORIZONTAL_RESOLUTION:
1018 // pixel/mm * EGL_DISPLAY_SCALING
1019 // TODO: get the DPI from avd config
1020 currWidth = surface->getWidth();
1021 scaledResolution = currWidth / surface->getNativeWidth();
1022 effectiveSurfaceDPI =
1023 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1024 *value = (EGLint)(effectiveSurfaceDPI);
1026 case EGL_VERTICAL_RESOLUTION:
1027 // pixel/mm * EGL_DISPLAY_SCALING
1028 // TODO: get the real DPI from avd config
1029 currHeight = surface->getHeight();
1030 scaledResolution = currHeight / surface->getNativeHeight();
1031 effectiveSurfaceDPI =
1032 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1033 *value = (EGLint)(effectiveSurfaceDPI);
1035 case EGL_PIXEL_ASPECT_RATIO:
1036 // w / h * EGL_DISPLAY_SCALING
1037 // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
1038 *value = 1 * EGL_DISPLAY_SCALING;
1040 case EGL_RENDER_BUFFER:
1041 switch (surface->getSurfaceType()) {
1042 case EGL_PBUFFER_BIT:
1043 *value = EGL_BACK_BUFFER;
1045 case EGL_PIXMAP_BIT:
1046 *value = EGL_SINGLE_BUFFER;
1048 case EGL_WINDOW_BIT:
1049 // ignored when creating the surface, return default
1050 *value = EGL_BACK_BUFFER;
1053 ALOGE("eglQuerySurface %x unknown surface type %x",
1054 attribute, surface->getSurfaceType());
1055 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1059 case EGL_VG_COLORSPACE:
1060 // ignored when creating the surface, return default
1061 *value = EGL_VG_COLORSPACE_sRGB;
1063 case EGL_VG_ALPHA_FORMAT:
1064 // ignored when creating the surface, return default
1065 *value = EGL_VG_ALPHA_FORMAT_NONPRE;
1067 //TODO: complete other attributes
1069 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
1070 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1077 EGLBoolean eglBindAPI(EGLenum api)
1079 if (api != EGL_OPENGL_ES_API)
1080 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1084 EGLenum eglQueryAPI()
1086 return EGL_OPENGL_ES_API;
1089 EGLBoolean eglWaitClient()
1094 EGLBoolean eglReleaseThread()
1096 EGLThreadInfo *tInfo = getEGLThreadInfo();
1098 tInfo->eglError = EGL_SUCCESS;
1099 EGLContext_t* context = tInfo->currentContext;
1101 // The following code is doing pretty much the same thing as
1102 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1103 // with the only issue that we do not require a valid display here.
1104 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1105 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1106 if (context->version == 2) {
1107 hostCon->gl2Encoder()->setClientState(NULL);
1108 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
1111 hostCon->glEncoder()->setClientState(NULL);
1112 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
1114 context->flags &= ~EGLContext_t::IS_CURRENT;
1116 if (context->deletePending) {
1117 if (context->rcContext) {
1118 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1119 context->rcContext = 0;
1123 tInfo->currentContext = 0;
1129 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1137 ALOGW("%s not implemented", __FUNCTION__);
1141 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1143 // Right now we don't do anything when using host GPU.
1144 // This is purely just to pass the data through
1145 // without issuing a warning. We may benefit from validating the
1146 // display and surface for debug purposes.
1147 // TODO: Find cases where we actually need to do something.
1148 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1149 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1150 if (surface == EGL_NO_SURFACE) {
1151 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1156 egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1157 switch (attribute) {
1158 case EGL_MIPMAP_LEVEL:
1161 case EGL_MULTISAMPLE_RESOLVE:
1163 if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1164 EGLint surface_type;
1165 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1166 if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1167 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1173 case EGL_SWAP_BEHAVIOR:
1174 if (value == EGL_BUFFER_PRESERVED) {
1175 EGLint surface_type;
1176 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1177 if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1178 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1184 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1185 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1190 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1192 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1193 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1194 if (eglSurface == EGL_NO_SURFACE) {
1195 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1198 if (buffer != EGL_BACK_BUFFER) {
1199 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1202 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1204 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1205 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1208 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1209 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1212 //It's now safe to cast to pbuffer surface
1213 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1215 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1216 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1221 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1227 ALOGW("%s not implemented", __FUNCTION__);
1231 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1233 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1234 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1236 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1238 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1241 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1243 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1244 draw->setSwapInterval(interval);
1246 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1251 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1253 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1254 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1256 EGLint version = 1; //default
1257 while (attrib_list && attrib_list[0] != EGL_NONE) {
1258 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
1259 version = attrib_list[1];
1260 } else if (attrib_list[0] == EGL_CONTEXT_PRIORITY_LEVEL_IMG) {
1261 // https://www.khronos.org/registry/egl/extensions/IMG/EGL_IMG_context_priority.txt
1262 // It it not yet supported in the emulator.
1263 ALOGW("EGL_CONTEXT_PRIORITY_LEVEL_IMG not supported, ignored");
1264 } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
1265 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1270 // Currently only support GLES1 and 2
1271 if (version != 1 && version != 2) {
1272 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1275 uint32_t rcShareCtx = 0;
1276 EGLContext_t * shareCtx = NULL;
1277 if (share_context) {
1278 shareCtx = static_cast<EGLContext_t*>(share_context);
1279 rcShareCtx = shareCtx->rcContext;
1280 if (shareCtx->dpy != dpy)
1281 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1284 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1285 // We've created EGL context. Disconnecting
1286 // would be dangerous at this point.
1287 hostCon->setGrallocOnly(false);
1289 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1291 ALOGE("rcCreateContext returned 0");
1292 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1295 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1297 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1299 context->version = version;
1300 context->rcContext = rcContext;
1306 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1308 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1309 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1311 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1313 if (!context) return EGL_TRUE;
1315 if (getEGLThreadInfo()->currentContext == context) {
1316 getEGLThreadInfo()->currentContext->deletePending = 1;
1320 if (context->rcContext) {
1321 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1322 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1323 context->rcContext = 0;
1330 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1332 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1333 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1334 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1336 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1337 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1338 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1339 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1341 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1342 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1343 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1344 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1345 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1346 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1349 // Nothing to do if no binding change has made
1351 EGLThreadInfo *tInfo = getEGLThreadInfo();
1353 if (tInfo->currentContext == context &&
1355 (context && context->draw == draw && context->read == read))) {
1359 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1360 if (tInfo->currentContext != context) {
1361 EGLContext_t * contextToDelete = tInfo->currentContext;
1362 tInfo->currentContext = 0;
1363 eglDestroyContext(dpy, contextToDelete);
1367 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1368 //context is current to another thread
1369 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1372 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1373 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1374 ALOGE("rcMakeCurrent returned EGL_FALSE");
1375 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1378 //Now make the local bind
1380 // This is a nontrivial context.
1381 // The thread cannot be gralloc-only anymore.
1382 hostCon->setGrallocOnly(false);
1383 context->draw = draw;
1384 context->read = read;
1385 context->flags |= EGLContext_t::IS_CURRENT;
1386 //set the client state
1387 if (context->version == 2) {
1388 hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1389 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1392 hostCon->glEncoder()->setClientState(context->getClientState());
1393 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1396 else if (tInfo->currentContext) {
1397 //release ClientState & SharedGroup
1398 if (tInfo->currentContext->version == 2) {
1399 hostCon->gl2Encoder()->setClientState(NULL);
1400 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1403 hostCon->glEncoder()->setClientState(NULL);
1404 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1409 if (tInfo->currentContext)
1410 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1413 tInfo->currentContext = context;
1415 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1416 if (tInfo->currentContext) {
1417 if (tInfo->currentContext->version == 2) {
1418 if (!hostCon->gl2Encoder()->isInitialized()) {
1419 s_display.gles2_iface()->init();
1420 hostCon->gl2Encoder()->setInitialized();
1421 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1425 if (!hostCon->glEncoder()->isInitialized()) {
1426 s_display.gles_iface()->init();
1427 hostCon->glEncoder()->setInitialized();
1428 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1436 EGLContext eglGetCurrentContext()
1438 return getEGLThreadInfo()->currentContext;
1441 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1443 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1445 return EGL_NO_SURFACE; //not an error
1449 return context->read;
1451 return context->draw;
1453 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1457 EGLDisplay eglGetCurrentDisplay()
1459 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1461 return EGL_NO_DISPLAY; //not an error
1463 return context->dpy;
1466 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1468 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1469 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1471 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1473 EGLBoolean ret = EGL_TRUE;
1474 switch (attribute) {
1476 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1478 case EGL_CONTEXT_CLIENT_TYPE:
1479 *value = EGL_OPENGL_ES_API;
1481 case EGL_CONTEXT_CLIENT_VERSION:
1482 *value = context->version;
1484 case EGL_RENDER_BUFFER:
1488 *value = EGL_BACK_BUFFER; //single buffer not supported
1491 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1492 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1499 EGLBoolean eglWaitGL()
1501 EGLThreadInfo *tInfo = getEGLThreadInfo();
1502 if (!tInfo || !tInfo->currentContext) {
1506 if (tInfo->currentContext->version == 2) {
1507 s_display.gles2_iface()->finish();
1510 s_display.gles_iface()->finish();
1516 EGLBoolean eglWaitNative(EGLint engine)
1522 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1524 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1525 if (eglSurface == EGL_NO_SURFACE)
1526 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1528 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1530 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1532 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1535 EGLBoolean ret = d->swapBuffers();
1541 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1550 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1559 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1567 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1571 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1573 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1574 if (ctx != EGL_NO_CONTEXT) {
1575 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1578 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1580 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1581 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1583 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1584 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1586 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1588 switch (cb->format) {
1589 case HAL_PIXEL_FORMAT_RGBA_8888:
1590 case HAL_PIXEL_FORMAT_RGBX_8888:
1591 case HAL_PIXEL_FORMAT_RGB_888:
1592 case HAL_PIXEL_FORMAT_RGB_565:
1593 case HAL_PIXEL_FORMAT_YV12:
1594 case HAL_PIXEL_FORMAT_BGRA_8888:
1597 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1600 native_buffer->common.incRef(&native_buffer->common);
1602 EGLImage_t *image = new EGLImage_t();
1604 image->target = target;
1605 image->native_buffer = native_buffer;
1607 return (EGLImageKHR)image;
1609 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1610 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1612 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1613 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1615 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1616 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1617 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1618 EGLImage_t *image = new EGLImage_t();
1620 image->target = target;
1621 image->host_egl_image = img;
1623 return (EGLImageKHR)image;
1626 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1629 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1631 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1632 EGLImage_t *image = (EGLImage_t*)img;
1634 if (!image || image->dpy != dpy) {
1635 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1638 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1639 android_native_buffer_t* native_buffer = image->native_buffer;
1641 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1642 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1644 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1645 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1647 native_buffer->common.decRef(&native_buffer->common);
1652 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1653 uint32_t host_egl_image = image->host_egl_image;
1655 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1656 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1659 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1662 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1663 #define MAX_EGL_SYNC_ATTRIBS 10
1665 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1666 const EGLint *attrib_list)
1668 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1669 DPRINT("type for eglCreateSyncKHR: 0x%x", type);
1671 DEFINE_HOST_CONNECTION;
1673 if ((type != EGL_SYNC_FENCE_KHR &&
1674 type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
1675 (type != EGL_SYNC_FENCE_KHR &&
1676 !rcEnc->hasNativeSync())) {
1677 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1680 EGLThreadInfo *tInfo = getEGLThreadInfo();
1681 if (!tInfo || !tInfo->currentContext) {
1682 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1685 int num_actual_attribs = 0;
1687 // If attrib_list is not NULL,
1688 // ensure attrib_list contains (key, value) pairs
1689 // followed by a single EGL_NONE.
1690 // Also validate attribs.
1691 int inputFenceFd = -1;
1693 for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
1694 if (attrib_list[i] == EGL_NONE) {
1695 num_actual_attribs = i;
1698 if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
1699 DPRINT("ERROR: attrib list without EGL_NONE");
1700 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1704 // Validate and input attribs
1705 for (int i = 0; i < num_actual_attribs; i += 2) {
1706 if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
1707 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
1709 if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
1710 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
1712 if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
1713 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
1715 EGLint attrib_key = attrib_list[i];
1716 EGLint attrib_val = attrib_list[i + 1];
1717 if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
1718 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
1719 inputFenceFd = attrib_val;
1722 DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
1726 uint64_t sync_handle = 0;
1727 int newFenceFd = -1;
1729 if (rcEnc->hasNativeSync()) {
1731 createNativeSync(type, attrib_list, num_actual_attribs,
1732 false /* don't destroy when signaled on the host;
1733 let the guest clean this up,
1734 because the guest called eglCreateSyncKHR. */,
1739 // Just trigger a glFinish if the native sync on host
1744 EGLSync_t* syncRes = new EGLSync_t(sync_handle);
1746 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
1747 syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
1749 if (inputFenceFd < 0) {
1750 syncRes->android_native_fence_fd = newFenceFd;
1752 DPRINT("has input fence fd %d",
1754 syncRes->android_native_fence_fd = inputFenceFd;
1757 syncRes->type = EGL_SYNC_FENCE_KHR;
1758 syncRes->android_native_fence_fd = -1;
1759 if (!rcEnc->hasNativeSync()) {
1760 syncRes->status = EGL_SIGNALED_KHR;
1764 return (EGLSyncKHR)syncRes;
1767 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
1772 DPRINT("WARNING: null sync object")
1776 EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
1778 if (sync && sync->android_native_fence_fd > 0) {
1779 close(sync->android_native_fence_fd);
1780 sync->android_native_fence_fd = -1;
1784 DEFINE_HOST_CONNECTION;
1785 if (rcEnc->hasNativeSync()) {
1786 rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
1794 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
1800 DPRINT("WARNING: null sync object");
1801 return EGL_CONDITION_SATISFIED_KHR;
1804 EGLSync_t* sync = (EGLSync_t*)eglsync;
1806 DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
1807 sync, sync->handle, flags, timeout);
1809 DEFINE_HOST_CONNECTION;
1812 if (rcEnc->hasNativeSync()) {
1813 retval = rcEnc->rcClientWaitSyncKHR
1814 (rcEnc, sync->handle, flags, timeout);
1816 retval = EGL_CONDITION_SATISFIED_KHR;
1819 switch (sync->type) {
1820 case EGL_SYNC_FENCE_KHR:
1821 res_status = EGL_SIGNALED_KHR;
1823 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1824 res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
1827 res_status = EGL_SIGNALED_KHR;
1829 sync->status = res_status;
1833 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
1834 EGLint attribute, EGLint *value)
1838 EGLSync_t* sync = (EGLSync_t*)eglsync;
1840 switch (attribute) {
1841 case EGL_SYNC_TYPE_KHR:
1842 *value = sync->type;
1844 case EGL_SYNC_STATUS_KHR:
1845 *value = sync->status;
1847 case EGL_SYNC_CONDITION_KHR:
1848 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1851 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1855 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
1860 EGLSync_t* sync = (EGLSync_t*)eglsync;
1861 if (sync && sync->android_native_fence_fd > 0) {
1862 int res = dup(sync->android_native_fence_fd);
1869 // TODO: Implement EGL_KHR_wait_sync
1870 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {