summaryrefslogtreecommitdiffstats
path: root/opengl/system/egl
diff options
context:
space:
mode:
authorkeunyoung <keunyoung@google.com>2013-03-08 12:28:03 -0800
committerkeunyoung <keunyoung@google.com>2013-03-11 10:57:27 -0700
commit8a94683196406b83b14218d1beef66067f126a16 (patch)
treea4b534173fee983175f175d611eb0840d0a4ff59 /opengl/system/egl
parenta76102f225ebb6b00b0d3f84624a285e0f8df773 (diff)
downloadandroid_device_generic_goldfish-8a94683196406b83b14218d1beef66067f126a16.tar.gz
android_device_generic_goldfish-8a94683196406b83b14218d1beef66067f126a16.tar.bz2
android_device_generic_goldfish-8a94683196406b83b14218d1beef66067f126a16.zip
migrate opengl and system from development/tools
- components under system are moved one directory up like all other HALs Change-Id: I03b870b870d83b247ac398cadfb155f03c9adfa0
Diffstat (limited to 'opengl/system/egl')
-rw-r--r--opengl/system/egl/Android.mk41
-rw-r--r--opengl/system/egl/ClientAPIExts.cpp157
-rw-r--r--opengl/system/egl/ClientAPIExts.h29
-rw-r--r--opengl/system/egl/ClientAPIExts.in201
-rw-r--r--opengl/system/egl/egl.cfg1
-rw-r--r--opengl/system/egl/egl.cpp1254
-rw-r--r--opengl/system/egl/eglContext.h51
-rw-r--r--opengl/system/egl/eglDisplay.cpp497
-rw-r--r--opengl/system/egl/eglDisplay.h89
-rw-r--r--opengl/system/egl/egl_ftable.h64
10 files changed, 2384 insertions, 0 deletions
diff --git a/opengl/system/egl/Android.mk b/opengl/system/egl/Android.mk
new file mode 100644
index 0000000..a979089
--- /dev/null
+++ b/opengl/system/egl/Android.mk
@@ -0,0 +1,41 @@
+ifneq (false,$(BUILD_EMULATOR_OPENGL_DRIVER))
+
+LOCAL_PATH := $(call my-dir)
+
+$(call emugl-begin-shared-library,libEGL_emulation)
+$(call emugl-import,libOpenglSystemCommon)
+$(call emugl-set-shared-library-subpath,egl)
+
+LOCAL_CFLAGS += -DLOG_TAG=\"EGL_emulation\" -DEGL_EGLEXT_PROTOTYPES -DWITH_GLES2
+
+LOCAL_SRC_FILES := \
+ eglDisplay.cpp \
+ egl.cpp \
+ ClientAPIExts.cpp
+
+LOCAL_SHARED_LIBRARIES += libdl
+
+# Used to access the Bionic private OpenGL TLS slot
+LOCAL_C_INCLUDES += bionic/libc/private
+
+$(call emugl-end-module)
+
+#### egl.cfg ####
+
+# Ensure that this file is only copied to emulator-specific builds.
+# Other builds are device-specific and will provide their own
+# version of this file to point to the appropriate HW EGL libraries.
+#
+ifneq (,$(filter full full_x86 full_mips sdk sdk_x86 sdk_mips google_sdk google_sdk_x86 google_sdk_mips,$(TARGET_PRODUCT)))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := egl.cfg
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl
+LOCAL_MODULE_CLASS := ETC
+
+include $(BUILD_PREBUILT)
+endif # TARGET_PRODUCT in 'full full_x86 full_mips sdk sdk_x86 sdk_mips google_sdk google_sdk_x86 google_sdk_mips')
+
+endif # BUILD_EMULATOR_OPENGL_DRIVER != false
diff --git a/opengl/system/egl/ClientAPIExts.cpp b/opengl/system/egl/ClientAPIExts.cpp
new file mode 100644
index 0000000..5e81afe
--- /dev/null
+++ b/opengl/system/egl/ClientAPIExts.cpp
@@ -0,0 +1,157 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#include "ClientAPIExts.h"
+#include "ThreadInfo.h"
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include "eglContext.h"
+
+namespace ClientAPIExts
+{
+
+//
+// define function pointer type for each extention function
+// typename has the form __egl_{funcname}_t
+//
+#define FUNC_TYPE(fname) __egl_ ## fname ## _t
+#define API_ENTRY(fname,params,args) \
+ typedef void (GL_APIENTRY *FUNC_TYPE(fname)) params;
+
+#define API_ENTRY_RET(rtype,fname,params,args) \
+ typedef rtype (GL_APIENTRY *FUNC_TYPE(fname)) params;
+
+#include "ClientAPIExts.in"
+#undef API_ENTRY
+#undef API_ENTRY_RET
+
+/////
+// Define static table to store the function value for each
+// client API. functions pointers will get initialized through
+// ClientAPIExts::initClientFuncs function after each client API has been
+// loaded.
+/////
+#define API_ENTRY(fname,params,args) \
+ FUNC_TYPE(fname) fname;
+
+#define API_ENTRY_RET(rtype,fname,params,args) \
+ API_ENTRY(fname,params,args)
+
+static struct _ext_table
+{
+#include "ClientAPIExts.in"
+} s_client_extensions[2];
+
+#undef API_ENTRY
+#undef API_ENTRY_RET
+
+//
+// This function initialized each entry in the s_client_extensions
+// struct at the givven index using the givven client interface
+//
+void initClientFuncs(const EGLClient_glesInterface *iface, int idx)
+{
+#define API_ENTRY(fname,params,args) \
+ s_client_extensions[idx].fname = \
+ (FUNC_TYPE(fname))iface->getProcAddress(#fname);
+
+#define API_ENTRY_RET(rtype,fname,params,args) \
+ API_ENTRY(fname,params,args)
+
+ //
+ // reset all func pointers to NULL
+ //
+ memset(&s_client_extensions[idx], 0, sizeof(struct _ext_table));
+
+ //
+ // And now query the GLES library for each proc address
+ //
+#include "ClientAPIExts.in"
+#undef API_ENTRY
+#undef API_ENTRY_RET
+}
+
+//
+// Define implementation for each extension function which checks
+// the current context version and calls to the correct client API
+// function.
+//
+#define API_ENTRY(fname,params,args) \
+ static void _egl_ ## fname params \
+ { \
+ EGLThreadInfo* thread = getEGLThreadInfo(); \
+ if (!thread->currentContext) { \
+ return; \
+ } \
+ int idx = (int)thread->currentContext->version - 1; \
+ if (!s_client_extensions[idx].fname) { \
+ return; \
+ } \
+ (*s_client_extensions[idx].fname) args; \
+ }
+
+#define API_ENTRY_RET(rtype,fname,params,args) \
+ static rtype _egl_ ## fname params \
+ { \
+ EGLThreadInfo* thread = getEGLThreadInfo(); \
+ if (!thread->currentContext) { \
+ return (rtype)0; \
+ } \
+ int idx = (int)thread->currentContext->version - 1; \
+ if (!s_client_extensions[idx].fname) { \
+ return (rtype)0; \
+ } \
+ return (*s_client_extensions[idx].fname) args; \
+ }
+
+#include "ClientAPIExts.in"
+#undef API_ENTRY
+#undef API_ENTRY_RET
+
+//
+// Define a table to map function names to the local _egl_ version of
+// the extension function, to be used in eglGetProcAddress.
+//
+#define API_ENTRY(fname,params,args) \
+ { #fname, (void*)_egl_ ## fname},
+#define API_ENTRY_RET(rtype,fname,params,args) \
+ API_ENTRY(fname,params,args)
+
+static const struct _client_ext_funcs {
+ const char *fname;
+ void* proc;
+} s_client_ext_funcs[] = {
+#include "ClientAPIExts.in"
+};
+static const int numExtFuncs = sizeof(s_client_ext_funcs) /
+ sizeof(s_client_ext_funcs[0]);
+
+#undef API_ENTRY
+#undef API_ENTRY_RET
+
+//
+// returns the __egl_ version of the givven extension function name.
+//
+void* getProcAddress(const char *fname)
+{
+ for (int i=0; i<numExtFuncs; i++) {
+ if (!strcmp(fname, s_client_ext_funcs[i].fname)) {
+ return s_client_ext_funcs[i].proc;
+ }
+ }
+ return NULL;
+}
+
+} // of namespace ClientAPIExts
diff --git a/opengl/system/egl/ClientAPIExts.h b/opengl/system/egl/ClientAPIExts.h
new file mode 100644
index 0000000..eee9172
--- /dev/null
+++ b/opengl/system/egl/ClientAPIExts.h
@@ -0,0 +1,29 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#ifndef _CLIENT_APIS_EXTS_H
+#define _CLIENT_APIS_EXTS_H
+
+#include "EGLClientIface.h"
+
+namespace ClientAPIExts
+{
+
+void initClientFuncs(const EGLClient_glesInterface *iface, int idx);
+void* getProcAddress(const char *fname);
+
+} // of namespace ClientAPIExts
+
+#endif
diff --git a/opengl/system/egl/ClientAPIExts.in b/opengl/system/egl/ClientAPIExts.in
new file mode 100644
index 0000000..5850701
--- /dev/null
+++ b/opengl/system/egl/ClientAPIExts.in
@@ -0,0 +1,201 @@
+//
+// Each extension function should have one of the following
+// macro definitions:
+// API_ENTRY(funcname, paramlist, arglist)
+// -or- (if the function has a return value)
+// API_ENTRY_RET(return_type,funcname, paramlist, arglist)
+//
+API_ENTRY(glEGLImageTargetTexture2DOES,
+ (GLenum target, GLeglImageOES image),
+ (target, image))
+
+API_ENTRY(glEGLImageTargetRenderbufferStorageOES,
+ (GLenum target, GLeglImageOES image),
+ (target, image))
+
+API_ENTRY(glBlendEquationSeparateOES,
+ (GLenum modeRGB, GLenum modeAlpha),
+ (modeRGB, modeAlpha))
+
+API_ENTRY(glBlendFuncSeparateOES,
+ (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha),
+ (srcRGB, dstRGB, srcAlpha, dstAlpha))
+
+API_ENTRY(glBlendEquationOES,
+ (GLenum mode),
+ (mode))
+
+API_ENTRY(glCurrentPaletteMatrixOES,
+ (GLuint matrixpaletteindex),
+ (matrixpaletteindex))
+
+API_ENTRY(glLoadPaletteFromModelViewMatrixOES,
+ (void),
+ ())
+
+API_ENTRY(glMatrixIndexPointerOES,
+ (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer),
+ (size, type, stride, pointer))
+
+API_ENTRY(glWeightPointerOES,
+ (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer),
+ (size, type, stride, pointer))
+
+API_ENTRY(glDepthRangefOES,
+ (GLclampf zNear, GLclampf zFar),
+ (zNear, zFar))
+
+API_ENTRY(glFrustumfOES,
+ (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar),
+ (left, right, bottom, top, zNear, zFar))
+
+API_ENTRY(glOrthofOES,
+ (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar),
+ (left, right, bottom, top, zNear, zFar))
+
+API_ENTRY(glClipPlanefOES,
+ (GLenum plane, const GLfloat *equation),
+ (plane, equation))
+
+API_ENTRY(glGetClipPlanefOES,
+ (GLenum pname, GLfloat * eqn),
+ (pname, eqn))
+
+API_ENTRY(glClearDepthfOES,
+ (GLclampf depth),
+ (depth))
+
+API_ENTRY(glPointSizePointerOES,
+ (GLenum type, GLsizei stride, const GLvoid *pointer),
+ (type, stride, pointer))
+
+API_ENTRY(glTexGenfOES,
+ (GLenum coord, GLenum pname, GLfloat param),
+ (coord, pname, param))
+
+API_ENTRY(glTexGenfvOES,
+ (GLenum coord, GLenum pname, const GLfloat *params),
+ (coord, pname, params))
+
+API_ENTRY(glTexGeniOES,
+ (GLenum coord, GLenum pname, GLint param),
+ (coord, pname, param))
+
+API_ENTRY(glTexGenivOES,
+ (GLenum coord, GLenum pname, const GLint *params),
+ (coord, pname, params))
+
+API_ENTRY(glTexGenxOES,
+ (GLenum coord, GLenum pname, GLfixed param),
+ (coord, pname, param))
+
+API_ENTRY(glTexGenxvOES,
+ (GLenum coord, GLenum pname, const GLfixed *params),
+ (coord, pname, params))
+
+API_ENTRY(glGetTexGenfvOES,
+ (GLenum coord, GLenum pname, GLfloat *params),
+ (coord, pname, params))
+
+API_ENTRY(glGetTexGenivOES,
+ (GLenum coord, GLenum pname, GLint *params),
+ (coord, pname, params))
+
+API_ENTRY(glGetTexGenxvOES,
+ (GLenum coord, GLenum pname, GLfixed *params),
+ (coord, pname, params))
+
+API_ENTRY_RET(GLboolean,
+ glIsRenderbufferOES,
+ (GLuint renderbuffer),
+ (renderbuffer))
+
+API_ENTRY(glBindRenderbufferOES,
+ (GLenum target, GLuint renderbuffer),
+ (target, renderbuffer))
+
+API_ENTRY(glDeleteRenderbuffersOES,
+ (GLsizei n, const GLuint* renderbuffers),
+ (n, renderbuffers))
+
+API_ENTRY(glGenRenderbuffersOES,
+ (GLsizei n, GLuint* renderbuffers),
+ (n, renderbuffers))
+
+API_ENTRY(glRenderbufferStorageOES,
+ (GLenum target, GLenum internalformat, GLsizei width, GLsizei height),
+ (target, internalformat, width, height))
+
+API_ENTRY(glGetRenderbufferParameterivOES,
+ (GLenum target, GLenum pname, GLint* params),
+ (target, pname, params))
+
+API_ENTRY_RET(GLboolean,
+ glIsFramebufferOES,
+ (GLuint framebuffer),
+ (framebuffer))
+
+API_ENTRY(glBindFramebufferOES,
+ (GLenum target, GLuint framebuffer),
+ (target, framebuffer))
+
+API_ENTRY(glDeleteFramebuffersOES,
+ (GLsizei n, const GLuint* framebuffers),
+ (n, framebuffers))
+
+API_ENTRY(glGenFramebuffersOES,
+ (GLsizei n, GLuint* framebuffers),
+ (n, framebuffers))
+
+API_ENTRY_RET(GLenum,
+ glCheckFramebufferStatusOES,
+ (GLenum target),
+ (target))
+
+API_ENTRY(glFramebufferTexture2DOES,
+ (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level),
+ (target, attachment, textarget, texture, level))
+
+API_ENTRY(glFramebufferRenderbufferOES,
+ (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer),
+ (target, attachment, renderbuffertarget, renderbuffer))
+
+API_ENTRY(glGetFramebufferAttachmentParameterivOES,
+ (GLenum target, GLenum attachment, GLenum pname, GLint* params),
+ (target, attachment, pname, params))
+
+API_ENTRY(glGenerateMipmapOES,
+ (GLenum target),
+ (target))
+
+API_ENTRY(glDrawTexsOES,
+ (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height),
+ (x, y, z, width, height))
+
+API_ENTRY(glDrawTexiOES,
+ (GLint x, GLint y, GLint z, GLint width, GLint height),
+ (x, y, z, width, height))
+
+API_ENTRY(glDrawTexfOES,
+ (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height),
+ (x, y, z, width, height))
+
+API_ENTRY(glDrawTexxOES,
+ (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height),
+ (x, y, z, width, height))
+
+API_ENTRY(glDrawTexsvOES,
+ (const GLshort *coords),
+ (coords))
+
+API_ENTRY(glDrawTexivOES,
+ (const GLint *coords),
+ (coords))
+
+API_ENTRY(glDrawTexfvOES,
+ (const GLfloat *coords),
+ (coords))
+
+API_ENTRY(glDrawTexxvOES,
+ (const GLfixed *coords),
+ (coords))
diff --git a/opengl/system/egl/egl.cfg b/opengl/system/egl/egl.cfg
new file mode 100644
index 0000000..9d3f2dc
--- /dev/null
+++ b/opengl/system/egl/egl.cfg
@@ -0,0 +1 @@
+0 0 emulation
diff --git a/opengl/system/egl/egl.cpp b/opengl/system/egl/egl.cpp
new file mode 100644
index 0000000..da89c4d
--- /dev/null
+++ b/opengl/system/egl/egl.cpp
@@ -0,0 +1,1254 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "HostConnection.h"
+#include "ThreadInfo.h"
+#include "eglDisplay.h"
+#include "egl_ftable.h"
+#include <cutils/log.h>
+#include "gralloc_cb.h"
+#include "GLClientState.h"
+#include "GLSharedGroup.h"
+#include "eglContext.h"
+#include "ClientAPIExts.h"
+
+#include "GLEncoder.h"
+#ifdef WITH_GLES2
+#include "GL2Encoder.h"
+#endif
+
+#include <system/window.h>
+
+template<typename T>
+static T setErrorFunc(GLint error, T returnValue) {
+ getEGLThreadInfo()->eglError = error;
+ return returnValue;
+}
+
+const char * eglStrError(EGLint err)
+{
+ switch (err){
+ case EGL_SUCCESS: return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
+ case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
+ case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
+ case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
+ case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
+ case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
+ default: return "UNKNOWN";
+ }
+}
+
+#define LOG_EGL_ERRORS 1
+
+#ifdef LOG_EGL_ERRORS
+
+#define setErrorReturn(error, retVal) \
+ { \
+ ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
+ return setErrorFunc(error, retVal); \
+ }
+
+#define RETURN_ERROR(ret,err) \
+ ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
+ getEGLThreadInfo()->eglError = err; \
+ return ret;
+
+#else //!LOG_EGL_ERRORS
+
+#define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
+
+#define RETURN_ERROR(ret,err) \
+ getEGLThreadInfo()->eglError = err; \
+ return ret;
+
+#endif //LOG_EGL_ERRORS
+
+#define VALIDATE_CONFIG(cfg,ret) \
+ if(((int)cfg<0)||((int)cfg>s_display.getNumConfigs())) { \
+ RETURN_ERROR(ret,EGL_BAD_CONFIG); \
+ }
+
+#define VALIDATE_DISPLAY(dpy,ret) \
+ if ((dpy) != (EGLDisplay)&s_display) { \
+ RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
+ }
+
+#define VALIDATE_DISPLAY_INIT(dpy,ret) \
+ VALIDATE_DISPLAY(dpy, ret) \
+ if (!s_display.initialized()) { \
+ RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
+ }
+
+#define DEFINE_HOST_CONNECTION \
+ HostConnection *hostCon = HostConnection::get(); \
+ renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
+
+#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
+ HostConnection *hostCon = HostConnection::get(); \
+ if (!hostCon) { \
+ ALOGE("egl: Failed to get host connection\n"); \
+ return ret; \
+ } \
+ renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
+ if (!rcEnc) { \
+ ALOGE("egl: Failed to get renderControl encoder context\n"); \
+ return ret; \
+ }
+
+#define VALIDATE_CONTEXT_RETURN(context,ret) \
+ if (!context) { \
+ RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
+ }
+
+#define VALIDATE_SURFACE_RETURN(surface, ret) \
+ if (surface != EGL_NO_SURFACE) { \
+ egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
+ if (s->dpy != (EGLDisplay)&s_display) \
+ setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
+ }
+
+
+EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
+ dpy(dpy),
+ config(config),
+ read(EGL_NO_SURFACE),
+ draw(EGL_NO_SURFACE),
+ shareCtx(shareCtx),
+ rcContext(0),
+ versionString(NULL),
+ vendorString(NULL),
+ rendererString(NULL),
+ extensionString(NULL)
+{
+ flags = 0;
+ version = 1;
+ clientState = new GLClientState();
+ if (shareCtx)
+ sharedGroup = shareCtx->getSharedGroup();
+ else
+ sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
+};
+
+EGLContext_t::~EGLContext_t()
+{
+ delete clientState;
+ delete [] versionString;
+ delete [] vendorString;
+ delete [] rendererString;
+ delete [] extensionString;
+}
+
+// ----------------------------------------------------------------------------
+//egl_surface_t
+
+//we don't need to handle depth since it's handled when window created on the host
+
+struct egl_surface_t {
+
+ EGLDisplay dpy;
+ EGLConfig config;
+
+
+ egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
+ virtual ~egl_surface_t();
+
+ virtual void setSwapInterval(int interval) = 0;
+ virtual EGLBoolean swapBuffers() = 0;
+
+ EGLint getSwapBehavior() const;
+ uint32_t getRcSurface() { return rcSurface; }
+ EGLint getSurfaceType() { return surfaceType; }
+
+ EGLint getWidth(){ return width; }
+ EGLint getHeight(){ return height; }
+ void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
+ EGLint getTextureFormat() { return texFormat; }
+ void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
+ EGLint getTextureTarget() { return texTarget; }
+
+private:
+ //
+ //Surface attributes
+ //
+ EGLint width;
+ EGLint height;
+ EGLint texFormat;
+ EGLint texTarget;
+
+protected:
+ void setWidth(EGLint w) { width = w; }
+ void setHeight(EGLint h) { height = h; }
+
+ EGLint surfaceType;
+ uint32_t rcSurface; //handle to surface created via remote control
+};
+
+egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
+ : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
+{
+ width = 0;
+ height = 0;
+ texFormat = EGL_NO_TEXTURE;
+ texTarget = EGL_NO_TEXTURE;
+}
+
+EGLint egl_surface_t::getSwapBehavior() const {
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl_surface_t::~egl_surface_t()
+{
+}
+
+// ----------------------------------------------------------------------------
+// egl_window_surface_t
+
+struct egl_window_surface_t : public egl_surface_t {
+ static egl_window_surface_t* create(
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window);
+
+ virtual ~egl_window_surface_t();
+
+ virtual void setSwapInterval(int interval);
+ virtual EGLBoolean swapBuffers();
+
+private:
+ egl_window_surface_t(
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window);
+ EGLBoolean init();
+
+ ANativeWindow* nativeWindow;
+ android_native_buffer_t* buffer;
+};
+
+egl_window_surface_t::egl_window_surface_t (
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window)
+: egl_surface_t(dpy, config, surfType),
+ nativeWindow(window),
+ buffer(NULL)
+{
+ // keep a reference on the window
+ nativeWindow->common.incRef(&nativeWindow->common);
+ EGLint w,h;
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
+ setWidth(w);
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
+ setHeight(h);
+}
+
+EGLBoolean egl_window_surface_t::init()
+{
+ if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
+ setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
+ getWidth(), getHeight());
+ if (!rcSurface) {
+ ALOGE("rcCreateWindowSurface returned 0");
+ return EGL_FALSE;
+ }
+ rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
+ ((cb_handle_t*)(buffer->handle))->hostHandle);
+
+ return EGL_TRUE;
+}
+
+egl_window_surface_t* egl_window_surface_t::create(
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window)
+{
+ egl_window_surface_t* wnd = new egl_window_surface_t(
+ dpy, config, surfType, window);
+ if (wnd && !wnd->init()) {
+ delete wnd;
+ wnd = NULL;
+ }
+ return wnd;
+}
+
+egl_window_surface_t::~egl_window_surface_t() {
+ DEFINE_HOST_CONNECTION;
+ if (rcSurface && rcEnc) {
+ rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
+ }
+ if (buffer) {
+ nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
+ }
+ nativeWindow->common.decRef(&nativeWindow->common);
+}
+
+void egl_window_surface_t::setSwapInterval(int interval)
+{
+ nativeWindow->setSwapInterval(nativeWindow, interval);
+}
+
+EGLBoolean egl_window_surface_t::swapBuffers()
+{
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+
+ rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
+
+ nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
+ if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
+ buffer = NULL;
+ setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
+ ((cb_handle_t *)(buffer->handle))->hostHandle);
+
+ return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+//egl_pbuffer_surface_t
+
+struct egl_pbuffer_surface_t : public egl_surface_t {
+ static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
+ EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
+
+ virtual ~egl_pbuffer_surface_t();
+
+ virtual void setSwapInterval(int interval) {}
+ virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
+
+ uint32_t getRcColorBuffer() { return rcColorBuffer; }
+
+private:
+ egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ int32_t w, int32_t h);
+ EGLBoolean init(GLenum format);
+
+ uint32_t rcColorBuffer;
+};
+
+egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
+ EGLint surfType, int32_t w, int32_t h)
+: egl_surface_t(dpy, config, surfType),
+ rcColorBuffer(0)
+{
+ setWidth(w);
+ setHeight(h);
+}
+
+egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
+{
+ DEFINE_HOST_CONNECTION;
+ if (rcEnc) {
+ if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
+ if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
+ }
+}
+
+EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
+{
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+
+ rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
+ getWidth(), getHeight());
+ if (!rcSurface) {
+ ALOGE("rcCreateWindowSurface returned 0");
+ return EGL_FALSE;
+ }
+
+ rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
+ pixelFormat);
+ if (!rcColorBuffer) {
+ ALOGE("rcCreateColorBuffer returned 0");
+ return EGL_FALSE;
+ }
+
+ rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
+
+ return EGL_TRUE;
+}
+
+egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
+ EGLConfig config, EGLint surfType, int32_t w, int32_t h,
+ GLenum pixelFormat)
+{
+ egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
+ w, h);
+ if (pb && !pb->init(pixelFormat)) {
+ delete pb;
+ pb = NULL;
+ }
+ return pb;
+}
+
+static const char *getGLString(int glEnum)
+{
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (!tInfo || !tInfo->currentContext) {
+ return NULL;
+ }
+
+ const char** strPtr = NULL;
+
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+ switch(glEnum) {
+ case GL_VERSION:
+ strPtr = &tInfo->currentContext->versionString;
+ break;
+ case GL_VENDOR:
+ strPtr = &tInfo->currentContext->vendorString;
+ break;
+ case GL_RENDERER:
+ strPtr = &tInfo->currentContext->rendererString;
+ break;
+ case GL_EXTENSIONS:
+ strPtr = &tInfo->currentContext->extensionString;
+ break;
+ }
+
+ if (!strPtr) {
+ return NULL;
+ }
+
+ if (*strPtr != NULL) {
+ //
+ // string is already cached
+ //
+ return *strPtr;
+ }
+
+ //
+ // first query of that string - need to query host
+ //
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
+ char *hostStr = NULL;
+ int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
+ if (n < 0) {
+ hostStr = new char[-n+1];
+ n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
+ if (n <= 0) {
+ delete [] hostStr;
+ hostStr = NULL;
+ }
+ }
+
+ //
+ // keep the string in the context and return its value
+ //
+ *strPtr = hostStr;
+ return hostStr;
+}
+
+// ----------------------------------------------------------------------------
+
+// The one and only supported display object.
+static eglDisplay s_display;
+
+static EGLClient_eglInterface s_eglIface = {
+ getThreadInfo: getEGLThreadInfo,
+ getGLString: getGLString
+};
+
+#define DBG_FUNC DBG("%s\n", __FUNCTION__)
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
+{
+ //
+ // we support only EGL_DEFAULT_DISPLAY.
+ //
+ if (display_id != EGL_DEFAULT_DISPLAY) {
+ return EGL_NO_DISPLAY;
+ }
+
+ return (EGLDisplay)&s_display;
+}
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+ VALIDATE_DISPLAY(dpy,EGL_FALSE);
+
+ if (!s_display.initialize(&s_eglIface)) {
+ return EGL_FALSE;
+ }
+ if (major!=NULL)
+ *major = s_display.getVersionMajor();
+ if (minor!=NULL)
+ *minor = s_display.getVersionMinor();
+ return EGL_TRUE;
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+
+ s_display.terminate();
+ return EGL_TRUE;
+}
+
+EGLint eglGetError()
+{
+ EGLint error = getEGLThreadInfo()->eglError;
+ getEGLThreadInfo()->eglError = EGL_SUCCESS;
+ return error;
+}
+
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
+{
+ // search in EGL function table
+ for (int i=0; i<egl_num_funcs; i++) {
+ if (!strcmp(egl_funcs_by_name[i].name, procname)) {
+ return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
+ }
+ }
+
+ //
+ // Make sure display is initialized before searching in client APIs
+ //
+ if (!s_display.initialized()) {
+ if (!s_display.initialize(&s_eglIface)) {
+ return NULL;
+ }
+ }
+
+ // look in gles client api's extensions table
+ return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
+
+ // Fail - function not found.
+ return NULL;
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name)
+{
+ VALIDATE_DISPLAY_INIT(dpy, NULL);
+
+ return s_display.queryString(name);
+}
+
+EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ VALIDATE_DISPLAY_INIT(dpy, NULL);
+
+ if(!num_config) {
+ RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
+ }
+
+ GLint numConfigs = s_display.getNumConfigs();
+ if (!configs) {
+ *num_config = numConfigs;
+ return EGL_TRUE;
+ }
+
+ int i=0;
+ for (i=0 ; i<numConfigs && i<config_size ; i++) {
+ *configs++ = (EGLConfig)i;
+ }
+ *num_config = i;
+ return EGL_TRUE;
+}
+
+EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+
+ int attribs_size = 0;
+ if (attrib_list) {
+ const EGLint * attrib_p = attrib_list;
+ while (attrib_p[0] != EGL_NONE) {
+ attribs_size += 2;
+ attrib_p += 2;
+ }
+ attribs_size++; //for the terminating EGL_NONE
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)configs, config_size);
+
+ return EGL_TRUE;
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+ VALIDATE_DISPLAY_INIT(dpy, NULL);
+ VALIDATE_CONFIG(config, EGL_FALSE);
+
+ if (s_display.getConfigAttrib(config, attribute, value))
+ {
+ return EGL_TRUE;
+ }
+ else
+ {
+ RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
+ }
+}
+
+EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+{
+ VALIDATE_DISPLAY_INIT(dpy, NULL);
+ VALIDATE_CONFIG(config, EGL_FALSE);
+ if (win == 0) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ EGLint surfaceType;
+ if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
+
+ if (!(surfaceType & EGL_WINDOW_BIT)) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
+ setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+
+ egl_surface_t* surface = egl_window_surface_t::create(
+ &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
+ if (!surface) {
+ setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return surface;
+}
+
+EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ VALIDATE_DISPLAY_INIT(dpy, NULL);
+ VALIDATE_CONFIG(config, EGL_FALSE);
+
+ EGLint surfaceType;
+ if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
+
+ if (!(surfaceType & EGL_PBUFFER_BIT)) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ int32_t w = 0;
+ int32_t h = 0;
+ EGLint texFormat = EGL_NO_TEXTURE;
+ EGLint texTarget = EGL_NO_TEXTURE;
+ while (attrib_list[0]) {
+ switch (attrib_list[0]) {
+ case EGL_WIDTH:
+ w = attrib_list[1];
+ break;
+ case EGL_HEIGHT:
+ h = attrib_list[1];
+ break;
+ case EGL_TEXTURE_FORMAT:
+ texFormat = attrib_list[1];
+ break;
+ case EGL_TEXTURE_TARGET:
+ texTarget = attrib_list[1];
+ break;
+ default:
+ break;
+ };
+ attrib_list+=2;
+ }
+ if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
+ ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+ // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
+
+ GLenum pixelFormat;
+ if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+ egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
+ surfaceType, w, h, pixelFormat);
+ if (!surface) {
+ setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ //setup attributes
+ surface->setTextureFormat(texFormat);
+ surface->setTextureTarget(texTarget);
+
+ return surface;
+}
+
+EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+ //XXX: Pixmap not supported. The host cannot render to a pixmap resource
+ // located on host. In order to support Pixmaps we should either punt
+ // to s/w rendering -or- let the host render to a buffer that will be
+ // copied back to guest at some sync point. None of those methods not
+ // implemented and pixmaps are not used with OpenGL anyway ...
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+
+ egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
+ delete surface;
+
+ return EGL_TRUE;
+}
+
+EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+
+ egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+ EGLBoolean ret = EGL_TRUE;
+ switch (attribute) {
+ case EGL_CONFIG_ID:
+ ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
+ break;
+ case EGL_WIDTH:
+ *value = surface->getWidth();
+ break;
+ case EGL_HEIGHT:
+ *value = surface->getHeight();
+ break;
+ case EGL_TEXTURE_FORMAT:
+ *value = surface->getTextureFormat();
+ break;
+ case EGL_TEXTURE_TARGET:
+ *value = surface->getTextureTarget();
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ *value = surface->getSwapBehavior();
+ break;
+ case EGL_LARGEST_PBUFFER:
+ // not modified for a window or pixmap surface
+ // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
+ if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
+ break;
+ //TODO: complete other attributes
+ default:
+ ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
+ ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ break;
+ }
+
+ return ret;
+}
+
+EGLBoolean eglBindAPI(EGLenum api)
+{
+ if (api != EGL_OPENGL_ES_API)
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+ return EGL_TRUE;
+}
+
+EGLenum eglQueryAPI()
+{
+ return EGL_OPENGL_ES_API;
+}
+
+EGLBoolean eglWaitClient()
+{
+ return eglWaitGL();
+}
+
+EGLBoolean eglReleaseThread()
+{
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (tInfo && tInfo->currentContext) {
+ return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+ }
+ return EGL_TRUE;
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+ //TODO
+ ALOGW("%s not implemented", __FUNCTION__);
+ return 0;
+}
+
+EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+ //TODO
+ ALOGW("%s not implemented", __FUNCTION__);
+ return 0;
+}
+
+EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+ if (eglSurface == EGL_NO_SURFACE) {
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+
+ if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
+ }
+
+ if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ //It's now safe to cast to pbuffer surface
+ egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
+
+ return GL_TRUE;
+}
+
+EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ //TODO
+ ALOGW("%s not implemented", __FUNCTION__);
+ return 0;
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+
+ EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
+ if (!ctx) {
+ setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
+ }
+ if (!ctx->draw) {
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+ egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
+ draw->setSwapInterval(interval);
+
+ rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
+
+ return EGL_TRUE;
+}
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
+ VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
+
+ EGLint version = 1; //default
+ while (attrib_list && attrib_list[0]) {
+ if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
+ attrib_list+=2;
+ }
+
+ uint32_t rcShareCtx = 0;
+ EGLContext_t * shareCtx = NULL;
+ if (share_context) {
+ shareCtx = static_cast<EGLContext_t*>(share_context);
+ rcShareCtx = shareCtx->rcContext;
+ if (shareCtx->dpy != dpy)
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
+ uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uint32_t)config, rcShareCtx, version);
+ if (!rcContext) {
+ ALOGE("rcCreateContext returned 0");
+ setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
+
+ EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
+ if (!context)
+ setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+
+ context->version = version;
+ context->rcContext = rcContext;
+
+
+ return context;
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
+
+ EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
+
+ if (getEGLThreadInfo()->currentContext == context)
+ {
+ eglMakeCurrent(dpy, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+ }
+
+ if (context->rcContext) {
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ rcEnc->rcDestroyContext(rcEnc, context->rcContext);
+ context->rcContext = 0;
+ }
+
+ delete context;
+ return EGL_TRUE;
+}
+
+EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
+ VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
+
+ if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
+ setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
+ if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
+ setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
+
+ EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
+ uint32_t ctxHandle = (context) ? context->rcContext : 0;
+ egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
+ uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
+ egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
+ uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
+
+ //
+ // Nothing to do if no binding change has made
+ //
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (tInfo->currentContext == context &&
+ (context == NULL ||
+ (context && context->draw == draw && context->read == read))) {
+ return EGL_TRUE;
+ }
+
+ if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
+ //context is current to another thread
+ setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
+ ALOGE("rcMakeCurrent returned EGL_FALSE");
+ setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
+ }
+
+ //Now make the local bind
+ if (context) {
+ context->draw = draw;
+ context->read = read;
+ context->flags |= EGLContext_t::IS_CURRENT;
+ //set the client state
+ if (context->version == 2) {
+ hostCon->gl2Encoder()->setClientState(context->getClientState());
+ hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
+ }
+ else {
+ hostCon->glEncoder()->setClientState(context->getClientState());
+ hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
+ }
+ }
+ else {
+ //release ClientState & SharedGroup
+ if (tInfo->currentContext->version == 2) {
+ hostCon->gl2Encoder()->setClientState(NULL);
+ hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
+ }
+ else {
+ hostCon->glEncoder()->setClientState(NULL);
+ hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
+ }
+
+ }
+
+ if (tInfo->currentContext)
+ tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
+
+ //Now make current
+ tInfo->currentContext = context;
+
+ //Check maybe we need to init the encoder, if it's first eglMakeCurrent
+ if (tInfo->currentContext) {
+ if (tInfo->currentContext->version == 2) {
+ if (!hostCon->gl2Encoder()->isInitialized()) {
+ s_display.gles2_iface()->init();
+ hostCon->gl2Encoder()->setInitialized();
+ ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
+ }
+ }
+ else {
+ if (!hostCon->glEncoder()->isInitialized()) {
+ s_display.gles_iface()->init();
+ hostCon->glEncoder()->setInitialized();
+ ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
+ }
+ }
+ }
+
+ return EGL_TRUE;
+}
+
+EGLContext eglGetCurrentContext()
+{
+ return getEGLThreadInfo()->currentContext;
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw)
+{
+ EGLContext_t * context = getEGLThreadInfo()->currentContext;
+ if (!context)
+ return EGL_NO_SURFACE; //not an error
+
+ switch (readdraw) {
+ case EGL_READ:
+ return context->read;
+ case EGL_DRAW:
+ return context->draw;
+ default:
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ }
+}
+
+EGLDisplay eglGetCurrentDisplay()
+{
+ EGLContext_t * context = getEGLThreadInfo()->currentContext;
+ if (!context)
+ return EGL_NO_DISPLAY; //not an error
+
+ return context->dpy;
+}
+
+EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
+
+ EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
+
+ EGLBoolean ret = EGL_TRUE;
+ switch (attribute) {
+ case EGL_CONFIG_ID:
+ ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
+ break;
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = EGL_OPENGL_ES_API;
+ break;
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = context->version;
+ break;
+ case EGL_RENDER_BUFFER:
+ if (!context->draw)
+ *value = EGL_NONE;
+ else
+ *value = EGL_BACK_BUFFER; //single buffer not supported
+ break;
+ default:
+ ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
+ setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ break;
+ }
+
+ return ret;
+}
+
+EGLBoolean eglWaitGL()
+{
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (!tInfo || !tInfo->currentContext) {
+ return EGL_FALSE;
+ }
+
+ if (tInfo->currentContext->version == 2) {
+ s_display.gles2_iface()->finish();
+ }
+ else {
+ s_display.gles_iface()->finish();
+ }
+
+ return EGL_TRUE;
+}
+
+EGLBoolean eglWaitNative(EGLint engine)
+{
+ return EGL_TRUE;
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ if (eglSurface == EGL_NO_SURFACE)
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+
+ egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
+ if (d->dpy != dpy)
+ setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ // post the surface
+ d->swapBuffers();
+
+ hostCon->flush();
+ return EGL_TRUE;
+}
+
+EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+ //TODO :later
+ return 0;
+}
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
+{
+ //TODO later
+ return 0;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
+{
+ //TODO later
+ return 0;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
+ if (ctx != EGL_NO_CONTEXT) {
+ setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+ }
+ if (target != EGL_NATIVE_BUFFER_ANDROID) {
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+ }
+
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
+
+ switch (cb->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ break;
+ default:
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+ }
+
+ native_buffer->common.incRef(&native_buffer->common);
+ return (EGLImageKHR)native_buffer;
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+ VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+
+ native_buffer->common.decRef(&native_buffer->common);
+
+ return EGL_TRUE;
+}
+
+#define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
+
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
+ const EGLint *attrib_list)
+{
+ // TODO: This implementation could be faster. We should require the host EGL
+ // to support KHR_fence_sync, or at least pipe the fence command to the host
+ // and wait for it (probably involving a glFinish on the host) in
+ // eglClientWaitSyncKHR.
+
+ VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
+
+ if (type != EGL_SYNC_FENCE_KHR ||
+ (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
+ setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+ }
+
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (!tInfo || !tInfo->currentContext) {
+ setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
+ }
+
+ if (tInfo->currentContext->version == 2) {
+ s_display.gles2_iface()->finish();
+ } else {
+ s_display.gles_iface()->finish();
+ }
+
+ return FENCE_SYNC_HANDLE;
+}
+
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+ if (sync != FENCE_SYNC_HANDLE) {
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ return EGL_TRUE;
+}
+
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
+ EGLTimeKHR timeout)
+{
+ if (sync != FENCE_SYNC_HANDLE) {
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ return EGL_CONDITION_SATISFIED_KHR;
+}
+
+EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
+ EGLint attribute, EGLint *value)
+{
+ if (sync != FENCE_SYNC_HANDLE) {
+ setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ switch (attribute) {
+ case EGL_SYNC_TYPE_KHR:
+ *value = EGL_SYNC_FENCE_KHR;
+ return EGL_TRUE;
+ case EGL_SYNC_STATUS_KHR:
+ *value = EGL_SIGNALED_KHR;
+ return EGL_TRUE;
+ case EGL_SYNC_CONDITION_KHR:
+ *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
+ return EGL_TRUE;
+ default:
+ setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+}
diff --git a/opengl/system/egl/eglContext.h b/opengl/system/egl/eglContext.h
new file mode 100644
index 0000000..2ca6d0c
--- /dev/null
+++ b/opengl/system/egl/eglContext.h
@@ -0,0 +1,51 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#ifndef _EGL_CONTEXT_H
+#define _EGL_CONTEXT_H
+
+#include "GLClientState.h"
+#include "GLSharedGroup.h"
+
+struct EGLContext_t {
+
+ enum {
+ IS_CURRENT = 0x00010000,
+ NEVER_CURRENT = 0x00020000
+ };
+
+ EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx);
+ ~EGLContext_t();
+ uint32_t flags;
+ EGLDisplay dpy;
+ EGLConfig config;
+ EGLSurface read;
+ EGLSurface draw;
+ EGLContext_t * shareCtx;
+ EGLint version;
+ uint32_t rcContext;
+ const char* versionString;
+ const char* vendorString;
+ const char* rendererString;
+ const char* extensionString;
+
+ GLClientState * getClientState(){ return clientState; }
+ GLSharedGroupPtr getSharedGroup(){ return sharedGroup; }
+private:
+ GLClientState * clientState;
+ GLSharedGroupPtr sharedGroup;
+};
+
+#endif
diff --git a/opengl/system/egl/eglDisplay.cpp b/opengl/system/egl/eglDisplay.cpp
new file mode 100644
index 0000000..bcb0d4b
--- /dev/null
+++ b/opengl/system/egl/eglDisplay.cpp
@@ -0,0 +1,497 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#include "eglDisplay.h"
+#include "HostConnection.h"
+#include <dlfcn.h>
+
+static const int systemEGLVersionMajor = 1;
+static const int systemEGLVersionMinor = 4;
+static const char systemEGLVendor[] = "Google Android emulator";
+
+// list of extensions supported by this EGL implementation
+// NOTE that each extension name should be suffixed with space
+static const char systemStaticEGLExtensions[] =
+ "EGL_ANDROID_image_native_buffer "
+ "EGL_KHR_fence_sync ";
+
+// list of extensions supported by this EGL implementation only if supported
+// on the host implementation.
+// NOTE that each extension name should be suffixed with space
+static const char systemDynamicEGLExtensions[] =
+ "EGL_KHR_image_base "
+ "EGL_KHR_gl_texture_2d_image ";
+
+
+static void *s_gles_lib = NULL;
+static void *s_gles2_lib = NULL;
+
+// The following function will be called when we (libEGL)
+// gets unloaded
+// At this point we want to unload the gles libraries we
+// might have loaded during initialization
+static void __attribute__ ((destructor)) do_on_unload(void)
+{
+ if (s_gles_lib) {
+ dlclose(s_gles_lib);
+ }
+
+ if (s_gles2_lib) {
+ dlclose(s_gles2_lib);
+ }
+}
+
+eglDisplay::eglDisplay() :
+ m_initialized(false),
+ m_major(0),
+ m_minor(0),
+ m_hostRendererVersion(0),
+ m_numConfigs(0),
+ m_numConfigAttribs(0),
+ m_attribs(DefaultKeyedVector<EGLint, EGLint>(ATTRIBUTE_NONE)),
+ m_configs(NULL),
+ m_gles_iface(NULL),
+ m_gles2_iface(NULL),
+ m_versionString(NULL),
+ m_vendorString(NULL),
+ m_extensionString(NULL)
+{
+ pthread_mutex_init(&m_lock, NULL);
+}
+
+eglDisplay::~eglDisplay()
+{
+ pthread_mutex_destroy(&m_lock);
+}
+
+bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
+{
+ pthread_mutex_lock(&m_lock);
+ if (!m_initialized) {
+
+ //
+ // load GLES client API
+ //
+ m_gles_iface = loadGLESClientAPI("/system/lib/egl/libGLESv1_CM_emulation.so",
+ eglIface,
+ &s_gles_lib);
+ if (!m_gles_iface) {
+ pthread_mutex_unlock(&m_lock);
+ ALOGE("Failed to load gles1 iface");
+ return false;
+ }
+
+#ifdef WITH_GLES2
+ m_gles2_iface = loadGLESClientAPI("/system/lib/egl/libGLESv2_emulation.so",
+ eglIface,
+ &s_gles2_lib);
+ // Note that if loading gles2 failed, we can still run with no
+ // GLES2 support, having GLES2 is not mandatory.
+#endif
+
+ //
+ // establish connection with the host
+ //
+ HostConnection *hcon = HostConnection::get();
+ if (!hcon) {
+ pthread_mutex_unlock(&m_lock);
+ ALOGE("Failed to establish connection with the host\n");
+ return false;
+ }
+
+ //
+ // get renderControl encoder instance
+ //
+ renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
+ if (!rcEnc) {
+ pthread_mutex_unlock(&m_lock);
+ ALOGE("Failed to get renderControl encoder instance");
+ return false;
+ }
+
+ //
+ // Query host reneder and EGL version
+ //
+ m_hostRendererVersion = rcEnc->rcGetRendererVersion(rcEnc);
+ EGLint status = rcEnc->rcGetEGLVersion(rcEnc, &m_major, &m_minor);
+ if (status != EGL_TRUE) {
+ // host EGL initialization failed !!
+ pthread_mutex_unlock(&m_lock);
+ return false;
+ }
+
+ //
+ // Take minimum version beween what we support and what the host support
+ //
+ if (m_major > systemEGLVersionMajor) {
+ m_major = systemEGLVersionMajor;
+ m_minor = systemEGLVersionMinor;
+ }
+ else if (m_major == systemEGLVersionMajor &&
+ m_minor > systemEGLVersionMinor) {
+ m_minor = systemEGLVersionMinor;
+ }
+
+ //
+ // Query the host for the set of configs
+ //
+ m_numConfigs = rcEnc->rcGetNumConfigs(rcEnc, (uint32_t*)&m_numConfigAttribs);
+ if (m_numConfigs <= 0 || m_numConfigAttribs <= 0) {
+ // just sanity check - should never happen
+ pthread_mutex_unlock(&m_lock);
+ return false;
+ }
+
+ uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1);
+ EGLint tmp_buf[nInts];
+ m_configs = new EGLint[nInts-m_numConfigAttribs];
+ if (!m_configs) {
+ pthread_mutex_unlock(&m_lock);
+ return false;
+ }
+
+ //EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), m_configs);
+ EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf);
+ if (n != m_numConfigs) {
+ pthread_mutex_unlock(&m_lock);
+ return false;
+ }
+
+ //Fill the attributes vector.
+ //The first m_numConfigAttribs values of tmp_buf are the actual attributes enums.
+ for (int i=0; i<m_numConfigAttribs; i++) {
+ m_attribs.add(tmp_buf[i], i);
+ }
+
+ //Copy the actual configs data to m_configs
+ memcpy(m_configs, tmp_buf + m_numConfigAttribs, m_numConfigs*m_numConfigAttribs*sizeof(EGLint));
+
+ m_initialized = true;
+ }
+ pthread_mutex_unlock(&m_lock);
+
+ processConfigs();
+
+ return true;
+}
+
+void eglDisplay::processConfigs()
+{
+ for (int i=0; i<m_numConfigs; i++) {
+ EGLConfig config = (EGLConfig)i;
+ //Setup the EGL_NATIVE_VISUAL_ID attribute
+ PixelFormat format;
+ if (getConfigNativePixelFormat(config, &format)) {
+ setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
+ }
+ }
+}
+
+void eglDisplay::terminate()
+{
+ pthread_mutex_lock(&m_lock);
+ if (m_initialized) {
+ m_initialized = false;
+ delete [] m_configs;
+ m_configs = NULL;
+
+ if (m_versionString) {
+ free(m_versionString);
+ m_versionString = NULL;
+ }
+ if (m_vendorString) {
+ free(m_vendorString);
+ m_vendorString = NULL;
+ }
+ if (m_extensionString) {
+ free(m_extensionString);
+ m_extensionString = NULL;
+ }
+ }
+ pthread_mutex_unlock(&m_lock);
+}
+
+EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *libName,
+ EGLClient_eglInterface *eglIface,
+ void **libHandle)
+{
+ void *lib = dlopen(libName, RTLD_NOW);
+ if (!lib) {
+ ALOGE("Failed to dlopen %s", libName);
+ return NULL;
+ }
+
+ init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles");
+ if (!init_gles_func) {
+ ALOGE("Failed to find init_emul_gles");
+ dlclose((void*)lib);
+ return NULL;
+ }
+
+ *libHandle = lib;
+ return (*init_gles_func)(eglIface);
+}
+
+static char *queryHostEGLString(EGLint name)
+{
+ HostConnection *hcon = HostConnection::get();
+ if (hcon) {
+ renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
+ if (rcEnc) {
+ int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0);
+ if (n < 0) {
+ // allocate space for the string with additional
+ // space charachter to be suffixed at the end.
+ char *str = (char *)malloc(-n+2);
+ n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n);
+ if (n > 0) {
+ // add extra space at end of string which will be
+ // needed later when filtering the extension list.
+ strcat(str, " ");
+ return str;
+ }
+
+ free(str);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static bool findExtInList(const char* token, int tokenlen, const char* list)
+{
+ const char* p = list;
+ while (*p != '\0') {
+ const char* q = strchr(p, ' ');
+ if (q == NULL) {
+ /* should not happen, list must be space-terminated */
+ break;
+ }
+ if (tokenlen == (q - p) && !memcmp(token, p, tokenlen)) {
+ return true; /* found it */
+ }
+ p = q+1;
+ }
+ return false; /* not found */
+}
+
+static char *buildExtensionString()
+{
+ //Query host extension string
+ char *hostExt = queryHostEGLString(EGL_EXTENSIONS);
+ if (!hostExt || (hostExt[1] == '\0')) {
+ // no extensions on host - only static extension list supported
+ return strdup(systemStaticEGLExtensions);
+ }
+
+ //
+ // Filter host extension list to include only extensions
+ // we can support (in the systemDynamicEGLExtensions list)
+ //
+ char *ext = (char *)hostExt;
+ char *c = ext;
+ char *insert = ext;
+ while(*c != '\0') {
+ if (*c == ' ') {
+ int len = c - ext;
+ if (findExtInList(ext, len, systemDynamicEGLExtensions)) {
+ if (ext != insert) {
+ memcpy(insert, ext, len+1); // including space
+ }
+ insert += (len + 1);
+ }
+ ext = c + 1;
+ }
+ c++;
+ }
+ *insert = '\0';
+
+ int n = strlen(hostExt);
+ if (n > 0) {
+ char *str;
+ asprintf(&str,"%s%s", systemStaticEGLExtensions, hostExt);
+ free((char*)hostExt);
+ return str;
+ }
+ else {
+ free((char*)hostExt);
+ return strdup(systemStaticEGLExtensions);
+ }
+}
+
+const char *eglDisplay::queryString(EGLint name)
+{
+ if (name == EGL_CLIENT_APIS) {
+ return "OpenGL_ES";
+ }
+ else if (name == EGL_VERSION) {
+ pthread_mutex_lock(&m_lock);
+ if (m_versionString) {
+ pthread_mutex_unlock(&m_lock);
+ return m_versionString;
+ }
+
+ // build version string
+ asprintf(&m_versionString, "%d.%d", m_major, m_minor);
+ pthread_mutex_unlock(&m_lock);
+
+ return m_versionString;
+ }
+ else if (name == EGL_VENDOR) {
+ pthread_mutex_lock(&m_lock);
+ if (m_vendorString) {
+ pthread_mutex_unlock(&m_lock);
+ return m_vendorString;
+ }
+
+ // build vendor string
+ const char *hostVendor = queryHostEGLString(EGL_VENDOR);
+
+ if (hostVendor) {
+ asprintf(&m_vendorString, "%s Host: %s",
+ systemEGLVendor, hostVendor);
+ free((char*)hostVendor);
+ }
+ else {
+ m_vendorString = (char *)systemEGLVendor;
+ }
+ pthread_mutex_unlock(&m_lock);
+
+ return m_vendorString;
+ }
+ else if (name == EGL_EXTENSIONS) {
+ pthread_mutex_lock(&m_lock);
+ if (m_extensionString) {
+ pthread_mutex_unlock(&m_lock);
+ return m_extensionString;
+ }
+
+ // build extension string
+ m_extensionString = buildExtensionString();
+ pthread_mutex_unlock(&m_lock);
+
+ return m_extensionString;
+ }
+ else {
+ ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name);
+ return NULL;
+ }
+}
+
+/* To get the value of attribute <a> of config <c> use the following formula:
+ * value = *(m_configs + (int)c*m_numConfigAttribs + a);
+ */
+EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
+{
+ if (attribIdx == ATTRIBUTE_NONE)
+ {
+ ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
+ return EGL_FALSE;
+ }
+ *value = *(m_configs + (int)config*m_numConfigAttribs + attribIdx);
+ return EGL_TRUE;
+}
+
+EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
+{
+ //Though it seems that valueFor() is thread-safe, we don't take chanses
+ pthread_mutex_lock(&m_lock);
+ EGLBoolean ret = getAttribValue(config, m_attribs.valueFor(attrib), value);
+ pthread_mutex_unlock(&m_lock);
+ return ret;
+}
+
+void eglDisplay::dumpConfig(EGLConfig config)
+{
+ EGLint value = 0;
+ DBG("^^^^^^^^^^ dumpConfig %d ^^^^^^^^^^^^^^^^^^", (int)config);
+ for (int i=0; i<m_numConfigAttribs; i++) {
+ getAttribValue(config, i, &value);
+ DBG("{%d}[%d] %d\n", (int)config, i, value);
+ }
+}
+
+/* To set the value of attribute <a> of config <c> use the following formula:
+ * *(m_configs + (int)c*m_numConfigAttribs + a) = value;
+ */
+EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value)
+{
+ if (attribIdx == ATTRIBUTE_NONE)
+ {
+ ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
+ return EGL_FALSE;
+ }
+ *(m_configs + (int)config*m_numConfigAttribs + attribIdx) = value;
+ return EGL_TRUE;
+}
+
+EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value)
+{
+ //Though it seems that valueFor() is thread-safe, we don't take chanses
+ pthread_mutex_lock(&m_lock);
+ EGLBoolean ret = setAttribValue(config, m_attribs.valueFor(attrib), value);
+ pthread_mutex_unlock(&m_lock);
+ return ret;
+}
+
+
+EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, PixelFormat * format)
+{
+ EGLint redSize, blueSize, greenSize, alphaSize;
+
+ if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) )
+ {
+ ALOGE("Couldn't find value for one of the pixel format attributes");
+ return EGL_FALSE;
+ }
+
+ //calculate the GL internal format
+ if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = PIXEL_FORMAT_RGBA_8888; //XXX: BGR?
+ else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGBX_8888; //XXX or PIXEL_FORMAT_RGB_888
+ else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGB_565;
+ else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = PIXEL_FORMAT_RGBA_5551;
+ else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = PIXEL_FORMAT_RGBA_4444;
+ else {
+ return EGL_FALSE;
+ }
+ return EGL_TRUE;
+}
+EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format)
+{
+ EGLint redSize, blueSize, greenSize, alphaSize;
+
+ if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) &&
+ getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) )
+ {
+ ALOGE("Couldn't find value for one of the pixel format attributes");
+ return EGL_FALSE;
+ }
+
+ //calculate the GL internal format
+ if ((redSize==8)&&(blueSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = GL_RGBA;
+ else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = GL_RGB;
+ else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
+ else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
+ else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
+ else return EGL_FALSE;
+
+ return EGL_TRUE;
+}
diff --git a/opengl/system/egl/eglDisplay.h b/opengl/system/egl/eglDisplay.h
new file mode 100644
index 0000000..9d979d9
--- /dev/null
+++ b/opengl/system/egl/eglDisplay.h
@@ -0,0 +1,89 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#ifndef _SYSTEM_EGL_DISPLAY_H
+#define _SYSTEM_EGL_DISPLAY_H
+
+#include <pthread.h>
+#include "glUtils.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "EGLClientIface.h"
+#include <utils/KeyedVector.h>
+
+#include <ui/PixelFormat.h>
+
+#define ATTRIBUTE_NONE -1
+//FIXME: are we in this namespace?
+using namespace android;
+
+class eglDisplay
+{
+public:
+ eglDisplay();
+ ~eglDisplay();
+
+ bool initialize(EGLClient_eglInterface *eglIface);
+ void terminate();
+
+ int getVersionMajor() const { return m_major; }
+ int getVersionMinor() const { return m_minor; }
+ bool initialized() const { return m_initialized; }
+
+ const char *queryString(EGLint name);
+
+ const EGLClient_glesInterface *gles_iface() const { return m_gles_iface; }
+ const EGLClient_glesInterface *gles2_iface() const { return m_gles2_iface; }
+
+ int getNumConfigs(){ return m_numConfigs; }
+ EGLBoolean getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value);
+ EGLBoolean setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value);
+ EGLBoolean getConfigGLPixelFormat(EGLConfig config, GLenum * format);
+ EGLBoolean getConfigNativePixelFormat(EGLConfig config, PixelFormat * format);
+
+ void dumpConfig(EGLConfig config);
+private:
+ EGLClient_glesInterface *loadGLESClientAPI(const char *libName,
+ EGLClient_eglInterface *eglIface,
+ void **libHandle);
+ EGLBoolean getAttribValue(EGLConfig config, EGLint attribIdxi, EGLint * value);
+ EGLBoolean setAttribValue(EGLConfig config, EGLint attribIdxi, EGLint value);
+ void processConfigs();
+
+private:
+ pthread_mutex_t m_lock;
+ bool m_initialized;
+ int m_major;
+ int m_minor;
+ int m_hostRendererVersion;
+ int m_numConfigs;
+ int m_numConfigAttribs;
+
+ /* This is the mapping between an attribute name to it's index in any given config */
+ DefaultKeyedVector<EGLint, EGLint> m_attribs;
+ /* This is an array of all config's attributes values stored in the following sequencial fasion (read: v[c,a] = the value of attribute <a> of config <c>)
+ * v[0,0],..,v[0,m_numConfigAttribs-1],
+ *...
+ * v[m_numConfigs-1,0],..,v[m_numConfigs-1,m_numConfigAttribs-1]
+ */
+ EGLint *m_configs;
+ EGLClient_glesInterface *m_gles_iface;
+ EGLClient_glesInterface *m_gles2_iface;
+ char *m_versionString;
+ char *m_vendorString;
+ char *m_extensionString;
+};
+
+#endif
diff --git a/opengl/system/egl/egl_ftable.h b/opengl/system/egl/egl_ftable.h
new file mode 100644
index 0000000..16d130c
--- /dev/null
+++ b/opengl/system/egl/egl_ftable.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+static const struct _egl_funcs_by_name {
+ const char *name;
+ void *proc;
+} egl_funcs_by_name[] = {
+ {"eglGetError", (void *)eglGetError},
+ {"eglGetDisplay", (void *)eglGetDisplay},
+ {"eglInitialize", (void *)eglInitialize},
+ {"eglTerminate", (void *)eglTerminate},
+ {"eglQueryString", (void *)eglQueryString},
+ {"eglGetConfigs", (void *)eglGetConfigs},
+ {"eglChooseConfig", (void *)eglChooseConfig},
+ {"eglGetConfigAttrib", (void *)eglGetConfigAttrib},
+ {"eglCreateWindowSurface", (void *)eglCreateWindowSurface},
+ {"eglCreatePbufferSurface", (void *)eglCreatePbufferSurface},
+ {"eglCreatePixmapSurface", (void *)eglCreatePixmapSurface},
+ {"eglDestroySurface", (void *)eglDestroySurface},
+ {"eglQuerySurface", (void *)eglQuerySurface},
+ {"eglBindAPI", (void *)eglBindAPI},
+ {"eglQueryAPI", (void *)eglQueryAPI},
+ {"eglWaitClient", (void *)eglWaitClient},
+ {"eglReleaseThread", (void *)eglReleaseThread},
+ {"eglCreatePbufferFromClientBuffer", (void *)eglCreatePbufferFromClientBuffer},
+ {"eglSurfaceAttrib", (void *)eglSurfaceAttrib},
+ {"eglBindTexImage", (void *)eglBindTexImage},
+ {"eglReleaseTexImage", (void *)eglReleaseTexImage},
+ {"eglSwapInterval", (void *)eglSwapInterval},
+ {"eglCreateContext", (void *)eglCreateContext},
+ {"eglDestroyContext", (void *)eglDestroyContext},
+ {"eglMakeCurrent", (void *)eglMakeCurrent},
+ {"eglGetCurrentContext", (void *)eglGetCurrentContext},
+ {"eglGetCurrentSurface", (void *)eglGetCurrentSurface},
+ {"eglGetCurrentDisplay", (void *)eglGetCurrentDisplay},
+ {"eglQueryContext", (void *)eglQueryContext},
+ {"eglWaitGL", (void *)eglWaitGL},
+ {"eglWaitNative", (void *)eglWaitNative},
+ {"eglSwapBuffers", (void *)eglSwapBuffers},
+ {"eglCopyBuffers", (void *)eglCopyBuffers},
+ {"eglGetProcAddress", (void *)eglGetProcAddress},
+ {"eglLockSurfaceKHR", (void *)eglLockSurfaceKHR},
+ {"eglUnlockSurfaceKHR", (void *)eglUnlockSurfaceKHR},
+ {"eglCreateImageKHR", (void *)eglCreateImageKHR},
+ {"eglDestroyImageKHR", (void *)eglDestroyImageKHR},
+ {"eglCreateSyncKHR", (void *)eglCreateSyncKHR},
+ {"eglDestroySyncKHR", (void *)eglDestroySyncKHR},
+ {"eglClientWaitSyncKHR", (void *)eglClientWaitSyncKHR},
+ {"eglGetSyncAttribKHR", (void *)eglGetSyncAttribKHR}
+};
+
+static const int egl_num_funcs = sizeof(egl_funcs_by_name) / sizeof(struct _egl_funcs_by_name);