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"
28 #include "GLEncoder.h"
30 #include "GL2Encoder.h"
33 #include <system/window.h>
36 static T setErrorFunc(GLint error, T returnValue) {
37 getEGLThreadInfo()->eglError = error;
41 const char * eglStrError(EGLint err)
44 case EGL_SUCCESS: return "EGL_SUCCESS";
45 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
46 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
47 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
48 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
49 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
50 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
51 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
52 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
53 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
54 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
55 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
56 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
57 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
58 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
59 default: return "UNKNOWN";
63 #define LOG_EGL_ERRORS 1
67 #define setErrorReturn(error, retVal) \
69 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
70 return setErrorFunc(error, retVal); \
73 #define RETURN_ERROR(ret,err) \
74 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
75 getEGLThreadInfo()->eglError = err; \
78 #else //!LOG_EGL_ERRORS
80 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
82 #define RETURN_ERROR(ret,err) \
83 getEGLThreadInfo()->eglError = err; \
86 #endif //LOG_EGL_ERRORS
88 #define VALIDATE_CONFIG(cfg,ret) \
89 if(((intptr_t)cfg<0)||((intptr_t)cfg>s_display.getNumConfigs())) { \
90 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
93 #define VALIDATE_DISPLAY(dpy,ret) \
94 if ((dpy) != (EGLDisplay)&s_display) { \
95 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
98 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
99 VALIDATE_DISPLAY(dpy, ret) \
100 if (!s_display.initialized()) { \
101 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
104 #define DEFINE_HOST_CONNECTION \
105 HostConnection *hostCon = HostConnection::get(); \
106 renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
108 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
109 HostConnection *hostCon = HostConnection::get(); \
111 ALOGE("egl: Failed to get host connection\n"); \
114 renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
116 ALOGE("egl: Failed to get renderControl encoder context\n"); \
120 #define VALIDATE_CONTEXT_RETURN(context,ret) \
122 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
125 #define VALIDATE_SURFACE_RETURN(surface, ret) \
126 if (surface != EGL_NO_SURFACE) { \
127 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
128 if (s->dpy != (EGLDisplay)&s_display) \
129 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
133 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
136 read(EGL_NO_SURFACE),
137 draw(EGL_NO_SURFACE),
142 rendererString(NULL),
143 shaderVersionString(NULL),
144 extensionString(NULL),
149 clientState = new GLClientState();
151 sharedGroup = shareCtx->getSharedGroup();
153 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
156 EGLContext_t::~EGLContext_t()
159 delete [] versionString;
160 delete [] vendorString;
161 delete [] rendererString;
162 delete [] shaderVersionString;
163 delete [] extensionString;
166 // ----------------------------------------------------------------------------
169 //we don't need to handle depth since it's handled when window created on the host
171 struct egl_surface_t {
177 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
178 virtual ~egl_surface_t();
180 virtual void setSwapInterval(int interval) = 0;
181 virtual EGLBoolean swapBuffers() = 0;
183 EGLint getSwapBehavior() const;
184 uint32_t getRcSurface() { return rcSurface; }
185 EGLint getSurfaceType() { return surfaceType; }
187 EGLint getWidth(){ return width; }
188 EGLint getHeight(){ return height; }
189 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
190 EGLint getTextureFormat() { return texFormat; }
191 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
192 EGLint getTextureTarget() { return texTarget; }
204 void setWidth(EGLint w) { width = w; }
205 void setHeight(EGLint h) { height = h; }
208 uint32_t rcSurface; //handle to surface created via remote control
211 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
212 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
216 texFormat = EGL_NO_TEXTURE;
217 texTarget = EGL_NO_TEXTURE;
220 EGLint egl_surface_t::getSwapBehavior() const {
221 return EGL_BUFFER_PRESERVED;
224 egl_surface_t::~egl_surface_t()
228 // ----------------------------------------------------------------------------
229 // egl_window_surface_t
231 struct egl_window_surface_t : public egl_surface_t {
232 static egl_window_surface_t* create(
233 EGLDisplay dpy, EGLConfig config, EGLint surfType,
234 ANativeWindow* window);
236 virtual ~egl_window_surface_t();
238 virtual void setSwapInterval(int interval);
239 virtual EGLBoolean swapBuffers();
242 egl_window_surface_t(
243 EGLDisplay dpy, EGLConfig config, EGLint surfType,
244 ANativeWindow* window);
247 ANativeWindow* nativeWindow;
248 android_native_buffer_t* buffer;
251 egl_window_surface_t::egl_window_surface_t (
252 EGLDisplay dpy, EGLConfig config, EGLint surfType,
253 ANativeWindow* window)
254 : egl_surface_t(dpy, config, surfType),
255 nativeWindow(window),
258 // keep a reference on the window
259 nativeWindow->common.incRef(&nativeWindow->common);
261 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
263 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
267 EGLBoolean egl_window_surface_t::init()
269 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
270 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
273 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
274 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
275 getWidth(), getHeight());
277 ALOGE("rcCreateWindowSurface returned 0");
280 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
281 ((cb_handle_t*)(buffer->handle))->hostHandle);
286 egl_window_surface_t* egl_window_surface_t::create(
287 EGLDisplay dpy, EGLConfig config, EGLint surfType,
288 ANativeWindow* window)
290 egl_window_surface_t* wnd = new egl_window_surface_t(
291 dpy, config, surfType, window);
292 if (wnd && !wnd->init()) {
299 egl_window_surface_t::~egl_window_surface_t() {
300 DEFINE_HOST_CONNECTION;
301 if (rcSurface && rcEnc) {
302 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
305 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
307 nativeWindow->common.decRef(&nativeWindow->common);
310 void egl_window_surface_t::setSwapInterval(int interval)
312 nativeWindow->setSwapInterval(nativeWindow, interval);
315 EGLBoolean egl_window_surface_t::swapBuffers()
317 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
319 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
321 nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
322 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
324 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
327 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
328 ((cb_handle_t *)(buffer->handle))->hostHandle);
333 // ----------------------------------------------------------------------------
334 //egl_pbuffer_surface_t
336 struct egl_pbuffer_surface_t : public egl_surface_t {
337 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
338 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
340 virtual ~egl_pbuffer_surface_t();
342 virtual void setSwapInterval(int interval) { (void)interval; }
343 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
345 uint32_t getRcColorBuffer() { return rcColorBuffer; }
348 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
349 int32_t w, int32_t h);
350 EGLBoolean init(GLenum format);
352 uint32_t rcColorBuffer;
355 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
356 EGLint surfType, int32_t w, int32_t h)
357 : egl_surface_t(dpy, config, surfType),
364 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
366 DEFINE_HOST_CONNECTION;
368 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
369 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
373 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
375 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
377 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
378 getWidth(), getHeight());
380 ALOGE("rcCreateWindowSurface returned 0");
384 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
386 if (!rcColorBuffer) {
387 ALOGE("rcCreateColorBuffer returned 0");
391 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
396 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
397 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
400 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
402 if (pb && !pb->init(pixelFormat)) {
409 static const char *getGLString(int glEnum)
411 EGLThreadInfo *tInfo = getEGLThreadInfo();
412 if (!tInfo || !tInfo->currentContext) {
416 const char** strPtr = NULL;
418 #define GL_VENDOR 0x1F00
419 #define GL_RENDERER 0x1F01
420 #define GL_VERSION 0x1F02
421 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
422 #define GL_EXTENSIONS 0x1F03
426 strPtr = &tInfo->currentContext->versionString;
429 strPtr = &tInfo->currentContext->vendorString;
432 strPtr = &tInfo->currentContext->rendererString;
434 case GL_SHADING_LANGUAGE_VERSION:
435 strPtr = &tInfo->currentContext->shaderVersionString;
438 strPtr = &tInfo->currentContext->extensionString;
446 if (*strPtr != NULL) {
448 // string is already cached
454 // first query of that string - need to query host
456 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
457 char *hostStr = NULL;
458 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
460 hostStr = new char[-n+1];
461 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
469 // keep the string in the context and return its value
475 // ----------------------------------------------------------------------------
477 // The one and only supported display object.
478 static eglDisplay s_display;
480 static EGLClient_eglInterface s_eglIface = {
481 getThreadInfo: getEGLThreadInfo,
482 getGLString: getGLString
485 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
486 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
489 // we support only EGL_DEFAULT_DISPLAY.
491 if (display_id != EGL_DEFAULT_DISPLAY) {
492 return EGL_NO_DISPLAY;
495 return (EGLDisplay)&s_display;
498 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
500 VALIDATE_DISPLAY(dpy,EGL_FALSE);
502 if (!s_display.initialize(&s_eglIface)) {
506 *major = s_display.getVersionMajor();
508 *minor = s_display.getVersionMinor();
512 EGLBoolean eglTerminate(EGLDisplay dpy)
514 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
516 s_display.terminate();
522 EGLint error = getEGLThreadInfo()->eglError;
523 getEGLThreadInfo()->eglError = EGL_SUCCESS;
527 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
529 // search in EGL function table
530 for (int i=0; i<egl_num_funcs; i++) {
531 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
532 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
536 // look in gles client api's extensions table
537 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
539 // Fail - function not found.
543 const char* eglQueryString(EGLDisplay dpy, EGLint name)
545 VALIDATE_DISPLAY_INIT(dpy, NULL);
547 return s_display.queryString(name);
550 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
552 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
555 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
558 GLint numConfigs = s_display.getNumConfigs();
560 *num_config = numConfigs;
565 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
566 *configs++ = (EGLConfig)(uintptr_t)i;
572 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
574 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
576 int attribs_size = 0;
578 const EGLint * attrib_p = attrib_list;
579 while (attrib_p[0] != EGL_NONE) {
583 attribs_size++; //for the terminating EGL_NONE
586 uint32_t* tempConfigs[config_size];
587 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
588 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
591 for (i=0;i<(*num_config);i++) {
592 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
596 if (*num_config <= 0)
601 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
603 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
604 VALIDATE_CONFIG(config, EGL_FALSE);
606 if (s_display.getConfigAttrib(config, attribute, value))
612 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
616 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
620 VALIDATE_DISPLAY_INIT(dpy, NULL);
621 VALIDATE_CONFIG(config, EGL_FALSE);
623 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
627 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
629 if (!(surfaceType & EGL_WINDOW_BIT)) {
630 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
633 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
634 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
637 egl_surface_t* surface = egl_window_surface_t::create(
638 &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
640 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
646 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
648 VALIDATE_DISPLAY_INIT(dpy, NULL);
649 VALIDATE_CONFIG(config, EGL_FALSE);
652 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
654 if (!(surfaceType & EGL_PBUFFER_BIT)) {
655 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
660 EGLint texFormat = EGL_NO_TEXTURE;
661 EGLint texTarget = EGL_NO_TEXTURE;
662 while (attrib_list[0]) {
663 switch (attrib_list[0]) {
670 case EGL_TEXTURE_FORMAT:
671 texFormat = attrib_list[1];
673 case EGL_TEXTURE_TARGET:
674 texTarget = attrib_list[1];
681 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
682 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
683 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
685 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
688 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
689 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
691 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
692 surfaceType, w, h, pixelFormat);
694 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
698 surface->setTextureFormat(texFormat);
699 surface->setTextureTarget(texTarget);
704 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
706 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
707 // located on host. In order to support Pixmaps we should either punt
708 // to s/w rendering -or- let the host render to a buffer that will be
709 // copied back to guest at some sync point. None of those methods not
710 // implemented and pixmaps are not used with OpenGL anyway ...
715 return EGL_NO_SURFACE;
718 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
720 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
721 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
723 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
729 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
731 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
732 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
734 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
735 EGLBoolean ret = EGL_TRUE;
738 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
741 *value = surface->getWidth();
744 *value = surface->getHeight();
746 case EGL_TEXTURE_FORMAT:
747 *value = surface->getTextureFormat();
749 case EGL_TEXTURE_TARGET:
750 *value = surface->getTextureTarget();
752 case EGL_SWAP_BEHAVIOR:
753 *value = surface->getSwapBehavior();
755 case EGL_LARGEST_PBUFFER:
756 // not modified for a window or pixmap surface
757 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
758 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
760 //TODO: complete other attributes
762 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
763 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
770 EGLBoolean eglBindAPI(EGLenum api)
772 if (api != EGL_OPENGL_ES_API)
773 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
777 EGLenum eglQueryAPI()
779 return EGL_OPENGL_ES_API;
782 EGLBoolean eglWaitClient()
787 EGLBoolean eglReleaseThread()
789 EGLThreadInfo *tInfo = getEGLThreadInfo();
790 if (tInfo && tInfo->currentContext) {
791 return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
796 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
804 ALOGW("%s not implemented", __FUNCTION__);
808 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
815 ALOGW("%s not implemented", __FUNCTION__);
819 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
821 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
822 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
823 if (eglSurface == EGL_NO_SURFACE) {
824 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
827 if (buffer != EGL_BACK_BUFFER) {
828 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
831 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
833 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
834 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
837 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
838 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
841 //It's now safe to cast to pbuffer surface
842 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
844 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
845 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
850 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
856 ALOGW("%s not implemented", __FUNCTION__);
860 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
862 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
863 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
865 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
867 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
870 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
872 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
873 draw->setSwapInterval(interval);
875 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
880 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
882 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
883 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
885 EGLint version = 1; //default
886 while (attrib_list && attrib_list[0]) {
887 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
891 uint32_t rcShareCtx = 0;
892 EGLContext_t * shareCtx = NULL;
894 shareCtx = static_cast<EGLContext_t*>(share_context);
895 rcShareCtx = shareCtx->rcContext;
896 if (shareCtx->dpy != dpy)
897 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
900 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
901 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
903 ALOGE("rcCreateContext returned 0");
904 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
907 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
909 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
911 context->version = version;
912 context->rcContext = rcContext;
918 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
920 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
921 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
923 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
925 if (!context) return EGL_TRUE;
927 if (getEGLThreadInfo()->currentContext == context) {
928 getEGLThreadInfo()->currentContext->deletePending = 1;
932 if (context->rcContext) {
933 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
934 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
935 context->rcContext = 0;
942 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
944 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
945 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
946 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
948 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
949 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
950 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
951 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
953 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
954 uint32_t ctxHandle = (context) ? context->rcContext : 0;
955 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
956 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
957 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
958 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
961 // Nothing to do if no binding change has made
963 EGLThreadInfo *tInfo = getEGLThreadInfo();
965 if (tInfo->currentContext == context &&
967 (context && context->draw == draw && context->read == read))) {
971 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
972 if (tInfo->currentContext != context) {
973 EGLContext_t * contextToDelete = tInfo->currentContext;
974 tInfo->currentContext = 0;
975 eglDestroyContext(dpy, contextToDelete);
979 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
980 //context is current to another thread
981 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
984 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
985 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
986 ALOGE("rcMakeCurrent returned EGL_FALSE");
987 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
990 //Now make the local bind
992 context->draw = draw;
993 context->read = read;
994 context->flags |= EGLContext_t::IS_CURRENT;
995 //set the client state
996 if (context->version == 2) {
997 hostCon->gl2Encoder()->setClientState(context->getClientState());
998 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1001 hostCon->glEncoder()->setClientState(context->getClientState());
1002 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1005 else if (tInfo->currentContext) {
1006 //release ClientState & SharedGroup
1007 if (tInfo->currentContext->version == 2) {
1008 hostCon->gl2Encoder()->setClientState(NULL);
1009 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1012 hostCon->glEncoder()->setClientState(NULL);
1013 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1018 if (tInfo->currentContext)
1019 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1022 tInfo->currentContext = context;
1024 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1025 if (tInfo->currentContext) {
1026 if (tInfo->currentContext->version == 2) {
1027 if (!hostCon->gl2Encoder()->isInitialized()) {
1028 s_display.gles2_iface()->init();
1029 hostCon->gl2Encoder()->setInitialized();
1030 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1034 if (!hostCon->glEncoder()->isInitialized()) {
1035 s_display.gles_iface()->init();
1036 hostCon->glEncoder()->setInitialized();
1037 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1045 EGLContext eglGetCurrentContext()
1047 return getEGLThreadInfo()->currentContext;
1050 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1052 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1054 return EGL_NO_SURFACE; //not an error
1058 return context->read;
1060 return context->draw;
1062 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1066 EGLDisplay eglGetCurrentDisplay()
1068 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1070 return EGL_NO_DISPLAY; //not an error
1072 return context->dpy;
1075 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1077 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1078 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1080 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1082 EGLBoolean ret = EGL_TRUE;
1083 switch (attribute) {
1085 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1087 case EGL_CONTEXT_CLIENT_TYPE:
1088 *value = EGL_OPENGL_ES_API;
1090 case EGL_CONTEXT_CLIENT_VERSION:
1091 *value = context->version;
1093 case EGL_RENDER_BUFFER:
1097 *value = EGL_BACK_BUFFER; //single buffer not supported
1100 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1101 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1108 EGLBoolean eglWaitGL()
1110 EGLThreadInfo *tInfo = getEGLThreadInfo();
1111 if (!tInfo || !tInfo->currentContext) {
1115 if (tInfo->currentContext->version == 2) {
1116 s_display.gles2_iface()->finish();
1119 s_display.gles_iface()->finish();
1125 EGLBoolean eglWaitNative(EGLint engine)
1131 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1133 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1134 if (eglSurface == EGL_NO_SURFACE)
1135 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1137 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1139 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1141 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1150 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1159 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1168 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1176 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1180 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1181 if (ctx != EGL_NO_CONTEXT) {
1182 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1184 if (target != EGL_NATIVE_BUFFER_ANDROID) {
1185 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1188 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1190 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1191 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1193 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1194 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1196 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1198 switch (cb->format) {
1199 case HAL_PIXEL_FORMAT_RGBA_8888:
1200 case HAL_PIXEL_FORMAT_RGBX_8888:
1201 case HAL_PIXEL_FORMAT_RGB_888:
1202 case HAL_PIXEL_FORMAT_RGB_565:
1203 case HAL_PIXEL_FORMAT_BGRA_8888:
1206 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1209 native_buffer->common.incRef(&native_buffer->common);
1210 return (EGLImageKHR)native_buffer;
1213 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1215 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1216 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
1218 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1219 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1221 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1222 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1224 native_buffer->common.decRef(&native_buffer->common);
1229 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1231 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1232 const EGLint *attrib_list)
1234 // TODO: This implementation could be faster. We should require the host EGL
1235 // to support KHR_fence_sync, or at least pipe the fence command to the host
1236 // and wait for it (probably involving a glFinish on the host) in
1237 // eglClientWaitSyncKHR.
1239 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1241 if (type != EGL_SYNC_FENCE_KHR ||
1242 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1243 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1246 EGLThreadInfo *tInfo = getEGLThreadInfo();
1247 if (!tInfo || !tInfo->currentContext) {
1248 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1251 if (tInfo->currentContext->version == 2) {
1252 s_display.gles2_iface()->finish();
1254 s_display.gles_iface()->finish();
1257 return FENCE_SYNC_HANDLE;
1260 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1264 if (sync != FENCE_SYNC_HANDLE) {
1265 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1271 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1278 if (sync != FENCE_SYNC_HANDLE) {
1279 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1282 return EGL_CONDITION_SATISFIED_KHR;
1285 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1286 EGLint attribute, EGLint *value)
1290 if (sync != FENCE_SYNC_HANDLE) {
1291 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1294 switch (attribute) {
1295 case EGL_SYNC_TYPE_KHR:
1296 *value = EGL_SYNC_FENCE_KHR;
1298 case EGL_SYNC_STATUS_KHR:
1299 *value = EGL_SIGNALED_KHR;
1301 case EGL_SYNC_CONDITION_KHR:
1302 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1305 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);