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 #include <system/window.h>
38 static T setErrorFunc(GLint error, T returnValue) {
39 getEGLThreadInfo()->eglError = error;
43 const char * eglStrError(EGLint err)
46 case EGL_SUCCESS: return "EGL_SUCCESS";
47 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
48 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
49 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
50 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
51 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
52 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
53 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
54 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
55 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
56 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
57 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
58 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
59 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
60 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
61 default: return "UNKNOWN";
65 #define LOG_EGL_ERRORS 1
69 #define setErrorReturn(error, retVal) \
71 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
72 return setErrorFunc(error, retVal); \
75 #define RETURN_ERROR(ret,err) \
76 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
77 getEGLThreadInfo()->eglError = err; \
80 #else //!LOG_EGL_ERRORS
82 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
84 #define RETURN_ERROR(ret,err) \
85 getEGLThreadInfo()->eglError = err; \
88 #endif //LOG_EGL_ERRORS
90 #define VALIDATE_CONFIG(cfg,ret) \
91 if(((intptr_t)cfg<0)||((intptr_t)cfg>s_display.getNumConfigs())) { \
92 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
95 #define VALIDATE_DISPLAY(dpy,ret) \
96 if ((dpy) != (EGLDisplay)&s_display) { \
97 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
100 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
101 VALIDATE_DISPLAY(dpy, ret) \
102 if (!s_display.initialized()) { \
103 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
106 #define DEFINE_HOST_CONNECTION \
107 HostConnection *hostCon = HostConnection::get(); \
108 renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
110 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
111 HostConnection *hostCon = HostConnection::get(); \
113 ALOGE("egl: Failed to get host connection\n"); \
116 renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
118 ALOGE("egl: Failed to get renderControl encoder context\n"); \
122 #define VALIDATE_CONTEXT_RETURN(context,ret) \
124 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
127 #define VALIDATE_SURFACE_RETURN(surface, ret) \
128 if (surface != EGL_NO_SURFACE) { \
129 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
130 if (s->dpy != (EGLDisplay)&s_display) \
131 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
134 // The one and only supported display object.
135 static eglDisplay s_display;
137 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
140 read(EGL_NO_SURFACE),
141 draw(EGL_NO_SURFACE),
146 rendererString(NULL),
147 shaderVersionString(NULL),
148 extensionString(NULL),
153 clientState = new GLClientState();
155 sharedGroup = shareCtx->getSharedGroup();
157 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
158 assert(dpy == (EGLDisplay)&s_display);
159 s_display.onCreateContext((EGLContext)this);
162 EGLContext_t::~EGLContext_t()
164 assert(dpy == (EGLDisplay)&s_display);
165 s_display.onDestroyContext((EGLContext)this);
167 delete [] versionString;
168 delete [] vendorString;
169 delete [] rendererString;
170 delete [] shaderVersionString;
171 delete [] extensionString;
174 // ----------------------------------------------------------------------------
177 //we don't need to handle depth since it's handled when window created on the host
179 struct egl_surface_t {
185 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
186 virtual ~egl_surface_t();
188 virtual void setSwapInterval(int interval) = 0;
189 virtual EGLBoolean swapBuffers() = 0;
191 EGLint getSwapBehavior() const;
192 uint32_t getRcSurface() { return rcSurface; }
193 EGLint getSurfaceType() { return surfaceType; }
195 EGLint getWidth(){ return width; }
196 EGLint getHeight(){ return height; }
197 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
198 EGLint getTextureFormat() { return texFormat; }
199 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
200 EGLint getTextureTarget() { return texTarget; }
212 void setWidth(EGLint w) { width = w; }
213 void setHeight(EGLint h) { height = h; }
216 uint32_t rcSurface; //handle to surface created via remote control
219 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
220 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
224 texFormat = EGL_NO_TEXTURE;
225 texTarget = EGL_NO_TEXTURE;
226 assert(dpy == (EGLDisplay)&s_display);
227 s_display.onCreateSurface((EGLSurface)this);
230 EGLint egl_surface_t::getSwapBehavior() const {
231 return EGL_BUFFER_PRESERVED;
234 egl_surface_t::~egl_surface_t()
236 assert(dpy == (EGLDisplay)&s_display);
237 s_display.onDestroySurface((EGLSurface)this);
240 // ----------------------------------------------------------------------------
241 // egl_window_surface_t
243 struct egl_window_surface_t : public egl_surface_t {
244 static egl_window_surface_t* create(
245 EGLDisplay dpy, EGLConfig config, EGLint surfType,
246 ANativeWindow* window);
248 virtual ~egl_window_surface_t();
250 virtual void setSwapInterval(int interval);
251 virtual EGLBoolean swapBuffers();
254 egl_window_surface_t(
255 EGLDisplay dpy, EGLConfig config, EGLint surfType,
256 ANativeWindow* window);
259 ANativeWindow* nativeWindow;
260 android_native_buffer_t* buffer;
263 egl_window_surface_t::egl_window_surface_t (
264 EGLDisplay dpy, EGLConfig config, EGLint surfType,
265 ANativeWindow* window)
266 : egl_surface_t(dpy, config, surfType),
267 nativeWindow(window),
270 // keep a reference on the window
271 nativeWindow->common.incRef(&nativeWindow->common);
274 EGLBoolean egl_window_surface_t::init()
276 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
277 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
279 setWidth(buffer->width);
280 setHeight(buffer->height);
282 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
283 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
284 getWidth(), getHeight());
286 ALOGE("rcCreateWindowSurface returned 0");
289 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
290 ((cb_handle_t*)(buffer->handle))->hostHandle);
295 egl_window_surface_t* egl_window_surface_t::create(
296 EGLDisplay dpy, EGLConfig config, EGLint surfType,
297 ANativeWindow* window)
299 egl_window_surface_t* wnd = new egl_window_surface_t(
300 dpy, config, surfType, window);
301 if (wnd && !wnd->init()) {
308 egl_window_surface_t::~egl_window_surface_t() {
309 DEFINE_HOST_CONNECTION;
310 if (rcSurface && rcEnc) {
311 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
314 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
316 nativeWindow->common.decRef(&nativeWindow->common);
319 void egl_window_surface_t::setSwapInterval(int interval)
321 nativeWindow->setSwapInterval(nativeWindow, interval);
324 EGLBoolean egl_window_surface_t::swapBuffers()
326 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
328 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
330 nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
331 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
333 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
336 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
337 ((cb_handle_t *)(buffer->handle))->hostHandle);
339 setWidth(buffer->width);
340 setHeight(buffer->height);
345 // ----------------------------------------------------------------------------
346 //egl_pbuffer_surface_t
348 struct egl_pbuffer_surface_t : public egl_surface_t {
349 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
350 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
352 virtual ~egl_pbuffer_surface_t();
354 virtual void setSwapInterval(int interval) { (void)interval; }
355 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
357 uint32_t getRcColorBuffer() { return rcColorBuffer; }
360 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
361 int32_t w, int32_t h);
362 EGLBoolean init(GLenum format);
364 uint32_t rcColorBuffer;
367 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
368 EGLint surfType, int32_t w, int32_t h)
369 : egl_surface_t(dpy, config, surfType),
376 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
378 DEFINE_HOST_CONNECTION;
380 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
381 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
385 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
387 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
389 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
390 getWidth(), getHeight());
392 ALOGE("rcCreateWindowSurface returned 0");
396 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
398 if (!rcColorBuffer) {
399 ALOGE("rcCreateColorBuffer returned 0");
403 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
408 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
409 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
412 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
414 if (pb && !pb->init(pixelFormat)) {
421 static const char *getGLString(int glEnum)
423 EGLThreadInfo *tInfo = getEGLThreadInfo();
424 if (!tInfo || !tInfo->currentContext) {
428 const char** strPtr = NULL;
430 #define GL_VENDOR 0x1F00
431 #define GL_RENDERER 0x1F01
432 #define GL_VERSION 0x1F02
433 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
434 #define GL_EXTENSIONS 0x1F03
438 strPtr = &tInfo->currentContext->versionString;
441 strPtr = &tInfo->currentContext->vendorString;
444 strPtr = &tInfo->currentContext->rendererString;
446 case GL_SHADING_LANGUAGE_VERSION:
447 strPtr = &tInfo->currentContext->shaderVersionString;
450 strPtr = &tInfo->currentContext->extensionString;
458 if (*strPtr != NULL) {
460 // string is already cached
466 // first query of that string - need to query host
468 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
469 char *hostStr = NULL;
470 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
472 hostStr = new char[-n+1];
473 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
481 // keep the string in the context and return its value
487 // ----------------------------------------------------------------------------
489 static EGLClient_eglInterface s_eglIface = {
490 getThreadInfo: getEGLThreadInfo,
491 getGLString: getGLString
494 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
495 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
498 // we support only EGL_DEFAULT_DISPLAY.
500 if (display_id != EGL_DEFAULT_DISPLAY) {
501 return EGL_NO_DISPLAY;
504 return (EGLDisplay)&s_display;
507 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
509 VALIDATE_DISPLAY(dpy,EGL_FALSE);
511 if (!s_display.initialize(&s_eglIface)) {
515 *major = s_display.getVersionMajor();
517 *minor = s_display.getVersionMinor();
521 EGLBoolean eglTerminate(EGLDisplay dpy)
523 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
525 s_display.terminate();
531 EGLint error = getEGLThreadInfo()->eglError;
532 getEGLThreadInfo()->eglError = EGL_SUCCESS;
536 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
538 // search in EGL function table
539 for (int i=0; i<egl_num_funcs; i++) {
540 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
541 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
545 // look in gles client api's extensions table
546 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
548 // Fail - function not found.
552 const char* eglQueryString(EGLDisplay dpy, EGLint name)
554 VALIDATE_DISPLAY_INIT(dpy, NULL);
556 return s_display.queryString(name);
559 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
561 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
564 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
567 GLint numConfigs = s_display.getNumConfigs();
569 *num_config = numConfigs;
574 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
575 *configs++ = (EGLConfig)(uintptr_t)i;
581 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
583 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
585 int attribs_size = 0;
587 const EGLint * attrib_p = attrib_list;
588 while (attrib_p[0] != EGL_NONE) {
592 attribs_size++; //for the terminating EGL_NONE
595 uint32_t* tempConfigs[config_size];
596 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
597 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
600 for (i=0;i<(*num_config);i++) {
601 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
605 if (*num_config <= 0)
610 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
612 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
613 VALIDATE_CONFIG(config, EGL_FALSE);
615 if (s_display.getConfigAttrib(config, attribute, value))
621 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
625 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
629 VALIDATE_DISPLAY_INIT(dpy, NULL);
630 VALIDATE_CONFIG(config, EGL_FALSE);
632 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
636 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
638 if (!(surfaceType & EGL_WINDOW_BIT)) {
639 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
642 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
643 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
646 egl_surface_t* surface = egl_window_surface_t::create(
647 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
649 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
655 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
657 VALIDATE_DISPLAY_INIT(dpy, NULL);
658 VALIDATE_CONFIG(config, EGL_FALSE);
661 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
663 if (!(surfaceType & EGL_PBUFFER_BIT)) {
664 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
669 EGLint texFormat = EGL_NO_TEXTURE;
670 EGLint texTarget = EGL_NO_TEXTURE;
671 while (attrib_list[0] != EGL_NONE) {
672 switch (attrib_list[0]) {
679 case EGL_TEXTURE_FORMAT:
680 texFormat = attrib_list[1];
682 case EGL_TEXTURE_TARGET:
683 texTarget = attrib_list[1];
690 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
691 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
692 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
694 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
697 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
698 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
700 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
701 EGL_PBUFFER_BIT, w, h, pixelFormat);
703 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
707 surface->setTextureFormat(texFormat);
708 surface->setTextureTarget(texTarget);
713 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
715 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
716 // located on host. In order to support Pixmaps we should either punt
717 // to s/w rendering -or- let the host render to a buffer that will be
718 // copied back to guest at some sync point. None of those methods not
719 // implemented and pixmaps are not used with OpenGL anyway ...
724 return EGL_NO_SURFACE;
727 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
729 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
730 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
732 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
738 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
740 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
741 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
743 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
744 EGLBoolean ret = EGL_TRUE;
747 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
750 *value = surface->getWidth();
753 *value = surface->getHeight();
755 case EGL_TEXTURE_FORMAT:
756 *value = surface->getTextureFormat();
758 case EGL_TEXTURE_TARGET:
759 *value = surface->getTextureTarget();
761 case EGL_SWAP_BEHAVIOR:
762 *value = surface->getSwapBehavior();
764 case EGL_LARGEST_PBUFFER:
765 // not modified for a window or pixmap surface
766 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
767 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
769 case EGL_MIPMAP_LEVEL:
770 // not modified for a window or pixmap surface
771 // and we ignore it when creating a PBuffer surface (default is 0)
772 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
774 case EGL_MULTISAMPLE_RESOLVE:
775 // ignored when creating the surface, return default
776 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
778 //TODO: complete other attributes
780 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
781 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
788 EGLBoolean eglBindAPI(EGLenum api)
790 if (api != EGL_OPENGL_ES_API)
791 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
795 EGLenum eglQueryAPI()
797 return EGL_OPENGL_ES_API;
800 EGLBoolean eglWaitClient()
805 EGLBoolean eglReleaseThread()
807 EGLThreadInfo *tInfo = getEGLThreadInfo();
809 tInfo->eglError = EGL_SUCCESS;
810 EGLContext_t* context = tInfo->currentContext;
812 // The following code is doing pretty much the same thing as
813 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
814 // with the only issue that we do not require a valid display here.
815 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
816 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
817 if (context->version == 2) {
818 hostCon->gl2Encoder()->setClientState(NULL);
819 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
822 hostCon->glEncoder()->setClientState(NULL);
823 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
825 context->flags &= ~EGLContext_t::IS_CURRENT;
827 if (context->deletePending) {
828 if (context->rcContext) {
829 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
830 context->rcContext = 0;
834 tInfo->currentContext = 0;
840 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
848 ALOGW("%s not implemented", __FUNCTION__);
852 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
854 // Right now we don't do anything when using host GPU.
855 // This is purely just to pass the data through
856 // without issuing a warning. We may benefit from validating the
857 // display and surface for debug purposes.
858 // TODO: Find cases where we actually need to do something.
859 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
860 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
861 if (surface == EGL_NO_SURFACE) {
862 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
868 case EGL_MIPMAP_LEVEL:
869 case EGL_MULTISAMPLE_RESOLVE:
870 case EGL_SWAP_BEHAVIOR:
874 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
879 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
881 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
882 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
883 if (eglSurface == EGL_NO_SURFACE) {
884 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
887 if (buffer != EGL_BACK_BUFFER) {
888 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
891 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
893 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
894 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
897 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
898 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
901 //It's now safe to cast to pbuffer surface
902 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
904 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
905 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
910 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
916 ALOGW("%s not implemented", __FUNCTION__);
920 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
922 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
923 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
925 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
927 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
930 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
932 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
933 draw->setSwapInterval(interval);
935 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
940 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
942 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
943 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
945 EGLint version = 1; //default
946 while (attrib_list && attrib_list[0] != EGL_NONE) {
947 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
948 version = attrib_list[1];
949 } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
950 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
955 // Currently only support GLES1 and 2
956 if (version != 1 && version != 2) {
957 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
960 uint32_t rcShareCtx = 0;
961 EGLContext_t * shareCtx = NULL;
963 shareCtx = static_cast<EGLContext_t*>(share_context);
964 rcShareCtx = shareCtx->rcContext;
965 if (shareCtx->dpy != dpy)
966 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
969 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
970 // We've created EGL context. Disconnecting
971 // would be dangerous at this point.
972 hostCon->setGrallocOnly(false);
974 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
976 ALOGE("rcCreateContext returned 0");
977 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
980 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
982 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
984 context->version = version;
985 context->rcContext = rcContext;
991 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
993 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
994 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
996 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
998 if (!context) return EGL_TRUE;
1000 if (getEGLThreadInfo()->currentContext == context) {
1001 getEGLThreadInfo()->currentContext->deletePending = 1;
1005 if (context->rcContext) {
1006 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1007 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1008 context->rcContext = 0;
1015 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1017 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1018 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1019 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1021 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1022 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1023 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1024 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1026 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1027 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1028 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1029 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1030 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1031 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1034 // Nothing to do if no binding change has made
1036 EGLThreadInfo *tInfo = getEGLThreadInfo();
1038 if (tInfo->currentContext == context &&
1040 (context && context->draw == draw && context->read == read))) {
1044 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1045 if (tInfo->currentContext != context) {
1046 EGLContext_t * contextToDelete = tInfo->currentContext;
1047 tInfo->currentContext = 0;
1048 eglDestroyContext(dpy, contextToDelete);
1052 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1053 //context is current to another thread
1054 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1057 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1058 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1059 ALOGE("rcMakeCurrent returned EGL_FALSE");
1060 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1063 //Now make the local bind
1065 // This is a nontrivial context.
1066 // The thread cannot be gralloc-only anymore.
1067 hostCon->setGrallocOnly(false);
1068 context->draw = draw;
1069 context->read = read;
1070 context->flags |= EGLContext_t::IS_CURRENT;
1071 //set the client state
1072 if (context->version == 2) {
1073 hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1074 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1077 hostCon->glEncoder()->setClientState(context->getClientState());
1078 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1081 else if (tInfo->currentContext) {
1082 //release ClientState & SharedGroup
1083 if (tInfo->currentContext->version == 2) {
1084 hostCon->gl2Encoder()->setClientState(NULL);
1085 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1088 hostCon->glEncoder()->setClientState(NULL);
1089 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1094 if (tInfo->currentContext)
1095 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1098 tInfo->currentContext = context;
1100 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1101 if (tInfo->currentContext) {
1102 if (tInfo->currentContext->version == 2) {
1103 if (!hostCon->gl2Encoder()->isInitialized()) {
1104 s_display.gles2_iface()->init();
1105 hostCon->gl2Encoder()->setInitialized();
1106 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1110 if (!hostCon->glEncoder()->isInitialized()) {
1111 s_display.gles_iface()->init();
1112 hostCon->glEncoder()->setInitialized();
1113 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1121 EGLContext eglGetCurrentContext()
1123 return getEGLThreadInfo()->currentContext;
1126 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1128 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1130 return EGL_NO_SURFACE; //not an error
1134 return context->read;
1136 return context->draw;
1138 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1142 EGLDisplay eglGetCurrentDisplay()
1144 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1146 return EGL_NO_DISPLAY; //not an error
1148 return context->dpy;
1151 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1153 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1154 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1156 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1158 EGLBoolean ret = EGL_TRUE;
1159 switch (attribute) {
1161 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1163 case EGL_CONTEXT_CLIENT_TYPE:
1164 *value = EGL_OPENGL_ES_API;
1166 case EGL_CONTEXT_CLIENT_VERSION:
1167 *value = context->version;
1169 case EGL_RENDER_BUFFER:
1173 *value = EGL_BACK_BUFFER; //single buffer not supported
1176 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1177 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1184 EGLBoolean eglWaitGL()
1186 EGLThreadInfo *tInfo = getEGLThreadInfo();
1187 if (!tInfo || !tInfo->currentContext) {
1191 if (tInfo->currentContext->version == 2) {
1192 s_display.gles2_iface()->finish();
1195 s_display.gles_iface()->finish();
1201 EGLBoolean eglWaitNative(EGLint engine)
1207 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1209 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1210 if (eglSurface == EGL_NO_SURFACE)
1211 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1213 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1215 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1217 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1226 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1235 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1244 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1252 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1256 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1258 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1259 if (ctx != EGL_NO_CONTEXT) {
1260 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1263 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1265 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1266 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1268 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1269 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1271 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1273 switch (cb->format) {
1274 case HAL_PIXEL_FORMAT_RGBA_8888:
1275 case HAL_PIXEL_FORMAT_RGBX_8888:
1276 case HAL_PIXEL_FORMAT_RGB_888:
1277 case HAL_PIXEL_FORMAT_RGB_565:
1278 case HAL_PIXEL_FORMAT_BGRA_8888:
1281 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1284 native_buffer->common.incRef(&native_buffer->common);
1286 EGLImage_t *image = new EGLImage_t();
1288 image->target = target;
1289 image->native_buffer = native_buffer;
1291 return (EGLImageKHR)image;
1293 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1294 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1296 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1297 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1299 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1300 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1301 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1302 EGLImage_t *image = new EGLImage_t();
1304 image->target = target;
1305 image->host_egl_image = img;
1307 return (EGLImageKHR)image;
1310 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1313 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1315 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1316 EGLImage_t *image = (EGLImage_t*)img;
1318 if (!image || image->dpy != dpy) {
1319 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1322 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1323 android_native_buffer_t* native_buffer = image->native_buffer;
1325 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1326 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1328 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1329 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1331 native_buffer->common.decRef(&native_buffer->common);
1336 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1337 uint32_t host_egl_image = image->host_egl_image;
1339 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1340 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1343 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1346 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1348 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1349 const EGLint *attrib_list)
1351 // TODO: This implementation could be faster. We should require the host EGL
1352 // to support KHR_fence_sync, or at least pipe the fence command to the host
1353 // and wait for it (probably involving a glFinish on the host) in
1354 // eglClientWaitSyncKHR.
1356 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1358 if (type != EGL_SYNC_FENCE_KHR ||
1359 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1360 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1363 EGLThreadInfo *tInfo = getEGLThreadInfo();
1364 if (!tInfo || !tInfo->currentContext) {
1365 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1368 if (tInfo->currentContext->version == 2) {
1369 s_display.gles2_iface()->finish();
1371 s_display.gles_iface()->finish();
1374 return FENCE_SYNC_HANDLE;
1377 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1381 if (sync != FENCE_SYNC_HANDLE) {
1382 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1388 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1395 if (sync != FENCE_SYNC_HANDLE) {
1396 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1399 return EGL_CONDITION_SATISFIED_KHR;
1402 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1403 EGLint attribute, EGLint *value)
1407 if (sync != FENCE_SYNC_HANDLE) {
1408 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1411 switch (attribute) {
1412 case EGL_SYNC_TYPE_KHR:
1413 *value = EGL_SYNC_FENCE_KHR;
1415 case EGL_SYNC_STATUS_KHR:
1416 *value = EGL_SIGNALED_KHR;
1418 case EGL_SYNC_CONDITION_KHR:
1419 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1422 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);