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 "gralloc_cb.h"
24 #include "GLClientState.h"
25 #include "GLSharedGroup.h"
26 #include "eglContext.h"
27 #include "ClientAPIExts.h"
30 #include "GLEncoder.h"
32 #include "GL2Encoder.h"
35 #if PLATFORM_SDK_VERSION >= 16
36 #include <system/window.h>
37 #else // PLATFORM_SDK_VERSION >= 16
38 #include <private/ui/android_natives_priv.h>
39 #endif // PLATFORM_SDK_VERSION >= 16
41 #if PLATFORM_SDK_VERSION <= 16
42 #define queueBuffer_DEPRECATED queueBuffer
43 #define dequeueBuffer_DEPRECATED dequeueBuffer
44 #define cancelBuffer_DEPRECATED cancelBuffer
45 #endif // PLATFORM_SDK_VERSION <= 16
48 static T setErrorFunc(GLint error, T returnValue) {
49 getEGLThreadInfo()->eglError = error;
53 const char * eglStrError(EGLint err)
56 case EGL_SUCCESS: return "EGL_SUCCESS";
57 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
58 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
59 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
60 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
61 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
62 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
63 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
64 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
65 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
66 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
67 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
68 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
69 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
70 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
71 default: return "UNKNOWN";
75 #define LOG_EGL_ERRORS 1
79 #define setErrorReturn(error, retVal) \
81 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
82 return setErrorFunc(error, retVal); \
85 #define RETURN_ERROR(ret,err) \
86 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
87 getEGLThreadInfo()->eglError = err; \
90 #else //!LOG_EGL_ERRORS
92 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
94 #define RETURN_ERROR(ret,err) \
95 getEGLThreadInfo()->eglError = err; \
98 #endif //LOG_EGL_ERRORS
100 #define VALIDATE_CONFIG(cfg,ret) \
101 if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
102 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
105 #define VALIDATE_DISPLAY(dpy,ret) \
106 if ((dpy) != (EGLDisplay)&s_display) { \
107 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
110 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
111 VALIDATE_DISPLAY(dpy, ret) \
112 if (!s_display.initialized()) { \
113 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
116 #define DEFINE_HOST_CONNECTION \
117 HostConnection *hostCon = HostConnection::get(); \
118 ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
120 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
121 HostConnection *hostCon = HostConnection::get(); \
123 ALOGE("egl: Failed to get host connection\n"); \
126 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
128 ALOGE("egl: Failed to get renderControl encoder context\n"); \
132 #define VALIDATE_CONTEXT_RETURN(context,ret) \
134 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
137 #define VALIDATE_SURFACE_RETURN(surface, ret) \
138 if ((surface) != EGL_NO_SURFACE) { \
139 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
140 if (s->dpy != (EGLDisplay)&s_display) \
141 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
144 // The one and only supported display object.
145 static eglDisplay s_display;
147 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
150 read(EGL_NO_SURFACE),
151 draw(EGL_NO_SURFACE),
156 rendererString(NULL),
157 shaderVersionString(NULL),
158 extensionString(NULL),
163 clientState = new GLClientState();
165 sharedGroup = shareCtx->getSharedGroup();
167 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
168 assert(dpy == (EGLDisplay)&s_display);
169 s_display.onCreateContext((EGLContext)this);
172 EGLContext_t::~EGLContext_t()
174 assert(dpy == (EGLDisplay)&s_display);
175 s_display.onDestroyContext((EGLContext)this);
177 delete [] versionString;
178 delete [] vendorString;
179 delete [] rendererString;
180 delete [] shaderVersionString;
181 delete [] extensionString;
184 // ----------------------------------------------------------------------------
187 //we don't need to handle depth since it's handled when window created on the host
189 struct egl_surface_t {
195 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
196 virtual ~egl_surface_t();
198 virtual void setSwapInterval(int interval) = 0;
199 virtual EGLBoolean swapBuffers() = 0;
201 EGLint getSwapBehavior() const;
202 uint32_t getRcSurface() { return rcSurface; }
203 EGLint getSurfaceType() { return surfaceType; }
205 EGLint getWidth(){ return width; }
206 EGLint getHeight(){ return height; }
207 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
208 EGLint getTextureFormat() { return texFormat; }
209 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
210 EGLint getTextureTarget() { return texTarget; }
222 void setWidth(EGLint w) { width = w; }
223 void setHeight(EGLint h) { height = h; }
226 uint32_t rcSurface; //handle to surface created via remote control
229 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
230 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
234 texFormat = EGL_NO_TEXTURE;
235 texTarget = EGL_NO_TEXTURE;
236 assert(dpy == (EGLDisplay)&s_display);
237 s_display.onCreateSurface((EGLSurface)this);
240 EGLint egl_surface_t::getSwapBehavior() const {
241 return EGL_BUFFER_PRESERVED;
244 egl_surface_t::~egl_surface_t()
246 assert(dpy == (EGLDisplay)&s_display);
247 s_display.onDestroySurface((EGLSurface)this);
250 // ----------------------------------------------------------------------------
251 // egl_window_surface_t
253 struct egl_window_surface_t : public egl_surface_t {
254 static egl_window_surface_t* create(
255 EGLDisplay dpy, EGLConfig config, EGLint surfType,
256 ANativeWindow* window);
258 virtual ~egl_window_surface_t();
260 virtual void setSwapInterval(int interval);
261 virtual EGLBoolean swapBuffers();
264 egl_window_surface_t(
265 EGLDisplay dpy, EGLConfig config, EGLint surfType,
266 ANativeWindow* window);
269 ANativeWindow* nativeWindow;
270 android_native_buffer_t* buffer;
273 egl_window_surface_t::egl_window_surface_t (
274 EGLDisplay dpy, EGLConfig config, EGLint surfType,
275 ANativeWindow* window)
276 : egl_surface_t(dpy, config, surfType),
277 nativeWindow(window),
280 // keep a reference on the window
281 nativeWindow->common.incRef(&nativeWindow->common);
284 EGLBoolean egl_window_surface_t::init()
286 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
287 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
289 setWidth(buffer->width);
290 setHeight(buffer->height);
292 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
293 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
294 getWidth(), getHeight());
296 ALOGE("rcCreateWindowSurface returned 0");
299 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
300 ((cb_handle_t*)(buffer->handle))->hostHandle);
305 egl_window_surface_t* egl_window_surface_t::create(
306 EGLDisplay dpy, EGLConfig config, EGLint surfType,
307 ANativeWindow* window)
309 egl_window_surface_t* wnd = new egl_window_surface_t(
310 dpy, config, surfType, window);
311 if (wnd && !wnd->init()) {
318 egl_window_surface_t::~egl_window_surface_t() {
319 DEFINE_HOST_CONNECTION;
320 if (rcSurface && rcEnc) {
321 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
324 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
326 nativeWindow->common.decRef(&nativeWindow->common);
329 void egl_window_surface_t::setSwapInterval(int interval)
331 nativeWindow->setSwapInterval(nativeWindow, interval);
334 EGLBoolean egl_window_surface_t::swapBuffers()
336 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
338 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
340 nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
341 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
343 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
346 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
347 ((cb_handle_t *)(buffer->handle))->hostHandle);
349 setWidth(buffer->width);
350 setHeight(buffer->height);
355 // ----------------------------------------------------------------------------
356 //egl_pbuffer_surface_t
358 struct egl_pbuffer_surface_t : public egl_surface_t {
359 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
360 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
362 virtual ~egl_pbuffer_surface_t();
364 virtual void setSwapInterval(int interval) { (void)interval; }
365 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
367 uint32_t getRcColorBuffer() { return rcColorBuffer; }
370 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
371 int32_t w, int32_t h);
372 EGLBoolean init(GLenum format);
374 uint32_t rcColorBuffer;
377 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
378 EGLint surfType, int32_t w, int32_t h)
379 : egl_surface_t(dpy, config, surfType),
386 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
388 DEFINE_HOST_CONNECTION;
390 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
391 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
395 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
397 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
399 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
400 getWidth(), getHeight());
402 ALOGE("rcCreateWindowSurface returned 0");
406 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
408 if (!rcColorBuffer) {
409 ALOGE("rcCreateColorBuffer returned 0");
413 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
418 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
419 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
422 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
424 if (pb && !pb->init(pixelFormat)) {
431 static const char *getGLString(int glEnum)
433 EGLThreadInfo *tInfo = getEGLThreadInfo();
434 if (!tInfo || !tInfo->currentContext) {
438 const char** strPtr = NULL;
440 #define GL_VENDOR 0x1F00
441 #define GL_RENDERER 0x1F01
442 #define GL_VERSION 0x1F02
443 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
444 #define GL_EXTENSIONS 0x1F03
448 strPtr = &tInfo->currentContext->versionString;
451 strPtr = &tInfo->currentContext->vendorString;
454 strPtr = &tInfo->currentContext->rendererString;
456 case GL_SHADING_LANGUAGE_VERSION:
457 strPtr = &tInfo->currentContext->shaderVersionString;
460 strPtr = &tInfo->currentContext->extensionString;
468 if (*strPtr != NULL) {
470 // string is already cached
476 // first query of that string - need to query host
478 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
479 char *hostStr = NULL;
480 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
482 hostStr = new char[-n+1];
483 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
491 // keep the string in the context and return its value
497 // ----------------------------------------------------------------------------
499 static EGLClient_eglInterface s_eglIface = {
500 getThreadInfo: getEGLThreadInfo,
501 getGLString: getGLString
504 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
505 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
508 // we support only EGL_DEFAULT_DISPLAY.
510 if (display_id != EGL_DEFAULT_DISPLAY) {
511 return EGL_NO_DISPLAY;
514 return (EGLDisplay)&s_display;
517 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
519 VALIDATE_DISPLAY(dpy,EGL_FALSE);
521 if (!s_display.initialize(&s_eglIface)) {
525 *major = s_display.getVersionMajor();
527 *minor = s_display.getVersionMinor();
531 EGLBoolean eglTerminate(EGLDisplay dpy)
533 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
535 s_display.terminate();
541 EGLint error = getEGLThreadInfo()->eglError;
542 getEGLThreadInfo()->eglError = EGL_SUCCESS;
546 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
548 // search in EGL function table
549 for (int i=0; i<egl_num_funcs; i++) {
550 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
551 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
555 // look in gles client api's extensions table
556 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
558 // Fail - function not found.
562 const char* eglQueryString(EGLDisplay dpy, EGLint name)
564 VALIDATE_DISPLAY_INIT(dpy, NULL);
566 return s_display.queryString(name);
569 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
571 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
574 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
577 GLint numConfigs = s_display.getNumConfigs();
579 *num_config = numConfigs;
584 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
585 *configs++ = (EGLConfig)(uintptr_t)i;
591 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
593 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
595 int attribs_size = 0;
597 const EGLint * attrib_p = attrib_list;
598 while (attrib_p[0] != EGL_NONE) {
602 attribs_size++; //for the terminating EGL_NONE
605 uint32_t* tempConfigs[config_size];
606 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
607 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
610 for (i=0;i<(*num_config);i++) {
611 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
615 if (*num_config <= 0)
620 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
622 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
623 VALIDATE_CONFIG(config, EGL_FALSE);
625 if (s_display.getConfigAttrib(config, attribute, value))
631 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
635 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
639 VALIDATE_DISPLAY_INIT(dpy, NULL);
640 VALIDATE_CONFIG(config, EGL_FALSE);
642 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
646 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
648 if (!(surfaceType & EGL_WINDOW_BIT)) {
649 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
652 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
653 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
656 egl_surface_t* surface = egl_window_surface_t::create(
657 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
659 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
665 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
667 VALIDATE_DISPLAY_INIT(dpy, NULL);
668 VALIDATE_CONFIG(config, EGL_FALSE);
671 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
673 if (!(surfaceType & EGL_PBUFFER_BIT)) {
674 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
679 EGLint texFormat = EGL_NO_TEXTURE;
680 EGLint texTarget = EGL_NO_TEXTURE;
681 while (attrib_list[0] != EGL_NONE) {
682 switch (attrib_list[0]) {
689 case EGL_TEXTURE_FORMAT:
690 texFormat = attrib_list[1];
692 case EGL_TEXTURE_TARGET:
693 texTarget = attrib_list[1];
700 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
701 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
702 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
704 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
707 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
708 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
710 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
711 EGL_PBUFFER_BIT, w, h, pixelFormat);
713 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
717 surface->setTextureFormat(texFormat);
718 surface->setTextureTarget(texTarget);
723 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
725 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
726 // located on host. In order to support Pixmaps we should either punt
727 // to s/w rendering -or- let the host render to a buffer that will be
728 // copied back to guest at some sync point. None of those methods not
729 // implemented and pixmaps are not used with OpenGL anyway ...
734 return EGL_NO_SURFACE;
737 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
739 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
740 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
742 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
748 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
750 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
751 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
753 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
754 EGLBoolean ret = EGL_TRUE;
757 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
760 *value = surface->getWidth();
763 *value = surface->getHeight();
765 case EGL_TEXTURE_FORMAT:
766 *value = surface->getTextureFormat();
768 case EGL_TEXTURE_TARGET:
769 *value = surface->getTextureTarget();
771 case EGL_SWAP_BEHAVIOR:
772 *value = surface->getSwapBehavior();
774 case EGL_LARGEST_PBUFFER:
775 // not modified for a window or pixmap surface
776 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
777 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
779 case EGL_MIPMAP_LEVEL:
780 // not modified for a window or pixmap surface
781 // and we ignore it when creating a PBuffer surface (default is 0)
782 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
784 case EGL_MULTISAMPLE_RESOLVE:
785 // ignored when creating the surface, return default
786 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
788 //TODO: complete other attributes
790 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
791 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
798 EGLBoolean eglBindAPI(EGLenum api)
800 if (api != EGL_OPENGL_ES_API)
801 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
805 EGLenum eglQueryAPI()
807 return EGL_OPENGL_ES_API;
810 EGLBoolean eglWaitClient()
815 EGLBoolean eglReleaseThread()
817 EGLThreadInfo *tInfo = getEGLThreadInfo();
819 tInfo->eglError = EGL_SUCCESS;
820 EGLContext_t* context = tInfo->currentContext;
822 // The following code is doing pretty much the same thing as
823 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
824 // with the only issue that we do not require a valid display here.
825 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
826 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
827 if (context->version == 2) {
828 hostCon->gl2Encoder()->setClientState(NULL);
829 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
832 hostCon->glEncoder()->setClientState(NULL);
833 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
835 context->flags &= ~EGLContext_t::IS_CURRENT;
837 if (context->deletePending) {
838 if (context->rcContext) {
839 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
840 context->rcContext = 0;
844 tInfo->currentContext = 0;
850 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
858 ALOGW("%s not implemented", __FUNCTION__);
862 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
864 // Right now we don't do anything when using host GPU.
865 // This is purely just to pass the data through
866 // without issuing a warning. We may benefit from validating the
867 // display and surface for debug purposes.
868 // TODO: Find cases where we actually need to do something.
869 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
870 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
871 if (surface == EGL_NO_SURFACE) {
872 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
878 case EGL_MIPMAP_LEVEL:
879 case EGL_MULTISAMPLE_RESOLVE:
880 case EGL_SWAP_BEHAVIOR:
884 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
889 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
891 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
892 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
893 if (eglSurface == EGL_NO_SURFACE) {
894 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
897 if (buffer != EGL_BACK_BUFFER) {
898 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
901 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
903 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
904 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
907 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
908 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
911 //It's now safe to cast to pbuffer surface
912 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
914 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
915 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
920 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
926 ALOGW("%s not implemented", __FUNCTION__);
930 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
932 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
933 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
935 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
937 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
940 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
942 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
943 draw->setSwapInterval(interval);
945 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
950 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
952 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
953 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
955 EGLint version = 1; //default
956 while (attrib_list && attrib_list[0] != EGL_NONE) {
957 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
958 version = attrib_list[1];
959 } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
960 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
965 // Currently only support GLES1 and 2
966 if (version != 1 && version != 2) {
967 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
970 uint32_t rcShareCtx = 0;
971 EGLContext_t * shareCtx = NULL;
973 shareCtx = static_cast<EGLContext_t*>(share_context);
974 rcShareCtx = shareCtx->rcContext;
975 if (shareCtx->dpy != dpy)
976 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
979 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
980 // We've created EGL context. Disconnecting
981 // would be dangerous at this point.
982 hostCon->setGrallocOnly(false);
984 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
986 ALOGE("rcCreateContext returned 0");
987 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
990 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
992 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
994 context->version = version;
995 context->rcContext = rcContext;
1001 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1003 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1004 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1006 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1008 if (!context) return EGL_TRUE;
1010 if (getEGLThreadInfo()->currentContext == context) {
1011 getEGLThreadInfo()->currentContext->deletePending = 1;
1015 if (context->rcContext) {
1016 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1017 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1018 context->rcContext = 0;
1025 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1027 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1028 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1029 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1031 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1032 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1033 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1034 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1036 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1037 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1038 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1039 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1040 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1041 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1044 // Nothing to do if no binding change has made
1046 EGLThreadInfo *tInfo = getEGLThreadInfo();
1048 if (tInfo->currentContext == context &&
1050 (context && context->draw == draw && context->read == read))) {
1054 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1055 if (tInfo->currentContext != context) {
1056 EGLContext_t * contextToDelete = tInfo->currentContext;
1057 tInfo->currentContext = 0;
1058 eglDestroyContext(dpy, contextToDelete);
1062 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1063 //context is current to another thread
1064 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1067 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1068 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1069 ALOGE("rcMakeCurrent returned EGL_FALSE");
1070 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1073 //Now make the local bind
1075 // This is a nontrivial context.
1076 // The thread cannot be gralloc-only anymore.
1077 hostCon->setGrallocOnly(false);
1078 context->draw = draw;
1079 context->read = read;
1080 context->flags |= EGLContext_t::IS_CURRENT;
1081 //set the client state
1082 if (context->version == 2) {
1083 hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1084 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1087 hostCon->glEncoder()->setClientState(context->getClientState());
1088 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1091 else if (tInfo->currentContext) {
1092 //release ClientState & SharedGroup
1093 if (tInfo->currentContext->version == 2) {
1094 hostCon->gl2Encoder()->setClientState(NULL);
1095 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1098 hostCon->glEncoder()->setClientState(NULL);
1099 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1104 if (tInfo->currentContext)
1105 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1108 tInfo->currentContext = context;
1110 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1111 if (tInfo->currentContext) {
1112 if (tInfo->currentContext->version == 2) {
1113 if (!hostCon->gl2Encoder()->isInitialized()) {
1114 s_display.gles2_iface()->init();
1115 hostCon->gl2Encoder()->setInitialized();
1116 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1120 if (!hostCon->glEncoder()->isInitialized()) {
1121 s_display.gles_iface()->init();
1122 hostCon->glEncoder()->setInitialized();
1123 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1131 EGLContext eglGetCurrentContext()
1133 return getEGLThreadInfo()->currentContext;
1136 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1138 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1140 return EGL_NO_SURFACE; //not an error
1144 return context->read;
1146 return context->draw;
1148 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1152 EGLDisplay eglGetCurrentDisplay()
1154 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1156 return EGL_NO_DISPLAY; //not an error
1158 return context->dpy;
1161 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1163 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1164 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1166 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1168 EGLBoolean ret = EGL_TRUE;
1169 switch (attribute) {
1171 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1173 case EGL_CONTEXT_CLIENT_TYPE:
1174 *value = EGL_OPENGL_ES_API;
1176 case EGL_CONTEXT_CLIENT_VERSION:
1177 *value = context->version;
1179 case EGL_RENDER_BUFFER:
1183 *value = EGL_BACK_BUFFER; //single buffer not supported
1186 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1187 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1194 EGLBoolean eglWaitGL()
1196 EGLThreadInfo *tInfo = getEGLThreadInfo();
1197 if (!tInfo || !tInfo->currentContext) {
1201 if (tInfo->currentContext->version == 2) {
1202 s_display.gles2_iface()->finish();
1205 s_display.gles_iface()->finish();
1211 EGLBoolean eglWaitNative(EGLint engine)
1217 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1219 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1220 if (eglSurface == EGL_NO_SURFACE)
1221 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1223 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1225 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1227 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1236 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1245 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1254 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1262 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1266 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1268 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1269 if (ctx != EGL_NO_CONTEXT) {
1270 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1273 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1275 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1276 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1278 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1279 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1281 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1283 switch (cb->format) {
1284 case HAL_PIXEL_FORMAT_RGBA_8888:
1285 case HAL_PIXEL_FORMAT_RGBX_8888:
1286 case HAL_PIXEL_FORMAT_RGB_888:
1287 case HAL_PIXEL_FORMAT_RGB_565:
1288 case HAL_PIXEL_FORMAT_BGRA_8888:
1291 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1294 native_buffer->common.incRef(&native_buffer->common);
1296 EGLImage_t *image = new EGLImage_t();
1298 image->target = target;
1299 image->native_buffer = native_buffer;
1301 return (EGLImageKHR)image;
1303 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1304 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1306 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1307 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1309 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1310 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1311 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1312 EGLImage_t *image = new EGLImage_t();
1314 image->target = target;
1315 image->host_egl_image = img;
1317 return (EGLImageKHR)image;
1320 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1323 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1325 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1326 EGLImage_t *image = (EGLImage_t*)img;
1328 if (!image || image->dpy != dpy) {
1329 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1332 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1333 android_native_buffer_t* native_buffer = image->native_buffer;
1335 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1336 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1338 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1339 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1341 native_buffer->common.decRef(&native_buffer->common);
1346 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1347 uint32_t host_egl_image = image->host_egl_image;
1349 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1350 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1353 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1356 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1358 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1359 const EGLint *attrib_list)
1361 // TODO: This implementation could be faster. We should require the host EGL
1362 // to support KHR_fence_sync, or at least pipe the fence command to the host
1363 // and wait for it (probably involving a glFinish on the host) in
1364 // eglClientWaitSyncKHR.
1366 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1368 if (type != EGL_SYNC_FENCE_KHR ||
1369 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1370 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1373 EGLThreadInfo *tInfo = getEGLThreadInfo();
1374 if (!tInfo || !tInfo->currentContext) {
1375 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1378 if (tInfo->currentContext->version == 2) {
1379 s_display.gles2_iface()->finish();
1381 s_display.gles_iface()->finish();
1384 return FENCE_SYNC_HANDLE;
1387 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1391 if (sync != FENCE_SYNC_HANDLE) {
1392 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1398 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1405 if (sync != FENCE_SYNC_HANDLE) {
1406 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1409 return EGL_CONDITION_SATISFIED_KHR;
1412 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1413 EGLint attribute, EGLint *value)
1417 if (sync != FENCE_SYNC_HANDLE) {
1418 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1421 switch (attribute) {
1422 case EGL_SYNC_TYPE_KHR:
1423 *value = EGL_SYNC_FENCE_KHR;
1425 case EGL_SYNC_STATUS_KHR:
1426 *value = EGL_SIGNALED_KHR;
1428 case EGL_SYNC_CONDITION_KHR:
1429 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1432 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);