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.
17 #include "HostConnection.h"
18 #include "ThreadInfo.h"
19 #include "eglDisplay.h"
20 #include "egl_ftable.h"
21 #include <cutils/log.h>
22 #include "gralloc_cb.h"
23 #include "GLClientState.h"
24 #include "GLSharedGroup.h"
25 #include "eglContext.h"
26 #include "ClientAPIExts.h"
29 #include "GLEncoder.h"
31 #include "GL2Encoder.h"
34 #include <system/window.h>
37 static T setErrorFunc(GLint error, T returnValue) {
38 getEGLThreadInfo()->eglError = error;
42 const char * eglStrError(EGLint err)
45 case EGL_SUCCESS: return "EGL_SUCCESS";
46 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
47 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
48 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
49 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
50 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
51 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
52 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
53 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
54 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
55 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
56 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
57 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
58 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
59 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
60 default: return "UNKNOWN";
64 #define LOG_EGL_ERRORS 1
68 #define setErrorReturn(error, retVal) \
70 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
71 return setErrorFunc(error, retVal); \
74 #define RETURN_ERROR(ret,err) \
75 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
76 getEGLThreadInfo()->eglError = err; \
79 #else //!LOG_EGL_ERRORS
81 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
83 #define RETURN_ERROR(ret,err) \
84 getEGLThreadInfo()->eglError = err; \
87 #endif //LOG_EGL_ERRORS
89 #define VALIDATE_CONFIG(cfg,ret) \
90 if(((intptr_t)cfg<0)||((intptr_t)cfg>s_display.getNumConfigs())) { \
91 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
94 #define VALIDATE_DISPLAY(dpy,ret) \
95 if ((dpy) != (EGLDisplay)&s_display) { \
96 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
99 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
100 VALIDATE_DISPLAY(dpy, ret) \
101 if (!s_display.initialized()) { \
102 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
105 #define DEFINE_HOST_CONNECTION \
106 HostConnection *hostCon = HostConnection::get(); \
107 renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
109 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
110 HostConnection *hostCon = HostConnection::get(); \
112 ALOGE("egl: Failed to get host connection\n"); \
115 renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
117 ALOGE("egl: Failed to get renderControl encoder context\n"); \
121 #define VALIDATE_CONTEXT_RETURN(context,ret) \
123 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
126 #define VALIDATE_SURFACE_RETURN(surface, ret) \
127 if (surface != EGL_NO_SURFACE) { \
128 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
129 if (s->dpy != (EGLDisplay)&s_display) \
130 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
134 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
137 read(EGL_NO_SURFACE),
138 draw(EGL_NO_SURFACE),
143 rendererString(NULL),
144 shaderVersionString(NULL),
145 extensionString(NULL),
150 clientState = new GLClientState();
152 sharedGroup = shareCtx->getSharedGroup();
154 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
157 EGLContext_t::~EGLContext_t()
160 delete [] versionString;
161 delete [] vendorString;
162 delete [] rendererString;
163 delete [] shaderVersionString;
164 delete [] extensionString;
167 // ----------------------------------------------------------------------------
170 //we don't need to handle depth since it's handled when window created on the host
172 struct egl_surface_t {
178 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
179 virtual ~egl_surface_t();
181 virtual void setSwapInterval(int interval) = 0;
182 virtual EGLBoolean swapBuffers() = 0;
184 EGLint getSwapBehavior() const;
185 uint32_t getRcSurface() { return rcSurface; }
186 EGLint getSurfaceType() { return surfaceType; }
188 EGLint getWidth(){ return width; }
189 EGLint getHeight(){ return height; }
190 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
191 EGLint getTextureFormat() { return texFormat; }
192 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
193 EGLint getTextureTarget() { return texTarget; }
205 void setWidth(EGLint w) { width = w; }
206 void setHeight(EGLint h) { height = h; }
209 uint32_t rcSurface; //handle to surface created via remote control
212 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
213 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
217 texFormat = EGL_NO_TEXTURE;
218 texTarget = EGL_NO_TEXTURE;
221 EGLint egl_surface_t::getSwapBehavior() const {
222 return EGL_BUFFER_PRESERVED;
225 egl_surface_t::~egl_surface_t()
229 // ----------------------------------------------------------------------------
230 // egl_window_surface_t
232 struct egl_window_surface_t : public egl_surface_t {
233 static egl_window_surface_t* create(
234 EGLDisplay dpy, EGLConfig config, EGLint surfType,
235 ANativeWindow* window);
237 virtual ~egl_window_surface_t();
239 virtual void setSwapInterval(int interval);
240 virtual EGLBoolean swapBuffers();
243 egl_window_surface_t(
244 EGLDisplay dpy, EGLConfig config, EGLint surfType,
245 ANativeWindow* window);
248 ANativeWindow* nativeWindow;
249 android_native_buffer_t* buffer;
252 egl_window_surface_t::egl_window_surface_t (
253 EGLDisplay dpy, EGLConfig config, EGLint surfType,
254 ANativeWindow* window)
255 : egl_surface_t(dpy, config, surfType),
256 nativeWindow(window),
259 // keep a reference on the window
260 nativeWindow->common.incRef(&nativeWindow->common);
263 EGLBoolean egl_window_surface_t::init()
265 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
266 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
268 setWidth(buffer->width);
269 setHeight(buffer->height);
271 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
272 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
273 getWidth(), getHeight());
275 ALOGE("rcCreateWindowSurface returned 0");
278 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
279 ((cb_handle_t*)(buffer->handle))->hostHandle);
284 egl_window_surface_t* egl_window_surface_t::create(
285 EGLDisplay dpy, EGLConfig config, EGLint surfType,
286 ANativeWindow* window)
288 egl_window_surface_t* wnd = new egl_window_surface_t(
289 dpy, config, surfType, window);
290 if (wnd && !wnd->init()) {
297 egl_window_surface_t::~egl_window_surface_t() {
298 DEFINE_HOST_CONNECTION;
299 if (rcSurface && rcEnc) {
300 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
303 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
305 nativeWindow->common.decRef(&nativeWindow->common);
308 void egl_window_surface_t::setSwapInterval(int interval)
310 nativeWindow->setSwapInterval(nativeWindow, interval);
313 EGLBoolean egl_window_surface_t::swapBuffers()
315 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
317 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
319 nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
320 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
322 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
325 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
326 ((cb_handle_t *)(buffer->handle))->hostHandle);
328 setWidth(buffer->width);
329 setHeight(buffer->height);
334 // ----------------------------------------------------------------------------
335 //egl_pbuffer_surface_t
337 struct egl_pbuffer_surface_t : public egl_surface_t {
338 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
339 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
341 virtual ~egl_pbuffer_surface_t();
343 virtual void setSwapInterval(int interval) { (void)interval; }
344 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
346 uint32_t getRcColorBuffer() { return rcColorBuffer; }
349 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
350 int32_t w, int32_t h);
351 EGLBoolean init(GLenum format);
353 uint32_t rcColorBuffer;
356 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
357 EGLint surfType, int32_t w, int32_t h)
358 : egl_surface_t(dpy, config, surfType),
365 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
367 DEFINE_HOST_CONNECTION;
369 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
370 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
374 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
376 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
378 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
379 getWidth(), getHeight());
381 ALOGE("rcCreateWindowSurface returned 0");
385 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
387 if (!rcColorBuffer) {
388 ALOGE("rcCreateColorBuffer returned 0");
392 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
397 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
398 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
401 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
403 if (pb && !pb->init(pixelFormat)) {
410 static const char *getGLString(int glEnum)
412 EGLThreadInfo *tInfo = getEGLThreadInfo();
413 if (!tInfo || !tInfo->currentContext) {
417 const char** strPtr = NULL;
419 #define GL_VENDOR 0x1F00
420 #define GL_RENDERER 0x1F01
421 #define GL_VERSION 0x1F02
422 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
423 #define GL_EXTENSIONS 0x1F03
427 strPtr = &tInfo->currentContext->versionString;
430 strPtr = &tInfo->currentContext->vendorString;
433 strPtr = &tInfo->currentContext->rendererString;
435 case GL_SHADING_LANGUAGE_VERSION:
436 strPtr = &tInfo->currentContext->shaderVersionString;
439 strPtr = &tInfo->currentContext->extensionString;
447 if (*strPtr != NULL) {
449 // string is already cached
455 // first query of that string - need to query host
457 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
458 char *hostStr = NULL;
459 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
461 hostStr = new char[-n+1];
462 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
470 // keep the string in the context and return its value
476 // ----------------------------------------------------------------------------
478 // The one and only supported display object.
479 static eglDisplay s_display;
481 static EGLClient_eglInterface s_eglIface = {
482 getThreadInfo: getEGLThreadInfo,
483 getGLString: getGLString
486 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
487 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
490 // we support only EGL_DEFAULT_DISPLAY.
492 if (display_id != EGL_DEFAULT_DISPLAY) {
493 return EGL_NO_DISPLAY;
496 return (EGLDisplay)&s_display;
499 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
501 VALIDATE_DISPLAY(dpy,EGL_FALSE);
503 if (!s_display.initialize(&s_eglIface)) {
507 *major = s_display.getVersionMajor();
509 *minor = s_display.getVersionMinor();
513 EGLBoolean eglTerminate(EGLDisplay dpy)
515 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
517 s_display.terminate();
523 EGLint error = getEGLThreadInfo()->eglError;
524 getEGLThreadInfo()->eglError = EGL_SUCCESS;
528 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
530 // search in EGL function table
531 for (int i=0; i<egl_num_funcs; i++) {
532 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
533 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
537 // look in gles client api's extensions table
538 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
540 // Fail - function not found.
544 const char* eglQueryString(EGLDisplay dpy, EGLint name)
546 VALIDATE_DISPLAY_INIT(dpy, NULL);
548 return s_display.queryString(name);
551 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
553 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
556 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
559 GLint numConfigs = s_display.getNumConfigs();
561 *num_config = numConfigs;
566 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
567 *configs++ = (EGLConfig)(uintptr_t)i;
573 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
575 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
577 int attribs_size = 0;
579 const EGLint * attrib_p = attrib_list;
580 while (attrib_p[0] != EGL_NONE) {
584 attribs_size++; //for the terminating EGL_NONE
587 uint32_t* tempConfigs[config_size];
588 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
589 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
592 for (i=0;i<(*num_config);i++) {
593 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
597 if (*num_config <= 0)
602 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
604 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
605 VALIDATE_CONFIG(config, EGL_FALSE);
607 if (s_display.getConfigAttrib(config, attribute, value))
613 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
617 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
621 VALIDATE_DISPLAY_INIT(dpy, NULL);
622 VALIDATE_CONFIG(config, EGL_FALSE);
624 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
628 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
630 if (!(surfaceType & EGL_WINDOW_BIT)) {
631 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
634 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
635 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
638 egl_surface_t* surface = egl_window_surface_t::create(
639 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
641 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
647 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
649 VALIDATE_DISPLAY_INIT(dpy, NULL);
650 VALIDATE_CONFIG(config, EGL_FALSE);
653 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
655 if (!(surfaceType & EGL_PBUFFER_BIT)) {
656 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
661 EGLint texFormat = EGL_NO_TEXTURE;
662 EGLint texTarget = EGL_NO_TEXTURE;
663 while (attrib_list[0] != EGL_NONE) {
664 switch (attrib_list[0]) {
671 case EGL_TEXTURE_FORMAT:
672 texFormat = attrib_list[1];
674 case EGL_TEXTURE_TARGET:
675 texTarget = attrib_list[1];
682 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
683 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
684 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
686 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
689 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
690 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
692 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
693 EGL_PBUFFER_BIT, w, h, pixelFormat);
695 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
699 surface->setTextureFormat(texFormat);
700 surface->setTextureTarget(texTarget);
705 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
707 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
708 // located on host. In order to support Pixmaps we should either punt
709 // to s/w rendering -or- let the host render to a buffer that will be
710 // copied back to guest at some sync point. None of those methods not
711 // implemented and pixmaps are not used with OpenGL anyway ...
716 return EGL_NO_SURFACE;
719 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
721 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
722 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
724 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
730 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
732 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
733 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
735 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
736 EGLBoolean ret = EGL_TRUE;
739 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
742 *value = surface->getWidth();
745 *value = surface->getHeight();
747 case EGL_TEXTURE_FORMAT:
748 *value = surface->getTextureFormat();
750 case EGL_TEXTURE_TARGET:
751 *value = surface->getTextureTarget();
753 case EGL_SWAP_BEHAVIOR:
754 *value = surface->getSwapBehavior();
756 case EGL_LARGEST_PBUFFER:
757 // not modified for a window or pixmap surface
758 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
759 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
761 case EGL_MIPMAP_LEVEL:
762 // not modified for a window or pixmap surface
763 // and we ignore it when creating a PBuffer surface (default is 0)
764 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
766 case EGL_MULTISAMPLE_RESOLVE:
767 // ignored when creating the surface, return default
768 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
770 //TODO: complete other attributes
772 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
773 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
780 EGLBoolean eglBindAPI(EGLenum api)
782 if (api != EGL_OPENGL_ES_API)
783 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
787 EGLenum eglQueryAPI()
789 return EGL_OPENGL_ES_API;
792 EGLBoolean eglWaitClient()
797 EGLBoolean eglReleaseThread()
799 EGLThreadInfo *tInfo = getEGLThreadInfo();
800 if (tInfo && tInfo->currentContext) {
801 return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
806 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
814 ALOGW("%s not implemented", __FUNCTION__);
818 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
825 ALOGW("%s not implemented", __FUNCTION__);
829 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
831 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
832 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
833 if (eglSurface == EGL_NO_SURFACE) {
834 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
837 if (buffer != EGL_BACK_BUFFER) {
838 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
841 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
843 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
844 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
847 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
848 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
851 //It's now safe to cast to pbuffer surface
852 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
854 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
855 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
860 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
866 ALOGW("%s not implemented", __FUNCTION__);
870 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
872 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
873 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
875 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
877 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
880 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
882 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
883 draw->setSwapInterval(interval);
885 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
890 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
892 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
893 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
895 EGLint version = 1; //default
896 while (attrib_list && attrib_list[0] != EGL_NONE) {
897 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
901 // Currently only support GLES1 and 2
902 if (version != 1 && version != 2) {
903 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
906 uint32_t rcShareCtx = 0;
907 EGLContext_t * shareCtx = NULL;
909 shareCtx = static_cast<EGLContext_t*>(share_context);
910 rcShareCtx = shareCtx->rcContext;
911 if (shareCtx->dpy != dpy)
912 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
915 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
916 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
918 ALOGE("rcCreateContext returned 0");
919 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
922 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
924 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
926 context->version = version;
927 context->rcContext = rcContext;
933 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
935 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
936 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
938 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
940 if (!context) return EGL_TRUE;
942 if (getEGLThreadInfo()->currentContext == context) {
943 getEGLThreadInfo()->currentContext->deletePending = 1;
947 if (context->rcContext) {
948 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
949 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
950 context->rcContext = 0;
957 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
959 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
960 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
961 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
963 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
964 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
965 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
966 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
968 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
969 uint32_t ctxHandle = (context) ? context->rcContext : 0;
970 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
971 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
972 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
973 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
976 // Nothing to do if no binding change has made
978 EGLThreadInfo *tInfo = getEGLThreadInfo();
980 if (tInfo->currentContext == context &&
982 (context && context->draw == draw && context->read == read))) {
986 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
987 if (tInfo->currentContext != context) {
988 EGLContext_t * contextToDelete = tInfo->currentContext;
989 tInfo->currentContext = 0;
990 eglDestroyContext(dpy, contextToDelete);
994 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
995 //context is current to another thread
996 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
999 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1000 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1001 ALOGE("rcMakeCurrent returned EGL_FALSE");
1002 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1005 //Now make the local bind
1007 context->draw = draw;
1008 context->read = read;
1009 context->flags |= EGLContext_t::IS_CURRENT;
1010 //set the client state
1011 if (context->version == 2) {
1012 hostCon->gl2Encoder()->setClientState(context->getClientState());
1013 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1016 hostCon->glEncoder()->setClientState(context->getClientState());
1017 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1020 else if (tInfo->currentContext) {
1021 //release ClientState & SharedGroup
1022 if (tInfo->currentContext->version == 2) {
1023 hostCon->gl2Encoder()->setClientState(NULL);
1024 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1027 hostCon->glEncoder()->setClientState(NULL);
1028 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1033 if (tInfo->currentContext)
1034 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1037 tInfo->currentContext = context;
1039 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1040 if (tInfo->currentContext) {
1041 if (tInfo->currentContext->version == 2) {
1042 if (!hostCon->gl2Encoder()->isInitialized()) {
1043 s_display.gles2_iface()->init();
1044 hostCon->gl2Encoder()->setInitialized();
1045 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1049 if (!hostCon->glEncoder()->isInitialized()) {
1050 s_display.gles_iface()->init();
1051 hostCon->glEncoder()->setInitialized();
1052 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1060 EGLContext eglGetCurrentContext()
1062 return getEGLThreadInfo()->currentContext;
1065 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1067 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1069 return EGL_NO_SURFACE; //not an error
1073 return context->read;
1075 return context->draw;
1077 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1081 EGLDisplay eglGetCurrentDisplay()
1083 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1085 return EGL_NO_DISPLAY; //not an error
1087 return context->dpy;
1090 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1092 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1093 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1095 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1097 EGLBoolean ret = EGL_TRUE;
1098 switch (attribute) {
1100 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1102 case EGL_CONTEXT_CLIENT_TYPE:
1103 *value = EGL_OPENGL_ES_API;
1105 case EGL_CONTEXT_CLIENT_VERSION:
1106 *value = context->version;
1108 case EGL_RENDER_BUFFER:
1112 *value = EGL_BACK_BUFFER; //single buffer not supported
1115 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1116 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1123 EGLBoolean eglWaitGL()
1125 EGLThreadInfo *tInfo = getEGLThreadInfo();
1126 if (!tInfo || !tInfo->currentContext) {
1130 if (tInfo->currentContext->version == 2) {
1131 s_display.gles2_iface()->finish();
1134 s_display.gles_iface()->finish();
1140 EGLBoolean eglWaitNative(EGLint engine)
1146 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1148 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1149 if (eglSurface == EGL_NO_SURFACE)
1150 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1152 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1154 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1156 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1165 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1174 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1183 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1191 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1195 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1197 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1198 if (ctx != EGL_NO_CONTEXT) {
1199 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1202 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1204 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1205 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1207 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1208 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1210 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1212 switch (cb->format) {
1213 case HAL_PIXEL_FORMAT_RGBA_8888:
1214 case HAL_PIXEL_FORMAT_RGBX_8888:
1215 case HAL_PIXEL_FORMAT_RGB_888:
1216 case HAL_PIXEL_FORMAT_RGB_565:
1217 case HAL_PIXEL_FORMAT_BGRA_8888:
1220 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1223 native_buffer->common.incRef(&native_buffer->common);
1225 EGLImage_t *image = new EGLImage_t();
1227 image->target = target;
1228 image->native_buffer = native_buffer;
1230 return (EGLImageKHR)image;
1232 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1233 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1235 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1236 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1238 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1239 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1240 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1241 EGLImage_t *image = new EGLImage_t();
1243 image->target = target;
1244 image->host_egl_image = img;
1246 return (EGLImageKHR)image;
1249 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1252 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1254 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1255 EGLImage_t *image = (EGLImage_t*)img;
1257 if (!image || image->dpy != dpy) {
1258 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1261 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1262 android_native_buffer_t* native_buffer = image->native_buffer;
1264 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1265 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1267 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1268 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1270 native_buffer->common.decRef(&native_buffer->common);
1275 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1276 uint32_t host_egl_image = image->host_egl_image;
1278 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1279 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1282 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1285 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1287 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1288 const EGLint *attrib_list)
1290 // TODO: This implementation could be faster. We should require the host EGL
1291 // to support KHR_fence_sync, or at least pipe the fence command to the host
1292 // and wait for it (probably involving a glFinish on the host) in
1293 // eglClientWaitSyncKHR.
1295 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1297 if (type != EGL_SYNC_FENCE_KHR ||
1298 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1299 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1302 EGLThreadInfo *tInfo = getEGLThreadInfo();
1303 if (!tInfo || !tInfo->currentContext) {
1304 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1307 if (tInfo->currentContext->version == 2) {
1308 s_display.gles2_iface()->finish();
1310 s_display.gles_iface()->finish();
1313 return FENCE_SYNC_HANDLE;
1316 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1320 if (sync != FENCE_SYNC_HANDLE) {
1321 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1327 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1334 if (sync != FENCE_SYNC_HANDLE) {
1335 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1338 return EGL_CONDITION_SATISFIED_KHR;
1341 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1342 EGLint attribute, EGLint *value)
1346 if (sync != FENCE_SYNC_HANDLE) {
1347 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1350 switch (attribute) {
1351 case EGL_SYNC_TYPE_KHR:
1352 *value = EGL_SYNC_FENCE_KHR;
1354 case EGL_SYNC_STATUS_KHR:
1355 *value = EGL_SIGNALED_KHR;
1357 case EGL_SYNC_CONDITION_KHR:
1358 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1361 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);