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"
21 #include "egl_ftable.h"
22 #include <cutils/log.h>
23 #include "goldfish_sync.h"
24 #include "gralloc_cb.h"
25 #include "GLClientState.h"
26 #include "GLSharedGroup.h"
27 #include "eglContext.h"
28 #include "ClientAPIExts.h"
31 #include "GLEncoder.h"
33 #include "GL2Encoder.h"
36 #if PLATFORM_SDK_VERSION >= 16
37 #include <system/window.h>
38 #else // PLATFORM_SDK_VERSION >= 16
39 #include <private/ui/android_natives_priv.h>
40 #endif // PLATFORM_SDK_VERSION >= 16
42 #if PLATFORM_SDK_VERSION <= 16
43 #define queueBuffer_DEPRECATED queueBuffer
44 #define dequeueBuffer_DEPRECATED dequeueBuffer
45 #define cancelBuffer_DEPRECATED cancelBuffer
46 #endif // PLATFORM_SDK_VERSION <= 16
51 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
57 static T setErrorFunc(GLint error, T returnValue) {
58 getEGLThreadInfo()->eglError = error;
62 const char * eglStrError(EGLint err)
65 case EGL_SUCCESS: return "EGL_SUCCESS";
66 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
67 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
68 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
69 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
70 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
71 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
72 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
73 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
74 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
75 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
76 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
77 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
78 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
79 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
80 default: return "UNKNOWN";
84 #define LOG_EGL_ERRORS 1
88 #define setErrorReturn(error, retVal) \
90 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
91 return setErrorFunc(error, retVal); \
94 #define RETURN_ERROR(ret,err) \
95 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
96 getEGLThreadInfo()->eglError = err; \
99 #else //!LOG_EGL_ERRORS
101 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
103 #define RETURN_ERROR(ret,err) \
104 getEGLThreadInfo()->eglError = err; \
107 #endif //LOG_EGL_ERRORS
109 #define VALIDATE_CONFIG(cfg,ret) \
110 if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
111 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
114 #define VALIDATE_DISPLAY(dpy,ret) \
115 if ((dpy) != (EGLDisplay)&s_display) { \
116 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
119 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
120 VALIDATE_DISPLAY(dpy, ret) \
121 if (!s_display.initialized()) { \
122 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
125 #define DEFINE_HOST_CONNECTION \
126 HostConnection *hostCon = HostConnection::get(); \
127 ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
129 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
130 HostConnection *hostCon = HostConnection::get(); \
132 ALOGE("egl: Failed to get host connection\n"); \
135 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
137 ALOGE("egl: Failed to get renderControl encoder context\n"); \
141 #define VALIDATE_CONTEXT_RETURN(context,ret) \
143 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
146 #define VALIDATE_SURFACE_RETURN(surface, ret) \
147 if ((surface) != EGL_NO_SURFACE) { \
148 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
149 if (s->dpy != (EGLDisplay)&s_display) \
150 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
153 // The one and only supported display object.
154 static eglDisplay s_display;
156 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
159 read(EGL_NO_SURFACE),
160 draw(EGL_NO_SURFACE),
165 rendererString(NULL),
166 shaderVersionString(NULL),
167 extensionString(NULL),
173 clientState = new GLClientState();
175 sharedGroup = shareCtx->getSharedGroup();
177 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
178 assert(dpy == (EGLDisplay)&s_display);
179 s_display.onCreateContext((EGLContext)this);
182 int EGLContext_t::getGoldfishSyncFd() {
183 if (goldfishSyncFd < 0) {
184 goldfishSyncFd = goldfish_sync_open();
186 return goldfishSyncFd;
189 EGLContext_t::~EGLContext_t()
191 assert(dpy == (EGLDisplay)&s_display);
192 s_display.onDestroyContext((EGLContext)this);
194 delete [] versionString;
195 delete [] vendorString;
196 delete [] rendererString;
197 delete [] shaderVersionString;
198 delete [] extensionString;
201 // ----------------------------------------------------------------------------
204 //we don't need to handle depth since it's handled when window created on the host
206 struct egl_surface_t {
212 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
213 virtual ~egl_surface_t();
215 virtual void setSwapInterval(int interval) = 0;
216 virtual EGLBoolean swapBuffers() = 0;
218 EGLint getSwapBehavior() const;
219 uint32_t getRcSurface() { return rcSurface; }
220 EGLint getSurfaceType() { return surfaceType; }
222 EGLint getWidth(){ return width; }
223 EGLint getHeight(){ return height; }
224 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
225 EGLint getTextureFormat() { return texFormat; }
226 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
227 EGLint getTextureTarget() { return texTarget; }
239 void setWidth(EGLint w) { width = w; }
240 void setHeight(EGLint h) { height = h; }
243 uint32_t rcSurface; //handle to surface created via remote control
246 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
247 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
251 texFormat = EGL_NO_TEXTURE;
252 texTarget = EGL_NO_TEXTURE;
253 assert(dpy == (EGLDisplay)&s_display);
254 s_display.onCreateSurface((EGLSurface)this);
257 EGLint egl_surface_t::getSwapBehavior() const {
258 return EGL_BUFFER_PRESERVED;
261 egl_surface_t::~egl_surface_t()
263 assert(dpy == (EGLDisplay)&s_display);
264 s_display.onDestroySurface((EGLSurface)this);
267 // ----------------------------------------------------------------------------
268 // egl_window_surface_t
270 struct egl_window_surface_t : public egl_surface_t {
271 static egl_window_surface_t* create(
272 EGLDisplay dpy, EGLConfig config, EGLint surfType,
273 ANativeWindow* window);
275 virtual ~egl_window_surface_t();
277 virtual void setSwapInterval(int interval);
278 virtual EGLBoolean swapBuffers();
281 egl_window_surface_t(
282 EGLDisplay dpy, EGLConfig config, EGLint surfType,
283 ANativeWindow* window);
286 ANativeWindow* nativeWindow;
287 android_native_buffer_t* buffer;
290 egl_window_surface_t::egl_window_surface_t (
291 EGLDisplay dpy, EGLConfig config, EGLint surfType,
292 ANativeWindow* window)
293 : egl_surface_t(dpy, config, surfType),
294 nativeWindow(window),
297 // keep a reference on the window
298 nativeWindow->common.incRef(&nativeWindow->common);
302 EGLBoolean egl_window_surface_t::init()
304 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
305 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
307 setWidth(buffer->width);
308 setHeight(buffer->height);
310 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
311 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
312 getWidth(), getHeight());
314 ALOGE("rcCreateWindowSurface returned 0");
317 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
318 ((cb_handle_t*)(buffer->handle))->hostHandle);
323 egl_window_surface_t* egl_window_surface_t::create(
324 EGLDisplay dpy, EGLConfig config, EGLint surfType,
325 ANativeWindow* window)
327 egl_window_surface_t* wnd = new egl_window_surface_t(
328 dpy, config, surfType, window);
329 if (wnd && !wnd->init()) {
336 egl_window_surface_t::~egl_window_surface_t() {
337 DEFINE_HOST_CONNECTION;
338 if (rcSurface && rcEnc) {
339 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
342 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
344 nativeWindow->common.decRef(&nativeWindow->common);
347 void egl_window_surface_t::setSwapInterval(int interval)
349 nativeWindow->setSwapInterval(nativeWindow, interval);
352 EGLBoolean egl_window_surface_t::swapBuffers()
354 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
356 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
358 nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
359 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
361 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
364 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
365 ((cb_handle_t *)(buffer->handle))->hostHandle);
367 setWidth(buffer->width);
368 setHeight(buffer->height);
373 // ----------------------------------------------------------------------------
374 //egl_pbuffer_surface_t
376 struct egl_pbuffer_surface_t : public egl_surface_t {
377 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
378 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
380 virtual ~egl_pbuffer_surface_t();
382 virtual void setSwapInterval(int interval) { (void)interval; }
383 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
385 uint32_t getRcColorBuffer() { return rcColorBuffer; }
388 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
389 int32_t w, int32_t h);
390 EGLBoolean init(GLenum format);
392 uint32_t rcColorBuffer;
395 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
396 EGLint surfType, int32_t w, int32_t h)
397 : egl_surface_t(dpy, config, surfType),
404 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
406 DEFINE_HOST_CONNECTION;
408 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
409 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
413 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
415 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
417 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
418 getWidth(), getHeight());
420 ALOGE("rcCreateWindowSurface returned 0");
424 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
426 if (!rcColorBuffer) {
427 ALOGE("rcCreateColorBuffer returned 0");
431 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
436 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
437 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
440 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
442 if (pb && !pb->init(pixelFormat)) {
449 static const char *getGLString(int glEnum)
451 EGLThreadInfo *tInfo = getEGLThreadInfo();
452 if (!tInfo || !tInfo->currentContext) {
456 const char** strPtr = NULL;
458 #define GL_VENDOR 0x1F00
459 #define GL_RENDERER 0x1F01
460 #define GL_VERSION 0x1F02
461 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
462 #define GL_EXTENSIONS 0x1F03
466 strPtr = &tInfo->currentContext->versionString;
469 strPtr = &tInfo->currentContext->vendorString;
472 strPtr = &tInfo->currentContext->rendererString;
474 case GL_SHADING_LANGUAGE_VERSION:
475 strPtr = &tInfo->currentContext->shaderVersionString;
478 strPtr = &tInfo->currentContext->extensionString;
486 if (*strPtr != NULL) {
488 // string is already cached
494 // first query of that string - need to query host
496 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
497 char *hostStr = NULL;
498 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
500 hostStr = new char[-n+1];
501 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
509 // keep the string in the context and return its value
515 // ----------------------------------------------------------------------------
517 static EGLClient_eglInterface s_eglIface = {
518 getThreadInfo: getEGLThreadInfo,
519 getGLString: getGLString
522 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
523 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
526 // we support only EGL_DEFAULT_DISPLAY.
528 if (display_id != EGL_DEFAULT_DISPLAY) {
529 return EGL_NO_DISPLAY;
532 return (EGLDisplay)&s_display;
535 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
537 VALIDATE_DISPLAY(dpy,EGL_FALSE);
539 if (!s_display.initialize(&s_eglIface)) {
543 *major = s_display.getVersionMajor();
545 *minor = s_display.getVersionMinor();
549 EGLBoolean eglTerminate(EGLDisplay dpy)
551 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
553 s_display.terminate();
559 EGLint error = getEGLThreadInfo()->eglError;
560 getEGLThreadInfo()->eglError = EGL_SUCCESS;
564 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
566 // search in EGL function table
567 for (int i=0; i<egl_num_funcs; i++) {
568 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
569 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
573 // look in gles client api's extensions table
574 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
576 // Fail - function not found.
580 const char* eglQueryString(EGLDisplay dpy, EGLint name)
582 VALIDATE_DISPLAY_INIT(dpy, NULL);
584 return s_display.queryString(name);
587 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
589 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
592 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
595 GLint numConfigs = s_display.getNumConfigs();
597 *num_config = numConfigs;
602 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
603 *configs++ = (EGLConfig)(uintptr_t)i;
609 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
611 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
613 int attribs_size = 0;
615 const EGLint * attrib_p = attrib_list;
616 while (attrib_p[0] != EGL_NONE) {
620 attribs_size++; //for the terminating EGL_NONE
623 uint32_t* tempConfigs[config_size];
624 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
625 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
628 for (i=0;i<(*num_config);i++) {
629 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
633 if (*num_config <= 0)
638 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
640 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
641 VALIDATE_CONFIG(config, EGL_FALSE);
643 if (s_display.getConfigAttrib(config, attribute, value))
649 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
653 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
657 VALIDATE_DISPLAY_INIT(dpy, NULL);
658 VALIDATE_CONFIG(config, EGL_FALSE);
660 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
664 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
666 if (!(surfaceType & EGL_WINDOW_BIT)) {
667 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
670 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
671 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
674 egl_surface_t* surface = egl_window_surface_t::create(
675 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
677 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
683 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
685 VALIDATE_DISPLAY_INIT(dpy, NULL);
686 VALIDATE_CONFIG(config, EGL_FALSE);
689 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
691 if (!(surfaceType & EGL_PBUFFER_BIT)) {
692 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
697 EGLint texFormat = EGL_NO_TEXTURE;
698 EGLint texTarget = EGL_NO_TEXTURE;
699 while (attrib_list[0] != EGL_NONE) {
700 switch (attrib_list[0]) {
707 case EGL_TEXTURE_FORMAT:
708 texFormat = attrib_list[1];
710 case EGL_TEXTURE_TARGET:
711 texTarget = attrib_list[1];
718 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
719 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
720 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
722 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
725 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
726 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
728 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
729 EGL_PBUFFER_BIT, w, h, pixelFormat);
731 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
735 surface->setTextureFormat(texFormat);
736 surface->setTextureTarget(texTarget);
741 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
743 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
744 // located on host. In order to support Pixmaps we should either punt
745 // to s/w rendering -or- let the host render to a buffer that will be
746 // copied back to guest at some sync point. None of those methods not
747 // implemented and pixmaps are not used with OpenGL anyway ...
752 return EGL_NO_SURFACE;
755 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
757 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
758 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
760 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
766 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
768 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
769 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
771 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
772 EGLBoolean ret = EGL_TRUE;
775 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
778 *value = surface->getWidth();
781 *value = surface->getHeight();
783 case EGL_TEXTURE_FORMAT:
784 *value = surface->getTextureFormat();
786 case EGL_TEXTURE_TARGET:
787 *value = surface->getTextureTarget();
789 case EGL_SWAP_BEHAVIOR:
790 *value = surface->getSwapBehavior();
792 case EGL_LARGEST_PBUFFER:
793 // not modified for a window or pixmap surface
794 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
795 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
797 case EGL_MIPMAP_LEVEL:
798 // not modified for a window or pixmap surface
799 // and we ignore it when creating a PBuffer surface (default is 0)
800 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
802 case EGL_MULTISAMPLE_RESOLVE:
803 // ignored when creating the surface, return default
804 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
806 //TODO: complete other attributes
808 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
809 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
816 EGLBoolean eglBindAPI(EGLenum api)
818 if (api != EGL_OPENGL_ES_API)
819 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
823 EGLenum eglQueryAPI()
825 return EGL_OPENGL_ES_API;
828 EGLBoolean eglWaitClient()
833 EGLBoolean eglReleaseThread()
835 EGLThreadInfo *tInfo = getEGLThreadInfo();
837 tInfo->eglError = EGL_SUCCESS;
838 EGLContext_t* context = tInfo->currentContext;
840 // The following code is doing pretty much the same thing as
841 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
842 // with the only issue that we do not require a valid display here.
843 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
844 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
845 if (context->version == 2) {
846 hostCon->gl2Encoder()->setClientState(NULL);
847 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
850 hostCon->glEncoder()->setClientState(NULL);
851 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
853 context->flags &= ~EGLContext_t::IS_CURRENT;
855 if (context->deletePending) {
856 if (context->rcContext) {
857 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
858 context->rcContext = 0;
862 tInfo->currentContext = 0;
868 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
876 ALOGW("%s not implemented", __FUNCTION__);
880 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
882 // Right now we don't do anything when using host GPU.
883 // This is purely just to pass the data through
884 // without issuing a warning. We may benefit from validating the
885 // display and surface for debug purposes.
886 // TODO: Find cases where we actually need to do something.
887 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
888 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
889 if (surface == EGL_NO_SURFACE) {
890 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
896 case EGL_MIPMAP_LEVEL:
897 case EGL_MULTISAMPLE_RESOLVE:
898 case EGL_SWAP_BEHAVIOR:
902 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
907 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
909 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
910 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
911 if (eglSurface == EGL_NO_SURFACE) {
912 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
915 if (buffer != EGL_BACK_BUFFER) {
916 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
919 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
921 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
922 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
925 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
926 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
929 //It's now safe to cast to pbuffer surface
930 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
932 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
933 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
938 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
944 ALOGW("%s not implemented", __FUNCTION__);
948 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
950 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
951 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
953 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
955 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
958 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
960 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
961 draw->setSwapInterval(interval);
963 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
968 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
970 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
971 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
973 EGLint version = 1; //default
974 while (attrib_list && attrib_list[0] != EGL_NONE) {
975 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
976 version = attrib_list[1];
977 } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
978 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
983 // Currently only support GLES1 and 2
984 if (version != 1 && version != 2) {
985 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
988 uint32_t rcShareCtx = 0;
989 EGLContext_t * shareCtx = NULL;
991 shareCtx = static_cast<EGLContext_t*>(share_context);
992 rcShareCtx = shareCtx->rcContext;
993 if (shareCtx->dpy != dpy)
994 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
997 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
998 // We've created EGL context. Disconnecting
999 // would be dangerous at this point.
1000 hostCon->setGrallocOnly(false);
1002 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1004 ALOGE("rcCreateContext returned 0");
1005 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1008 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1010 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1012 context->version = version;
1013 context->rcContext = rcContext;
1019 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1021 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1022 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1024 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1026 if (!context) return EGL_TRUE;
1028 if (getEGLThreadInfo()->currentContext == context) {
1029 getEGLThreadInfo()->currentContext->deletePending = 1;
1033 if (context->rcContext) {
1034 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1035 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1036 context->rcContext = 0;
1043 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1045 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1046 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1047 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1049 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1050 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1051 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1052 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1054 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1055 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1056 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1057 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1058 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1059 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1062 // Nothing to do if no binding change has made
1064 EGLThreadInfo *tInfo = getEGLThreadInfo();
1066 if (tInfo->currentContext == context &&
1068 (context && context->draw == draw && context->read == read))) {
1072 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1073 if (tInfo->currentContext != context) {
1074 EGLContext_t * contextToDelete = tInfo->currentContext;
1075 tInfo->currentContext = 0;
1076 eglDestroyContext(dpy, contextToDelete);
1080 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1081 //context is current to another thread
1082 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1085 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1086 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1087 ALOGE("rcMakeCurrent returned EGL_FALSE");
1088 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1091 //Now make the local bind
1093 // This is a nontrivial context.
1094 // The thread cannot be gralloc-only anymore.
1095 hostCon->setGrallocOnly(false);
1096 context->draw = draw;
1097 context->read = read;
1098 context->flags |= EGLContext_t::IS_CURRENT;
1099 //set the client state
1100 if (context->version == 2) {
1101 hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1102 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1105 hostCon->glEncoder()->setClientState(context->getClientState());
1106 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1109 else if (tInfo->currentContext) {
1110 //release ClientState & SharedGroup
1111 if (tInfo->currentContext->version == 2) {
1112 hostCon->gl2Encoder()->setClientState(NULL);
1113 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1116 hostCon->glEncoder()->setClientState(NULL);
1117 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1122 if (tInfo->currentContext)
1123 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1126 tInfo->currentContext = context;
1128 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1129 if (tInfo->currentContext) {
1130 if (tInfo->currentContext->version == 2) {
1131 if (!hostCon->gl2Encoder()->isInitialized()) {
1132 s_display.gles2_iface()->init();
1133 hostCon->gl2Encoder()->setInitialized();
1134 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1138 if (!hostCon->glEncoder()->isInitialized()) {
1139 s_display.gles_iface()->init();
1140 hostCon->glEncoder()->setInitialized();
1141 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1149 EGLContext eglGetCurrentContext()
1151 return getEGLThreadInfo()->currentContext;
1154 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1156 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1158 return EGL_NO_SURFACE; //not an error
1162 return context->read;
1164 return context->draw;
1166 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1170 EGLDisplay eglGetCurrentDisplay()
1172 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1174 return EGL_NO_DISPLAY; //not an error
1176 return context->dpy;
1179 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1181 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1182 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1184 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1186 EGLBoolean ret = EGL_TRUE;
1187 switch (attribute) {
1189 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1191 case EGL_CONTEXT_CLIENT_TYPE:
1192 *value = EGL_OPENGL_ES_API;
1194 case EGL_CONTEXT_CLIENT_VERSION:
1195 *value = context->version;
1197 case EGL_RENDER_BUFFER:
1201 *value = EGL_BACK_BUFFER; //single buffer not supported
1204 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1205 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1212 EGLBoolean eglWaitGL()
1214 EGLThreadInfo *tInfo = getEGLThreadInfo();
1215 if (!tInfo || !tInfo->currentContext) {
1219 if (tInfo->currentContext->version == 2) {
1220 s_display.gles2_iface()->finish();
1223 s_display.gles_iface()->finish();
1229 EGLBoolean eglWaitNative(EGLint engine)
1235 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1237 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1238 if (eglSurface == EGL_NO_SURFACE)
1239 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1241 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1243 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1245 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1254 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1263 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1272 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1280 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1284 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1286 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1287 if (ctx != EGL_NO_CONTEXT) {
1288 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1291 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1293 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1294 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1296 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1297 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1299 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1301 switch (cb->format) {
1302 case HAL_PIXEL_FORMAT_RGBA_8888:
1303 case HAL_PIXEL_FORMAT_RGBX_8888:
1304 case HAL_PIXEL_FORMAT_RGB_888:
1305 case HAL_PIXEL_FORMAT_RGB_565:
1306 case HAL_PIXEL_FORMAT_BGRA_8888:
1309 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1312 native_buffer->common.incRef(&native_buffer->common);
1314 EGLImage_t *image = new EGLImage_t();
1316 image->target = target;
1317 image->native_buffer = native_buffer;
1319 return (EGLImageKHR)image;
1321 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1322 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1324 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1325 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1327 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1328 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1329 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1330 EGLImage_t *image = new EGLImage_t();
1332 image->target = target;
1333 image->host_egl_image = img;
1335 return (EGLImageKHR)image;
1338 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1341 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1343 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1344 EGLImage_t *image = (EGLImage_t*)img;
1346 if (!image || image->dpy != dpy) {
1347 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1350 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1351 android_native_buffer_t* native_buffer = image->native_buffer;
1353 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1354 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1356 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1357 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1359 native_buffer->common.decRef(&native_buffer->common);
1364 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1365 uint32_t host_egl_image = image->host_egl_image;
1367 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1368 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1371 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1374 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1376 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1377 const EGLint *attrib_list)
1379 // TODO: This implementation could be faster. We should require the host EGL
1380 // to support KHR_fence_sync, or at least pipe the fence command to the host
1381 // and wait for it (probably involving a glFinish on the host) in
1382 // eglClientWaitSyncKHR.
1384 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1386 if (type != EGL_SYNC_FENCE_KHR ||
1387 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1388 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1391 EGLThreadInfo *tInfo = getEGLThreadInfo();
1392 if (!tInfo || !tInfo->currentContext) {
1393 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1396 if (tInfo->currentContext->version == 2) {
1397 s_display.gles2_iface()->finish();
1399 s_display.gles_iface()->finish();
1402 return FENCE_SYNC_HANDLE;
1405 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1409 if (sync != FENCE_SYNC_HANDLE) {
1410 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1416 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1423 if (sync != FENCE_SYNC_HANDLE) {
1424 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1427 return EGL_CONDITION_SATISFIED_KHR;
1430 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1431 EGLint attribute, EGLint *value)
1435 if (sync != FENCE_SYNC_HANDLE) {
1436 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1439 switch (attribute) {
1440 case EGL_SYNC_TYPE_KHR:
1441 *value = EGL_SYNC_FENCE_KHR;
1443 case EGL_SYNC_STATUS_KHR:
1444 *value = EGL_SIGNALED_KHR;
1446 case EGL_SYNC_CONDITION_KHR:
1447 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1450 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);