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 "goldfish_sync.h"
25 #include "gralloc_cb.h"
26 #include "GLClientState.h"
27 #include "GLSharedGroup.h"
28 #include "eglContext.h"
29 #include "ClientAPIExts.h"
31 #include "ProcessPipe.h"
33 #include "GLEncoder.h"
35 #include "GL2Encoder.h"
38 #if PLATFORM_SDK_VERSION >= 16
39 #include <system/window.h>
40 #else // PLATFORM_SDK_VERSION >= 16
41 #include <private/ui/android_natives_priv.h>
42 #endif // PLATFORM_SDK_VERSION >= 16
44 #if PLATFORM_SDK_VERSION <= 16
45 #define queueBuffer_DEPRECATED queueBuffer
46 #define dequeueBuffer_DEPRECATED dequeueBuffer
47 #define cancelBuffer_DEPRECATED cancelBuffer
48 #endif // PLATFORM_SDK_VERSION <= 16
53 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
59 static T setErrorFunc(GLint error, T returnValue) {
60 getEGLThreadInfo()->eglError = error;
64 const char * eglStrError(EGLint err)
67 case EGL_SUCCESS: return "EGL_SUCCESS";
68 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
69 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
70 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
71 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
72 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
73 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
74 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
75 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
76 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
77 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
78 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
79 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
80 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
81 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
82 default: return "UNKNOWN";
86 #define LOG_EGL_ERRORS 1
90 #define setErrorReturn(error, retVal) \
92 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
93 return setErrorFunc(error, retVal); \
96 #define RETURN_ERROR(ret,err) \
97 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
98 getEGLThreadInfo()->eglError = err; \
101 #else //!LOG_EGL_ERRORS
103 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
105 #define RETURN_ERROR(ret,err) \
106 getEGLThreadInfo()->eglError = err; \
109 #endif //LOG_EGL_ERRORS
111 #define VALIDATE_CONFIG(cfg,ret) \
112 if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
113 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
116 #define VALIDATE_DISPLAY(dpy,ret) \
117 if ((dpy) != (EGLDisplay)&s_display) { \
118 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
121 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
122 VALIDATE_DISPLAY(dpy, ret) \
123 if (!s_display.initialized()) { \
124 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
127 #define DEFINE_HOST_CONNECTION \
128 HostConnection *hostCon = HostConnection::get(); \
129 ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
131 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
132 HostConnection *hostCon = HostConnection::get(); \
134 ALOGE("egl: Failed to get host connection\n"); \
137 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
139 ALOGE("egl: Failed to get renderControl encoder context\n"); \
143 #define VALIDATE_CONTEXT_RETURN(context,ret) \
145 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
148 #define VALIDATE_SURFACE_RETURN(surface, ret) \
149 if ((surface) != EGL_NO_SURFACE) { \
150 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
151 if (s->dpy != (EGLDisplay)&s_display) \
152 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
155 // The one and only supported display object.
156 static eglDisplay s_display;
158 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
161 read(EGL_NO_SURFACE),
162 draw(EGL_NO_SURFACE),
167 rendererString(NULL),
168 shaderVersionString(NULL),
169 extensionString(NULL),
175 clientState = new GLClientState();
177 sharedGroup = shareCtx->getSharedGroup();
179 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
180 assert(dpy == (EGLDisplay)&s_display);
181 s_display.onCreateContext((EGLContext)this);
184 int EGLContext_t::getGoldfishSyncFd() {
185 if (goldfishSyncFd < 0) {
186 goldfishSyncFd = goldfish_sync_open();
188 return goldfishSyncFd;
191 EGLContext_t::~EGLContext_t()
193 if (goldfishSyncFd > 0) {
194 goldfish_sync_close(goldfishSyncFd);
197 assert(dpy == (EGLDisplay)&s_display);
198 s_display.onDestroyContext((EGLContext)this);
200 delete [] versionString;
201 delete [] vendorString;
202 delete [] rendererString;
203 delete [] shaderVersionString;
204 delete [] extensionString;
207 // ----------------------------------------------------------------------------
210 //we don't need to handle depth since it's handled when window created on the host
212 struct egl_surface_t {
218 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
219 virtual ~egl_surface_t();
221 virtual void setSwapInterval(int interval) = 0;
222 virtual EGLBoolean swapBuffers() = 0;
224 EGLint getSwapBehavior() const;
225 uint32_t getRcSurface() { return rcSurface; }
226 EGLint getSurfaceType() { return surfaceType; }
228 EGLint getWidth(){ return width; }
229 EGLint getHeight(){ return height; }
230 EGLint getNativeWidth(){ return nativeWidth; }
231 EGLint getNativeHeight(){ return nativeHeight; }
232 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
233 EGLint getTextureFormat() { return texFormat; }
234 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
235 EGLint getTextureTarget() { return texTarget; }
246 // Width of the actual window being presented (not the EGL texture)
247 // Give it some default values.
252 void setWidth(EGLint w) { width = w; }
253 void setHeight(EGLint h) { height = h; }
254 void setNativeWidth(int w) { nativeWidth = w; }
255 void setNativeHeight(int h) { nativeHeight = h; }
258 uint32_t rcSurface; //handle to surface created via remote control
261 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
262 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
266 // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
269 texFormat = EGL_NO_TEXTURE;
270 texTarget = EGL_NO_TEXTURE;
271 assert(dpy == (EGLDisplay)&s_display);
272 s_display.onCreateSurface((EGLSurface)this);
275 EGLint egl_surface_t::getSwapBehavior() const {
276 return EGL_BUFFER_PRESERVED;
279 egl_surface_t::~egl_surface_t()
281 assert(dpy == (EGLDisplay)&s_display);
282 s_display.onDestroySurface((EGLSurface)this);
285 // ----------------------------------------------------------------------------
286 // egl_window_surface_t
288 struct egl_window_surface_t : public egl_surface_t {
289 static egl_window_surface_t* create(
290 EGLDisplay dpy, EGLConfig config, EGLint surfType,
291 ANativeWindow* window);
293 virtual ~egl_window_surface_t();
295 virtual void setSwapInterval(int interval);
296 virtual EGLBoolean swapBuffers();
299 egl_window_surface_t(
300 EGLDisplay dpy, EGLConfig config, EGLint surfType,
301 ANativeWindow* window);
304 ANativeWindow* nativeWindow;
305 android_native_buffer_t* buffer;
308 egl_window_surface_t::egl_window_surface_t (
309 EGLDisplay dpy, EGLConfig config, EGLint surfType,
310 ANativeWindow* window)
311 : egl_surface_t(dpy, config, surfType),
312 nativeWindow(window),
315 // keep a reference on the window
316 nativeWindow->common.incRef(&nativeWindow->common);
320 EGLBoolean egl_window_surface_t::init()
322 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
323 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
325 setWidth(buffer->width);
326 setHeight(buffer->height);
328 int nativeWidth, nativeHeight;
329 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
330 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
332 setNativeWidth(nativeWidth);
333 setNativeHeight(nativeHeight);
335 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
336 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
337 getWidth(), getHeight());
339 ALOGE("rcCreateWindowSurface returned 0");
342 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
343 ((cb_handle_t*)(buffer->handle))->hostHandle);
348 egl_window_surface_t* egl_window_surface_t::create(
349 EGLDisplay dpy, EGLConfig config, EGLint surfType,
350 ANativeWindow* window)
352 egl_window_surface_t* wnd = new egl_window_surface_t(
353 dpy, config, surfType, window);
354 if (wnd && !wnd->init()) {
361 egl_window_surface_t::~egl_window_surface_t() {
362 DEFINE_HOST_CONNECTION;
363 if (rcSurface && rcEnc) {
364 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
367 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
369 nativeWindow->common.decRef(&nativeWindow->common);
372 void egl_window_surface_t::setSwapInterval(int interval)
374 nativeWindow->setSwapInterval(nativeWindow, interval);
377 // createNativeSync() creates an OpenGL sync object on the host
378 // using rcCreateSyncKHR. If necessary, a native fence FD will
379 // also be created through the goldfish sync device.
380 // Returns a handle to the host-side FenceSync object.
381 static uint64_t createNativeSync(EGLenum type,
382 const EGLint* attrib_list,
383 int num_actual_attribs,
384 bool destroy_when_signaled,
387 DEFINE_HOST_CONNECTION;
389 uint64_t sync_handle;
390 uint64_t thread_handle;
392 EGLint* actual_attribs =
393 (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
395 rcEnc->rcCreateSyncKHR(rcEnc, type,
397 num_actual_attribs * sizeof(EGLint),
398 destroy_when_signaled,
402 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
404 goldfish_sync_queue_work(
405 getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
410 DPRINT("got native fence fd=%d queue_work_err=%d",
411 *fd_out, queue_work_err);
417 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
418 // that are needed by only this goldfish opengl driver,
419 // such as in swapBuffers().
420 // The guest will not see any of these, and these sync objects will be
421 // destroyed on the host when signaled.
422 // A native fence FD is possibly returned.
423 static void createGoldfishOpenGLNativeSync(int* fd_out) {
424 createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
425 NULL /* empty attrib list */,
426 0 /* 0 attrib count */,
427 true /* destroy when signaled. this is host-only
428 and there will only be one waiter */,
429 -1 /* we want a new fd */,
433 EGLBoolean egl_window_surface_t::swapBuffers()
436 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
438 // Follow up flushWindowColorBuffer with a fence command.
439 // When the fence command finishes,
440 // we're sure that the buffer on the host
443 // |presentFenceFd| guards the presentation of the
444 // current frame with a goldfish sync fence fd.
446 // When |presentFenceFd| is signaled, the recipient
447 // of the buffer that was sent through queueBuffer
448 // can be sure that the buffer is current.
450 // If we don't take care of this synchronization,
451 // an old frame can be processed by surfaceflinger,
452 // resulting in out of order frames.
454 int presentFenceFd = -1;
456 #if PLATFORM_SDK_VERSION <= 16
457 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
458 // equivalent to glFinish if no native sync
460 nativeWindow->queueBuffer(nativeWindow, buffer);
462 if (rcEnc->hasNativeSync()) {
463 rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
464 createGoldfishOpenGLNativeSync(&presentFenceFd);
466 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
467 // equivalent to glFinish if no native sync
471 DPRINT("queueBuffer with fence %d", presentFenceFd);
472 nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
475 DPRINT("calling dequeueBuffer...");
477 #if PLATFORM_SDK_VERSION <= 16
478 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
480 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
483 int acquireFenceFd = -1;
484 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
486 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
489 DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
491 if (acquireFenceFd > 0) {
492 close(acquireFenceFd);
496 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
497 ((cb_handle_t *)(buffer->handle))->hostHandle);
499 setWidth(buffer->width);
500 setHeight(buffer->height);
505 // ----------------------------------------------------------------------------
506 //egl_pbuffer_surface_t
508 struct egl_pbuffer_surface_t : public egl_surface_t {
509 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
510 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
512 virtual ~egl_pbuffer_surface_t();
514 virtual void setSwapInterval(int interval) { (void)interval; }
515 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
517 uint32_t getRcColorBuffer() { return rcColorBuffer; }
520 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
521 int32_t w, int32_t h);
522 EGLBoolean init(GLenum format);
524 uint32_t rcColorBuffer;
527 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
528 EGLint surfType, int32_t w, int32_t h)
529 : egl_surface_t(dpy, config, surfType),
536 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
538 DEFINE_HOST_CONNECTION;
540 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
541 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
545 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
547 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
549 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
550 getWidth(), getHeight());
552 ALOGE("rcCreateWindowSurface returned 0");
556 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
558 if (!rcColorBuffer) {
559 ALOGE("rcCreateColorBuffer returned 0");
563 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
568 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
569 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
572 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
574 if (pb && !pb->init(pixelFormat)) {
581 static const char *getGLString(int glEnum)
583 EGLThreadInfo *tInfo = getEGLThreadInfo();
584 if (!tInfo || !tInfo->currentContext) {
588 const char** strPtr = NULL;
590 #define GL_VENDOR 0x1F00
591 #define GL_RENDERER 0x1F01
592 #define GL_VERSION 0x1F02
593 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
594 #define GL_EXTENSIONS 0x1F03
598 strPtr = &tInfo->currentContext->versionString;
601 strPtr = &tInfo->currentContext->vendorString;
604 strPtr = &tInfo->currentContext->rendererString;
606 case GL_SHADING_LANGUAGE_VERSION:
607 strPtr = &tInfo->currentContext->shaderVersionString;
610 strPtr = &tInfo->currentContext->extensionString;
618 if (*strPtr != NULL) {
620 // string is already cached
626 // first query of that string - need to query host
628 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
629 char *hostStr = NULL;
630 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
632 hostStr = new char[-n+1];
633 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
641 // keep the string in the context and return its value
647 // ----------------------------------------------------------------------------
649 static EGLClient_eglInterface s_eglIface = {
650 getThreadInfo: getEGLThreadInfo,
651 getGLString: getGLString
654 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
655 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
658 // we support only EGL_DEFAULT_DISPLAY.
660 if (display_id != EGL_DEFAULT_DISPLAY) {
661 return EGL_NO_DISPLAY;
664 return (EGLDisplay)&s_display;
667 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
669 VALIDATE_DISPLAY(dpy,EGL_FALSE);
671 if (!s_display.initialize(&s_eglIface)) {
675 *major = s_display.getVersionMajor();
677 *minor = s_display.getVersionMinor();
681 EGLBoolean eglTerminate(EGLDisplay dpy)
683 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
685 s_display.terminate();
691 EGLint error = getEGLThreadInfo()->eglError;
692 getEGLThreadInfo()->eglError = EGL_SUCCESS;
696 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
698 // search in EGL function table
699 for (int i=0; i<egl_num_funcs; i++) {
700 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
701 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
705 // look in gles client api's extensions table
706 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
708 // Fail - function not found.
712 const char* eglQueryString(EGLDisplay dpy, EGLint name)
714 VALIDATE_DISPLAY_INIT(dpy, NULL);
716 return s_display.queryString(name);
719 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
721 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
724 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
727 GLint numConfigs = s_display.getNumConfigs();
729 *num_config = numConfigs;
734 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
735 *configs++ = (EGLConfig)(uintptr_t)i;
741 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
743 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
746 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
749 int attribs_size = 0;
751 const EGLint * attrib_p = attrib_list;
752 while (attrib_p[0] != EGL_NONE) {
756 attribs_size++; //for the terminating EGL_NONE
759 uint32_t* tempConfigs[config_size];
760 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
761 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
763 if (*num_config <= 0) {
764 EGLint err = -(*num_config);
767 case EGL_BAD_ATTRIBUTE:
768 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
776 for (i=0;i<(*num_config);i++) {
777 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
784 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
786 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
787 VALIDATE_CONFIG(config, EGL_FALSE);
789 if (s_display.getConfigAttrib(config, attribute, value))
795 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
799 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
803 VALIDATE_DISPLAY_INIT(dpy, NULL);
804 VALIDATE_CONFIG(config, EGL_FALSE);
806 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
810 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
812 if (!(surfaceType & EGL_WINDOW_BIT)) {
813 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
816 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
817 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
820 egl_surface_t* surface = egl_window_surface_t::create(
821 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
823 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
829 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
831 VALIDATE_DISPLAY_INIT(dpy, NULL);
832 VALIDATE_CONFIG(config, EGL_FALSE);
835 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
837 if (!(surfaceType & EGL_PBUFFER_BIT)) {
838 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
843 EGLint texFormat = EGL_NO_TEXTURE;
844 EGLint texTarget = EGL_NO_TEXTURE;
845 while (attrib_list[0] != EGL_NONE) {
846 switch (attrib_list[0]) {
849 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
853 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
855 case EGL_TEXTURE_FORMAT:
856 texFormat = attrib_list[1];
858 case EGL_TEXTURE_TARGET:
859 texTarget = attrib_list[1];
861 // the followings are not supported
862 case EGL_LARGEST_PBUFFER:
863 case EGL_MIPMAP_TEXTURE:
864 case EGL_VG_ALPHA_FORMAT:
865 case EGL_VG_COLORSPACE:
868 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
872 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
873 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
874 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
876 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
879 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
880 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
882 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
883 EGL_PBUFFER_BIT, w, h, pixelFormat);
885 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
889 surface->setTextureFormat(texFormat);
890 surface->setTextureTarget(texTarget);
895 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
897 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
898 // located on host. In order to support Pixmaps we should either punt
899 // to s/w rendering -or- let the host render to a buffer that will be
900 // copied back to guest at some sync point. None of those methods not
901 // implemented and pixmaps are not used with OpenGL anyway ...
902 VALIDATE_CONFIG(config, EGL_FALSE);
906 return EGL_NO_SURFACE;
909 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
911 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
912 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
914 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
920 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
922 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
923 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
925 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
927 // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
928 // TODO: get the DPI from avd config
929 float fakeNativeDPI = 420.0;
930 float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
931 EGLBoolean ret = EGL_TRUE;
934 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
937 *value = surface->getWidth();
940 *value = surface->getHeight();
942 case EGL_TEXTURE_FORMAT:
943 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
944 *value = surface->getTextureFormat();
947 case EGL_TEXTURE_TARGET:
948 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
949 *value = surface->getTextureTarget();
952 case EGL_SWAP_BEHAVIOR:
955 ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
957 if (ret == EGL_TRUE) {
958 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
959 *value = EGL_BUFFER_PRESERVED;
961 *value = EGL_BUFFER_DESTROYED;
966 case EGL_LARGEST_PBUFFER:
967 // not modified for a window or pixmap surface
968 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
969 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
971 case EGL_MIPMAP_TEXTURE:
972 // not modified for a window or pixmap surface
973 // and we ignore it when creating a PBuffer surface (default is 0)
974 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
976 case EGL_MIPMAP_LEVEL:
977 // not modified for a window or pixmap surface
978 // and we ignore it when creating a PBuffer surface (default is 0)
979 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
981 case EGL_MULTISAMPLE_RESOLVE:
982 // ignored when creating the surface, return default
983 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
985 case EGL_HORIZONTAL_RESOLUTION:
986 // pixel/mm * EGL_DISPLAY_SCALING
987 // TODO: get the DPI from avd config
988 currWidth = surface->getWidth();
989 scaledResolution = currWidth / surface->getNativeWidth();
990 effectiveSurfaceDPI =
991 scaledResolution * fakeNativeDPI * EGL_DISPLAY_SCALING;
992 *value = (EGLint)(effectiveSurfaceDPI);
994 case EGL_VERTICAL_RESOLUTION:
995 // pixel/mm * EGL_DISPLAY_SCALING
996 // TODO: get the real DPI from avd config
997 currHeight = surface->getHeight();
998 scaledResolution = currHeight / surface->getNativeHeight();
999 effectiveSurfaceDPI =
1000 scaledResolution * fakeNativeDPI * EGL_DISPLAY_SCALING;
1001 *value = (EGLint)(effectiveSurfaceDPI);
1003 case EGL_PIXEL_ASPECT_RATIO:
1004 // w / h * EGL_DISPLAY_SCALING
1005 // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
1006 *value = 1 * EGL_DISPLAY_SCALING;
1008 case EGL_RENDER_BUFFER:
1009 switch (surface->getSurfaceType()) {
1010 case EGL_PBUFFER_BIT:
1011 *value = EGL_BACK_BUFFER;
1013 case EGL_PIXMAP_BIT:
1014 *value = EGL_SINGLE_BUFFER;
1016 case EGL_WINDOW_BIT:
1017 // ignored when creating the surface, return default
1018 *value = EGL_BACK_BUFFER;
1021 ALOGE("eglQuerySurface %x unknown surface type %x",
1022 attribute, surface->getSurfaceType());
1023 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1027 case EGL_VG_COLORSPACE:
1028 // ignored when creating the surface, return default
1029 *value = EGL_VG_COLORSPACE_sRGB;
1031 case EGL_VG_ALPHA_FORMAT:
1032 // ignored when creating the surface, return default
1033 *value = EGL_VG_ALPHA_FORMAT_NONPRE;
1035 //TODO: complete other attributes
1037 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
1038 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1045 EGLBoolean eglBindAPI(EGLenum api)
1047 if (api != EGL_OPENGL_ES_API)
1048 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1052 EGLenum eglQueryAPI()
1054 return EGL_OPENGL_ES_API;
1057 EGLBoolean eglWaitClient()
1062 EGLBoolean eglReleaseThread()
1064 EGLThreadInfo *tInfo = getEGLThreadInfo();
1066 tInfo->eglError = EGL_SUCCESS;
1067 EGLContext_t* context = tInfo->currentContext;
1069 // The following code is doing pretty much the same thing as
1070 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1071 // with the only issue that we do not require a valid display here.
1072 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1073 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1074 if (context->version == 2) {
1075 hostCon->gl2Encoder()->setClientState(NULL);
1076 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
1079 hostCon->glEncoder()->setClientState(NULL);
1080 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
1082 context->flags &= ~EGLContext_t::IS_CURRENT;
1084 if (context->deletePending) {
1085 if (context->rcContext) {
1086 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1087 context->rcContext = 0;
1091 tInfo->currentContext = 0;
1097 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1105 ALOGW("%s not implemented", __FUNCTION__);
1109 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1111 // Right now we don't do anything when using host GPU.
1112 // This is purely just to pass the data through
1113 // without issuing a warning. We may benefit from validating the
1114 // display and surface for debug purposes.
1115 // TODO: Find cases where we actually need to do something.
1116 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1117 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1118 if (surface == EGL_NO_SURFACE) {
1119 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1124 egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1125 switch (attribute) {
1126 case EGL_MIPMAP_LEVEL:
1129 case EGL_MULTISAMPLE_RESOLVE:
1131 if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1132 EGLint surface_type;
1133 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1134 if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1135 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1141 case EGL_SWAP_BEHAVIOR:
1142 if (value == EGL_BUFFER_PRESERVED) {
1143 EGLint surface_type;
1144 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1145 if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1146 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1152 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1153 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1158 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1160 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1161 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1162 if (eglSurface == EGL_NO_SURFACE) {
1163 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1166 if (buffer != EGL_BACK_BUFFER) {
1167 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1170 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1172 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1173 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1176 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1177 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1180 //It's now safe to cast to pbuffer surface
1181 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1183 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1184 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1189 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1195 ALOGW("%s not implemented", __FUNCTION__);
1199 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1201 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1202 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1204 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1206 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1209 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1211 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1212 draw->setSwapInterval(interval);
1214 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1219 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1221 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1222 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1224 EGLint version = 1; //default
1225 while (attrib_list && attrib_list[0] != EGL_NONE) {
1226 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
1227 version = attrib_list[1];
1228 } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
1229 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1234 // Currently only support GLES1 and 2
1235 if (version != 1 && version != 2) {
1236 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1239 uint32_t rcShareCtx = 0;
1240 EGLContext_t * shareCtx = NULL;
1241 if (share_context) {
1242 shareCtx = static_cast<EGLContext_t*>(share_context);
1243 rcShareCtx = shareCtx->rcContext;
1244 if (shareCtx->dpy != dpy)
1245 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1248 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1249 // We've created EGL context. Disconnecting
1250 // would be dangerous at this point.
1251 hostCon->setGrallocOnly(false);
1253 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1255 ALOGE("rcCreateContext returned 0");
1256 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1259 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1261 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1263 context->version = version;
1264 context->rcContext = rcContext;
1270 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1272 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1273 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1275 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1277 if (!context) return EGL_TRUE;
1279 if (getEGLThreadInfo()->currentContext == context) {
1280 getEGLThreadInfo()->currentContext->deletePending = 1;
1284 if (context->rcContext) {
1285 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1286 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1287 context->rcContext = 0;
1294 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1296 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1297 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1298 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1300 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1301 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1302 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1303 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1305 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1306 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1307 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1308 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1309 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1310 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1313 // Nothing to do if no binding change has made
1315 EGLThreadInfo *tInfo = getEGLThreadInfo();
1317 if (tInfo->currentContext == context &&
1319 (context && context->draw == draw && context->read == read))) {
1323 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1324 if (tInfo->currentContext != context) {
1325 EGLContext_t * contextToDelete = tInfo->currentContext;
1326 tInfo->currentContext = 0;
1327 eglDestroyContext(dpy, contextToDelete);
1331 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1332 //context is current to another thread
1333 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1336 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1337 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1338 ALOGE("rcMakeCurrent returned EGL_FALSE");
1339 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1342 //Now make the local bind
1344 // This is a nontrivial context.
1345 // The thread cannot be gralloc-only anymore.
1346 hostCon->setGrallocOnly(false);
1347 context->draw = draw;
1348 context->read = read;
1349 context->flags |= EGLContext_t::IS_CURRENT;
1350 //set the client state
1351 if (context->version == 2) {
1352 hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1353 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1356 hostCon->glEncoder()->setClientState(context->getClientState());
1357 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1360 else if (tInfo->currentContext) {
1361 //release ClientState & SharedGroup
1362 if (tInfo->currentContext->version == 2) {
1363 hostCon->gl2Encoder()->setClientState(NULL);
1364 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1367 hostCon->glEncoder()->setClientState(NULL);
1368 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1373 if (tInfo->currentContext)
1374 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1377 tInfo->currentContext = context;
1379 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1380 if (tInfo->currentContext) {
1381 if (tInfo->currentContext->version == 2) {
1382 if (!hostCon->gl2Encoder()->isInitialized()) {
1383 s_display.gles2_iface()->init();
1384 hostCon->gl2Encoder()->setInitialized();
1385 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1389 if (!hostCon->glEncoder()->isInitialized()) {
1390 s_display.gles_iface()->init();
1391 hostCon->glEncoder()->setInitialized();
1392 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1400 EGLContext eglGetCurrentContext()
1402 return getEGLThreadInfo()->currentContext;
1405 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1407 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1409 return EGL_NO_SURFACE; //not an error
1413 return context->read;
1415 return context->draw;
1417 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1421 EGLDisplay eglGetCurrentDisplay()
1423 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1425 return EGL_NO_DISPLAY; //not an error
1427 return context->dpy;
1430 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1432 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1433 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1435 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1437 EGLBoolean ret = EGL_TRUE;
1438 switch (attribute) {
1440 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1442 case EGL_CONTEXT_CLIENT_TYPE:
1443 *value = EGL_OPENGL_ES_API;
1445 case EGL_CONTEXT_CLIENT_VERSION:
1446 *value = context->version;
1448 case EGL_RENDER_BUFFER:
1452 *value = EGL_BACK_BUFFER; //single buffer not supported
1455 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1456 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1463 EGLBoolean eglWaitGL()
1465 EGLThreadInfo *tInfo = getEGLThreadInfo();
1466 if (!tInfo || !tInfo->currentContext) {
1470 if (tInfo->currentContext->version == 2) {
1471 s_display.gles2_iface()->finish();
1474 s_display.gles_iface()->finish();
1480 EGLBoolean eglWaitNative(EGLint engine)
1486 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1488 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1489 if (eglSurface == EGL_NO_SURFACE)
1490 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1492 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1494 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1496 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1505 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1514 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1523 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1531 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1535 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1537 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1538 if (ctx != EGL_NO_CONTEXT) {
1539 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1542 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1544 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1545 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1547 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1548 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1550 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1552 switch (cb->format) {
1553 case HAL_PIXEL_FORMAT_RGBA_8888:
1554 case HAL_PIXEL_FORMAT_RGBX_8888:
1555 case HAL_PIXEL_FORMAT_RGB_888:
1556 case HAL_PIXEL_FORMAT_RGB_565:
1557 case HAL_PIXEL_FORMAT_YV12:
1558 case HAL_PIXEL_FORMAT_BGRA_8888:
1561 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1564 native_buffer->common.incRef(&native_buffer->common);
1566 EGLImage_t *image = new EGLImage_t();
1568 image->target = target;
1569 image->native_buffer = native_buffer;
1571 return (EGLImageKHR)image;
1573 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1574 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1576 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1577 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1579 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1580 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1581 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1582 EGLImage_t *image = new EGLImage_t();
1584 image->target = target;
1585 image->host_egl_image = img;
1587 return (EGLImageKHR)image;
1590 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1593 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1595 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1596 EGLImage_t *image = (EGLImage_t*)img;
1598 if (!image || image->dpy != dpy) {
1599 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1602 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1603 android_native_buffer_t* native_buffer = image->native_buffer;
1605 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1606 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1608 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1609 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1611 native_buffer->common.decRef(&native_buffer->common);
1616 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1617 uint32_t host_egl_image = image->host_egl_image;
1619 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1620 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1623 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1626 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1627 #define MAX_EGL_SYNC_ATTRIBS 10
1629 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1630 const EGLint *attrib_list)
1632 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1633 DPRINT("type for eglCreateSyncKHR: 0x%x", type);
1635 DEFINE_HOST_CONNECTION;
1637 if ((type != EGL_SYNC_FENCE_KHR &&
1638 type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
1639 (type != EGL_SYNC_FENCE_KHR &&
1640 !rcEnc->hasNativeSync())) {
1641 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1644 EGLThreadInfo *tInfo = getEGLThreadInfo();
1645 if (!tInfo || !tInfo->currentContext) {
1646 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1649 int num_actual_attribs = 0;
1651 // If attrib_list is not NULL,
1652 // ensure attrib_list contains (key, value) pairs
1653 // followed by a single EGL_NONE.
1654 // Also validate attribs.
1655 int inputFenceFd = -1;
1657 for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
1658 if (attrib_list[i] == EGL_NONE) {
1659 num_actual_attribs = i;
1662 if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
1663 DPRINT("ERROR: attrib list without EGL_NONE");
1664 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1668 // Validate and input attribs
1669 for (int i = 0; i < num_actual_attribs; i += 2) {
1670 if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
1671 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
1673 if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
1674 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
1676 if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
1677 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
1679 EGLint attrib_key = attrib_list[i];
1680 EGLint attrib_val = attrib_list[i + 1];
1681 if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
1682 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
1683 inputFenceFd = attrib_val;
1686 DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
1690 uint64_t sync_handle = 0;
1691 int newFenceFd = -1;
1693 if (rcEnc->hasNativeSync()) {
1695 createNativeSync(type, attrib_list, num_actual_attribs,
1696 false /* don't destroy when signaled on the host;
1697 let the guest clean this up,
1698 because the guest called eglCreateSyncKHR. */,
1703 // Just trigger a glFinish if the native sync on host
1708 EGLSync_t* syncRes = new EGLSync_t(sync_handle);
1710 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
1711 syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
1713 if (inputFenceFd < 0) {
1714 syncRes->android_native_fence_fd = newFenceFd;
1716 DPRINT("has input fence fd %d",
1718 syncRes->android_native_fence_fd = inputFenceFd;
1721 syncRes->type = EGL_SYNC_FENCE_KHR;
1722 syncRes->android_native_fence_fd = -1;
1723 if (!rcEnc->hasNativeSync()) {
1724 syncRes->status = EGL_SIGNALED_KHR;
1728 return (EGLSyncKHR)syncRes;
1731 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
1736 DPRINT("WARNING: null sync object")
1740 EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
1742 if (sync && sync->android_native_fence_fd > 0) {
1743 close(sync->android_native_fence_fd);
1744 sync->android_native_fence_fd = -1;
1748 DEFINE_HOST_CONNECTION;
1749 if (rcEnc->hasNativeSync()) {
1750 rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
1758 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
1764 DPRINT("WARNING: null sync object");
1765 return EGL_CONDITION_SATISFIED_KHR;
1768 EGLSync_t* sync = (EGLSync_t*)eglsync;
1770 DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
1771 sync, sync->handle, flags, timeout);
1773 DEFINE_HOST_CONNECTION;
1776 if (rcEnc->hasNativeSync()) {
1777 retval = rcEnc->rcClientWaitSyncKHR
1778 (rcEnc, sync->handle, flags, timeout);
1780 retval = EGL_CONDITION_SATISFIED_KHR;
1783 switch (sync->type) {
1784 case EGL_SYNC_FENCE_KHR:
1785 res_status = EGL_SIGNALED_KHR;
1787 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1788 res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
1791 res_status = EGL_SIGNALED_KHR;
1793 sync->status = res_status;
1797 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
1798 EGLint attribute, EGLint *value)
1802 EGLSync_t* sync = (EGLSync_t*)eglsync;
1804 switch (attribute) {
1805 case EGL_SYNC_TYPE_KHR:
1806 *value = sync->type;
1808 case EGL_SYNC_STATUS_KHR:
1809 *value = sync->status;
1811 case EGL_SYNC_CONDITION_KHR:
1812 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1815 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1819 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
1824 EGLSync_t* sync = (EGLSync_t*)eglsync;
1825 if (sync && sync->android_native_fence_fd > 0) {
1826 int res = dup(sync->android_native_fence_fd);
1833 // TODO: Implement EGL_KHR_wait_sync
1834 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {