From 085e3c56a3d1fac53729fee62f3de57eeb97ef98 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 23 Aug 2016 23:41:53 +0200 Subject: [PATCH] Import EGL/GLES translator --- external/android-emugl/CMakeLists.txt | 2 +- .../android-emugl/host/libs/CMakeLists.txt | 1 + .../host/libs/Translator/CMakeLists.txt | 4 + .../host/libs/Translator/EGL/Android.mk | 46 + .../host/libs/Translator/EGL/CMakeLists.txt | 26 + .../libs/Translator/EGL/ClientAPIExts.cpp | 159 ++ .../host/libs/Translator/EGL/ClientAPIExts.h | 29 + .../host/libs/Translator/EGL/ClientAPIExts.in | 201 ++ .../host/libs/Translator/EGL/EglConfig.cpp | 345 +++ .../host/libs/Translator/EGL/EglConfig.h | 148 ++ .../host/libs/Translator/EGL/EglContext.cpp | 96 + .../host/libs/Translator/EGL/EglContext.h | 74 + .../host/libs/Translator/EGL/EglDisplay.cpp | 416 +++ .../host/libs/Translator/EGL/EglDisplay.h | 116 + .../libs/Translator/EGL/EglGlobalInfo.cpp | 113 + .../host/libs/Translator/EGL/EglGlobalInfo.h | 110 + .../host/libs/Translator/EGL/EglImp.cpp | 981 +++++++ .../host/libs/Translator/EGL/EglOsApi.h | 188 ++ .../libs/Translator/EGL/EglOsApi_darwin.cpp | 395 +++ .../host/libs/Translator/EGL/EglOsApi_glx.cpp | 464 ++++ .../host/libs/Translator/EGL/EglOsApi_mir.cpp | 583 ++++ .../libs/Translator/EGL/EglOsApi_null.cpp | 46 + .../host/libs/Translator/EGL/EglOsApi_wgl.cpp | 1022 +++++++ .../libs/Translator/EGL/EglPbufferSurface.cpp | 75 + .../libs/Translator/EGL/EglPbufferSurface.h | 49 + .../host/libs/Translator/EGL/EglSurface.cpp | 45 + .../host/libs/Translator/EGL/EglSurface.h | 89 + .../libs/Translator/EGL/EglThreadInfo.cpp | 49 + .../host/libs/Translator/EGL/EglThreadInfo.h | 49 + .../host/libs/Translator/EGL/EglValidate.cpp | 112 + .../host/libs/Translator/EGL/EglValidate.h | 75 + .../libs/Translator/EGL/EglWindowSurface.cpp | 69 + .../libs/Translator/EGL/EglWindowSurface.h | 44 + .../host/libs/Translator/EGL/MacNative.h | 53 + .../host/libs/Translator/EGL/MacNative.m | 207 ++ .../Translator/EGL/MacPixelFormatsAttribs.h | 23 + .../Translator/EGL/MacPixelFormatsAttribs.m | 214 ++ .../host/libs/Translator/EGL/ThreadInfo.cpp | 83 + .../host/libs/Translator/EGL/ThreadInfo.h | 42 + .../host/libs/Translator/GLES_CM/Android.mk | 14 + .../libs/Translator/GLES_CM/CMakeLists.txt | 8 + .../libs/Translator/GLES_CM/GLEScmContext.cpp | 430 +++ .../libs/Translator/GLES_CM/GLEScmContext.h | 71 + .../libs/Translator/GLES_CM/GLEScmImp.cpp | 2367 +++++++++++++++++ .../libs/Translator/GLES_CM/GLEScmUtils.cpp | 101 + .../libs/Translator/GLES_CM/GLEScmUtils.h | 22 + .../Translator/GLES_CM/GLEScmValidate.cpp | 306 +++ .../libs/Translator/GLES_CM/GLEScmValidate.h | 50 + .../Translator/GLES_V2/.GLESv2Imp.cpp.swp | Bin 0 -> 16384 bytes .../host/libs/Translator/GLES_V2/Android.mk | 17 + .../libs/Translator/GLES_V2/CMakeLists.txt | 9 + .../libs/Translator/GLES_V2/GLESv2Context.cpp | 175 ++ .../libs/Translator/GLES_V2/GLESv2Context.h | 54 + .../libs/Translator/GLES_V2/GLESv2Imp.cpp | 2277 ++++++++++++++++ .../Translator/GLES_V2/GLESv2Validate.cpp | 198 ++ .../libs/Translator/GLES_V2/GLESv2Validate.h | 44 + .../libs/Translator/GLES_V2/ProgramData.cpp | 98 + .../libs/Translator/GLES_V2/ProgramData.h | 51 + .../libs/Translator/GLES_V2/ShaderParser.cpp | 350 +++ .../libs/Translator/GLES_V2/ShaderParser.h | 61 + .../host/libs/Translator/GLcommon/Android.mk | 43 + .../libs/Translator/GLcommon/CMakeLists.txt | 17 + .../Translator/GLcommon/FramebufferData.cpp | 215 ++ .../libs/Translator/GLcommon/GLDispatch.cpp | 117 + .../libs/Translator/GLcommon/GLESbuffer.cpp | 55 + .../libs/Translator/GLcommon/GLEScontext.cpp | 865 ++++++ .../libs/Translator/GLcommon/GLESpointer.cpp | 109 + .../libs/Translator/GLcommon/GLESvalidate.cpp | 194 ++ .../host/libs/Translator/GLcommon/GLutils.cpp | 20 + .../Translator/GLcommon/PaletteTexture.cpp | 170 ++ .../libs/Translator/GLcommon/RangeManip.cpp | 127 + .../libs/Translator/GLcommon/TextureUtils.cpp | 109 + .../host/libs/Translator/GLcommon/etc1.cpp | 670 +++++ .../Translator/GLcommon/objectNameManager.cpp | 369 +++ .../include/GLcommon/FramebufferData.h | 72 + .../Translator/include/GLcommon/GLDispatch.h | 50 + .../Translator/include/GLcommon/GLESbuffer.h | 47 + .../Translator/include/GLcommon/GLEScontext.h | 222 ++ .../Translator/include/GLcommon/GLESmacros.h | 48 + .../Translator/include/GLcommon/GLESpointer.h | 58 + .../include/GLcommon/GLESvalidate.h | 44 + .../Translator/include/GLcommon/GLLibrary.h | 36 + .../include/GLcommon/GLconversion_macros.h | 31 + .../Translator/include/GLcommon/GLutils.h | 54 + .../include/GLcommon/PaletteTexture.h | 25 + .../Translator/include/GLcommon/RangeManip.h | 69 + .../include/GLcommon/TextureUtils.h | 31 + .../include/GLcommon/TranslatorIfaces.h | 120 + .../libs/Translator/include/GLcommon/etc1.h | 108 + .../include/GLcommon/objectNameManager.h | 269 ++ .../shared/emugl/common/shared_library.h | 8 +- 91 files changed, 17910 insertions(+), 8 deletions(-) create mode 100644 external/android-emugl/host/libs/Translator/CMakeLists.txt create mode 100644 external/android-emugl/host/libs/Translator/EGL/Android.mk create mode 100644 external/android-emugl/host/libs/Translator/EGL/CMakeLists.txt create mode 100644 external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.in create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglConfig.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglConfig.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglContext.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglContext.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglDisplay.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglDisplay.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglImp.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi_darwin.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi_glx.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi_mir.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi_null.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglOsApi_wgl.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglSurface.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglSurface.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglValidate.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglValidate.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/MacNative.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/MacNative.m create mode 100644 external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.h create mode 100644 external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.m create mode 100644 external/android-emugl/host/libs/Translator/EGL/ThreadInfo.cpp create mode 100644 external/android-emugl/host/libs/Translator/EGL/ThreadInfo.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/Android.mk create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/CMakeLists.txt create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmImp.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/Android.mk create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/CMakeLists.txt create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Context.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Context.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.h create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.h create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/Android.mk create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/CMakeLists.txt create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/FramebufferData.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLDispatch.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLESbuffer.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLEScontext.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLESpointer.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLESvalidate.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/GLutils.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/PaletteTexture.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/RangeManip.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/TextureUtils.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/etc1.cpp create mode 100644 external/android-emugl/host/libs/Translator/GLcommon/objectNameManager.cpp create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/FramebufferData.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLDispatch.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLESbuffer.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLEScontext.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLESpointer.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLESvalidate.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLLibrary.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLconversion_macros.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/GLutils.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/PaletteTexture.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/RangeManip.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/TextureUtils.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/etc1.h create mode 100644 external/android-emugl/host/libs/Translator/include/GLcommon/objectNameManager.h diff --git a/external/android-emugl/CMakeLists.txt b/external/android-emugl/CMakeLists.txt index dcaccc7..29edadb 100644 --- a/external/android-emugl/CMakeLists.txt +++ b/external/android-emugl/CMakeLists.txt @@ -7,7 +7,6 @@ include_directories( ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include ${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs - ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/include ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include/libOpenglRender ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv1_dec ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv1_dec @@ -15,6 +14,7 @@ include_directories( ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv2_dec ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/renderControl_dec ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/renderControl_dec + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/ ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/include ${MIRCLIENT_INCLUDE_DIRS}) diff --git a/external/android-emugl/host/libs/CMakeLists.txt b/external/android-emugl/host/libs/CMakeLists.txt index bb38eb0..2e7bf51 100644 --- a/external/android-emugl/host/libs/CMakeLists.txt +++ b/external/android-emugl/host/libs/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory(GLESv2_dec) add_subdirectory(libOpenGLESDispatch) add_subdirectory(libOpenglRender) add_subdirectory(renderControl_dec) +add_subdirectory(Translator) diff --git a/external/android-emugl/host/libs/Translator/CMakeLists.txt b/external/android-emugl/host/libs/Translator/CMakeLists.txt new file mode 100644 index 0000000..5c2e6d0 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(GLcommon) +add_subdirectory(EGL) +add_subdirectory(GLES_CM) +add_subdirectory(GLES_V2) diff --git a/external/android-emugl/host/libs/Translator/EGL/Android.mk b/external/android-emugl/host/libs/Translator/EGL/Android.mk new file mode 100644 index 0000000..28c2120 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/Android.mk @@ -0,0 +1,46 @@ +LOCAL_PATH := $(call my-dir) + +host_OS_SRCS := +host_common_LDLIBS := + +ifeq ($(BUILD_TARGET_OS),linux) + host_OS_SRCS = EglOsApi_glx.cpp + host_common_LDLIBS += -lGL -lX11 -ldl -lpthread +endif + +ifeq ($(BUILD_TARGET_OS),darwin) + host_OS_SRCS = EglOsApi_darwin.cpp \ + MacNative.m \ + MacPixelFormatsAttribs.m + + host_common_LDLIBS += -Wl,-framework,AppKit +endif + +ifeq ($(BUILD_TARGET_OS),windows) + host_OS_SRCS = EglOsApi_wgl.cpp + host_common_LDLIBS += -lgdi32 +endif + +host_common_SRC_FILES := \ + $(host_OS_SRCS) \ + ThreadInfo.cpp \ + EglImp.cpp \ + EglConfig.cpp \ + EglContext.cpp \ + EglGlobalInfo.cpp \ + EglValidate.cpp \ + EglSurface.cpp \ + EglWindowSurface.cpp \ + EglPbufferSurface.cpp \ + EglThreadInfo.cpp \ + EglDisplay.cpp \ + ClientAPIExts.cpp + +### EGL host implementation ######################## +$(call emugl-begin-host-shared-library,lib$(BUILD_TARGET_SUFFIX)EGL_translator) +$(call emugl-import,libGLcommon) + +LOCAL_LDLIBS += $(host_common_LDLIBS) +LOCAL_SRC_FILES := $(host_common_SRC_FILES) + +$(call emugl-end-module) diff --git a/external/android-emugl/host/libs/Translator/EGL/CMakeLists.txt b/external/android-emugl/host/libs/Translator/EGL/CMakeLists.txt new file mode 100644 index 0000000..3c55ead --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/CMakeLists.txt @@ -0,0 +1,26 @@ +set(SOURCES + ThreadInfo.cpp + EglImp.cpp + EglConfig.cpp + EglContext.cpp + EglGlobalInfo.cpp + EglValidate.cpp + EglSurface.cpp + EglWindowSurface.cpp + EglPbufferSurface.cpp + EglThreadInfo.cpp + EglDisplay.cpp + EglOsApi_glx.cpp + ClientAPIExts.cpp) + +include_directories(BEFORE + ${EGL_INCLUDE_DIRS} + ${GLESv2_INCLUDE_DIRS}) + +add_library(EGL_translator SHARED ${SOURCES}) +target_link_libraries(EGL_translator + GLcommon + ${EGL_LDFLAGS} + ${EGL_LIBRARIES} + ${GLESv2_LDFLAGS} + ${GLESv2_LIBRARIES}) diff --git a/external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.cpp b/external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.cpp new file mode 100644 index 0000000..0aeb44e --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/ClientAPIExts.cpp @@ -0,0 +1,159 @@ +/* +* 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 "EglGlobalInfo.h" +#include "GLcommon/GLutils.h" +#include "GLcommon/TranslatorIfaces.h" +#include "ThreadInfo.h" +#include +#include + +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[MAX_GLES_VERSION-1]; + +#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 GLESiface *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 \ + { \ + ThreadInfo* thread = getThreadInfo(); \ + if (!thread->eglContext.Ptr()) { \ + return; \ + } \ + int idx = (int)thread->eglContext->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 \ + { \ + ThreadInfo* thread = getThreadInfo(); \ + if (!thread->eglContext.Ptr()) { \ + return (rtype)0; \ + } \ + int idx = (int)thread->eglContext->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, (__translatorMustCastToProperFunctionPointerType)_egl_ ## fname}, +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + +static struct _client_ext_funcs { + const char *fname; + __translatorMustCastToProperFunctionPointerType 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. +// +__translatorMustCastToProperFunctionPointerType getProcAddress(const char *fname) +{ + for (int i=0; i 0 ? 1 : 0), + m_samples_per_pixel(samples_per_pixel), + m_stencil_size(stencil_size), + m_surface_type(surface_type), + m_transparent_type(transparent_type), + m_trans_red_val(trans_red_val), + m_trans_green_val(trans_green_val), + m_trans_blue_val(trans_blue_val), + m_conformant(((red_size + green_size + blue_size + alpha_size > 0) && + (caveat != EGL_NON_CONFORMANT_CONFIG)) ? + m_renderable_type : 0), + m_nativeFormat(frmt) {} + + +EglConfig::EglConfig(const EglConfig& conf) : + m_buffer_size(conf.m_buffer_size), + m_red_size(conf.m_red_size), + m_green_size(conf.m_green_size), + m_blue_size(conf.m_blue_size), + m_alpha_size(conf.m_alpha_size), + m_bind_to_tex_rgb(conf.m_bind_to_tex_rgb), + m_bind_to_tex_rgba(conf.m_bind_to_tex_rgba), + m_caveat(conf.m_caveat), + m_config_id(conf.m_config_id), + m_native_config_id(conf.m_native_config_id), + m_frame_buffer_level(conf.m_frame_buffer_level), + m_depth_size(conf.m_depth_size), + m_max_pbuffer_width(conf.m_max_pbuffer_width), + m_max_pbuffer_height(conf.m_max_pbuffer_height), + m_max_pbuffer_size(conf.m_max_pbuffer_size), + m_max_swap_interval(conf.m_max_swap_interval), + m_min_swap_interval(conf.m_min_swap_interval), + m_native_renderable(conf.m_native_renderable), + m_renderable_type(conf.m_renderable_type), + m_native_visual_id(conf.m_native_visual_id), + m_native_visual_type(conf.m_native_visual_type), + m_sample_buffers_num(conf.m_sample_buffers_num), + m_samples_per_pixel(conf.m_samples_per_pixel), + m_stencil_size(conf.m_stencil_size), + m_surface_type(conf.m_surface_type), + m_transparent_type(conf.m_transparent_type), + m_trans_red_val(conf.m_trans_red_val), + m_trans_green_val(conf.m_trans_green_val), + m_trans_blue_val(conf.m_trans_blue_val), + m_conformant(conf.m_conformant), + m_nativeFormat(conf.m_nativeFormat->clone()) {} + + +EglConfig::EglConfig(const EglConfig& conf, + EGLint config_id, + EGLint red_size, + EGLint green_size, + EGLint blue_size, + EGLint alpha_size) : + m_buffer_size(red_size + green_size + blue_size + alpha_size), + m_red_size(red_size), + m_green_size(green_size), + m_blue_size(blue_size), + m_alpha_size(alpha_size), + m_bind_to_tex_rgb(conf.m_bind_to_tex_rgb), + m_bind_to_tex_rgba(conf.m_bind_to_tex_rgba), + m_caveat(conf.m_caveat), + m_config_id(config_id), + m_native_config_id(conf.m_native_config_id), + m_frame_buffer_level(conf.m_frame_buffer_level), + m_depth_size(conf.m_depth_size), + m_max_pbuffer_width(conf.m_max_pbuffer_width), + m_max_pbuffer_height(conf.m_max_pbuffer_height), + m_max_pbuffer_size(conf.m_max_pbuffer_size), + m_max_swap_interval(conf.m_max_swap_interval), + m_min_swap_interval(conf.m_min_swap_interval), + m_native_renderable(conf.m_native_renderable), + m_renderable_type(conf.m_renderable_type), + m_native_visual_id(conf.m_native_visual_id), + m_native_visual_type(conf.m_native_visual_type), + m_sample_buffers_num(conf.m_sample_buffers_num), + m_samples_per_pixel(conf.m_samples_per_pixel), + m_stencil_size(conf.m_stencil_size), + m_surface_type(conf.m_surface_type), + m_transparent_type(conf.m_transparent_type), + m_trans_red_val(conf.m_trans_red_val), + m_trans_green_val(conf.m_trans_green_val), + m_trans_blue_val(conf.m_trans_blue_val), + m_conformant(conf.m_conformant), + m_nativeFormat(conf.m_nativeFormat->clone()) {}; + + +bool EglConfig::getConfAttrib(EGLint attrib,EGLint* val) const { + switch(attrib) { + case EGL_BUFFER_SIZE: + *val = m_buffer_size; + break; + case EGL_RED_SIZE: + *val = m_red_size; + break; + case EGL_GREEN_SIZE: + *val = m_green_size; + break; + case EGL_BLUE_SIZE: + *val = m_blue_size; + break; + case EGL_ALPHA_SIZE: + *val = m_alpha_size; + break; + case EGL_BIND_TO_TEXTURE_RGB: + *val = m_bind_to_tex_rgb; + break; + case EGL_BIND_TO_TEXTURE_RGBA: + *val = m_bind_to_tex_rgba; + break; + case EGL_CONFIG_CAVEAT: + *val = m_caveat; + break; + case EGL_CONFIG_ID: + *val = m_config_id; + break; + case EGL_DEPTH_SIZE: + *val = m_depth_size; + break; + case EGL_LEVEL: + *val = m_frame_buffer_level; + break; + case EGL_MAX_PBUFFER_WIDTH: + *val = m_max_pbuffer_width; + break; + case EGL_MAX_PBUFFER_HEIGHT: + *val = m_max_pbuffer_height; + break; + case EGL_MAX_PBUFFER_PIXELS: + *val = m_max_pbuffer_size; + break; + case EGL_MAX_SWAP_INTERVAL: + *val = m_max_swap_interval; + break; + case EGL_MIN_SWAP_INTERVAL: + *val = m_min_swap_interval; + break; + case EGL_NATIVE_RENDERABLE: + *val = m_native_renderable; + break; + case EGL_NATIVE_VISUAL_ID: + *val = m_native_visual_id; + break; + case EGL_NATIVE_VISUAL_TYPE: + *val = m_native_visual_type; + break; + case EGL_RENDERABLE_TYPE: + *val = m_renderable_type; + break; + case EGL_SAMPLE_BUFFERS: + *val = m_sample_buffers_num; + break; + case EGL_SAMPLES: + *val = m_samples_per_pixel; + break; + case EGL_STENCIL_SIZE: + *val = m_stencil_size; + break; + case EGL_SURFACE_TYPE: + *val = m_surface_type; + break; + case EGL_TRANSPARENT_TYPE: + *val =m_transparent_type; + break; + case EGL_TRANSPARENT_RED_VALUE: + *val = m_trans_red_val; + break; + case EGL_TRANSPARENT_GREEN_VALUE: + *val = m_trans_green_val; + break; + case EGL_TRANSPARENT_BLUE_VALUE: + *val = m_trans_blue_val; + break; + case EGL_CONFORMANT: + *val = m_conformant; + break; + default: + return false; + } + return true; +} + +// checking compitabilty between *this configuration and another configuration +// the compitability is checked againsed red,green,blue,buffer stencil and depth sizes +bool EglConfig::compatibleWith(const EglConfig& conf) const { + + return m_buffer_size == conf.m_buffer_size && + m_red_size == conf.m_red_size && + m_green_size == conf.m_green_size && + m_blue_size == conf.m_blue_size && + m_depth_size == conf.m_depth_size && + m_stencil_size == conf.m_stencil_size; +} + +//following the sorting EGLconfig as in spec +bool EglConfig::operator<(const EglConfig& conf) const { + //0 + if(m_conformant != conf.m_conformant) { + return m_conformant != 0; //We want the conformant ones first + } + //1 + if(m_caveat != conf.m_caveat) { + return m_caveat < conf.m_caveat; // EGL_NONE < EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG + } + //2 TODO: + + //3 + if(m_buffer_size != conf.m_buffer_size) { + return m_buffer_size < conf.m_buffer_size; + } + //4 + if(m_sample_buffers_num != conf.m_sample_buffers_num) { + return m_sample_buffers_num < conf.m_sample_buffers_num; + } + //5 + if(m_samples_per_pixel != conf.m_samples_per_pixel) { + return m_samples_per_pixel < conf.m_samples_per_pixel; + } + //6 + if(m_depth_size != conf.m_depth_size) { + return m_depth_size < conf.m_depth_size; + } + //7 + if(m_stencil_size != conf.m_stencil_size) { + return m_stencil_size < conf.m_stencil_size; + } + //8 implementation defined + if(m_native_visual_type != conf.m_native_visual_type) { + return m_native_visual_type < conf.m_native_visual_type; + } + //9 + return m_config_id < conf.m_config_id; +} + +bool EglConfig::operator>=(const EglConfig& conf) const { + return !((*this) < conf); +} +#define CHECK_PROP(dummy,prop_name,op) \ + if((dummy.prop_name != EGL_DONT_CARE) && (dummy.prop_name op prop_name)) return false; +#define CHECK_PROP_CAST(dummy,prop_name,op) \ + if((((EGLint)dummy.prop_name) != EGL_DONT_CARE) && (dummy.prop_name op prop_name)) return false; +//checking if config stands for all the selection crateria of dummy as defined by EGL spec +bool EglConfig::chosen(const EglConfig& dummy) const { + + //atleast + CHECK_PROP(dummy,m_buffer_size,>); + CHECK_PROP(dummy,m_red_size,>); + CHECK_PROP(dummy,m_green_size,>); + CHECK_PROP(dummy,m_blue_size,>); + CHECK_PROP(dummy,m_alpha_size,>); + CHECK_PROP(dummy,m_depth_size,>); + CHECK_PROP(dummy,m_stencil_size,>); + CHECK_PROP(dummy,m_sample_buffers_num,>); + CHECK_PROP(dummy,m_samples_per_pixel,>); + + //exact + CHECK_PROP(dummy,m_frame_buffer_level,!=); + CHECK_PROP(dummy,m_config_id,!=); + CHECK_PROP(dummy,m_native_visual_type,!=); + CHECK_PROP(dummy,m_max_swap_interval ,!=); + CHECK_PROP(dummy,m_min_swap_interval ,!=); + CHECK_PROP(dummy,m_trans_red_val ,!=); + CHECK_PROP(dummy,m_trans_green_val ,!=); + CHECK_PROP(dummy,m_trans_blue_val ,!=); + //exact - when cast to EGLint is needed when comparing to EGL_DONT_CARE + CHECK_PROP_CAST(dummy,m_bind_to_tex_rgb ,!=); + CHECK_PROP_CAST(dummy,m_bind_to_tex_rgba,!=); + CHECK_PROP_CAST(dummy,m_caveat,!=); + CHECK_PROP_CAST(dummy,m_native_renderable ,!=); + CHECK_PROP_CAST(dummy,m_transparent_type ,!=); + + //mask + if(dummy.m_surface_type != EGL_DONT_CARE && + ((dummy.m_surface_type & m_surface_type) != dummy.m_surface_type)) return false; + + if(dummy.m_conformant != (EGLenum)EGL_DONT_CARE && + ((dummy.m_conformant & m_conformant) != dummy.m_conformant)) return false; + + if(dummy.m_renderable_type != EGL_DONT_CARE && + ((dummy.m_renderable_type & m_renderable_type) != dummy.m_renderable_type)) return false; + + //passed all checks + return true; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglConfig.h b/external/android-emugl/host/libs/Translator/EGL/EglConfig.h new file mode 100644 index 0000000..9eee1fd --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglConfig.h @@ -0,0 +1,148 @@ +/* +* 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_CONFIG_H +#define EGL_CONFIG_H + +#include "EglOsApi.h" +#include + +#include + +#define MIN_SWAP_INTERVAL 1 +#define MAX_SWAP_INTERVAL 10 + +// A class used to model the content of an EGLConfig object. +// This is really a structure with several fields that can be queried +// individually with getConfigAttrib(), and compared for sorting according +// to the EGLConfig specification. +class EglConfig { +public: + // Return the value of a given attribute, identified by its name |attrib| + // (e.g. EGL_CONFIG_ID). On success, return true and sets |*val| to the + // attribute value. On failure (unknown |attrib| value), return false. + bool getConfAttrib(EGLint attrib, EGLint* val) const; + + // Comparison operators used to sort EglConfig instances. + bool operator<(const EglConfig& conf) const; + bool operator>=(const EglConfig& conf) const; + + // Return true iff this instance is compatible with |conf|, i.e. that + // they have the same red/green/blue/depth/stencil sizes. + bool compatibleWith(const EglConfig& conf) const; //compatibility + + // Return true iff this instance matches the minimal requirements of + // another EglConfig |dummy|. Any attribute value in |dummy| that isn't + // EGL_DONT_CARE will be tested against the corresponding value in the + // instance. + bool chosen(const EglConfig& dummy) const; + + // Return the EGL_SURFACE_TYPE value. + EGLint surfaceType() const { return m_surface_type;}; + + // Return the EGL_CONFIG_ID value. + EGLint id() const { return m_config_id; } + + // Return the native configuration id. By default, this is the same as id() + // Except if the EglConfig was created with the overriding copy-constructor + // below. In which case nativeId() is the id() value of the source + // EglConfig, while id() will return the overriden value. + EGLint nativeId() const { return m_native_config_id; } + + // Return the native pixel format for this config. + EglOS::PixelFormat* nativeFormat() const { return m_nativeFormat; } + + // Constructor for a new instance, all values explicitly defined. + EglConfig(EGLint red_size, + EGLint green_size, + EGLint blue_size, + EGLint alpha_size, + EGLenum caveat, + EGLint config_id, + EGLint depth_size, + EGLint frame_buffer_level, + EGLint max_pbuffer_width, + EGLint max_pbuffer_height, + EGLint max_pbuffer_size, + EGLBoolean native_renderable, + EGLint renderable_type, + EGLint native_visual_id, + EGLint native_visual_type, + EGLint samples_per_pixel, + EGLint stencil_size, + EGLint surface_type, + EGLenum transparent_type, + EGLint trans_red_val, + EGLint trans_green_val, + EGLint trans_blue_val, + EglOS::PixelFormat* frmt); + + // Copy-constructor. + EglConfig(const EglConfig& conf); + + // A copy-constructor that allows one to override the configuration ID + // and red/green/blue/alpha sizes. Note that this is how one creates + // an EglConfig instance where nativeId() and id() return different + // values (see comment for nativeId()). + EglConfig(const EglConfig& conf, + EGLint config_id, + EGLint red_size, + EGLint green_size, + EGLint blue_size, + EGLint alpha_size); + + // Destructor is required to get id of pixel format instance. + ~EglConfig() { + delete m_nativeFormat; + } + +private: + const EGLint m_buffer_size; + const EGLint m_red_size; + const EGLint m_green_size; + const EGLint m_blue_size; + const EGLint m_alpha_size; + const EGLBoolean m_bind_to_tex_rgb; + const EGLBoolean m_bind_to_tex_rgba; + const EGLenum m_caveat; + const EGLint m_config_id; + const EGLint m_native_config_id; + const EGLint m_frame_buffer_level; + const EGLint m_depth_size; + const EGLint m_max_pbuffer_width; + const EGLint m_max_pbuffer_height; + const EGLint m_max_pbuffer_size; + const EGLint m_max_swap_interval; + const EGLint m_min_swap_interval; + const EGLBoolean m_native_renderable; + const EGLint m_renderable_type; + const EGLint m_native_visual_id; + const EGLint m_native_visual_type; + const EGLint m_sample_buffers_num; + const EGLint m_samples_per_pixel; + const EGLint m_stencil_size; + const EGLint m_surface_type; + const EGLenum m_transparent_type; + const EGLint m_trans_red_val; + const EGLint m_trans_green_val; + const EGLint m_trans_blue_val; + const EGLenum m_conformant; + + EglOS::PixelFormat* m_nativeFormat; +}; + +typedef std::list ConfigsList; + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglContext.cpp b/external/android-emugl/host/libs/Translator/EGL/EglContext.cpp new file mode 100644 index 0000000..28247c6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglContext.cpp @@ -0,0 +1,96 @@ +/* +* 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 "EglContext.h" +#include "EglDisplay.h" +#include "EglGlobalInfo.h" +#include "EglOsApi.h" + +unsigned int EglContext::s_nextContextHndl = 0; + +extern EglGlobalInfo* g_eglInfo; // defined in EglImp.cpp + +bool EglContext::usingSurface(SurfacePtr surface) { + return surface.Ptr() == m_read.Ptr() || surface.Ptr() == m_draw.Ptr(); +} + +EglContext::EglContext(EglDisplay *dpy, + EglOS::Context* context, + ContextPtr shared_context, + EglConfig* config, + GLEScontext* glesCtx, + GLESVersion ver, + ObjectNameManager* mngr) : + m_dpy(dpy), + m_native(context), + m_config(config), + m_glesContext(glesCtx), + m_read(NULL), + m_draw(NULL), + m_version(ver), + m_mngr(mngr) { + m_shareGroup = shared_context.Ptr()? + mngr->attachShareGroup(context,shared_context->nativeType()): + mngr->createShareGroup(context); + m_hndl = ++s_nextContextHndl; +} + +EglContext::~EglContext() +{ + // + // remove the context in the underlying OS layer + // + m_dpy->nativeType()->destroyContext(m_native); + + // + // call the client-api to remove the GLES context + // + g_eglInfo->getIface(version())->deleteGLESContext(m_glesContext); + + if (m_mngr) + { + m_mngr->deleteShareGroup(m_native); + } +} + +void EglContext::setSurfaces(SurfacePtr read,SurfacePtr draw) +{ + m_read = read; + m_draw = draw; +} + +bool EglContext::getAttrib(EGLint attrib,EGLint* value) { + switch(attrib) { + case EGL_CONFIG_ID: + *value = m_config->id(); + break; + default: + return false; + } + return true; +} + +bool EglContext::attachImage(unsigned int imageId,ImagePtr img){ + if(m_attachedImages.find(imageId) == m_attachedImages.end()){ + m_attachedImages[imageId] = img; + return true; + } + return false; +} + +void EglContext::detachImage(unsigned int imageId){ + m_attachedImages.erase(imageId); +} + diff --git a/external/android-emugl/host/libs/Translator/EGL/EglContext.h b/external/android-emugl/host/libs/Translator/EGL/EglContext.h new file mode 100644 index 0000000..2189d94 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglContext.h @@ -0,0 +1,74 @@ +/* +* 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 "EglConfig.h" +#include "EglOsApi.h" +#include "EglSurface.h" + +#include +#include +#include + +#include "emugl/common/smart_ptr.h" + +#include + +#include + +class EglContext; +typedef emugl::SmartPtr ContextPtr; + +class EglDisplay; + +class EglContext { + +public: + + EglContext(EglDisplay *dpy, EglOS::Context* context,ContextPtr shared_context,EglConfig* config,GLEScontext* glesCtx,GLESVersion ver,ObjectNameManager* mngr); + bool usingSurface(SurfacePtr surface); + EglOS::Context* nativeType() const { return m_native; } + bool getAttrib(EGLint attrib,EGLint* value); + SurfacePtr read(){ return m_read;}; + SurfacePtr draw(){ return m_draw;}; + ShareGroupPtr getShareGroup(){return m_shareGroup;} + EglConfig* getConfig(){ return m_config;}; + GLESVersion version(){return m_version;}; + GLEScontext* getGlesContext(){return m_glesContext;} + void setSurfaces(SurfacePtr read,SurfacePtr draw); + unsigned int getHndl(){return m_hndl;} + bool attachImage(unsigned int imageId,ImagePtr img); + void detachImage(unsigned int imageId); + + ~EglContext(); + +private: + static unsigned int s_nextContextHndl; + EglDisplay *m_dpy; + EglOS::Context* m_native; + EglConfig* m_config; + GLEScontext* m_glesContext; + ShareGroupPtr m_shareGroup; + SurfacePtr m_read; + SurfacePtr m_draw; + GLESVersion m_version; + ObjectNameManager *m_mngr; + unsigned int m_hndl; + ImagesHndlMap m_attachedImages; +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglDisplay.cpp b/external/android-emugl/host/libs/Translator/EGL/EglDisplay.cpp new file mode 100644 index 0000000..33b8503 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglDisplay.cpp @@ -0,0 +1,416 @@ +/* +* 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 "EglConfig.h" +#include "EglOsApi.h" +#include + +EglDisplay::EglDisplay(EGLNativeDisplayType dpy, + EglOS::Display* idpy) : + m_dpy(dpy), + m_idpy(idpy), + m_initialized(false), + m_configInitialized(false), + m_nextEglImageId(0), + m_globalSharedContext(NULL) +{ + m_manager[GLES_1_1] = new ObjectNameManager(&m_globalNameSpace); + m_manager[GLES_2_0] = new ObjectNameManager(&m_globalNameSpace); +}; + +EglDisplay::~EglDisplay() { + emugl::Mutex::AutoLock mutex(m_lock); + + // + // Destroy the global context if one was created. + // (should be true for windows platform only) + // + if (m_globalSharedContext != NULL) { + m_idpy->destroyContext(m_globalSharedContext); + } + + m_idpy->release(); + + for(ConfigsList::iterator it = m_configs.begin(); + it != m_configs.end(); + it++) { + delete *it; + } + + delete m_manager[GLES_1_1]; + delete m_manager[GLES_2_0]; + + delete m_idpy; +} + +void EglDisplay::initialize(int renderableType) { + emugl::Mutex::AutoLock mutex(m_lock); + m_initialized = true; + initConfigurations(renderableType); + m_configInitialized = true; +} + +bool EglDisplay::isInitialize() { return m_initialized;} + +void EglDisplay::terminate(){ + emugl::Mutex::AutoLock mutex(m_lock); + m_contexts.clear(); + m_surfaces.clear(); + m_initialized = false; +} + +static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) { + return *first < *second ; +} + +void EglDisplay::addSimplePixelFormat(int red_size, + int green_size, + int blue_size, + int alpha_size) { + m_configs.sort(compareEglConfigsPtrs); + + EGLConfig match; + + EglConfig dummy(red_size, + green_size, + blue_size, + alpha_size, // RGB_565 + EGL_DONT_CARE, + EGL_DONT_CARE, + 16, // Depth + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + EGL_DONT_CARE, + NULL); + + if(!doChooseConfigs(dummy, &match, 1)) + { + return; + } + + const EglConfig* config = (EglConfig*)match; + + int bSize; + config->getConfAttrib(EGL_BUFFER_SIZE,&bSize); + + if(bSize == 16) + { + return; + } + + int max_config_id = 0; + + for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { + EGLint id; + (*it)->getConfAttrib(EGL_CONFIG_ID, &id); + if(id > max_config_id) + max_config_id = id; + } + + EglConfig* newConfig = new EglConfig(*config,max_config_id+1, + red_size, green_size, blue_size, + alpha_size); + + m_configs.push_back(newConfig); +} + +void EglDisplay::addMissingConfigs() { + addSimplePixelFormat(5, 6, 5, 0); // RGB_565 + addSimplePixelFormat(8, 8, 8, 0); // RGB_888 + // (Host GPUs that are newer may not list RGB_888 + // out of the box.) +} + +void EglDisplay::initConfigurations(int renderableType) { + if (m_configInitialized) { + return; + } + m_idpy->queryConfigs(renderableType, addConfig, this); + + addMissingConfigs(); + m_configs.sort(compareEglConfigsPtrs); + +#if EMUGL_DEBUG + for (ConfigsList::const_iterator it = m_configs.begin(); + it != m_configs.end(); + it++) { + EglConfig* config = *it; + EGLint red, green, blue, alpha, depth, stencil, renderable, surface; + config->getConfAttrib(EGL_RED_SIZE, &red); + config->getConfAttrib(EGL_GREEN_SIZE, &green); + config->getConfAttrib(EGL_BLUE_SIZE, &blue); + config->getConfAttrib(EGL_ALPHA_SIZE, &alpha); + config->getConfAttrib(EGL_DEPTH_SIZE, &depth); + config->getConfAttrib(EGL_STENCIL_SIZE, &stencil); + config->getConfAttrib(EGL_RENDERABLE_TYPE, &renderable); + config->getConfAttrib(EGL_SURFACE_TYPE, &surface); + } +#endif // EMUGL_DEBUG +} + +EglConfig* EglDisplay::getConfig(EGLConfig conf) const { + emugl::Mutex::AutoLock mutex(m_lock); + + for(ConfigsList::const_iterator it = m_configs.begin(); + it != m_configs.end(); + it++) { + if(static_cast(*it) == conf) { + return (*it); + } + } + return NULL; +} + +SurfacePtr EglDisplay::getSurface(EGLSurface surface) const { + emugl::Mutex::AutoLock mutex(m_lock); + /* surface is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(surface); + SurfacesHndlMap::const_iterator it = m_surfaces.find(hndl); + return it != m_surfaces.end() ? + (*it).second : + SurfacePtr(NULL); +} + +ContextPtr EglDisplay::getContext(EGLContext ctx) const { + emugl::Mutex::AutoLock mutex(m_lock); + /* ctx is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(ctx); + ContextsHndlMap::const_iterator it = m_contexts.find(hndl); + return it != m_contexts.end() ? + (*it).second : + ContextPtr(NULL); +} + +bool EglDisplay::removeSurface(EGLSurface s) { + emugl::Mutex::AutoLock mutex(m_lock); + /* s is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(s); + SurfacesHndlMap::iterator it = m_surfaces.find(hndl); + if(it != m_surfaces.end()) { + m_surfaces.erase(it); + return true; + } + return false; +} + +bool EglDisplay::removeContext(EGLContext ctx) { + emugl::Mutex::AutoLock mutex(m_lock); + /* ctx is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(ctx); + ContextsHndlMap::iterator it = m_contexts.find(hndl); + if(it != m_contexts.end()) { + m_contexts.erase(it); + return true; + } + return false; +} + +bool EglDisplay::removeContext(ContextPtr ctx) { + emugl::Mutex::AutoLock mutex(m_lock); + + ContextsHndlMap::iterator it; + for(it = m_contexts.begin(); it != m_contexts.end();it++) { + if((*it).second.Ptr() == ctx.Ptr()){ + break; + } + } + if(it != m_contexts.end()) { + m_contexts.erase(it); + return true; + } + return false; +} + +EglConfig* EglDisplay::getConfig(EGLint id) const { + emugl::Mutex::AutoLock mutex(m_lock); + + for(ConfigsList::const_iterator it = m_configs.begin(); + it != m_configs.end(); + it++) { + if((*it)->id() == id) { + return (*it); + + } + } + return NULL; +} + +int EglDisplay::getConfigs(EGLConfig* configs,int config_size) const { + emugl::Mutex::AutoLock mutex(m_lock); + int i = 0; + for(ConfigsList::const_iterator it = m_configs.begin(); + it != m_configs.end() && i < config_size; + i++, it++) { + configs[i] = static_cast(*it); + } + return i; +} + +int EglDisplay::chooseConfigs(const EglConfig& dummy, + EGLConfig* configs, + int config_size) const { + emugl::Mutex::AutoLock mutex(m_lock); + return doChooseConfigs(dummy, configs, config_size); +} + +int EglDisplay::doChooseConfigs(const EglConfig& dummy, + EGLConfig* configs, + int config_size) const { + int added = 0; + for(ConfigsList::const_iterator it = m_configs.begin(); + it != m_configs.end() && (added < config_size || !configs); + it++) { + if( (*it)->chosen(dummy)){ + if(configs) { + configs[added] = static_cast(*it); + } + added++; + } + } + //no need to sort since the configurations are saved already in sorted maner + return added; +} + +EGLSurface EglDisplay::addSurface(SurfacePtr s ) { + emugl::Mutex::AutoLock mutex(m_lock); + unsigned int hndl = s.Ptr()->getHndl(); + EGLSurface ret =reinterpret_cast (hndl); + + if(m_surfaces.find(hndl) != m_surfaces.end()) { + return ret; + } + + m_surfaces[hndl] = s; + return ret; +} + +EGLContext EglDisplay::addContext(ContextPtr ctx ) { + emugl::Mutex::AutoLock mutex(m_lock); + + unsigned int hndl = ctx.Ptr()->getHndl(); + EGLContext ret = reinterpret_cast (hndl); + + if(m_contexts.find(hndl) != m_contexts.end()) { + return ret; + } + m_contexts[hndl] = ctx; + return ret; +} + + +EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) { + emugl::Mutex::AutoLock mutex(m_lock); + do { ++m_nextEglImageId; } while(m_nextEglImageId == 0); + img->imageId = m_nextEglImageId; + m_eglImages[m_nextEglImageId] = img; + return reinterpret_cast(m_nextEglImageId); +} + +ImagePtr EglDisplay::getImage(EGLImageKHR img) const { + emugl::Mutex::AutoLock mutex(m_lock); + /* img is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(img); + ImagesHndlMap::const_iterator i( m_eglImages.find(hndl) ); + return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL); +} + +bool EglDisplay:: destroyImageKHR(EGLImageKHR img) { + emugl::Mutex::AutoLock mutex(m_lock); + /* img is "key" in map. */ + unsigned int hndl = SafeUIntFromPointer(img); + ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); + if (i != m_eglImages.end()) + { + m_eglImages.erase(i); + return true; + } + return false; +} + +EglOS::Context* EglDisplay::getGlobalSharedContext() const { + emugl::Mutex::AutoLock mutex(m_lock); +#ifndef _WIN32 + // find an existing OpenGL context to share with, if exist + EglOS::Context* ret = + (EglOS::Context*)m_manager[GLES_1_1]->getGlobalContext(); + if (!ret) + ret = (EglOS::Context*)m_manager[GLES_2_0]->getGlobalContext(); + return ret; +#else + if (!m_globalSharedContext) { + // + // On windows we create a dummy context to serve as the + // "global context" which all contexts share with. + // This is because on windows it is not possible to share + // with a context which is already current. This dummy context + // will never be current to any thread so it is safe to share with. + // Create that context using the first config + if (m_configs.size() < 1) { + // Should not happen! config list should be initialized at this point + return NULL; + } + EglConfig *cfg = (*m_configs.begin()); + m_globalSharedContext = m_idpy->createContext( + cfg->nativeFormat(), NULL); + } + + return m_globalSharedContext; +#endif +} + +// static +void EglDisplay::addConfig(void* opaque, const EglOS::ConfigInfo* info) { + EglDisplay* display = static_cast(opaque); + EglConfig* config = new EglConfig( + info->red_size, + info->green_size, + info->blue_size, + info->alpha_size, + info->caveat, + info->config_id, + info->depth_size, + info->frame_buffer_level, + info->max_pbuffer_width, + info->max_pbuffer_height, + info->max_pbuffer_size, + info->native_renderable, + info->renderable_type, + info->native_visual_id, + info->native_visual_type, + info->samples_per_pixel, + info->stencil_size, + info->surface_type, + info->transparent_type, + info->trans_red_val, + info->trans_green_val, + info->trans_blue_val, + info->frmt); + + display->m_configs.push_back(config); +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglDisplay.h b/external/android-emugl/host/libs/Translator/EGL/EglDisplay.h new file mode 100644 index 0000000..e890b78 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglDisplay.h @@ -0,0 +1,116 @@ +/* +* 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_DISPLAY_H +#define EGL_DISPLAY_H + +#include +#include +#include +#include +#include "emugl/common/mutex.h" +#include "emugl/common/smart_ptr.h" + +#include "EglConfig.h" +#include "EglContext.h" +#include "EglOsApi.h" +#include "EglSurface.h" +#include "EglWindowSurface.h" + + + +typedef std::map ContextsHndlMap; +typedef std::map SurfacesHndlMap; + +class EglDisplay { +public: + // Create new EglDisplay instance from a given native display |dpy|, + // with matching internal display |idpy|. If |isDefault| is true, + // this will be considered the default diplay. + EglDisplay(EGLNativeDisplayType dpy, EglOS::Display* idpy); + + // Return the native display handle for this EglDisplay. + EGLNativeDisplayType getNativeDisplay() const { return m_dpy; } + + // Return the native internal display handle for this EglDisplay. + EglOS::Display* nativeType() const { return m_idpy; } + + // Return the number of known configurations for this EglDisplay. + int nConfigs() const { return m_configs.size(); } + + // Write up to |config_size| EGLConfig values into the |configs| array. + // Return the number if values written. + int getConfigs(EGLConfig* configs,int config_size) const; + + // Select all display configurations that match at least the values + // in |dummy|. If |configs| is NULL, this returns the number of all + // matching configs. Otherwise, this writes into |configs| up to + // |config_size| matching EGLConfig values, and returns their number. + int chooseConfigs(const EglConfig& dummy, + EGLConfig* configs, + int config_size) const; + + // Return the EglConfig value that matches a given EGLConfig |conf|. + EglConfig* getConfig(EGLConfig conf) const; + + // Return the EglConfig value that matches a given EGLConfig with + // EGL_CONFIG_ID value |id|. + EglConfig* getConfig(EGLint id) const; + + EGLSurface addSurface(SurfacePtr s ); + SurfacePtr getSurface(EGLSurface surface) const; + bool removeSurface(EGLSurface s); + EGLContext addContext(ContextPtr ctx ); + ContextPtr getContext(EGLContext ctx) const; + bool removeContext(EGLContext ctx); + bool removeContext(ContextPtr ctx); + ObjectNameManager* getManager(GLESVersion ver) const { return m_manager[ver];} + + ~EglDisplay(); + void initialize(int renderableType); + void terminate(); + bool isInitialize(); + + ImagePtr getImage(EGLImageKHR img) const; + EGLImageKHR addImageKHR(ImagePtr); + bool destroyImageKHR(EGLImageKHR img); + EglOS::Context* getGlobalSharedContext() const; + +private: + static void addConfig(void* opaque, const EglOS::ConfigInfo* configInfo); + + int doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) const; + void addSimplePixelFormat(int red_size, int green_size, int blue_size, int alpha_size); + void addMissingConfigs(void); + void initConfigurations(int renderableType); + + EGLNativeDisplayType m_dpy; + EglOS::Display* m_idpy; + bool m_initialized; + bool m_configInitialized; + ConfigsList m_configs; + ContextsHndlMap m_contexts; + SurfacesHndlMap m_surfaces; + GlobalNameSpace m_globalNameSpace; + ObjectNameManager* m_manager[MAX_GLES_VERSION]; + mutable emugl::Mutex m_lock; + ImagesHndlMap m_eglImages; + unsigned int m_nextEglImageId; + mutable EglOS::Context* m_globalSharedContext; +}; + +#endif + + diff --git a/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.cpp b/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.cpp new file mode 100644 index 0000000..95bbcda --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.cpp @@ -0,0 +1,113 @@ +/* +* 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 "EglGlobalInfo.h" + +#include "ClientAPIExts.h" +#include "EglDisplay.h" +#include "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" + +#include + +namespace { + +// Use a LazyInstance to ensure thread-safe initialization. +emugl::LazyInstance sSingleton = LAZY_INSTANCE_INIT; + +} // namespace + +// static +EglGlobalInfo* EglGlobalInfo::getInstance() { + return sSingleton.ptr(); +} + +EglGlobalInfo::EglGlobalInfo() : + m_displays(), + m_engine(NULL), + m_display(NULL), + m_lock() { + // TODO(digit): Choose alternate engine based on env. variable? + m_engine = EglOS::Engine::getHostInstance(); + m_display = m_engine->getDefaultDisplay(); + + memset(m_gles_ifaces, 0, sizeof(m_gles_ifaces)); + memset(m_gles_extFuncs_inited, 0, sizeof(m_gles_extFuncs_inited)); +} + +EglGlobalInfo::~EglGlobalInfo() { + for (size_t n = 0; n < m_displays.size(); ++n) { + delete m_displays[n]; + } +} + +EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy, + EglOS::Display* idpy) { + //search if it already exists. + emugl::Mutex::AutoLock mutex(m_lock); + for (size_t n = 0; n < m_displays.size(); ++n) { + if (m_displays[n]->getNativeDisplay() == dpy) { + return m_displays[n]; + } + } + + if (!idpy) { + return NULL; + } + EglDisplay* result = new EglDisplay(dpy, idpy); + m_displays.push_back(result); + return result; +} + +bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) { + emugl::Mutex::AutoLock mutex(m_lock); + for (size_t n = 0; n < m_displays.size(); ++n) { + if (m_displays[n] == static_cast(dpy)) { + delete m_displays[n]; + m_displays.remove(n); + return true; + } + } + return false; +} + +EglDisplay* EglGlobalInfo::getDisplay(EGLNativeDisplayType dpy) const { + emugl::Mutex::AutoLock mutex(m_lock); + for (size_t n = 0; n < m_displays.size(); ++n) { + if (m_displays[n]->getNativeDisplay() == dpy) { + return m_displays[n]; + } + } + return NULL; +} + +EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) const { + emugl::Mutex::AutoLock mutex(m_lock); + for (size_t n = 0; n < m_displays.size(); ++n) { + if (m_displays[n] == static_cast(dpy)) { + return m_displays[n]; + } + } + return NULL; +} + +void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) { + emugl::Mutex::AutoLock mutex(m_lock); + if (!m_gles_extFuncs_inited[ver]) { + ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1); + m_gles_extFuncs_inited[ver] = true; + } +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.h b/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.h new file mode 100644 index 0000000..8fa8acc --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglGlobalInfo.h @@ -0,0 +1,110 @@ +/* +* 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_GLOBAL_INFO +#define EGL_GLOBAL_INFO + +#include "EglDisplay.h" +#include "EglConfig.h" +#include "EglContext.h" +#include "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/pod_vector.h" +#include "emugl/common/mutex.h" + +#include + +#include + +class EglDisplay; + +// Holds all global information shared by the EGL implementation in a given +// process. This really amounts to: +// +// - A list of EglDisplay instances, each identified by an +// EGLNativeDisplayType and EglOS::Display*. +// +// - GLES interface function pointers for all supported GLES versions. + +class EglGlobalInfo { + +public: + // Returns a pointer to the process' single instance, which will be + // created on demand. This can be called multiple times, each call will + // increment an internal reference-count. + static EglGlobalInfo* getInstance(); + + // Create a new EglDisplay instance from an existing native |dpy| value. + // |idpy| is the corresponding native internal display type. See + // generateInternalDisplay() below to understand how they differ. + EglDisplay* addDisplay(EGLNativeDisplayType dpy, + EglOS::Display* idpy); + + // Return the EglDisplay instance corresponding to a given native |dpy| + // value. + EglDisplay* getDisplay(EGLNativeDisplayType dpy) const; + + // Return the EglDisplay instance corresponding to a given EGLDisplay |dpy| + // value. NULL if none matches. + EglDisplay* getDisplay(EGLDisplay dpy) const; + + // Remove a given EGLDisplay identified by |dpy|. + bool removeDisplay(EGLDisplay dpy); + + // Return the default native internal display handle. + EglOS::Display* getDefaultNativeDisplay() const { + return m_display; + }; + + // Return the default engine handle. + EglOS::Engine* getOsEngine() const { + return m_engine; + } + + // Set the GLES interface pointer corresponding to a given GLES version. + // |iface| is a pointer to a structure containing function pointers + // related to a specific GLES version. + // |ver| is a version identifier, e.g. GLES_1_1 or GLES_2_0. + void setIface(const GLESiface* iface, GLESVersion ver) { + m_gles_ifaces[ver] = iface; + }; + + // Return the current GLES interface pointer for a given GLES version. + // |ver| is a version identifier, e.g. GLES_1_1 or GLES_2_0. + const GLESiface* getIface(GLESVersion ver) const { + return m_gles_ifaces[ver]; + } + + // Initialize the table of extension functions for a given GLES version + // |ver|. This must be called after setIface() for the corresponding + // version. + void initClientExtFuncTable(GLESVersion ver); + +private: + EglGlobalInfo(); + ~EglGlobalInfo(); + + friend struct emugl::LazyInstance; + + emugl::PodVector m_displays; + EglOS::Engine* m_engine; + EglOS::Display* m_display; + const GLESiface* m_gles_ifaces[MAX_GLES_VERSION]; + bool m_gles_extFuncs_inited[MAX_GLES_VERSION]; + mutable emugl::Mutex m_lock; +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglImp.cpp b/external/android-emugl/host/libs/Translator/EGL/EglImp.cpp new file mode 100644 index 0000000..df38472 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglImp.cpp @@ -0,0 +1,981 @@ +/* +* 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. +*/ +#ifdef _WIN32 +#undef EGLAPI +#define EGLAPI __declspec(dllexport) +#endif + +#include "ThreadInfo.h" +#include +#include "emugl/common/shared_library.h" +#include + +#include "EglWindowSurface.h" +#include "EglPbufferSurface.h" +#include "EglGlobalInfo.h" +#include "EglThreadInfo.h" +#include "EglValidate.h" +#include "EglDisplay.h" +#include "EglContext.h" +#include "EglConfig.h" +#include "EglOsApi.h" +#include "ClientAPIExts.h" + +#include + +#include +#include +#include + +#define MAJOR 1 +#define MINOR 4 + +//declarations + +EglImage *attachEGLImage(unsigned int imageId); +void detachEGLImage(unsigned int imageId); +GLEScontext* getGLESContext(); +GlLibrary* getGlLibrary(); + +#define tls_thread EglThreadInfo::get() + +EglGlobalInfo* g_eglInfo = NULL; +emugl::Mutex s_eglLock; + +void initGlobalInfo() +{ + emugl::Mutex::AutoLock mutex(s_eglLock); + if (!g_eglInfo) { + g_eglInfo = EglGlobalInfo::getInstance(); + } +} + +static const EGLiface s_eglIface = { + .getGLESContext = getGLESContext, + .eglAttachEGLImage = attachEGLImage, + .eglDetachEGLImage = detachEGLImage, + .eglGetGlLibrary = getGlLibrary, +}; + +static void initGLESx(GLESVersion version) { + const GLESiface* iface = g_eglInfo->getIface(version); + if (!iface) { + DBG("EGL failed to initialize GLESv%d; incompatible interface\n", version); + return; + } + iface->initGLESx(); +} + +/***************************************** supported extentions ***********************************************************************/ + +//extentions +#define EGL_EXTENTIONS 2 + +//decleration +extern "C" { +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image); +} // extern "C" + +// extentions descriptors +static const ExtentionDescriptor s_eglExtentions[] = { + {"eglCreateImageKHR" , + (__eglMustCastToProperFunctionPointerType)eglCreateImageKHR }, + {"eglDestroyImageKHR", + (__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR }, +}; + +static const int s_eglExtentionsSize = + sizeof(s_eglExtentions) / sizeof(ExtentionDescriptor); + +/****************************************************************************************************************************************/ +//macros for accessing global egl info & tls objects + +#define CURRENT_THREAD() do {} while (0); + +#define RETURN_ERROR(ret,err) \ + CURRENT_THREAD() \ + if(tls_thread->getError() == EGL_SUCCESS) { \ + tls_thread->setError(err); \ + } \ + return ret; + +#define VALIDATE_DISPLAY_RETURN(EGLDisplay,ret) \ + EglDisplay* dpy = g_eglInfo->getDisplay(EGLDisplay); \ + if(!dpy){ \ + RETURN_ERROR(ret,EGL_BAD_DISPLAY); \ + } \ + if(!dpy->isInitialize()) { \ + RETURN_ERROR(ret,EGL_NOT_INITIALIZED); \ + } + +#define VALIDATE_CONFIG_RETURN(EGLConfig,ret) \ + EglConfig* cfg = dpy->getConfig(EGLConfig); \ + if(!cfg) { \ + RETURN_ERROR(ret,EGL_BAD_CONFIG); \ + } + +#define VALIDATE_SURFACE_RETURN(EGLSurface,ret,varName) \ + SurfacePtr varName = dpy->getSurface(EGLSurface); \ + if(!varName.Ptr()) { \ + RETURN_ERROR(ret,EGL_BAD_SURFACE); \ + } + +#define VALIDATE_CONTEXT_RETURN(EGLContext,ret) \ + ContextPtr ctx = dpy->getContext(EGLContext); \ + if(!ctx.Ptr()) { \ + RETURN_ERROR(ret,EGL_BAD_CONTEXT); \ + } + + +#define VALIDATE_DISPLAY(EGLDisplay) \ + VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE) + +#define VALIDATE_CONFIG(EGLConfig) \ + VALIDATE_CONFIG_RETURN(EGLConfig,EGL_FALSE) + +#define VALIDATE_SURFACE(EGLSurface,varName) \ + VALIDATE_SURFACE_RETURN(EGLSurface,EGL_FALSE,varName) + +#define VALIDATE_CONTEXT(EGLContext) \ + VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE) + + +GLEScontext* getGLESContext() +{ + ThreadInfo* thread = getThreadInfo(); + return thread->glesContext; +} + +GlLibrary* getGlLibrary() { + return EglGlobalInfo::getInstance()->getOsEngine()->getGlLibrary(); +} + +EGLAPI EGLint EGLAPIENTRY eglGetError(void) { + CURRENT_THREAD(); + EGLint err = tls_thread->getError(); + tls_thread->setError(EGL_SUCCESS); + return err; +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { + EglDisplay* dpy = NULL; + EglOS::Display* internalDisplay = NULL; + + initGlobalInfo(); + + if ((dpy = g_eglInfo->getDisplay(display_id))) { + return dpy; + } + if (display_id != EGL_DEFAULT_DISPLAY) { + return EGL_NO_DISPLAY; + } + internalDisplay = g_eglInfo->getDefaultNativeDisplay(); + dpy = g_eglInfo->addDisplay(display_id,internalDisplay); + if(!dpy) { + return EGL_NO_DISPLAY; + } + return dpy; +} + + +#define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces" + +static __translator_getGLESIfaceFunc loadIfaces(const char* libName, + char* error, + size_t errorSize) { + emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open( + libName, error, errorSize); + if (!libGLES) { + return NULL; + } + __translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc) + libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME); + if (!func) { + snprintf(error, errorSize, "Missing symbol %s", + TRANSLATOR_GETIFACE_NAME); + return NULL; + } + return func; +} + +#define LIB_GLES_CM_NAME EMUGL_LIBNAME("GLES_CM_translator") +#define LIB_GLES_V2_NAME EMUGL_LIBNAME("GLES_V2_translator") + +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) { + + initGlobalInfo(); + + EglDisplay* dpy = g_eglInfo->getDisplay(display); + if(!dpy) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_DISPLAY); + } + + if(major) *major = MAJOR; + if(minor) *minor = MINOR; + + __translator_getGLESIfaceFunc func = NULL; + int renderableType = EGL_OPENGL_ES_BIT; + + char error[256]; + if(!g_eglInfo->getIface(GLES_1_1)) { + func = loadIfaces(LIB_GLES_CM_NAME, error, sizeof(error)); + if (func) { + g_eglInfo->setIface(func(&s_eglIface),GLES_1_1); + } else { + fprintf(stderr, "%s: Could not find ifaces for GLES CM 1.1 [%s]\n", + __FUNCTION__, error); + return EGL_FALSE; + } + initGLESx(GLES_1_1); + } + if(!g_eglInfo->getIface(GLES_2_0)) { + func = loadIfaces(LIB_GLES_V2_NAME, error, sizeof(error)); + if (func) { + renderableType |= EGL_OPENGL_ES2_BIT; + g_eglInfo->setIface(func(&s_eglIface),GLES_2_0); + } else { + fprintf(stderr, "%s: Could not find ifaces for GLES 2.0 [%s]\n", + __FUNCTION__, error); + } + initGLESx(GLES_2_0); + } + dpy->initialize(renderableType); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay display) { + VALIDATE_DISPLAY(display); + dpy->terminate(); + return EGL_TRUE; +} + +EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) { + VALIDATE_DISPLAY(display); + static const char* vendor = "Google"; + static const char* version = "1.4"; + static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2D_image"; + if(!EglValidate::stringName(name)) { + RETURN_ERROR(NULL,EGL_BAD_PARAMETER); + } + switch(name) { + case EGL_VENDOR: + return vendor; + case EGL_VERSION: + return version; + case EGL_EXTENSIONS: + return extensions; + } + return NULL; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay display, EGLConfig *configs, + EGLint config_size, EGLint *num_config) { + VALIDATE_DISPLAY(display); + if(!num_config) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + + if(configs == NULL) { + *num_config = dpy->nConfigs(); + } else { + *num_config = dpy->getConfigs(configs,config_size); + } + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config) { + VALIDATE_DISPLAY(display); + if(!num_config) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + + //selection defaults + // NOTE: Some variables below are commented out to reduce compiler warnings. + // TODO(digit): Look if these variables are really needed or not, and if so + // fix the code to do it properly. + EGLint surface_type = EGL_WINDOW_BIT; + EGLint renderable_type = EGL_OPENGL_ES_BIT; + //EGLBoolean bind_to_tex_rgb = EGL_DONT_CARE; + //EGLBoolean bind_to_tex_rgba = EGL_DONT_CARE; + EGLenum caveat = EGL_DONT_CARE; + EGLint config_id = EGL_DONT_CARE; + EGLBoolean native_renderable = EGL_DONT_CARE; + EGLint native_visual_type = EGL_DONT_CARE; + //EGLint max_swap_interval = EGL_DONT_CARE; + //EGLint min_swap_interval = EGL_DONT_CARE; + EGLint trans_red_val = EGL_DONT_CARE; + EGLint trans_green_val = EGL_DONT_CARE; + EGLint trans_blue_val = EGL_DONT_CARE; + EGLenum transparent_type = EGL_NONE; + //EGLint buffer_size = 0; + EGLint red_size = 0; + EGLint green_size = 0; + EGLint blue_size = 0; + EGLint alpha_size = 0; + EGLint depth_size = 0; + EGLint frame_buffer_level = 0; + //EGLint sample_buffers_num = 0; + EGLint samples_per_pixel = 0; + EGLint stencil_size = 0; + + if(!EglValidate::noAttribs(attrib_list)) { //there are attribs + int i = 0 ; + bool hasConfigId = false; + while(attrib_list[i] != EGL_NONE && !hasConfigId) { + switch(attrib_list[i]) { + case EGL_MAX_PBUFFER_WIDTH: + case EGL_MAX_PBUFFER_HEIGHT: + case EGL_MAX_PBUFFER_PIXELS: + case EGL_NATIVE_VISUAL_ID: + break; //we dont care from those selection crateria + case EGL_LEVEL: + if(attrib_list[i+1] == EGL_DONT_CARE) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + frame_buffer_level = attrib_list[i+1]; + break; + case EGL_BUFFER_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //buffer_size = attrib_list[i+1]; + break; + case EGL_RED_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + red_size = attrib_list[i+1]; + break; + case EGL_GREEN_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + green_size = attrib_list[i+1]; + break; + case EGL_BLUE_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + blue_size = attrib_list[i+1]; + break; + case EGL_ALPHA_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + alpha_size = attrib_list[i+1]; + break; + case EGL_BIND_TO_TEXTURE_RGB: + //bind_to_tex_rgb = attrib_list[i+1]; + break; + case EGL_BIND_TO_TEXTURE_RGBA: + //bind_to_tex_rgba = attrib_list[i+1]; + break; + case EGL_CONFIG_CAVEAT: + if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_SLOW_CONFIG && attrib_list[i+1] != EGL_NON_CONFORMANT_CONFIG) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + caveat = attrib_list[i+1]; + break; + case EGL_CONFIG_ID: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + config_id = attrib_list[i+1]; + hasConfigId = true; + break; + case EGL_DEPTH_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + depth_size = attrib_list[i+1]; + break; + case EGL_MAX_SWAP_INTERVAL: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //max_swap_interval = attrib_list[i+1]; + break; + case EGL_MIN_SWAP_INTERVAL: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //min_swap_interval = attrib_list[i+1]; + break; + case EGL_NATIVE_RENDERABLE: + native_renderable = attrib_list[i+1]; + break; + case EGL_RENDERABLE_TYPE: + renderable_type = attrib_list[i+1]; + break; + case EGL_NATIVE_VISUAL_TYPE: + native_visual_type = attrib_list[i+1]; + break; + if(attrib_list[i+1] < 0 || attrib_list[i+1] > 1 ) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + case EGL_SAMPLE_BUFFERS: + //sample_buffers_num = attrib_list[i+1]; + break; + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + case EGL_SAMPLES: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + samples_per_pixel = attrib_list[i+1]; + break; + case EGL_STENCIL_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + stencil_size = attrib_list[i+1]; + break; + case EGL_SURFACE_TYPE: + surface_type = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_TYPE: + if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_TRANSPARENT_RGB ) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + transparent_type = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_RED_VALUE: + trans_red_val = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_GREEN_VALUE: + trans_green_val = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_BLUE_VALUE: + trans_blue_val = attrib_list[i+1]; + break; + default: + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + if(hasConfigId) { + EglConfig* pConfig = dpy->getConfig(config_id); + if(pConfig) { + if(configs) { + configs[0] = static_cast(pConfig); + } + *num_config = 1; + return EGL_TRUE; + } else { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + } + } + EglConfig dummy(red_size,green_size,blue_size,alpha_size,caveat,config_id,depth_size, + frame_buffer_level,0,0,0,native_renderable,renderable_type,0,native_visual_type, + samples_per_pixel,stencil_size,surface_type,transparent_type, + trans_red_val,trans_green_val,trans_blue_val,NULL); + + *num_config = dpy->chooseConfigs(dummy,configs,config_size); + + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay display, EGLConfig config, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_CONFIG(config); + if(!EglValidate::confAttrib(attribute)){ + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return cfg->getConfAttrib(attribute,value)? EGL_TRUE:EGL_FALSE; +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay display, EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); + VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); + + if(!(cfg->surfaceType() & EGL_WINDOW_BIT)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); + } + if(!dpy->nativeType()->isValidNativeWin(win)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_NATIVE_WINDOW); + } + if(!EglValidate::noAttribs(attrib_list)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + if(EglWindowSurface::alreadyAssociatedWithConfig(win)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + unsigned int width,height; + if(!dpy->nativeType()->checkWindowPixelFormatMatch( + win, cfg->nativeFormat(), &width, &height)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + SurfacePtr wSurface(new EglWindowSurface(dpy, win,cfg,width,height)); + if(!wSurface.Ptr()) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + return dpy->addSurface(wSurface); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface( + EGLDisplay display, + EGLConfig config, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); + VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); + if(!(cfg->surfaceType() & EGL_PBUFFER_BIT)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); + } + + SurfacePtr pbSurface(new EglPbufferSurface(dpy,cfg)); + if(!pbSurface.Ptr()) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + if(!EglValidate::noAttribs(attrib_list)) { // There are attribs. + int i = 0 ; + while(attrib_list[i] != EGL_NONE) { + if(!pbSurface->setAttrib(attrib_list[i],attrib_list[i+1])) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + } + + EGLint width, height, largest, texTarget, texFormat; + EglPbufferSurface* tmpPbSurfacePtr = + static_cast(pbSurface.Ptr()); + + tmpPbSurfacePtr->getDim(&width, &height, &largest); + tmpPbSurfacePtr->getTexInfo(&texTarget, &texFormat); + + if(!EglValidate::pbufferAttribs(width, + height, + texFormat == EGL_NO_TEXTURE, + texTarget == EGL_NO_TEXTURE)) { + //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad_value + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + + EglOS::PbufferInfo pbinfo; + + pbinfo.width = width; + pbinfo.height = height; + pbinfo.largest = largest; + pbinfo.target = texTarget; + pbinfo.format = texFormat; + + tmpPbSurfacePtr->getAttrib(EGL_MIPMAP_TEXTURE, &pbinfo.hasMipmap); + + EglOS::Surface* pb = dpy->nativeType()->createPbufferSurface( + cfg->nativeFormat(), &pbinfo); + if(!pb) { + //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad value + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + + tmpPbSurfacePtr->setNativePbuffer(pb); + return dpy->addSurface(pbSurface); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface) { + VALIDATE_DISPLAY(display); + SurfacePtr srfc = dpy->getSurface(surface); + if(!srfc.Ptr()) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + + dpy->removeSurface(surface); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,srfc); + + if(!srfc->getAttrib(attribute,value)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface, + EGLint attribute, EGLint value) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,srfc); + if(!srfc->setAttrib(attribute,value)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config, + EGLContext share_context, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT); + VALIDATE_CONFIG_RETURN(config,EGL_NO_CONTEXT); + + GLESVersion version = GLES_1_1; + if(!EglValidate::noAttribs(attrib_list)) { + int i = 0; + while(attrib_list[i] != EGL_NONE) { + switch(attrib_list[i]) { + case EGL_CONTEXT_CLIENT_VERSION: + if(attrib_list[i+1] == 2) { + version = GLES_2_0; + } else { + version = GLES_1_1; + } + break; + default: + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + } + const GLESiface* iface = g_eglInfo->getIface(version); + GLEScontext* glesCtx = NULL; + if(iface) { + glesCtx = iface->createGLESContext(); + } else { // there is no interface for this gles version + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); + } + + ContextPtr sharedCtxPtr; + if(share_context != EGL_NO_CONTEXT) { + sharedCtxPtr = dpy->getContext(share_context); + if(!sharedCtxPtr.Ptr()) { + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT); + } + } + + EglOS::Context* globalSharedContext = dpy->getGlobalSharedContext(); + EglOS::Context* nativeContext = dpy->nativeType()->createContext( + cfg->nativeFormat(), globalSharedContext); + + if(nativeContext) { + ContextPtr ctx(new EglContext(dpy, nativeContext,sharedCtxPtr,cfg,glesCtx,version,dpy->getManager(version))); + return dpy->addContext(ctx); + } else { + iface->deleteGLESContext(glesCtx); + } + +return EGL_NO_CONTEXT; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context) { + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + dpy->removeContext(context); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, + EGLSurface draw, + EGLSurface read, + EGLContext context) { + VALIDATE_DISPLAY(display); + + bool releaseContext = EglValidate::releaseContext(context, read, draw); + if(!releaseContext && EglValidate::badContextMatch(context, read, draw)) { + RETURN_ERROR(EGL_FALSE, EGL_BAD_MATCH); + } + + ThreadInfo* thread = getThreadInfo(); + ContextPtr prevCtx = thread->eglContext; + + if(releaseContext) { //releasing current context + if(prevCtx.Ptr()) { + g_eglInfo->getIface(prevCtx->version())->flush(); + if(!dpy->nativeType()->makeCurrent(NULL,NULL,NULL)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); + } + thread->updateInfo(ContextPtr(NULL),dpy,NULL,ShareGroupPtr(NULL),dpy->getManager(prevCtx->version())); + } + } else { //assining new context + VALIDATE_CONTEXT(context); + VALIDATE_SURFACE(draw,newDrawSrfc); + VALIDATE_SURFACE(read,newReadSrfc); + + EglSurface* newDrawPtr = newDrawSrfc.Ptr(); + EglSurface* newReadPtr = newReadSrfc.Ptr(); + ContextPtr newCtx = ctx; + + if (newCtx.Ptr() && prevCtx.Ptr()) { + if (newCtx.Ptr() == prevCtx.Ptr()) { + if (newDrawPtr == prevCtx->draw().Ptr() && + newReadPtr == prevCtx->read().Ptr()) { + // nothing to do + return EGL_TRUE; + } + } + else { + // Make sure previous context is detached from surfaces + releaseContext = true; + } + } + + //surfaces compatibility check + if(!((*ctx->getConfig()).compatibleWith((*newDrawPtr->getConfig()))) || + !((*ctx->getConfig()).compatibleWith((*newReadPtr->getConfig())))) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); + } + + EglOS::Display* nativeDisplay = dpy->nativeType(); + EglOS::Surface* nativeRead = newReadPtr->native(); + EglOS::Surface* nativeDraw = newDrawPtr->native(); + //checking native window validity + if(newReadPtr->type() == EglSurface::WINDOW && + !nativeDisplay->isValidNativeWin(nativeRead)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); + } + if(newDrawPtr->type() == EglSurface::WINDOW && + !nativeDisplay->isValidNativeWin(nativeDraw)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); + } + + if(prevCtx.Ptr()) { + g_eglInfo->getIface(prevCtx->version())->flush(); + } + if (!dpy->nativeType()->makeCurrent( + newReadPtr->native(), + newDrawPtr->native(), + newCtx->nativeType())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); + } + //TODO: handle the following errors + // EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST , EGL_BAD_ACCESS + + thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version())); + newCtx->setSurfaces(newReadSrfc,newDrawSrfc); + g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup()); + + // Initialize the GLES extension function table used in + // eglGetProcAddress for the context's GLES version if not + // yet initialized. We initialize it here to make sure we call the + // GLES getProcAddress after when a context is bound. + g_eglInfo->initClientExtFuncTable(newCtx->version()); + } + + // release previous context surface binding + if(prevCtx.Ptr() && releaseContext) { + prevCtx->setSurfaces(SurfacePtr(NULL),SurfacePtr(NULL)); + } + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + if(!ctx->getAttrib(attribute,value)){ + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,Srfc); + ThreadInfo* thread = getThreadInfo(); + ContextPtr currentCtx = thread->eglContext; + + + //if surface not window return + if(Srfc->type() != EglSurface::WINDOW){ + RETURN_ERROR(EGL_TRUE,EGL_SUCCESS); + } + + if(!currentCtx.Ptr() || !currentCtx->usingSurface(Srfc) || + !dpy->nativeType()->isValidNativeWin(Srfc.Ptr()->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + + dpy->nativeType()->swapBuffers(Srfc->native()); + return EGL_TRUE; +} + +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) { + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + if(dpy && ctx.Ptr()){ + // This double check is required because a context might still be current after it is destroyed - in which case + // its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current + EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl()); + if(dpy->getContext(c).Ptr()) + { + return c; + } + } + return EGL_NO_CONTEXT; +} + +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { + if (!EglValidate::surfaceTarget(readdraw)) { + return EGL_NO_SURFACE; + } + + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + + if(dpy && ctx.Ptr()) { + SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw(); + if(surface.Ptr()) + { + // This double check is required because a surface might still be + // current after it is destroyed - in which case its handle should + // be invalid, that is EGL_NO_SURFACE should be returned even + // though the surface is current. + EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl()); + surface = dpy->getSurface(s); + if(surface.Ptr()) + { + return s; + } + } + } + return EGL_NO_SURFACE; +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { + ThreadInfo* thread = getThreadInfo(); + return (thread->eglContext.Ptr()) ? thread->eglDisplay : EGL_NO_DISPLAY; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { + if(!EglValidate::supportedApi(api)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + CURRENT_THREAD(); + tls_thread->setApi(api); + return EGL_TRUE; +} + +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) { + CURRENT_THREAD(); + return tls_thread->getApi(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) { + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast(thread->eglDisplay); + return eglMakeCurrent(dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY + eglGetProcAddress(const char *procname){ + __eglMustCastToProperFunctionPointerType retVal = NULL; + + initGlobalInfo(); + + if(!strncmp(procname,"egl",3)) { //EGL proc + for(int i=0;i < s_eglExtentionsSize;i++){ + if(strcmp(procname,s_eglExtentions[i].name) == 0){ + retVal = s_eglExtentions[i].address; + break; + } + } + } + else { + // Look at the clientAPI (GLES) supported extension + // function table. + retVal = ClientAPIExts::getProcAddress(procname); + } + return retVal; +} + +/************************** KHR IMAGE *************************************************************/ +EglImage *attachEGLImage(unsigned int imageId) +{ + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + if (ctx.Ptr()) { + ImagePtr img = dpy->getImage(reinterpret_cast(imageId)); + if(img.Ptr()) { + ctx->attachImage(imageId,img); + return img.Ptr(); + } + } + return NULL; +} + +void detachEGLImage(unsigned int imageId) +{ + ThreadInfo* thread = getThreadInfo(); + ContextPtr ctx = thread->eglContext; + if (ctx.Ptr()) { + ctx->detachImage(imageId); + } +} + + +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +{ + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + // We only support EGL_GL_TEXTURE_2D images + if (target != EGL_GL_TEXTURE_2D_KHR) { + RETURN_ERROR(EGL_NO_IMAGE_KHR,EGL_BAD_PARAMETER); + } + + ThreadInfo* thread = getThreadInfo(); + ShareGroupPtr sg = thread->shareGroup; + if (sg.Ptr() != NULL) { + unsigned int globalTexName = sg->getGlobalName(TEXTURE, SafeUIntFromPointer(buffer)); + if (!globalTexName) return EGL_NO_IMAGE_KHR; + + ImagePtr img( new EglImage() ); + if (img.Ptr() != NULL) { + + ObjectDataPtr objData = sg->getObjectData(TEXTURE, SafeUIntFromPointer(buffer)); + if (!objData.Ptr()) return EGL_NO_IMAGE_KHR; + + TextureData *texData = (TextureData *)objData.Ptr(); + if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR; + img->width = texData->width; + img->height = texData->height; + img->border = texData->border; + img->internalFormat = texData->internalFormat; + img->globalTexName = globalTexName; + return dpy->addImageKHR(img); + } + } + + return EGL_NO_IMAGE_KHR; +} + + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image) +{ + VALIDATE_DISPLAY(display); + return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE; +} + +/*********************************************************************************/ diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi.h b/external/android-emugl/host/libs/Translator/EGL/EglOsApi.h new file mode 100644 index 0000000..e1ec4fa --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi.h @@ -0,0 +1,188 @@ +/* +* 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_OS_API_H +#define EGL_OS_API_H + +#include + +#define PBUFFER_MAX_WIDTH 32767 +#define PBUFFER_MAX_HEIGHT 32767 +#define PBUFFER_MAX_PIXELS (PBUFFER_MAX_WIDTH * PBUFFER_MAX_HEIGHT) + +class GlLibrary; + +namespace EglOS { + +// This header contains declaration used to abstract the underlying +// desktop GL library (or equivalent) that is being used by our EGL +// and GLES translation libraries. + +// Use EglOS::Engine::getHostInstance() to retrieve an instance of the +// EglOS::Engine interface that matches the host display system. +// +// Alternate renderers (e.g. software-based Mesa) can also implement +// their own engine. + +// Base class used to wrap various GL Surface types. +class Surface { +public: + typedef enum { + WINDOW = 0, + PBUFFER = 1, + } SurfaceType; + + explicit Surface(SurfaceType type) : mType(type) {} + + virtual ~Surface() {} + + SurfaceType type() const { return mType; } + +protected: + SurfaceType mType; +}; + +// An interface class for engine-specific implementation of a GL context. +class Context { +public: + Context() {} + virtual ~Context() {} +}; + +// Base class used to wrap engine-specific pixel format descriptors. +class PixelFormat { +public: + PixelFormat() {} + + virtual ~PixelFormat() {} + + virtual PixelFormat* clone() = 0; +}; + +// Small structure used to describe the properties of an engine-specific +// config. +struct ConfigInfo { + EGLint red_size; + EGLint green_size; + EGLint blue_size; + EGLint alpha_size; + EGLenum caveat; + EGLint config_id; + EGLint depth_size; + EGLint frame_buffer_level; + EGLint max_pbuffer_width; + EGLint max_pbuffer_height; + EGLint max_pbuffer_size; + EGLBoolean native_renderable; + EGLint renderable_type; + EGLint native_visual_id; + EGLint native_visual_type; + EGLint samples_per_pixel; + EGLint stencil_size; + EGLint surface_type; + EGLenum transparent_type; + EGLint trans_red_val; + EGLint trans_green_val; + EGLint trans_blue_val; + PixelFormat* frmt; +}; + +// A callback function type used with Display::queryConfig() to report to the +// caller a new host EGLConfig. +// |opaque| is an opaque value passed to queryConfig(). +// All other parameters are config attributes. +// Note that ownership of |frmt| is transfered to the callback. +typedef void (AddConfigCallback)(void* opaque, const ConfigInfo* configInfo); + +// Pbuffer description. +// |width| and |height| are its dimensions. +// |largest| is set to ask the largest pixek buffer (see GLX_LARGEST_PBUFFER). +// |format| is one of EGL_TEXTURE_RGB or EGL_TEXTURE_RGBA +// |target| is one of EGL_TEXTURE_2D or EGL_NO_TEXTURE. +// |hasMipmap| is true if the Pbuffer has mipmaps. +struct PbufferInfo { + EGLint width; + EGLint height; + EGLint largest; + EGLint format; + EGLint target; + EGLint hasMipmap; +}; + +// A class to model the engine-specific implementation of a GL display +// connection. +class Display { +public: + Display() {} + virtual ~Display() {} + + virtual bool release() = 0; + + virtual void queryConfigs(int renderableType, + AddConfigCallback* addConfigFunc, + void* addConfigOpaque) = 0; + + virtual bool isValidNativeWin(Surface* win) = 0; + virtual bool isValidNativeWin(EGLNativeWindowType win) = 0; + + virtual bool checkWindowPixelFormatMatch(EGLNativeWindowType win, + const PixelFormat* pixelFormat, + unsigned int* width, + unsigned int* height) = 0; + + virtual Context* createContext( + const PixelFormat* pixelFormat, Context* sharedContext) = 0; + + virtual bool destroyContext(Context* context) = 0; + + virtual Surface* createPbufferSurface( + const PixelFormat* pixelFormat, const PbufferInfo* info) = 0; + + virtual bool releasePbuffer(Surface* pb) = 0; + + virtual bool makeCurrent(Surface* read, + Surface* draw, + Context* context) = 0; + + virtual void swapBuffers(Surface* srfc) = 0; +}; + +// An interface class to model a specific underlying GL graphics subsystem +// or engine. Use getHost() to retrieve the implementation for the current +// host. +class Engine { +public: + Engine() {} + virtual ~Engine() {} + + // Return a Display instance to the default display / window. + virtual Display* getDefaultDisplay() = 0; + + // Return to engine-specific implementation of GlLibrary. + virtual GlLibrary* getGlLibrary() = 0; + + // Create a new window surface. |wnd| is a host-specific window handle + // (e.g. a Windows HWND). A software renderer would always return NULL + // here. + virtual Surface* createWindowSurface(EGLNativeWindowType wnd) = 0; + + // Retrieve the implementation for the current host. This can be called + // multiple times, and will initialize the engine on first call. + static Engine* getHostInstance(); +}; + +} // namespace EglOS + +#endif // EGL_OS_API_H diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi_darwin.cpp b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_darwin.cpp new file mode 100644 index 0000000..c782e9f --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_darwin.cpp @@ -0,0 +1,395 @@ +/* +* 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 "EglOsApi.h" + +#include "MacNative.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/shared_library.h" +#include "GLcommon/GLLibrary.h" +#include "OpenglCodecCommon/ErrorLog.h" + +#include + +#define MAX_PBUFFER_MIPMAP_LEVEL 1 + +namespace { + +class MacSurface : public EglOS::Surface { +public: + MacSurface(void* handle, SurfaceType type) : + Surface(type), m_handle(handle), m_hasMipmap(false) {} + + void* handle() const { return m_handle; } + + bool hasMipmap() const { return m_hasMipmap; } + void setHasMipmap(bool value) { m_hasMipmap = value; } + + static MacSurface* from(EglOS::Surface* s) { + return static_cast(s); + } + +private: + void* m_handle; + bool m_hasMipmap; +}; + +class MacContext : public EglOS::Context { +public: + explicit MacContext(void* context) : mContext(context) {} + + virtual ~MacContext() { + nsDestroyContext(mContext); + } + + void* context() const { return mContext; } + + static void* from(EglOS::Context* c) { + return static_cast(c)->context(); + } + +private: + void* mContext; +}; + +typedef std::list NativeFormatList; + +NativeFormatList s_nativeFormats; + +void initNativeConfigs(){ + int nConfigs = getNumPixelFormats(); + if (s_nativeFormats.empty()) { + for(int i = 0; i < nConfigs; i++) { + void* frmt = getPixelFormat(i); + if (frmt) { + s_nativeFormats.push_back(frmt); + } + } + } +} + +class MacPixelFormat : public EglOS::PixelFormat { +public: + MacPixelFormat(void* handle, int redSize, int greenSize, int blueSize) : + mHandle(handle), + mRedSize(redSize), + mGreenSize(greenSize), + mBlueSize(blueSize) {} + + EglOS::PixelFormat* clone() { + return new MacPixelFormat(mHandle, mRedSize, mGreenSize, mBlueSize); + } + + void* handle() const { return mHandle; } + int redSize() const { return mRedSize; } + int greenSize() const { return mGreenSize; } + int blueSize() const { return mBlueSize; } + + static const MacPixelFormat* from(const EglOS::PixelFormat* f) { + return static_cast(f); + } + +private: + MacPixelFormat(); + MacPixelFormat(const MacPixelFormat& other); + + void* mHandle; + int mRedSize; + int mGreenSize; + int mBlueSize; +}; + + +void pixelFormatToConfig(int index, + int renderableType, + void* frmt, + EglOS::AddConfigCallback addConfigFunc, + void* addConfigOpaque) { + EglOS::ConfigInfo info; + memset(&info, 0, sizeof(info)); + + EGLint doubleBuffer; + getPixelFormatAttrib(frmt, MAC_HAS_DOUBLE_BUFFER, &doubleBuffer); + if (!doubleBuffer) { + return; //pixel double buffer + } + + EGLint window = 0, pbuffer = 0; + getPixelFormatAttrib(frmt, MAC_DRAW_TO_WINDOW, &window); + getPixelFormatAttrib(frmt, MAC_DRAW_TO_PBUFFER, &pbuffer); + + info.surface_type = 0; + if (window) { + info.surface_type |= EGL_WINDOW_BIT; + } + if (pbuffer) { + info.surface_type |= EGL_PBUFFER_BIT; + } + if (!info.surface_type) { + return; + } + + //default values + info.native_visual_id = 0; + info.native_visual_type = EGL_NONE; + info.caveat = EGL_NONE; + info.native_renderable = EGL_FALSE; + info.renderable_type = renderableType; + info.max_pbuffer_width = PBUFFER_MAX_WIDTH; + info.max_pbuffer_height = PBUFFER_MAX_HEIGHT; + info.max_pbuffer_size = PBUFFER_MAX_PIXELS; + info.samples_per_pixel = 0; + info.frame_buffer_level = 0; + info.trans_red_val = 0; + info.trans_green_val = 0; + info.trans_blue_val = 0; + + info.transparent_type = EGL_NONE; + + /* All configs can end up having an alpha channel even if none was requested. + * The default config chooser in GLSurfaceView will therefore not find any + * matching config. Thus, make sure alpha is zero (or at least signalled as + * zero to the calling EGL layer) for the configs where it was intended to + * be zero. */ + if (getPixelFormatDefinitionAlpha(index) == 0) { + info.alpha_size = 0; + } else { + getPixelFormatAttrib(frmt, MAC_ALPHA_SIZE, &info.alpha_size); + } + getPixelFormatAttrib(frmt, MAC_DEPTH_SIZE, &info.depth_size); + getPixelFormatAttrib(frmt, MAC_STENCIL_SIZE, &info.stencil_size); + getPixelFormatAttrib(frmt, MAC_SAMPLES_PER_PIXEL, &info.samples_per_pixel); + + //TODO: ask guy if it is OK + GLint colorSize = 0; + getPixelFormatAttrib(frmt, MAC_COLOR_SIZE, &colorSize); + info.red_size = info.green_size = info.blue_size = (colorSize / 4); + + info.config_id = (EGLint) index; + info.frmt = new MacPixelFormat( + frmt, info.red_size, info.green_size, info.blue_size); + + (*addConfigFunc)(addConfigOpaque, &info); +} + + +class MacDisplay : public EglOS::Display { +public: + explicit MacDisplay(EGLNativeDisplayType dpy) : mDpy(dpy) {} + + virtual bool release() { + return true; + } + + virtual void queryConfigs(int renderableType, + EglOS::AddConfigCallback* addConfigFunc, + void* addConfigOpaque) { + initNativeConfigs(); + int i = 0; + for (NativeFormatList::iterator it = s_nativeFormats.begin(); + it != s_nativeFormats.end(); + it++) { + pixelFormatToConfig(i++, + renderableType, + *it, + addConfigFunc, + addConfigOpaque); + } + } + + virtual bool isValidNativeWin(EglOS::Surface* win) { + if (win->type() != MacSurface::WINDOW) { + return false; + } else { + return isValidNativeWin(MacSurface::from(win)->handle()); + } + } + + virtual bool isValidNativeWin(EGLNativeWindowType win) { + unsigned int width, height; + return nsGetWinDims(win, &width, &height); + } + + virtual bool checkWindowPixelFormatMatch( + EGLNativeWindowType win, + const EglOS::PixelFormat* pixelFormat, + unsigned int* width, + unsigned int* height) { + bool ret = nsGetWinDims(win, width, height); + + const MacPixelFormat* format = MacPixelFormat::from(pixelFormat); + int r = format->redSize(); + int g = format->greenSize(); + int b = format->blueSize(); + + bool match = nsCheckColor(win, r + g + b); + + return ret && match; + } + + virtual EglOS::Context* createContext( + const EglOS::PixelFormat* pixelFormat, + EglOS::Context* sharedContext) { + void* macSharedContext = + sharedContext ? MacContext::from(sharedContext) : NULL; + return new MacContext( + nsCreateContext(MacPixelFormat::from(pixelFormat)->handle(), + macSharedContext)); + } + + virtual bool destroyContext(EglOS::Context* context) { + delete context; + return true; + } + + virtual EglOS::Surface* createPbufferSurface( + const EglOS::PixelFormat* pixelFormat, + const EglOS::PbufferInfo* info) { + GLenum glTexFormat = GL_RGBA, glTexTarget = GL_TEXTURE_2D; + switch (info->format) { + case EGL_TEXTURE_RGB: + glTexFormat = GL_RGB; + break; + case EGL_TEXTURE_RGBA: + glTexFormat = GL_RGBA; + break; + } + EGLint maxMipmap = info->hasMipmap ? MAX_PBUFFER_MIPMAP_LEVEL : 0; + + MacSurface* result = new MacSurface( + nsCreatePBuffer( + glTexTarget, + glTexFormat, + maxMipmap, + info->width, + info->height), + MacSurface::PBUFFER); + + result->setHasMipmap(info->hasMipmap); + return result; + } + + virtual bool releasePbuffer(EglOS::Surface* pb) { + if (pb) { + nsDestroyPBuffer(MacSurface::from(pb)->handle()); + } + return true; + } + + virtual bool makeCurrent(EglOS::Surface* read, + EglOS::Surface* draw, + EglOS::Context* ctx) { + // check for unbind + if (ctx == NULL && read == NULL && draw == NULL) { + nsWindowMakeCurrent(NULL, NULL); + return true; + } + else if (ctx == NULL || read == NULL || draw == NULL) { + // error ! + return false; + } + + //dont supporting diffrent read & draw surfaces on Mac + if (read != draw) { + return false; + } + switch (draw->type()) { + case MacSurface::WINDOW: + nsWindowMakeCurrent(MacContext::from(ctx), + MacSurface::from(draw)->handle()); + break; + case MacSurface::PBUFFER: + { + MacSurface* macdraw = MacSurface::from(draw); + int mipmapLevel = macdraw->hasMipmap() ? MAX_PBUFFER_MIPMAP_LEVEL : 0; + nsPBufferMakeCurrent(MacContext::from(ctx), + macdraw->handle(), mipmapLevel); + break; + } + default: + return false; + } + return true; + } + + virtual void swapBuffers(EglOS::Surface* srfc) { + nsSwapBuffers(); + } + + EGLNativeDisplayType dpy() const { return mDpy; } + +private: + EGLNativeDisplayType mDpy; +}; + +class MacGlLibrary : public GlLibrary { +public: + MacGlLibrary() : mLib(NULL) { + static const char kLibName[] = + "/System/Library/Frameworks/OpenGL.framework/OpenGL"; + char error[256]; + mLib = emugl::SharedLibrary::open(kLibName, error, sizeof(error)); + if (!mLib) { + ERR("%s: Could not open GL library %s [%s]\n", + __FUNCTION__, kLibName, error); + } + } + + ~MacGlLibrary() { + delete mLib; + } + + // override + virtual GlFunctionPointer findSymbol(const char* name) { + if (!mLib) { + return NULL; + } + return reinterpret_cast(mLib->findSymbol(name)); + } + +private: + emugl::SharedLibrary* mLib; +}; + +class MacEngine : public EglOS::Engine { +public: + MacEngine() : mGlLib() {} + + virtual EglOS::Display* getDefaultDisplay() { + return new MacDisplay(0); + } + + virtual GlLibrary* getGlLibrary() { + return &mGlLib; + } + + virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) { + return new MacSurface(wnd, MacSurface::WINDOW); + } + +private: + MacGlLibrary mGlLib; +}; + +emugl::LazyInstance sHostEngine = LAZY_INSTANCE_INIT; + +} // namespace + + +// static +EglOS::Engine* EglOS::Engine::getHostInstance() { + return sHostEngine.ptr(); +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi_glx.cpp b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_glx.cpp new file mode 100644 index 0000000..fdcf451 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_glx.cpp @@ -0,0 +1,464 @@ +/* +* 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 "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/mutex.h" +#include "emugl/common/shared_library.h" +#include "GLcommon/GLLibrary.h" + +#include "OpenglCodecCommon/ErrorLog.h" + +#include +#include +#include + +namespace { + +typedef Display X11Display; + +class ErrorHandler{ +public: + ErrorHandler(EGLNativeDisplayType dpy); + ~ErrorHandler(); + int getLastError() const { return s_lastErrorCode; } + +private: + static int s_lastErrorCode; + int (*m_oldErrorHandler)(Display *, XErrorEvent *); + static emugl::Mutex s_lock; + static int errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event); +}; + +// static +int ErrorHandler::s_lastErrorCode = 0; + +// static +emugl::Mutex ErrorHandler::s_lock; + +ErrorHandler::ErrorHandler(EGLNativeDisplayType dpy) { + emugl::Mutex::AutoLock mutex(s_lock); + XSync(dpy,False); + s_lastErrorCode = 0; + m_oldErrorHandler = XSetErrorHandler(errorHandlerProc); +} + +ErrorHandler::~ErrorHandler() { + emugl::Mutex::AutoLock mutex(s_lock); + XSetErrorHandler(m_oldErrorHandler); + s_lastErrorCode = 0; +} + +int ErrorHandler::errorHandlerProc(EGLNativeDisplayType dpy, + XErrorEvent* event) { + s_lastErrorCode = event->error_code; + return 0; +} + +#define IS_SUCCESS(a) \ + do { if (a != Success) return 0; } while (0) + +#define EXIT_IF_FALSE(a) \ + do { if (a != Success) return; } while (0) + +// Implementation of EglOS::PixelFormat based on GLX. +class GlxPixelFormat : public EglOS::PixelFormat { +public: + explicit GlxPixelFormat(GLXFBConfig fbconfig) : mFbConfig(fbconfig) {} + + virtual EglOS::PixelFormat* clone() { + return new GlxPixelFormat(mFbConfig); + } + + GLXFBConfig fbConfig() const { return mFbConfig; } + + static GLXFBConfig from(const EglOS::PixelFormat* f) { + return static_cast(f)->fbConfig(); + } + +private: + GLXFBConfig mFbConfig; +}; + +void pixelFormatToConfig(EGLNativeDisplayType dpy, + int renderableType, + GLXFBConfig frmt, + EglOS::AddConfigCallback* addConfigFunc, + void* addConfigOpaque) { + EglOS::ConfigInfo info; + int tmp; + + memset(&info, 0, sizeof(info)); + + EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_TRANSPARENT_TYPE, &tmp)); + if (tmp == GLX_TRANSPARENT_INDEX) { + return; // not supporting transparent index + } else if (tmp == GLX_NONE) { + info.transparent_type = EGL_NONE; + info.trans_red_val = 0; + info.trans_green_val = 0; + info.trans_blue_val = 0; + } else { + info.transparent_type = EGL_TRANSPARENT_RGB; + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_TRANSPARENT_RED_VALUE, &info.trans_red_val)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_TRANSPARENT_GREEN_VALUE, &info.trans_green_val)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_TRANSPARENT_BLUE_VALUE, &info.trans_blue_val)); + } + + // + // filter out single buffer configurations + // + int doubleBuffer = 0; + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_DOUBLEBUFFER, &doubleBuffer)); + if (!doubleBuffer) { + return; + } + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_RED_SIZE, &info.red_size)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_GREEN_SIZE, &info.green_size)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_BLUE_SIZE, &info.blue_size)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_ALPHA_SIZE, &info.alpha_size)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_DEPTH_SIZE, &info.depth_size)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy ,frmt, GLX_STENCIL_SIZE, &info.stencil_size)); + + info.renderable_type = renderableType; + int nativeRenderable = 0; + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_X_RENDERABLE, &nativeRenderable)); + info.native_renderable = !!nativeRenderable; + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_X_VISUAL_TYPE, &info.native_visual_type)); + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_VISUAL_ID, &info.native_visual_id)); + + //supported surfaces types + info.surface_type = 0; + EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_DRAWABLE_TYPE, &tmp)); + if (tmp & GLX_WINDOW_BIT && info.native_visual_id != 0) { + info.surface_type |= EGL_WINDOW_BIT; + } else { + info.native_visual_id = 0; + info.native_visual_type = EGL_NONE; + } + if (tmp & GLX_PBUFFER_BIT) { + info.surface_type |= EGL_PBUFFER_BIT; + } + + info.caveat = 0; + EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_CONFIG_CAVEAT, &tmp)); + if (tmp == GLX_NONE) { + info.caveat = EGL_NONE; + } else if (tmp == GLX_SLOW_CONFIG) { + info.caveat = EGL_SLOW_CONFIG; + } else if (tmp == GLX_NON_CONFORMANT_CONFIG) { + info.caveat = EGL_NON_CONFORMANT_CONFIG; + } + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_MAX_PBUFFER_WIDTH, &info.max_pbuffer_width)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_height)); + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_size)); + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_LEVEL, &info.frame_buffer_level)); + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_FBCONFIG_ID, &info.config_id)); + + EXIT_IF_FALSE(glXGetFBConfigAttrib( + dpy, frmt, GLX_SAMPLES, &info.samples_per_pixel)); + + //Filter out configs that do not support RGBA + EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_RENDER_TYPE, &tmp)); + if (!(tmp & GLX_RGBA_BIT)) { + return; + } + + info.frmt = new GlxPixelFormat(frmt); + + (*addConfigFunc)(addConfigOpaque, &info); +} + +// Implementation of EglOS::Surface based on GLX. +class GlxSurface : public EglOS::Surface { +public: + GlxSurface(GLXDrawable drawable, SurfaceType type) : + Surface(type), mDrawable(drawable) {} + + GLXDrawable drawable() const { return mDrawable; } + + // Helper routine to down-cast an EglOS::Surface and extract + // its drawable. + static GLXDrawable drawableFor(EglOS::Surface* surface) { + return static_cast(surface)->drawable(); + } + +private: + GLXDrawable mDrawable; +}; + +// Implementation of EglOS::Context based on GLX. +class GlxContext : public EglOS::Context { +public: + explicit GlxContext(GLXContext context) : mContext(context) {} + + GLXContext context() const { return mContext; } + + static GLXContext contextFor(EglOS::Context* context) { + return static_cast(context)->context(); + } +private: + GLXContext mContext; +}; + +// Implementation of EglOS::Display based on GLX. +class GlxDisplay : public EglOS::Display { +public: + explicit GlxDisplay(X11Display* disp) : mDisplay(disp) {} + + virtual bool release() { + return XCloseDisplay(mDisplay); + } + + virtual void queryConfigs(int renderableType, + EglOS::AddConfigCallback* addConfigFunc, + void* addConfigOpaque) { + int n; + GLXFBConfig* frmtList = glXGetFBConfigs(mDisplay, 0, &n); + for(int i = 0; i < n; i++) { + pixelFormatToConfig( + mDisplay, + renderableType, + frmtList[i], + addConfigFunc, + addConfigOpaque); + } + XFree(frmtList); + } + + virtual bool isValidNativeWin(EglOS::Surface* win) { + if (!win) { + return false; + } else { + return isValidNativeWin(GlxSurface::drawableFor(win)); + } + } + + virtual bool isValidNativeWin(EGLNativeWindowType win) { + Window root; + int t; + unsigned int u; + ErrorHandler handler(mDisplay); + if (!XGetGeometry(mDisplay, win, &root, &t, &t, &u, &u, &u, &u)) { + return false; + } + return handler.getLastError() == 0; + } + + virtual bool checkWindowPixelFormatMatch( + EGLNativeWindowType win, + const EglOS::PixelFormat* pixelFormat, + unsigned int* width, + unsigned int* height) { + //TODO: to check what does ATI & NVIDIA enforce on win pixelformat + unsigned int depth, configDepth, border; + int r, g, b, x, y; + GLXFBConfig fbconfig = GlxPixelFormat::from(pixelFormat); + + IS_SUCCESS(glXGetFBConfigAttrib( + mDisplay, fbconfig, GLX_RED_SIZE, &r)); + IS_SUCCESS(glXGetFBConfigAttrib( + mDisplay, fbconfig, GLX_GREEN_SIZE, &g)); + IS_SUCCESS(glXGetFBConfigAttrib( + mDisplay, fbconfig, GLX_BLUE_SIZE, &b)); + configDepth = r + g + b; + Window root; + if (!XGetGeometry( + mDisplay, win, &root, &x, &y, width, height, &border, &depth)) { + return false; + } + return depth >= configDepth; + } + + virtual EglOS::Context* createContext( + const EglOS::PixelFormat* pixelFormat, + EglOS::Context* sharedContext) { + ErrorHandler handler(mDisplay); + GLXContext ctx = glXCreateNewContext( + mDisplay, + GlxPixelFormat::from(pixelFormat), + GLX_RGBA_TYPE, + sharedContext ? GlxContext::contextFor(sharedContext) : NULL, + true); + + if (handler.getLastError()) { + return NULL; + } + + return new GlxContext(ctx); + } + + virtual bool destroyContext(EglOS::Context* context) { + glXDestroyContext(mDisplay, GlxContext::contextFor(context)); + return true; + } + + virtual EglOS::Surface* createPbufferSurface( + const EglOS::PixelFormat* pixelFormat, + const EglOS::PbufferInfo* info) { + const int attribs[] = { + GLX_PBUFFER_WIDTH, info->width, + GLX_PBUFFER_HEIGHT, info->height, + GLX_LARGEST_PBUFFER, info->largest, + None + }; + GLXPbuffer pb = glXCreatePbuffer( + mDisplay, + GlxPixelFormat::from(pixelFormat), + attribs); + return pb ? new GlxSurface(pb, GlxSurface::PBUFFER) : NULL; + } + + virtual bool releasePbuffer(EglOS::Surface* pb) { + if (!pb) { + return false; + } else { + glXDestroyPbuffer(mDisplay, GlxSurface::drawableFor(pb)); + return true; + } + } + + virtual bool makeCurrent(EglOS::Surface* read, + EglOS::Surface* draw, + EglOS::Context* context) { + ErrorHandler handler(mDisplay); + bool retval = false; + if (!context && !read && !draw) { + // unbind + retval = glXMakeContextCurrent(mDisplay, 0, 0, NULL); + } + else if (context && read && draw) { + retval = glXMakeContextCurrent( + mDisplay, + GlxSurface::drawableFor(draw), + GlxSurface::drawableFor(read), + GlxContext::contextFor(context)); + } + return (handler.getLastError() == 0) && retval; + } + + virtual void swapBuffers(EglOS::Surface* srfc) { + if (srfc) { + glXSwapBuffers(mDisplay, GlxSurface::drawableFor(srfc)); + } + } + +private: + X11Display* mDisplay; +}; + +class GlxLibrary : public GlLibrary { +public: + typedef GlFunctionPointer (ResolverFunc)(const char* name); + + // Important: Use libGL.so.1 explicitly, because it will always link to + // the vendor-specific version of the library. libGL.so might in some + // cases, depending on bad ldconfig configurations, link to the wrapper + // lib that doesn't behave the same. + GlxLibrary() : mLib(NULL), mResolver(NULL) { + static const char kLibName[] = "libGL.so.1"; + char error[256]; + mLib = emugl::SharedLibrary::open(kLibName, error, sizeof(error)); + if (!mLib) { + ERR("%s: Could not open GL library %s [%s]\n", + __FUNCTION__, kLibName, error); + return; + } + // NOTE: Don't use glXGetProcAddress here, only glXGetProcAddressARB + // is guaranteed to be supported by vendor-specific libraries. + static const char kResolverName[] = "glXGetProcAddressARB"; + mResolver = reinterpret_cast( + mLib->findSymbol(kResolverName)); + if (!mResolver) { + ERR("%s: Could not find resolver %s in %s\n", + __FUNCTION__, kResolverName, kLibName); + delete mLib; + mLib = NULL; + } + } + + ~GlxLibrary() { + delete mLib; + } + + // override + virtual GlFunctionPointer findSymbol(const char* name) { + if (!mLib) { + return NULL; + } + GlFunctionPointer ret = (*mResolver)(name); + if (!ret) { + ret = reinterpret_cast(mLib->findSymbol(name)); + } + return ret; + } + +private: + emugl::SharedLibrary* mLib; + ResolverFunc* mResolver; +}; + +class GlxEngine : public EglOS::Engine { +public: + GlxEngine() : mGlLib() {} + + virtual EglOS::Display* getDefaultDisplay() { + return new GlxDisplay(XOpenDisplay(0)); + } + + virtual GlLibrary* getGlLibrary() { + return &mGlLib; + } + + virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) { + return new GlxSurface(wnd, GlxSurface::WINDOW); + } +private: + GlxLibrary mGlLib; +}; + +emugl::LazyInstance sHostEngine = LAZY_INSTANCE_INIT; + +} // namespace + +// static +EglOS::Engine* EglOS::Engine::getHostInstance() { + return sHostEngine.ptr(); +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi_mir.cpp b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_mir.cpp new file mode 100644 index 0000000..b0970c6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_mir.cpp @@ -0,0 +1,583 @@ +/* +* 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. +*/ + +#define MIR_EGL_PLATFORM + +#include "mir_support/shared_state.h" + +#include "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/shared_library.h" +#include "GLcommon/GLLibrary.h" + +#include "OpenglCodecCommon/ErrorLog.h" + +#include + +#include +#include + +#include +#include + +#define EXIT_IF_FALSE(a) \ + do { if (!a) return; } while (0) + +namespace { +class HostEglImpl { +public: + static HostEglImpl* get() { + static HostEglImpl *inst = new HostEglImpl; + return inst; + } + + EGLint eglGetError() { + typedef EGLint (*_eglGetErrorFunc)(); + static _eglGetErrorFunc _eglGetError; + + if (!_eglGetError) + _eglGetError = reinterpret_cast<_eglGetErrorFunc>(lib_->findSymbol("eglGetError")); + + return _eglGetError(); + } + + EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) { + typedef EGLDisplay (*_eglGetDisplayFunc)(EGLNativeDisplayType display_id); + static _eglGetDisplayFunc _eglGetDisplay; + + if (!_eglGetDisplay) + _eglGetDisplay = reinterpret_cast<_eglGetDisplayFunc>(lib_->findSymbol("eglGetDisplay")); + + return _eglGetDisplay(display_id); + } + + EGLBoolean eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) { + typedef EGLBoolean (*_eglInitializeFunc)(EGLDisplay display, EGLint *major, EGLint *minor); + static _eglInitializeFunc _eglInitialize = nullptr; + + if (!_eglInitialize) + _eglInitialize = reinterpret_cast<_eglInitializeFunc>(lib_->findSymbol("eglInitialize")); + + return _eglInitialize(display, major, minor); + } + + EGLBoolean eglTerminate(EGLDisplay display) { + typedef EGLBoolean (*_eglTermianteFunc)(EGLDisplay display); + static _eglTermianteFunc _eglTerminate = nullptr; + + if (!_eglTerminate) + _eglTerminate = reinterpret_cast<_eglTermianteFunc>(lib_->findSymbol("eglTerminate")); + + return _eglTerminate(display); + } + + EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { + typedef EGLContext (*_eglCreateContextFunc)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); + static _eglCreateContextFunc _eglCreateContext = nullptr; + + if (!_eglCreateContext) + _eglCreateContext = reinterpret_cast<_eglCreateContextFunc>(lib_->findSymbol("eglCreateContext")); + + return _eglCreateContext(dpy, config, share_context, attrib_list); + } + + EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface read, EGLSurface draw, EGLContext context) { + typedef EGLBoolean (*_eglMakeCurrentFunc)(EGLDisplay display, EGLSurface read, EGLSurface draw, EGLContext context); + static _eglMakeCurrentFunc _eglMakeCurrent = nullptr; + + if (!_eglMakeCurrent) + _eglMakeCurrent = reinterpret_cast<_eglMakeCurrentFunc>(lib_->findSymbol("eglMakeCurrent")); + + return _eglMakeCurrent(display, read, draw, context); + } + + EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) { + typedef EGLBoolean (*_eglGetConfigsFunc)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); + static _eglGetConfigsFunc _eglGetConfigs = nullptr; + + if (!_eglGetConfigs) + _eglGetConfigs = reinterpret_cast<_eglGetConfigsFunc>(lib_->findSymbol("eglGetConfigs")); + + return _eglGetConfigs(dpy, configs, config_size, num_config); + } + + EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { + typedef EGLSurface (*_eglCreatePbufferSurfaceFunc)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); + static _eglCreatePbufferSurfaceFunc _eglCreatePbufferSurface = nullptr; + + if (!_eglCreatePbufferSurface) + _eglCreatePbufferSurface = reinterpret_cast<_eglCreatePbufferSurfaceFunc>(lib_->findSymbol("eglCreatePbufferSurface")); + + return _eglCreatePbufferSurface(dpy, config, attrib_list); + } + + EGLBoolean eglDestroySurface(EGLDisplay display, EGLSurface surface) { + typedef EGLBoolean (*_eglDestroySurfaceFunc)(EGLDisplay display, EGLSurface surface); + static _eglDestroySurfaceFunc _eglDestroySurface = nullptr; + + if (!_eglDestroySurface) + _eglDestroySurface = reinterpret_cast<_eglDestroySurfaceFunc>(lib_->findSymbol("eglDestroySurface")); + + return _eglDestroySurface(display, surface); + } + + EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface) { + typedef EGLBoolean (*_eglSwapBuffersFunc)(EGLDisplay display, EGLSurface surface); + static _eglSwapBuffersFunc _eglSwapBuffers = nullptr; + + if (!_eglSwapBuffers) + _eglSwapBuffers = reinterpret_cast<_eglSwapBuffersFunc>(lib_->findSymbol("eglSwapBuffers")); + + return _eglSwapBuffers(display, surface); + } + + EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) { + typedef EGLBoolean (*_eglGetConfigAttribFunc)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); + static _eglGetConfigAttribFunc _eglGetConfigAttrib = nullptr; + + if (!_eglGetConfigAttrib) + _eglGetConfigAttrib = reinterpret_cast<_eglGetConfigAttribFunc>(lib_->findSymbol("eglGetConfigAttrib")); + + return _eglGetConfigAttrib(dpy, config, attribute, value); + } + + EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, EGLNativeWindowType window, const EGLint *attribs) { + typedef EGLSurface (*_eglCreateWindowSurfaceFunc)(EGLDisplay display, EGLConfig config, EGLNativeWindowType window, const EGLint *attribs); + static _eglCreateWindowSurfaceFunc _eglCreateWindowSurface; + + if (!_eglCreateWindowSurface) + _eglCreateWindowSurface = reinterpret_cast<_eglCreateWindowSurfaceFunc>(lib_->findSymbol("eglCreateWindowSurface")); + + return _eglCreateWindowSurface(display, config, window, attribs); + } + +private: + HostEglImpl() { + static const char kLibName[] = "libEGL.so.1"; + + char error[256]; + lib_ = emugl::SharedLibrary::open(kLibName, error, sizeof(error)); + if (!lib_) { + ERR("%s: Could not open host EGL library %s [%s]\n", + __FUNCTION__, kLibName, error); + return; + } + } + + emugl::SharedLibrary *lib_; +}; + +class MirImplPixelFormat : public EglOS::PixelFormat { +public: + MirImplPixelFormat(EGLConfig config) : + config_(config) { + } + + EGLConfig nativeFormat() const { return config_; } + + virtual EglOS::PixelFormat* clone() { + return new MirImplPixelFormat(config_); + } + + static const MirImplPixelFormat* from(const EglOS::PixelFormat *format) { + return static_cast(format); + } + + EGLConfig config() const { + return config_; + } + +private: + EGLConfig config_; +}; + +class MirImplSurface : public EglOS::Surface { +public: + MirImplSurface(SurfaceType type) : + Surface(type), + surface_(EGL_NO_SURFACE) { + } + + static MirImplSurface* create_with_surface(EGLSurface surface) { + auto impl = new MirImplSurface(SurfaceType::PBUFFER); + impl->surface_ = surface; + return impl; + } + + static MirImplSurface* create_with_native_window(EGLSurface surface) { + auto impl = new MirImplSurface(SurfaceType::WINDOW); + impl->surface_ = surface; + return impl; + } + + EGLSurface drawable() { + return surface_; + } + + void invalidate() { + surface_ = EGL_NO_SURFACE; + } + + static MirImplSurface* from(EglOS::Surface *surface) { + if (!surface) + return nullptr; + + return static_cast(surface); + } + +private: + EGLSurface surface_; + EGLNativeWindowType native_window_; +}; + +class MirImplContext : public EglOS::Context { +public: + MirImplContext(EGLDisplay display, const MirImplPixelFormat *format, MirImplContext *shared_context) : + egl_display_(display), + egl_context_(EGL_NO_CONTEXT) { + + EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + egl_context_ = HostEglImpl::get()->eglCreateContext(egl_display_, + format ? format->nativeFormat() : nullptr, + shared_context ? shared_context->nativeContext() : EGL_NO_CONTEXT, + context_attribs); + if (egl_context_ == EGL_NO_CONTEXT) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create EGL context")); + } + + bool release() { + if (!eglDestroyContext(egl_display_, egl_context_)) + return false; + + egl_display_ = EGL_NO_DISPLAY; + egl_context_ = EGL_NO_CONTEXT; + + return true; + } + + EGLContext nativeContext() const { + return egl_context_; + } + + static MirImplContext* from(EglOS::Context *context) { + if (!context) + return nullptr; + + return static_cast(context); + } + +private: + EGLDisplay egl_display_; + EGLContext egl_context_; +}; + +class MirImplDisplay : public EglOS::Display { +public: + explicit MirImplDisplay(MirConnection *connection) : + connection_(connection) { + if (!mir_connection_is_valid(connection_)) + BOOST_THROW_EXCEPTION(std::runtime_error("Not connected to Mir server")); + + egl_display_ = HostEglImpl::get()->eglGetDisplay(mir_connection_get_egl_native_display(connection_)); + if (egl_display_ == EGL_NO_DISPLAY) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to get EGL display")); + + if (!HostEglImpl::get()->eglInitialize(egl_display_, nullptr, nullptr)) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize EGL")); + } + + virtual bool release() override { + HostEglImpl::get()->eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + HostEglImpl::get()->eglTerminate(egl_display_); + egl_display_ = EGL_NO_DISPLAY; + return true; + } + + virtual void queryConfigs(int renderable_type, EglOS::AddConfigCallback *callback, void *user_data) override { + int num_configs = 0; + HostEglImpl::get()->eglGetConfigs(egl_display_, nullptr, 0, &num_configs); + + auto configs = (EGLConfig*) calloc(num_configs, sizeof(EGLConfig)); + int num_config_available = 0; + HostEglImpl::get()->eglGetConfigs(egl_display_, configs, num_configs, &num_config_available); + + for (int n = 0; n < num_config_available; n++) { + EGLConfig config = configs[n]; + + EglOS::ConfigInfo info; + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_RED_SIZE, &info.red_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_GREEN_SIZE, &info.green_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_BLUE_SIZE, &info.blue_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_ALPHA_SIZE, &info.alpha_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_CONFIG_CAVEAT, &info.caveat)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_CONFIG_ID, &info.config_id)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_DEPTH_SIZE, &info.depth_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_LEVEL, &info.frame_buffer_level)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_WIDTH, &info.max_pbuffer_width)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_height)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_PIXELS, &info.max_pbuffer_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_RENDERABLE, &info.native_renderable)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_RENDERABLE_TYPE, &info.renderable_type)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_VISUAL_ID, &info.native_visual_id)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_VISUAL_TYPE, &info.native_visual_type)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_SAMPLES, &info.samples_per_pixel)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_STENCIL_SIZE, &info.stencil_size)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_SURFACE_TYPE, &info.surface_type)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_TYPE, &info.transparent_type)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_RED_VALUE, &info.trans_red_val)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_GREEN_VALUE, &info.trans_green_val)); + EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_BLUE_VALUE, &info.trans_blue_val)); + + info.frmt = new MirImplPixelFormat(config); + + (*callback)(user_data, &info); + } + + free(configs); + } + + virtual bool isValidNativeWin(EglOS::Surface *surface) override { + if (!surface) + return false; + + return surface->type() == EglOS::Surface::WINDOW; + } + + virtual bool isValidNativeWin(EGLNativeWindowType window) override { + return true; + } + + virtual bool checkWindowPixelFormatMatch( + EGLNativeWindowType window, + const EglOS::PixelFormat *format, + unsigned int *width, + unsigned int *height) override { + + auto impl = MirImplPixelFormat::from(format); + + EGLint r = 0, g = 0, b = 0; + if (!copy_egl_attrib(impl->nativeFormat(), EGL_RED_SIZE, &r)) + return false; + if (!copy_egl_attrib(impl->nativeFormat(), EGL_GREEN_SIZE, &g)) + return false; + if (!copy_egl_attrib(impl->nativeFormat(), EGL_BLUE_SIZE, &b)) + return false; + + const auto config_depth = r + g +b; + + return true; + } + + virtual EglOS::Context* createContext(const EglOS::PixelFormat *format, EglOS::Context *shared_context) override { + try { + return new MirImplContext(egl_display_, + MirImplPixelFormat::from(format), + MirImplContext::from(shared_context)); + } + catch (std::exception &err) { + ERR("Failed to create EGL context: %s\n", err.what()); + return nullptr; + } + } + + virtual bool destroyContext(EglOS::Context *context) override { + if (!context) + return context; + + return MirImplContext::from(context)->release(); + } + + virtual EglOS::Surface* createPbufferSurface( + const EglOS::PixelFormat* format, + const EglOS::PbufferInfo* info) override { + + EGLint attribs[] = { + EGL_WIDTH, info->width, + EGL_HEIGHT, info->height, + EGL_LARGEST_PBUFFER, info->largest, + EGL_MIPMAP_TEXTURE, info->hasMipmap, + EGL_TEXTURE_TARGET, info->target, + EGL_NONE, + }; + + auto surface = HostEglImpl::get()->eglCreatePbufferSurface(egl_display_, + MirImplPixelFormat::from(format)->nativeFormat(), + attribs); + if (surface == EGL_NO_SURFACE) + return nullptr; + + return MirImplSurface::create_with_surface(surface); + } + + virtual bool releasePbuffer(EglOS::Surface *surface) override { + if (!surface) + return false; + + auto impl = MirImplSurface::from(surface); + if (!impl) + return false; + + if (!HostEglImpl::get()->eglDestroySurface(egl_display_, impl->drawable())) + return false; + + impl->invalidate(); + return true; + } + + virtual bool makeCurrent(EglOS::Surface* input_surface, + EglOS::Surface* output_surface, + EglOS::Context* context) override { + + bool success = false; + + if (!input_surface && !output_surface && !context) { + success = HostEglImpl::get()->eglMakeCurrent(egl_display_, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); + } + else if (input_surface && output_surface && context) { + success = HostEglImpl::get()->eglMakeCurrent(egl_display_, + MirImplSurface::from(input_surface)->drawable(), + MirImplSurface::from(output_surface)->drawable(), + MirImplContext::from(context)->nativeContext()); + } + + return success; + } + + virtual void swapBuffers(EglOS::Surface *surface) override { + HostEglImpl::get()->eglSwapBuffers(egl_display_, MirImplSurface::from(surface)->drawable()); + } + + EGLDisplay display() const { + return egl_display_; + } + +private: + template + bool copy_egl_attrib(EGLConfig config, EGLint attribute, T *target) { + T value; + + if (!HostEglImpl::get()->eglGetConfigAttrib(egl_display_, config, attribute, reinterpret_cast(&value))) + return false; + + *target = value; + + return true; + } + + MirConnection *connection_; + EGLDisplay egl_display_; +}; + +class MirImplGlLibrary : public GlLibrary { +public: + typedef GlFunctionPointer (ResolverFunc)(const char* name); + + MirImplGlLibrary() { + static const char kLibName[] = "libGLESv2.so.2"; + static const char kEGLLibName[] = "libEGL.so.1"; + + char error[256]; + lib_ = emugl::SharedLibrary::open(kLibName, error, sizeof(error)); + if (!lib_) { + ERR("%s: Could not open host GLESv2 library %s [%s]\n", + __FUNCTION__, kLibName, error); + return; + } + + egl_lib_ = emugl::SharedLibrary::open(kEGLLibName, error, sizeof(error)); + if (!lib_) { + ERR("%s: Could not open host EGL library %s [%s]\n", + __FUNCTION__, kEGLLibName, error); + return; + } + + resolver_ = reinterpret_cast(egl_lib_->findSymbol("eglGetProcAddress")); + } + + virtual GlFunctionPointer findSymbol(const char *name) override { + if (!lib_) + return nullptr; + + ERR("Trying to resolved %s ...\n", name); + + GlFunctionPointer symbol = nullptr; + + if (resolver_) + symbol = (*resolver_)(name); + + if (!symbol) + symbol = reinterpret_cast(lib_->findSymbol(name)); + + ERR("-> %p\n", symbol); + + return symbol; + } + +private: + emugl::SharedLibrary *lib_; + emugl::SharedLibrary *egl_lib_; + ResolverFunc *resolver_; +}; + +class MirImplEngine : public EglOS::Engine { +public: + MirImplEngine() { + ERR("Initialized Mir EGL engine"); + } + + ~MirImplEngine() { + } + + virtual EglOS::Display* getDefaultDisplay() override { + mir::support::SharedState::get()->ensure_connection(); + + return new MirImplDisplay(mir::support::SharedState::get()->connection()); + } + + virtual GlLibrary* getGlLibrary() { + return &lib_; + } + + virtual EglOS::Surface* createWindowSurface(EglOS::Display *display, EGLNativeWindowType window, EglOS::PixelFormat *format) override { + mir::support::SharedState::get()->ensure_connection(); + + auto surface = HostEglImpl::get()->eglCreateWindowSurface( + static_cast(display)->display(), + static_cast(format)->config(), + window, + nullptr); + + return MirImplSurface::create_with_native_window(surface); + } + +private: + MirImplGlLibrary lib_; +}; + +emugl::LazyInstance sHostEngine = LAZY_INSTANCE_INIT; +} + +EglOS::Engine* EglOS::Engine::getHostInstance() { + return sHostEngine.ptr(); +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi_null.cpp b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_null.cpp new file mode 100644 index 0000000..6c791c6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_null.cpp @@ -0,0 +1,46 @@ +/* +* 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 "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" + +namespace { +class NullEngine : public EglOS::Engine { +public: + NullEngine() = default; + + virtual EglOS::Display* getDefaultDisplay() override { + return nullptr; + } + + virtual GlLibrary* getGlLibrary() { + return nullptr; + } + + virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType window) override { + return nullptr; + } +}; + +emugl::LazyInstance sHostEngine = LAZY_INSTANCE_INIT; +} + +#if 0 +EglOS::Engine* EglOS::Engine::getHostInstance() { + return sHostEngine.ptr(); +} +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglOsApi_wgl.cpp b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_wgl.cpp new file mode 100644 index 0000000..874ffc8 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglOsApi_wgl.cpp @@ -0,0 +1,1022 @@ +/* +* 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 "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/shared_library.h" +#include "GLcommon/GLLibrary.h" + +#include "OpenglCodecCommon/ErrorLog.h" + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#define IS_TRUE(a) \ + do { if (!(a)) return NULL; } while (0) + +#define EXIT_IF_FALSE(a) \ + do { if (!(a)) return; } while (0) + +#define DEBUG 0 +#if DEBUG +#define D(...) fprintf(stderr, __VA_ARGS__) +#else +#define D(...) ((void)0) +#endif + +namespace { + +using emugl::SharedLibrary; +typedef GlLibrary::GlFunctionPointer GlFunctionPointer; + +// Returns true if an extension is include in a given extension list. +// |extension| is an GL extension name. +// |extensionList| is a space-separated list of supported extension. +// Returns true if the extension is supported, false otherwise. +bool supportsExtension(const char* extension, const char* extensionList) { + size_t extensionLen = ::strlen(extension); + const char* list = extensionList; + for (;;) { + const char* p = const_cast(::strstr(list, extension)); + if (!p) { + return false; + } + // Check that the extension appears as a single word in the list + // i.e. that it is wrapped by either spaces or the start/end of + // the list. + if ((p == extensionList || p[-1] == ' ') && + (p[extensionLen] == '\0' || p[extensionLen] == ' ')) { + return true; + } + // otherwise, skip over the current position to find something else. + p += extensionLen; + } +} + +///// +///// W G L D I S P A T C H T A B L E S +///// + +// A technical note to explain what is going here, trust me, it's important. +// +// I. Library-dependent symbol resolution: +// --------------------------------------- +// +// The code here can deal with two kinds of OpenGL Windows libraries: the +// system-provided opengl32.dll, or alternate software renderers like Mesa +// (e.g. mesa_opengl32.dll). +// +// When using the system library, pixel-format related functions, like +// SetPixelFormat(), are provided by gdi32.dll, and _not_ opengl32.dll +// (even though they are documented as part of the Windows GL API). +// +// These functions must _not_ be used when using alternative renderers. +// Instead, these provide _undocumented_ alternatives with the 'wgl' prefix, +// as in wglSetPixelFormat(), wglDescribePixelFormat(), etc... which +// implement the same calling conventions. +// +// For more details about this, see 5.190 of the Windows OpenGL FAQ at: +// https://www.opengl.org/archives/resources/faq/technical/mswindows.htm +// +// Another good source of information on this topic: +// http://stackoverflow.com/questions/20645706/why-are-functions-duplicated-between-opengl32-dll-and-gdi32-dll +// +// In practice, it means that the code here should resolve 'naked' symbols +// (e.g. 'GetPixelFormat()) when using the system library, and 'prefixed' ones +// (e.g. 'wglGetPixelFormat()) otherwise. +// + +// List of WGL functions of interest to probe with GetProcAddress() +#define LIST_WGL_FUNCTIONS(X) \ + X(HGLRC, wglCreateContext, (HDC hdc)) \ + X(BOOL, wglDeleteContext, (HGLRC hglrc)) \ + X(BOOL, wglMakeCurrent, (HDC hdc, HGLRC hglrc)) \ + X(BOOL, wglShareLists, (HGLRC hglrc1, HGLRC hglrc2)) \ + X(HGLRC, wglGetCurrentContext, (void)) \ + X(HDC, wglGetCurrentDC, (void)) \ + X(GlFunctionPointer, wglGetProcAddress, (const char* functionName)) \ + +// List of WGL functions exported by GDI32 that must be used when using +// the system's opengl32.dll only, i.e. not with a software renderer like +// Mesa. For more information, see 5.190 at: +// And also: +#define LIST_GDI32_FUNCTIONS(X) \ + X(int, ChoosePixelFormat, (HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)) \ + X(BOOL, SetPixelFormat, (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR* pfd)) \ + X(int, GetPixelFormat, (HDC hdc)) \ + X(int, DescribePixelFormat, (HDC hdc, int iPixelFormat, UINT nbytes, LPPIXELFORMATDESCRIPTOR ppfd)) \ + X(BOOL, SwapBuffers, (HDC hdc)) \ + +// Declare a structure containing pointers to all functions listed above, +// and a way to initialize them. +struct WglBaseDispatch { + // declare all function pointers, followed by a dummy member used + // to terminate the constructor's initialization list properly. +#define DECLARE_WGL_POINTER(return_type, function_name, signature) \ + return_type (GL_APIENTRY* function_name) signature; + LIST_WGL_FUNCTIONS(DECLARE_WGL_POINTER) + LIST_GDI32_FUNCTIONS(DECLARE_WGL_POINTER) + SharedLibrary* mLib; + bool mIsSystemLib; + + // Default Constructor + WglBaseDispatch() : +#define INIT_WGL_POINTER(return_type, function_name, signature) \ + function_name(NULL), + LIST_WGL_FUNCTIONS(INIT_WGL_POINTER) + LIST_GDI32_FUNCTIONS(INIT_WGL_POINTER) + mLib(NULL), + mIsSystemLib(false) {} + + // Copy constructor + WglBaseDispatch(const WglBaseDispatch& other) : +#define COPY_WGL_POINTER(return_type, function_name, signature) \ + function_name(other.function_name), + LIST_WGL_FUNCTIONS(COPY_WGL_POINTER) + LIST_GDI32_FUNCTIONS(COPY_WGL_POINTER) + mLib(other.mLib), + mIsSystemLib(other.mIsSystemLib) {} + + // Initialize the dispatch table from shared library |glLib|, which + // must point to either the system or non-system opengl32.dll + // implementation. If |systemLib| is true, this considers the library + // to be the system one, and will try to find the GDI32 functions + // like GetPixelFormat() directly. If |systemLib| is false, this will + // try to load the wglXXX variants (e.g. for Mesa). See technical note + // above for details. + // Returns true on success, false otherwise (i.e. if one of the + // required symbols could not be loaded). + bool init(SharedLibrary* glLib, bool systemLib) { + bool result = true; + + mLib = glLib; + mIsSystemLib = systemLib; + +#define LOAD_WGL_POINTER(return_type, function_name, signature) \ + this->function_name = reinterpret_cast< \ + return_type (GL_APIENTRY*) signature>( \ + glLib->findSymbol(#function_name)); \ + if (!this->function_name) { \ + ERR("%s: Could not find %s in GL library\n", __FUNCTION__, \ + #function_name); \ + result = false; \ + } + +#define LOAD_WGL_GDI32_POINTER(return_type, function_name, signature) \ + this->function_name = reinterpret_cast< \ + return_type (GL_APIENTRY*) signature>( \ + GetProcAddress(gdi32, #function_name)); \ + if (!this->function_name) { \ + ERR("%s: Could not find %s in GDI32 library\n", __FUNCTION__, \ + #function_name); \ + result = false; \ + } + +#define LOAD_WGL_INNER_POINTER(return_type, function_name, signature) \ + this->function_name = reinterpret_cast< \ + return_type (GL_APIENTRY*) signature>( \ + glLib->findSymbol("wgl" #function_name)); \ + if (!this->function_name) { \ + ERR("%s: Could not find %s in GL library\n", __FUNCTION__, \ + "wgl" #function_name); \ + result = false; \ + } + + LIST_WGL_FUNCTIONS(LOAD_WGL_POINTER) + if (systemLib) { + HMODULE gdi32 = GetModuleHandle("gdi32.dll"); + LIST_GDI32_FUNCTIONS(LOAD_WGL_GDI32_POINTER) + } else { + LIST_GDI32_FUNCTIONS(LOAD_WGL_INNER_POINTER) + } + return result; + } + + // Find a function, using wglGetProcAddress() first, and if that doesn't + // work, SharedLibrary::findSymbol(). + // |functionName| is the function name. + // |glLib| is the GL library to probe with findSymbol() is needed. + GlFunctionPointer findFunction(const char* functionName) const { + GlFunctionPointer result = this->wglGetProcAddress(functionName); + if (!result && mLib) { + result = mLib->findSymbol(functionName); + } + return result; + } +}; + +// Used internally by createDummyWindow(). +LRESULT CALLBACK dummyWndProc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +// Create a new dummy window, and return its handle. +// Note that the window is 1x1 pixels and not visible, but +// it can be used to create a device context and associated +// OpenGL rendering context. +HWND createDummyWindow() { + WNDCLASSEX wcx; + wcx.cbSize = sizeof(wcx); // size of structure + wcx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; // redraw if size changes + wcx.lpfnWndProc = dummyWndProc; // points to window procedure + wcx.cbClsExtra = 0; // no extra class memory + wcx.cbWndExtra = sizeof(void*); // save extra window memory, to store VasWindow instance + wcx.hInstance = NULL; // handle to instance + wcx.hIcon = NULL; // predefined app. icon + wcx.hCursor = NULL; + wcx.hbrBackground = NULL; // no background brush + wcx.lpszMenuName = NULL; // name of menu resource + wcx.lpszClassName = "DummyWin"; // name of window class + wcx.hIconSm = (HICON) NULL; // small class icon + + RegisterClassEx(&wcx); + + HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, + "DummyWin", + "Dummy", + WS_POPUP, + 0, + 0, + 1, + 1, + NULL, + NULL, + 0,0); + return hwnd; +} + +// List of functions defined by the WGL_ARB_extensions_string extension. +#define LIST_WGL_ARB_extensions_string_FUNCTIONS(X) \ + X(const char*, wglGetExtensionsStringARB, (HDC hdc)) + +// List of functions defined by the WGL_ARB_pixel_format extension. +#define LIST_WGL_ARB_pixel_format_FUNCTIONS(X) \ + X(BOOL, wglGetPixelFormatAttribivARB, (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int* piValues)) \ + X(BOOL, wglGetPixelFormatAttribfvARB, (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT* pfValues)) \ + X(BOOL, wglChoosePixelFormatARB, (HDC, const int* piAttribList, const FLOAT* pfAttribList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats)) \ + +// List of functions defined by the WGL_ARB_make_current_read extension. +#define LIST_WGL_ARB_make_current_read_FUNCTIONS(X) \ + X(BOOL, wglMakeContextCurrentARB, (HDC hDrawDC, HDC hReadDC, HGLRC hglrc)) \ + X(HDC, wglGetCurrentReadDCARB, (void)) \ + +// List of functions defined by the WGL_ARB_pbuffer extension. +#define LIST_WGL_ARB_pbuffer_FUNCTIONS(X) \ + X(HPBUFFERARB, wglCreatePbufferARB, (HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList)) \ + X(HDC, wglGetPbufferDCARB, (HPBUFFERARB hPbuffer)) \ + X(int, wglReleasePbufferDCARB, (HPBUFFERARB hPbuffer, HDC hdc)) \ + X(BOOL, wglDestroyPbufferARB, (HPBUFFERARB hPbuffer)) \ + +#define LIST_WGL_EXTENSIONS_FUNCTIONS(X) \ + LIST_WGL_ARB_pixel_format_FUNCTIONS(X) \ + LIST_WGL_ARB_make_current_read_FUNCTIONS(X) \ + LIST_WGL_ARB_pbuffer_FUNCTIONS(X) \ + +// A structure used to hold pointers to WGL extension functions. +struct WglExtensionsDispatch : public WglBaseDispatch { +public: + LIST_WGL_EXTENSIONS_FUNCTIONS(DECLARE_WGL_POINTER) + int dummy; + + // Default constructor + explicit WglExtensionsDispatch(const WglBaseDispatch& baseDispatch) : + WglBaseDispatch(baseDispatch), + LIST_WGL_EXTENSIONS_FUNCTIONS(INIT_WGL_POINTER) + dummy(0) {} + + // Initialization + bool init(HDC hdc) { + // Base initialization happens first. + bool result = WglBaseDispatch::init(mLib, mIsSystemLib); + if (!result) { + return false; + } + + // Find the list of extensions. + typedef const char* (GL_APIENTRY* GetExtensionsStringFunc)(HDC hdc); + + GetExtensionsStringFunc wglGetExtensionsStringARB = + reinterpret_cast( + this->findFunction("wglGetExtensionsStringARB")); + if (!wglGetExtensionsStringARB) { + ERR("%s: Could not find wglGetExtensionsStringARB!\n", + __FUNCTION__); + return false; + } + const char* extensionList = wglGetExtensionsStringARB(hdc); + if (!extensionList) { + extensionList = ""; + } + + // Load each extension individually. +#define LOAD_WGL_EXTENSION_FUNCTION(return_type, function_name, signature) \ + this->function_name = reinterpret_cast< \ + return_type (GL_APIENTRY*) signature>( \ + this->findFunction(#function_name)); \ + if (!this->function_name) { \ + ERR("ERROR: %s: Missing extension function %s\n", __FUNCTION__, \ + #function_name); \ + result = false; \ + } + +#define LOAD_WGL_EXTENSION(extension) \ + if (!supportsExtension(#extension, extensionList)) { \ + ERR("WARNING: %s: Missing WGL extension %s\n", __FUNCTION__, #extension); \ + } else { \ + LIST_##extension##_FUNCTIONS(LOAD_WGL_EXTENSION_FUNCTION) \ + } + + LOAD_WGL_EXTENSION(WGL_ARB_pixel_format) + LOAD_WGL_EXTENSION(WGL_ARB_make_current_read) + LOAD_WGL_EXTENSION(WGL_ARB_pbuffer) + + // Done. + return result; + } + +private: + WglExtensionsDispatch(); // no default constructor. +}; + +const WglExtensionsDispatch* initExtensionsDispatch( + const WglBaseDispatch* dispatch) { + HWND hwnd = createDummyWindow(); + HDC hdc = GetDC(hwnd); + if (!hwnd || !hdc){ + fprintf(stderr,"error while getting DC\n"); + return NULL; + } + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 32, // 32-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 24, // 24-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + int iPixelFormat = dispatch->ChoosePixelFormat(hdc, &pfd); + if (iPixelFormat <= 0) { + int err = GetLastError(); + fprintf(stderr,"error while choosing pixel format 0x%x\n", err); + return NULL; + } + if (!dispatch->SetPixelFormat(hdc, iPixelFormat, &pfd)) { + int err = GetLastError(); + fprintf(stderr,"error while setting pixel format 0x%x\n", err); + return NULL; + } + + int err; + HGLRC ctx = dispatch->wglCreateContext(hdc); + if (!ctx) { + err = GetLastError(); + fprintf(stderr,"error while creating dummy context %d\n", err); + } + if (!dispatch->wglMakeCurrent(hdc, ctx)) { + err = GetLastError(); + fprintf(stderr,"error while making dummy context current %d\n", err); + } + + WglExtensionsDispatch* result = new WglExtensionsDispatch(*dispatch); + result->init(hdc); + + dispatch->wglMakeCurrent(hdc, NULL); + dispatch->wglDeleteContext(ctx); + DeleteDC(hdc); + DestroyWindow(hwnd); + + return result; +} + +class WinPixelFormat : public EglOS::PixelFormat { +public: + WinPixelFormat(const PIXELFORMATDESCRIPTOR* desc, int configId) { + mDesc = *desc; + mConfigId = configId; + } + + EglOS::PixelFormat* clone() { + return new WinPixelFormat(&mDesc, mConfigId); + } + + const PIXELFORMATDESCRIPTOR* desc() const { return &mDesc; } + const int configId() const { return mConfigId; } + + static const WinPixelFormat* from(const EglOS::PixelFormat* f) { + return static_cast(f); + } + +private: + WinPixelFormat(); + WinPixelFormat(const WinPixelFormat& other); + + PIXELFORMATDESCRIPTOR mDesc; + int mConfigId; +}; + +class WinSurface : public EglOS::Surface { +public: + explicit WinSurface(HWND wnd) : + Surface(WINDOW), + m_hwnd(wnd), + m_pb(NULL), + m_hdc(GetDC(wnd)) {} + + explicit WinSurface(HPBUFFERARB pb, const WglExtensionsDispatch* dispatch) : + Surface(PBUFFER), + m_hwnd(NULL), + m_pb(pb), + m_hdc(NULL) { + if (dispatch->wglGetPbufferDCARB) { + m_hdc = dispatch->wglGetPbufferDCARB(pb); + } + } + + ~WinSurface() { + if (type() == WINDOW) { + ReleaseDC(m_hwnd, m_hdc); + } + } + + HWND getHwnd() const { return m_hwnd; } + HDC getDC() const { return m_hdc; } + HPBUFFERARB getPbuffer() const { return m_pb; } + + static WinSurface* from(EglOS::Surface* s) { + return static_cast(s); + } + +private: + HWND m_hwnd; + HPBUFFERARB m_pb; + HDC m_hdc; +}; + +class WinContext : public EglOS::Context { +public: + explicit WinContext(HGLRC ctx) : mCtx(ctx) {} + + HGLRC context() const { return mCtx; } + + static HGLRC from(const EglOS::Context* c) { + return static_cast(c)->context(); + } + +private: + HGLRC mCtx; +}; + +struct DisplayInfo { + DisplayInfo() : dc(NULL), hwnd(NULL), isPixelFormatSet(false) {} + + DisplayInfo(HDC hdc, HWND wnd) : + dc(hdc), hwnd(wnd), isPixelFormatSet(false) {} + + void release() { + if (hwnd) { + DestroyWindow(hwnd); + } + DeleteDC(dc); + } + + HDC dc; + HWND hwnd; + bool isPixelFormatSet; +}; + +struct TlsData { + std::map m_map; +}; + +DWORD s_tlsIndex = 0; + +TlsData* getTLS() { + TlsData *tls = (TlsData *)TlsGetValue(s_tlsIndex); + if (!tls) { + tls = new TlsData(); + TlsSetValue(s_tlsIndex, tls); + } + return tls; +} + +} // namespace + +class WinDisplay { +public: + enum { DEFAULT_DISPLAY = 0 }; + + WinDisplay() {}; + + DisplayInfo& getInfo(int configurationIndex) const { + return getTLS()->m_map[configurationIndex]; + } + + HDC getDC(int configId) const { + return getInfo(configId).dc; + } + + void setInfo(int configurationIndex, const DisplayInfo& info); + + bool isPixelFormatSet(int cfgId) const { + return getInfo(cfgId).isPixelFormatSet; + } + + void pixelFormatWasSet(int cfgId) { + getTLS()->m_map[cfgId].isPixelFormatSet = true; + } + + bool infoExists(int configurationIndex); + + void releaseAll(); +}; + +void WinDisplay::releaseAll(){ + TlsData * tls = getTLS(); + + for(std::map::iterator it = tls->m_map.begin(); + it != tls->m_map.end(); + it++) { + (*it).second.release(); + } +} + +bool WinDisplay::infoExists(int configurationIndex) { + return getTLS()->m_map.find(configurationIndex) != getTLS()->m_map.end(); +} + +void WinDisplay::setInfo(int configurationIndex, const DisplayInfo& info) { + getTLS()->m_map[configurationIndex] = info; +} + +namespace { + +static HDC getDummyDC(WinDisplay* display, int cfgId) { + HDC dpy = NULL; + if (!display->infoExists(cfgId)) { + HWND hwnd = createDummyWindow(); + dpy = GetDC(hwnd); + display->setInfo(cfgId, DisplayInfo(dpy, hwnd)); + } else { + dpy = display->getDC(cfgId); + } + return dpy; +} + + +bool initPixelFormat(HDC dc, const WglExtensionsDispatch* dispatch) { + if (dispatch->wglChoosePixelFormatARB) { + unsigned int numpf; + int iPixelFormat; + int i0 = 0; + float f0 = 0.0f; + return dispatch->wglChoosePixelFormatARB( + dc, &i0, &f0, 1, &iPixelFormat, &numpf); + } else { + PIXELFORMATDESCRIPTOR pfd; + return dispatch->ChoosePixelFormat(dc, &pfd); + } +} + +void pixelFormatToConfig(WinDisplay* display, + const WglExtensionsDispatch* dispatch, + int renderableType, + const PIXELFORMATDESCRIPTOR* frmt, + int index, + EglOS::AddConfigCallback* addConfigFunc, + void* addConfigOpaque) { + EglOS::ConfigInfo info; + memset(&info, 0, sizeof(info)); + + HDC dpy = getDummyDC(display, WinDisplay::DEFAULT_DISPLAY); + + if (frmt->iPixelType != PFD_TYPE_RGBA) { + D("%s: Not an RGBA type!\n", __FUNCTION__); + return; // other formats are not supported yet + } + if (!(frmt->dwFlags & PFD_SUPPORT_OPENGL)) { + D("%s: No OpenGL support\n", __FUNCTION__); + return; + } + // NOTE: Software renderers don't always support double-buffering. + if (dispatch->mIsSystemLib && !(frmt->dwFlags & PFD_DOUBLEBUFFER)) { + D("%s: No double-buffer support\n", __FUNCTION__); + return; + } + if ((frmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_NEED_PALETTE)) != 0) { + //discard generic pixel formats as well as pallete pixel formats + D("%s: Generic format or needs palette\n", __FUNCTION__); + return; + } + + if (!dispatch->wglGetPixelFormatAttribivARB) { + D("%s: Missing wglGetPixelFormatAttribivARB\n", __FUNCTION__); + return; + } + + GLint window = 0, pbuffer = 0; + if (dispatch->mIsSystemLib) { + int windowAttrib = WGL_DRAW_TO_WINDOW_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy, index, 0, 1, &windowAttrib, &window)); + } + int pbufferAttrib = WGL_DRAW_TO_PBUFFER_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy, index, 0, 1, &pbufferAttrib, &pbuffer)); + + info.surface_type = 0; + if (window) { + info.surface_type |= EGL_WINDOW_BIT; + } + if (pbuffer) { + info.surface_type |= EGL_PBUFFER_BIT; + } + if (!info.surface_type) { + D("%s: Missing surface type\n", __FUNCTION__); + return; + } + + //default values + info.native_visual_id = 0; + info.native_visual_type = EGL_NONE; + info.caveat = EGL_NONE; + info.native_renderable = EGL_FALSE; + info.renderable_type = renderableType; + info.max_pbuffer_width = PBUFFER_MAX_WIDTH; + info.max_pbuffer_height = PBUFFER_MAX_HEIGHT; + info.max_pbuffer_size = PBUFFER_MAX_PIXELS; + info.samples_per_pixel = 0; + info.frame_buffer_level = 0; + + GLint transparent; + int transparentAttrib = WGL_TRANSPARENT_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy, index, 0, 1, &transparentAttrib, &transparent)); + if (transparent) { + info.transparent_type = EGL_TRANSPARENT_RGB; + int transparentRedAttrib = WGL_TRANSPARENT_RED_VALUE_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy, index, 0, 1, &transparentRedAttrib, &info.trans_red_val)); + int transparentGreenAttrib = WGL_TRANSPARENT_GREEN_VALUE_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy, index, 0, 1, &transparentGreenAttrib, + &info.trans_green_val)); + int transparentBlueAttrib = WGL_TRANSPARENT_RED_VALUE_ARB; + EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribivARB( + dpy,index, 0, 1, &transparentBlueAttrib, &info.trans_blue_val)); + } else { + info.transparent_type = EGL_NONE; + } + + info.red_size = frmt->cRedBits; + info.green_size = frmt->cGreenBits; + info.blue_size = frmt->cBlueBits; + info.alpha_size = frmt->cAlphaBits; + info.depth_size = frmt->cDepthBits; + info.stencil_size = frmt->cStencilBits; + + info.config_id = (EGLint) index; + info.frmt = new WinPixelFormat(frmt, index); + + (*addConfigFunc)(addConfigOpaque, &info); +} + +class WglDisplay : public EglOS::Display { +public: + // TODO(digit): Remove WinDisplay entirely. + explicit WglDisplay(WinDisplay* dpy, const WglExtensionsDispatch* dispatch) : + mDpy(dpy), mDispatch(dispatch) {} + + virtual ~WglDisplay() { + delete mDpy; + } + + virtual bool release() { + mDpy->releaseAll(); + return true; + } + + virtual void queryConfigs(int renderableType, + EglOS::AddConfigCallback addConfigFunc, + void* addConfigOpaque) { + HDC dpy = getDummyDC(mDpy, WinDisplay::DEFAULT_DISPLAY); + + // wglChoosePixelFormat() needs to be called at least once, + // i.e. it seems that the driver needs to initialize itself. + // Do it here during initialization. + initPixelFormat(dpy, mDispatch); + + // Quering number of formats + PIXELFORMATDESCRIPTOR pfd; + int maxFormat = mDispatch->DescribePixelFormat( + dpy, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + // Inserting rest of formats. Try to map each one to an EGL Config. + for (int configId = 1; configId <= maxFormat; configId++) { + mDispatch->DescribePixelFormat( + dpy, configId, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + pixelFormatToConfig( + mDpy, + mDispatch, + renderableType, + &pfd, + configId, + addConfigFunc, + addConfigOpaque); + } + } + + virtual bool isValidNativeWin(EglOS::Surface* win) { + if (!win) { + return false; + } else { + return isValidNativeWin(WinSurface::from(win)->getHwnd()); + } + } + + virtual bool isValidNativeWin(EGLNativeWindowType win) { + return IsWindow(win); + } + + virtual bool checkWindowPixelFormatMatch( + EGLNativeWindowType win, + const EglOS::PixelFormat* pixelFormat, + unsigned int* width, + unsigned int* height) { + RECT r; + if (!GetClientRect(win, &r)) { + return false; + } + *width = r.right - r.left; + *height = r.bottom - r.top; + HDC dc = GetDC(win); + const WinPixelFormat* format = WinPixelFormat::from(pixelFormat); + bool ret = mDispatch->SetPixelFormat(dc, + format->configId(), + format->desc()); + DeleteDC(dc); + return ret; + } + + virtual EglOS::Context* createContext( + const EglOS::PixelFormat* pixelFormat, + EglOS::Context* sharedContext) { + const WinPixelFormat* format = WinPixelFormat::from(pixelFormat); + HDC dpy = getDummyDC(mDpy, format->configId()); + + if (!mDpy->isPixelFormatSet(format->configId())) { + if (!mDispatch->SetPixelFormat(dpy, + format->configId(), + format->desc())) { + return NULL; + } + mDpy->pixelFormatWasSet(format->configId()); + } + + HGLRC ctx = mDispatch->wglCreateContext(dpy); + + if (ctx && sharedContext) { + if (!mDispatch->wglShareLists(WinContext::from(sharedContext), ctx)) { + mDispatch->wglDeleteContext(ctx); + return NULL; + } + } + return new WinContext(ctx); + } + + virtual bool destroyContext(EglOS::Context* context) { + if (!context) { + return false; + } + if (!mDispatch->wglDeleteContext(WinContext::from(context))) { + GetLastError(); + return false; + } + delete context; + return true; + } + + virtual EglOS::Surface* createPbufferSurface( + const EglOS::PixelFormat* pixelFormat, + const EglOS::PbufferInfo* info) { + int configId = WinPixelFormat::from(pixelFormat)->configId(); + HDC dpy = getDummyDC(mDpy, configId); + + int wglTexFormat = WGL_NO_TEXTURE_ARB; + int wglTexTarget = + (info->target == EGL_TEXTURE_2D) ? WGL_TEXTURE_2D_ARB + : WGL_NO_TEXTURE_ARB; + switch (info->format) { + case EGL_TEXTURE_RGB: + wglTexFormat = WGL_TEXTURE_RGB_ARB; + break; + case EGL_TEXTURE_RGBA: + wglTexFormat = WGL_TEXTURE_RGBA_ARB; + break; + } + + const int pbAttribs[] = { + WGL_TEXTURE_TARGET_ARB, wglTexTarget, + WGL_TEXTURE_FORMAT_ARB, wglTexFormat, + 0 + }; + + const WglExtensionsDispatch* dispatch = mDispatch; + if (!dispatch->wglCreatePbufferARB) { + return NULL; + } + HPBUFFERARB pb = dispatch->wglCreatePbufferARB( + dpy, configId, info->width, info->height, pbAttribs); + if (!pb) { + GetLastError(); + return NULL; + } + return new WinSurface(pb, dispatch); + } + + virtual bool releasePbuffer(EglOS::Surface* pb) { + if (!pb) { + return false; + } + const WglExtensionsDispatch* dispatch = mDispatch; + if (!dispatch->wglReleasePbufferDCARB || + !dispatch->wglDestroyPbufferARB) { + return false; + } + WinSurface* winpb = WinSurface::from(pb); + if (!dispatch->wglReleasePbufferDCARB( + winpb->getPbuffer(), winpb->getDC()) || + !dispatch->wglDestroyPbufferARB(winpb->getPbuffer())) { + GetLastError(); + return false; + } + return true; + } + + virtual bool makeCurrent(EglOS::Surface* read, + EglOS::Surface* draw, + EglOS::Context* context) { + HDC hdcRead = read ? WinSurface::from(read)->getDC() : NULL; + HDC hdcDraw = draw ? WinSurface::from(draw)->getDC() : NULL; + HGLRC hdcContext = context ? WinContext::from(context) : 0; + + const WglExtensionsDispatch* dispatch = mDispatch; + + if (hdcRead == hdcDraw){ + // The following loop is a work-around for a problem when + // occasionally the rendering is incorrect after hibernating and + // waking up windows. + // wglMakeCurrent will sometimes fail for a short period of time + // in such situation. + // + // For a stricter test, in addition to checking the return value, we + // might also want to check its error code. On my computer in such + // situation GetLastError() returns 0 (which is documented as + // success code). This is not a documented behaviour and is + // unreliable. But in case one needs to use it, here is the code: + // while (!(isSuccess = dispatch->wglMakeCurrent(hdcDraw, hdcContext)) && GetLastError()==0) Sleep(1000); + + while (!dispatch->wglMakeCurrent(hdcDraw, hdcContext)) { + Sleep(100); + } + return true; + } else if (!dispatch->wglMakeContextCurrentARB) { + return false; + } + bool retVal = dispatch->wglMakeContextCurrentARB( + hdcDraw, hdcRead, hdcContext); + return retVal; + } + + virtual void swapBuffers(EglOS::Surface* srfc) { + if (srfc && !mDispatch->SwapBuffers(WinSurface::from(srfc)->getDC())) { + GetLastError(); + } + } + +private: + WinDisplay* mDpy; + const WglExtensionsDispatch* mDispatch; +}; + +class WglLibrary : public GlLibrary { +public: + WglLibrary(const WglBaseDispatch* dispatch) : mDispatch(dispatch) {} + + virtual GlFunctionPointer findSymbol(const char* name) { + return mDispatch->findFunction(name); + } + +private: + const WglBaseDispatch* mDispatch; +}; + +class WinEngine : public EglOS::Engine { +public: + WinEngine(); + + ~WinEngine() { + delete mDispatch; + delete mLib; + } + + virtual EglOS::Display* getDefaultDisplay() { + WinDisplay* dpy = new WinDisplay(); + + HWND hwnd = createDummyWindow(); + HDC hdc = GetDC(hwnd); + dpy->setInfo(WinDisplay::DEFAULT_DISPLAY, DisplayInfo(hdc, hwnd)); + + return new WglDisplay(dpy, mDispatch); + } + + virtual GlLibrary* getGlLibrary() { + return &mGlLib; + } + + virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) { + return new WinSurface(wnd); + } + +private: + SharedLibrary* mLib; + const WglExtensionsDispatch* mDispatch; + WglBaseDispatch mBaseDispatch; + WglLibrary mGlLib; +}; + +WinEngine::WinEngine() : + mLib(NULL), + mDispatch(NULL), + mBaseDispatch(), + mGlLib(&mBaseDispatch) { + if (!s_tlsIndex) { + s_tlsIndex = TlsAlloc(); + } + const char* kLibName = "opengl32.dll"; + bool isSystemLib = true; + const char* env = ::getenv("ANDROID_GL_LIB"); + if (env && !strcmp(env, "mesa")) { + kLibName = "mesa_opengl32.dll"; + isSystemLib = false; + } + char error[256]; + D("%s: Trying to load %s\n", __FUNCTION__, kLibName); + mLib = SharedLibrary::open(kLibName, error, sizeof(error)); + if (!mLib) { + ERR("ERROR: %s: Could not open %s: %s\n", __FUNCTION__, + kLibName, error); + exit(1); + } + + D("%s: Library loaded at %p\n", __FUNCTION__, mLib); + mBaseDispatch.init(mLib, isSystemLib); + mDispatch = initExtensionsDispatch(&mBaseDispatch); + D("%s: Dispatch initialized\n", __FUNCTION__); +} + +emugl::LazyInstance sHostEngine = LAZY_INSTANCE_INIT; + +} // namespace + +// static +EglOS::Engine* EglOS::Engine::getHostInstance() { + return sHostEngine.ptr(); +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.cpp b/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.cpp new file mode 100644 index 0000000..8bcb31a --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.cpp @@ -0,0 +1,75 @@ +/* +* 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 "EglPbufferSurface.h" + +bool EglPbufferSurface::setAttrib(EGLint attrib,EGLint val) { + switch(attrib) { + case EGL_WIDTH: + if(val < 0) return false; + m_width = val; + break; + case EGL_HEIGHT: + if(val < 0) return false; + m_height = val; + break; + case EGL_LARGEST_PBUFFER: + m_largest = val; + break; + case EGL_TEXTURE_FORMAT: + if(val != EGL_NO_TEXTURE && val != EGL_TEXTURE_RGB && val != EGL_TEXTURE_RGBA) return false; + m_texFormat = val; + break; + case EGL_TEXTURE_TARGET: + if(val != EGL_NO_TEXTURE && val != EGL_TEXTURE_2D) return false; + m_texTarget = val; + break; + case EGL_MIPMAP_TEXTURE: + m_texMipmap = val; + break; + default: + return false; + } + return true; +} + +bool EglPbufferSurface::getAttrib(EGLint attrib,EGLint* val) { + switch(attrib) { + case EGL_CONFIG_ID: + *val = m_config->id(); + break; + case EGL_WIDTH: + *val = m_width; + break; + case EGL_HEIGHT: + *val = m_height; + break; + case EGL_LARGEST_PBUFFER: + *val = m_largest; + break; + case EGL_TEXTURE_FORMAT: + *val = m_texFormat; + break; + case EGL_TEXTURE_TARGET: + *val = m_texTarget; + break; + case EGL_MIPMAP_TEXTURE: + *val = m_texMipmap; + break; + default: + return false; + } + return true; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.h b/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.h new file mode 100644 index 0000000..12eae63 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglPbufferSurface.h @@ -0,0 +1,49 @@ +/* +* 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_PBUFFER_SURFACE_H +#define EGL_PBUFFER_SURFACE_H + +#include "EglSurface.h" + +class EglDisplay; + +class EglPbufferSurface:public EglSurface { +public: + EglPbufferSurface(EglDisplay *dpy, EglConfig* config): + EglSurface(dpy,PBUFFER,config,0,0), + m_texFormat(EGL_NO_TEXTURE), + m_texTarget(EGL_NO_TEXTURE), + m_texMipmap(EGL_FALSE), + m_largest(EGL_FALSE){}; + + void setNativePbuffer(EglOS::Surface* srfc) { m_native = srfc; } + bool setAttrib(EGLint attrib,EGLint val); + bool getAttrib(EGLint attrib,EGLint* val); + void getDim(EGLint* width,EGLint* height,EGLint* largest){ + *width = m_width; + *height = m_height; + *largest = m_largest; + }; + + void getTexInfo(EGLint* format,EGLint* target){ *format = m_texFormat; *target = m_texTarget;} + +private: + EGLint m_texFormat; + EGLint m_texTarget; + EGLint m_texMipmap; + EGLint m_largest; +}; +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglSurface.cpp b/external/android-emugl/host/libs/Translator/EGL/EglSurface.cpp new file mode 100644 index 0000000..26a6062 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglSurface.cpp @@ -0,0 +1,45 @@ +/* +* 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 "EglSurface.h" + +#include "EglDisplay.h" +#include "EglOsApi.h" + +unsigned int EglSurface::s_nextSurfaceHndl = 0; + +EglSurface::~EglSurface(){ + + if(m_type == EglSurface::PBUFFER) { + m_dpy->nativeType()->releasePbuffer(m_native); + } + + delete m_native; +} + +bool EglSurface::setAttrib(EGLint attrib,EGLint val) { + switch(attrib) { + case EGL_WIDTH: + case EGL_HEIGHT: + case EGL_LARGEST_PBUFFER: + case EGL_TEXTURE_FORMAT: + case EGL_TEXTURE_TARGET: + case EGL_MIPMAP_TEXTURE: + break; + default: + return false; + } + return true; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglSurface.h b/external/android-emugl/host/libs/Translator/EGL/EglSurface.h new file mode 100644 index 0000000..a3f675a --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglSurface.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 EGL_SURFACE_H +#define EGL_SURFACE_H + +#include + +#include "EglConfig.h" +#include "EglOsApi.h" + +#include "emugl/common/smart_ptr.h" + +#include + +class EglSurface; +typedef emugl::SmartPtr SurfacePtr; + +class EglDisplay; + +class EglSurface { +public: + typedef enum { + WINDOW = 0, + PBUFFER = 1, + PIXMAP = 3 + } ESurfaceType; + + ESurfaceType type() const { return m_type; } + + EglOS::Surface* native() const { return m_native; } + + virtual bool setAttrib(EGLint attrib, EGLint val); + virtual bool getAttrib(EGLint attrib, EGLint* val) = 0; + + void setDim(int width, int height) { + m_width = width; + m_height = height; + } + + EglConfig* getConfig() const { return m_config; } + + unsigned int getHndl() const { return m_hndl; } + + virtual ~EglSurface(); + +private: + static unsigned int s_nextSurfaceHndl; + + ESurfaceType m_type; + unsigned int m_hndl; + +protected: + EglSurface(EglDisplay *dpy, + ESurfaceType type, + EglConfig* config, + EGLint width, + EGLint height) : + m_type(type), + m_config(config), + m_width(width), + m_height(height), + m_native(NULL), + m_dpy(dpy) + { + m_hndl = ++s_nextSurfaceHndl; + } + +protected: + EglConfig* m_config; + EGLint m_width; + EGLint m_height; + EglOS::Surface* m_native; + EglDisplay *m_dpy; +}; + +#endif // EGL_SURFACE_H diff --git a/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.cpp b/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.cpp new file mode 100644 index 0000000..6481774 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.cpp @@ -0,0 +1,49 @@ +/* +* 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 "EglThreadInfo.h" +#include "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/thread_store.h" + +namespace { + +class EglThreadInfoStore : public emugl::ThreadStore { +public: + EglThreadInfoStore() : emugl::ThreadStore(&destructor) {} +private: + static void destructor(void* value) { + delete static_cast(value); + } +}; + +} // namespace + +EglThreadInfo::EglThreadInfo() : + m_err(EGL_SUCCESS), m_api(EGL_OPENGL_ES_API) {} + +static emugl::LazyInstance s_tls = LAZY_INSTANCE_INIT; + +EglThreadInfo* EglThreadInfo::get(void) +{ + EglThreadInfo *ti = static_cast(s_tls->get()); + if (!ti) { + ti = new EglThreadInfo(); + s_tls->set(ti); + } + return ti; +} + diff --git a/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.h b/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.h new file mode 100644 index 0000000..f5eeb6a --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglThreadInfo.h @@ -0,0 +1,49 @@ +/* +* 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_THREAD_INFO_H +#define EGL_THREAD_INFO_H + +#include + +// Model thread-specific EGL state. +class EglThreadInfo { +public: + // Return the thread-specific instance of EglThreadInfo to the caller. + // The instance will be created on first call, and destroyed automatically + // when the thread exits. + static EglThreadInfo* get(void) __attribute__((const)); + + // Set the error code |err|. Default value is EGL_NO_ERROR. + void setError(EGLint err) { m_err = err; } + + // Get the error code. Note that this doesn't change the value, + // unlike eglGetError() which resets it to EGL_NO_ERROR. + EGLint getError() const { return m_err; } + + // Change the |api| value. Default is EGL_OPENGL_ES + void setApi(EGLenum api) { m_api = api; } + + // Get the current API value. + EGLenum getApi() const { return m_api; } + +private: + EglThreadInfo(); + + EGLint m_err; + EGLenum m_api; +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglValidate.cpp b/external/android-emugl/host/libs/Translator/EGL/EglValidate.cpp new file mode 100644 index 0000000..1dde3c5 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglValidate.cpp @@ -0,0 +1,112 @@ +/* +* 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 "EglValidate.h" +#include + +// static +bool EglValidate::confAttrib(EGLint attrib) { + switch(attrib) { + case EGL_BUFFER_SIZE: + case EGL_RED_SIZE: + case EGL_GREEN_SIZE: + case EGL_BLUE_SIZE: + case EGL_ALPHA_SIZE: + case EGL_BIND_TO_TEXTURE_RGB: + case EGL_BIND_TO_TEXTURE_RGBA: + case EGL_CONFIG_CAVEAT: + case EGL_CONFIG_ID: + case EGL_DEPTH_SIZE: + case EGL_LEVEL: + case EGL_MAX_PBUFFER_WIDTH: + case EGL_MAX_PBUFFER_HEIGHT: + case EGL_MAX_PBUFFER_PIXELS: + case EGL_MAX_SWAP_INTERVAL: + case EGL_MIN_SWAP_INTERVAL: + case EGL_RENDERABLE_TYPE: + case EGL_NATIVE_RENDERABLE: + case EGL_NATIVE_VISUAL_ID: + case EGL_NATIVE_VISUAL_TYPE: + case EGL_SAMPLE_BUFFERS: + case EGL_SAMPLES: + case EGL_STENCIL_SIZE: + case EGL_SURFACE_TYPE: + case EGL_TRANSPARENT_TYPE: + case EGL_TRANSPARENT_RED_VALUE: + case EGL_TRANSPARENT_GREEN_VALUE: + case EGL_TRANSPARENT_BLUE_VALUE: + case EGL_CONFORMANT: + return true; + } + return false; +} + +// static +bool EglValidate::noAttribs(const EGLint* attrib) { + return !attrib || attrib[0] == EGL_NONE ; +} + +// static +bool EglValidate::pbufferAttribs(EGLint width, + EGLint height, + bool isTexFormatNoTex, + bool isTexTargetNoTex) { + if(!isTexFormatNoTex) { + if (!(isPowerOf2(width) && isPowerOf2(height))) { + return false; + } + } + return isTexFormatNoTex == isTexTargetNoTex ; +} + +// static +bool EglValidate::releaseContext(EGLContext ctx, + EGLSurface s1, + EGLSurface s2) { + return (ctx == EGL_NO_CONTEXT) && + (s1 == EGL_NO_SURFACE) && + (s2 == EGL_NO_SURFACE); +} + +// static +bool EglValidate::badContextMatch(EGLContext ctx, + EGLSurface s1, + EGLSurface s2) { + return (ctx != EGL_NO_CONTEXT) + ? (s1 == EGL_NO_SURFACE || s2 == EGL_NO_SURFACE) + : (s1 != EGL_NO_SURFACE || s2 != EGL_NO_SURFACE); +} + +// static +bool EglValidate::surfaceTarget(EGLint target) { + return target == EGL_READ || target == EGL_DRAW; +} + +// static +bool EglValidate::engine(EGLint engine) { + return engine == EGL_CORE_NATIVE_ENGINE; +} + +// static +bool EglValidate::stringName(EGLint name) { + return name == EGL_VENDOR || + name == EGL_VERSION || + name == EGL_EXTENSIONS; +} + +// static +bool EglValidate::supportedApi(EGLenum api) { + return api == EGL_OPENGL_ES_API; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglValidate.h b/external/android-emugl/host/libs/Translator/EGL/EglValidate.h new file mode 100644 index 0000000..a503153 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglValidate.h @@ -0,0 +1,75 @@ +/* +* 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_VALIDATE_H +#define EGL_VALIDATE_H + +#include + +class EglValidate { +public: + // Return true iff |attrib| is a valid EGLConfig attribute name. + static bool confAttrib(EGLint attrib); + + // Return true iff |attrib| is NULL, or |attrib[0]| is EGL_NONE, which + // correspond to empty config attribute lists. + static bool noAttribs(const EGLint* attrib); + + // Used to check that the config attributes used to create a new pbuffer + // are correct. |width| and |height| are the PBuffer's dimensions in + // pixels. |texFormatIsNoText| is true iff the PBuffer's texture format + // if EGL_NO_TEXTURE. |texTargetIsNoTex| is true iff the PBuffer's target + // is EGL_NO_TEXTURE. + static bool pbufferAttribs(EGLint width, + EGLint height, + bool texFormatIsNoTex, + bool texTargetIsNoTex); + + // Return true if |ctx| is EGL_NO_CONTEXT, and both |draw| and |read| + // are EGL_NO_SURFACE. This corresponds to an eglMakeCurrent operation + // used to release the current context and draw/read surfaces at the + // same time. + static bool releaseContext(EGLContext ctx, + EGLSurface draw, + EGLSurface read); + + // Return true if the values of |ctx|, |draw| and |read| do _not_ match + // the following rules: + // + // - If |ctx| is EGL_NO_CONTEXT, then |draw| and |read| must be + // EGL_NO_SURFACE. + // + // - If |ctx| is not EGL_NO_CONTEXT, then |draw| and |read| must not + // be EGL_NO_SURFACE. + // + static bool badContextMatch(EGLContext ctx, + EGLSurface draw, + EGLSurface read); + + // Returns true iff |target| is either EGL_DRAW or EGL_READ. + static bool surfaceTarget(EGLint target); + + // Returns true iff |engine| is EGL_CORE_NATIVE_RENDERER + static bool engine(EGLint engine); + + // Returns true iff |name| is the attribute name of a string, e.g. + // EGL_VENDOR, EGL_VERSION or EGL_EXTENSIONS. + static bool stringName(EGLint name); + + // Returns true iff |api| is the value of a supported API, e.g. + // EGL_OPENGL_ES_API. + static bool supportedApi(EGLenum api); +}; +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.cpp b/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.cpp new file mode 100644 index 0000000..d30afb9 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.cpp @@ -0,0 +1,69 @@ +/* +* 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 "EglWindowSurface.h" +#include "EglGlobalInfo.h" +#include "EglOsApi.h" + +#include "emugl/common/lazy_instance.h" + +// this static member is accessed from a function registered in onexit() +// for the emulator cleanup. As all static C++ objects are also being freed +// from a system handler registered in onexit(), we can't have a class object +// by value here - it would be prone to unstable deinitialization order issue; +static emugl::LazyInstance> + s_associatedWins = LAZY_INSTANCE_INIT; + +bool EglWindowSurface::alreadyAssociatedWithConfig(EGLNativeWindowType win) { + return s_associatedWins.get().find(win) != s_associatedWins.get().end(); +} + +EglWindowSurface::EglWindowSurface(EglDisplay* dpy, + EGLNativeWindowType win, + EglConfig* config, + unsigned int width, + unsigned int height) : + EglSurface(dpy, WINDOW, config, width, height), + m_win(win) { + s_associatedWins.get().insert(win); + EglOS::Engine* engine = EglGlobalInfo::getInstance()->getOsEngine(); + m_native = engine->createWindowSurface(win); +} + +EglWindowSurface::~EglWindowSurface() { + s_associatedWins.get().erase(m_win); +} + +bool EglWindowSurface::getAttrib(EGLint attrib,EGLint* val) { + switch(attrib) { + case EGL_CONFIG_ID: + *val = m_config->id(); + break; + case EGL_WIDTH: + *val = m_width; + break; + case EGL_HEIGHT: + *val = m_height; + break; + case EGL_LARGEST_PBUFFER: + case EGL_TEXTURE_FORMAT: + case EGL_TEXTURE_TARGET: + case EGL_MIPMAP_TEXTURE: + break; + default: + return false; + } + return true; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.h b/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.h new file mode 100644 index 0000000..182a450 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/EglWindowSurface.h @@ -0,0 +1,44 @@ +/* +* 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_WINDOW_SURFACE_H +#define EGL_WINDOW_SURFACE_H + +#include +#include +#include "EglSurface.h" +#include "EglConfig.h" + +class EglDisplay; + +class EglWindowSurface: public EglSurface { +public: + EglWindowSurface(EglDisplay* dpy, + EGLNativeWindowType win, + EglConfig* config, + unsigned width, + unsigned int height); + + ~EglWindowSurface(); + + bool getAttrib(EGLint attrib,EGLint* val); + + static bool alreadyAssociatedWithConfig(EGLNativeWindowType win); + +private: + EGLNativeWindowType m_win; +}; + +#endif // EGL_WINDOW_SURFACE_H diff --git a/external/android-emugl/host/libs/Translator/EGL/MacNative.h b/external/android-emugl/host/libs/Translator/EGL/MacNative.h new file mode 100644 index 0000000..c32e182 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/MacNative.h @@ -0,0 +1,53 @@ +/* +* Copyright 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 MAC_NATIVE_H +#define MAC_NATIVE_H + +#include + +typedef enum { // Mac equivalence + MAC_HAS_DOUBLE_BUFFER = 5, // NSOpenGLPFADoubleBuffer + MAC_DRAW_TO_WINDOW = 80, // NSOpenGLPFAWindow + MAC_DRAW_TO_PBUFFER = 90, // NSOpenGLPFAPixelBuffer + MAC_SAMPLES_PER_PIXEL = 56, // NSOpenGLPFASamples + MAC_COLOR_SIZE = 8, // NSOpenGLPFAColorSize + MAC_ALPHA_SIZE = 11, // NSOpenGLPFAAlphaSize + MAC_DEPTH_SIZE = 12, // NSOpenGLPFADepthSize + MAC_STENCIL_SIZE = 13 // NSOpenGLPFAStencilSize + } MacPixelFormatAttribs; + + +extern "C"{ + +int getNumPixelFormats(); +void* getPixelFormat(int i); +int getPixelFormatDefinitionAlpha(int i); +void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val); +void* nsCreateContext(void* format,void* share); +void nsWindowMakeCurrent(void* context,void* nativeWin); +void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level); +void nsSwapBuffers(); +void nsSwapInterval(int *interval); +void nsDestroyContext(void* context); +void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height); +void nsDestroyPBuffer(void* pbuffer); +bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height); +bool nsCheckColor(void* win,int colorSize); + +} + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/MacNative.m b/external/android-emugl/host/libs/Translator/EGL/MacNative.m new file mode 100644 index 0000000..a2cea93 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/MacNative.m @@ -0,0 +1,207 @@ +/* +* 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 +#include +#include +#include "MacPixelFormatsAttribs.h" + +// +// EmuGLContext inherit from NSOpenGLContext +// and adds binding state for the context to know +// if it was last bounded to a pbuffer or a window. +// This is because after the context was bounded to +// a Pbuffer, before we bind it to a window we must +// release it form the pbuffer by calling the +// clearDrawable method. We do not want to call clearDrawable +// more than really needed since when it is called at a time +// that a window is bounded to the context it will clear the +// window content causing flickering effect. +// Thererfore we call clearDrawable only when we bind the context +// to a window and it was previously bound to a Pbuffer. +// +@interface EmuGLContext : NSOpenGLContext { + @private + int boundToPbuffer; + int boundToWin; +} + +- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share; +- (void) preBind:(int)forPbuffer; +@end + +@implementation EmuGLContext +- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share +{ + self = [super initWithFormat:pixelFormat shareContext:share]; + if (self != nil) { + boundToPbuffer = 0; + boundToWin = 0; + } + return self; +} + +- (void) preBind:(int)forPbuffer +{ + if ((!forPbuffer && boundToPbuffer)) { + [self clearDrawable]; + } + boundToPbuffer = forPbuffer; + boundToWin = !boundToPbuffer; +} +@end + +int getNumPixelFormats(){ + int size; + NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); + return size; +} + +void* getPixelFormat(int i){ + int size; + NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]]; +} + +int getPixelFormatDefinitionAlpha(int i) { + int size; + NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); + NSOpenGLPixelFormatAttribute* attribs = attrib_lists[i]; + while (*attribs) { + switch (*attribs) { + // These are the ones that take a value, according to the current + // NSOpenGLPixelFormat docs + case NSOpenGLPFAAuxBuffers: + case NSOpenGLPFAColorSize: + case NSOpenGLPFADepthSize: + case NSOpenGLPFAStencilSize: + case NSOpenGLPFAAccumSize: + case NSOpenGLPFARendererID: + case NSOpenGLPFAScreenMask: + attribs += 2; + break; + case NSOpenGLPFAAlphaSize: + return attribs[1]; + break; + // All other attributes are boolean attributes that don't take a value + default: + attribs++; + } + } + return 0; +} + +void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){ + NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat; + [frmt getValues:val forAttribute:attrib forVirtualScreen:0]; +} + +void* nsCreateContext(void* format,void* share){ + NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format; + return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share]; +} + +void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){ + EmuGLContext* ctx = (EmuGLContext *)context; + NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer; + if(ctx == nil){ + [NSOpenGLContext clearCurrentContext]; + } else { + if(pbuff != nil){ + [ctx preBind:1]; + [ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0]; + [ctx makeCurrentContext]; + } + } +} + +void nsWindowMakeCurrent(void* context,void* nativeWin){ + EmuGLContext* ctx = (EmuGLContext *)context; + NSView* win = (NSView *)nativeWin; + if(ctx == nil){ + [NSOpenGLContext clearCurrentContext]; + } else if (win != nil) { + [ctx preBind:0]; + [ctx setView: win]; + [ctx makeCurrentContext]; + } +} + +void nsSwapBuffers(){ + NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; + if(ctx != nil){ + [ctx flushBuffer]; + } +} + +void nsSwapInterval(int *interval){ + NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; + if( ctx != nil){ + [ctx setValues:interval forParameter:NSOpenGLCPSwapInterval]; + } +} + + +void nsDestroyContext(void* context){ + EmuGLContext *ctx = (EmuGLContext*)context; + if(ctx != nil){ + [ctx release]; + } +} + + +void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){ + return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target + textureInternalFormat:format + textureMaxMipMapLevel:maxMip + pixelsWide:width pixelsHigh:height]; + +} + +void nsDestroyPBuffer(void* pbuffer){ + NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer; + if(pbuf != nil){ + [pbuf release]; + } +} + +bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){ + NSView* view = (NSView*)win; + if(view != nil){ + NSRect rect = [view bounds]; + *width = rect.size.width; + *height = rect.size.height; + return true; + } + return false; +} + +bool nsCheckColor(void* win,int colorSize){ + NSView* view = (NSView*)win; + if(view != nil){ + NSWindow* wnd = [view window]; + if(wnd != nil){ + NSWindowDepth limit = [wnd depthLimit]; + NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit]; + + int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit): + NSBitsPerPixelFromDepth(defaultLimit); + return depth >= colorSize; + + } + } + return false; + +} diff --git a/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.h b/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.h new file mode 100644 index 0000000..692ac22 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.h @@ -0,0 +1,23 @@ +/* +* Copyright 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 MAC_PIXELS_FORMATS_ATTRIBS_H +#define MAC_PIXELS_FORMATS_ATTRIBS_H + +#include +NSOpenGLPixelFormatAttribute** getPixelFormatsAttributes(int* size); + +#endif diff --git a/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.m b/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.m new file mode 100644 index 0000000..f5bc49c --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/MacPixelFormatsAttribs.m @@ -0,0 +1,214 @@ +/* +* Copyright 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 "MacPixelFormatsAttribs.h" + +static NSOpenGLPixelFormatAttribute attrs32_1[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_2[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFAAlphaSize ,8, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_3[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFAAlphaSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_4[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_5[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFASamples ,2, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_6[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFASamples ,4, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs32_7[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,32, + NSOpenGLPFAAlphaSize ,8, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + NSOpenGLPFASamples ,4, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs16_1[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,16, + NSOpenGLPFADepthSize ,24, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs16_2[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,16, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs64_1[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,64, + NSOpenGLPFAAlphaSize ,16, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs64_2[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,64, + NSOpenGLPFAAlphaSize ,16, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs64_3[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,64, + NSOpenGLPFAAlphaSize ,16, + NSOpenGLPFADepthSize ,24, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs64_4[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,64, + NSOpenGLPFADepthSize ,24, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs64_5[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,64, + NSOpenGLPFADepthSize ,24, + NSOpenGLPFAStencilSize ,8, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs128_1[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,128, + NSOpenGLPFAAlphaSize ,32, + 0 +}; + +static NSOpenGLPixelFormatAttribute attrs128_2[] = +{ + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAWindow, + NSOpenGLPFAPixelBuffer, + NSOpenGLPFAColorSize ,128, + NSOpenGLPFAAlphaSize ,32, + NSOpenGLPFADepthSize ,24, + 0 +}; + +NSOpenGLPixelFormatAttribute** getPixelFormatsAttributes(int* size){ +static NSOpenGLPixelFormatAttribute* arr[] = +{ + attrs16_1, + attrs16_2, + attrs32_1, + attrs32_2, + attrs32_3, + attrs32_4, + attrs32_5, + attrs32_6, + attrs32_7, + attrs64_1, + attrs64_2, + attrs64_3, + attrs64_4, + attrs64_5, + attrs128_1, + attrs128_2 +}; + *size = sizeof(arr)/sizeof(arr[0]); + return arr; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.cpp b/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.cpp new file mode 100644 index 0000000..1571b3a --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.cpp @@ -0,0 +1,83 @@ +/* +* 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 "ThreadInfo.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/thread_store.h" + +#include + +// Set TRACE_THREADINFO to 1 to debug creation/destruction of ThreadInfo +// instances. +#define TRACE_THREADINFO 0 + +#if TRACE_THREADINFO +#define LOG_THREADINFO(x...) fprintf(stderr, x) +#else +#define LOG_THREADINFO(x...) +#endif + +namespace { + +class ThreadInfoStore : public ::emugl::ThreadStore { +public: + ThreadInfoStore() : ::emugl::ThreadStore(&destructor) {} + + size_t getInstanceCount() const { return mNumInstances; } + +private: + static void destructor(void* value) { + LOG_THREADINFO("%s: EFL %p (%d instances)\n", __FUNCTION__, + value, mNumInstances); + delete static_cast(value); + mNumInstances--; + } + + static size_t mNumInstances; +}; + +size_t ThreadInfoStore::mNumInstances = 0; + +} // namespace + + +void ThreadInfo::updateInfo(ContextPtr eglCtx, + EglDisplay* dpy, + GLEScontext* glesCtx, + ShareGroupPtr share, + ObjectNameManager* manager) { + + eglContext = eglCtx; + eglDisplay = dpy; + glesContext = glesCtx; + shareGroup = share; + objManager = manager; +} + +static ::emugl::LazyInstance s_tls = LAZY_INSTANCE_INIT; + +ThreadInfo *getThreadInfo() +{ + ThreadInfo *ti = static_cast(s_tls->get()); + if (!ti) { + ti = new ThreadInfo(); + s_tls->set(ti); + LOG_THREADINFO("%s: EGL %p (%d instances)\n", __FUNCTION__, + ti, (int)ThreadInfoStore::getInstanceCount()); + } + return ti; +} diff --git a/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.h b/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.h new file mode 100644 index 0000000..ffc6e5f --- /dev/null +++ b/external/android-emugl/host/libs/Translator/EGL/ThreadInfo.h @@ -0,0 +1,42 @@ +/* +* 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 THREAD_INFO_H +#define THREAD_INFO_H + +#include "EglContext.h" + +class EglDisplay; +class GLEScontext; + +struct ThreadInfo { + ThreadInfo():eglDisplay(NULL),glesContext(NULL),objManager(NULL){} + + void updateInfo(ContextPtr eglctx, + EglDisplay* dpy, + GLEScontext* glesCtx, + ShareGroupPtr share, + ObjectNameManager* manager); + + ContextPtr eglContext; + EglDisplay* eglDisplay; + GLEScontext* glesContext; + ShareGroupPtr shareGroup; + ObjectNameManager* objManager; +}; + +ThreadInfo* getThreadInfo(); + +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/Android.mk b/external/android-emugl/host/libs/Translator/GLES_CM/Android.mk new file mode 100644 index 0000000..b44ad8b --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +host_common_SRC_FILES := \ + GLEScmImp.cpp \ + GLEScmUtils.cpp \ + GLEScmContext.cpp \ + GLEScmValidate.cpp + + +### GLES_CM host implementation (On top of OpenGL) ######################## +$(call emugl-begin-host-shared-library,lib$(BUILD_TARGET_SUFFIX)GLES_CM_translator) +$(call emugl-import,libGLcommon) +LOCAL_SRC_FILES := $(host_common_SRC_FILES) +$(call emugl-end-module) diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/CMakeLists.txt b/external/android-emugl/host/libs/Translator/GLES_CM/CMakeLists.txt new file mode 100644 index 0000000..3ba7cb2 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/CMakeLists.txt @@ -0,0 +1,8 @@ +set(SOURCES + GLEScmImp.cpp + GLEScmUtils.cpp + GLEScmContext.cpp + GLEScmValidate.cpp) + +add_library(GLES_CM_translator SHARED ${SOURCES}) +target_link_libraries(GLES_CM_translator GLcommon) diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.cpp b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.cpp new file mode 100644 index 0000000..92a09fc --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.cpp @@ -0,0 +1,430 @@ +/* +* 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 "GLEScmContext.h" +#include "GLEScmUtils.h" +#include +#include +#include +#include +#include + +void GLEScmContext::init(GlLibrary* glLib) { + emugl::Mutex::AutoLock mutex(s_lock); + if(!m_initialized) { + s_glDispatch.dispatchFuncs(GLES_1_1, glLib); + GLEScontext::init(glLib); + + m_texCoords = new GLESpointer[s_glSupport.maxTexUnits]; + m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture]; + + buildStrings((const char*)dispatcher().glGetString(GL_VENDOR), + (const char*)dispatcher().glGetString(GL_RENDERER), + (const char*)dispatcher().glGetString(GL_VERSION), + "OpenGL ES-CM 1.1"); + } + m_initialized = true; +} + +GLEScmContext::GLEScmContext():GLEScontext(),m_texCoords(NULL),m_pointsIndex(-1), m_clientActiveTexture(0) { + + m_map[GL_COLOR_ARRAY] = new GLESpointer(); + m_map[GL_NORMAL_ARRAY] = new GLESpointer(); + m_map[GL_VERTEX_ARRAY] = new GLESpointer(); + m_map[GL_POINT_SIZE_ARRAY_OES] = new GLESpointer(); +} + + +void GLEScmContext::setActiveTexture(GLenum tex) { + m_activeTexture = tex - GL_TEXTURE0; +} + +void GLEScmContext::setClientActiveTexture(GLenum tex) { + m_clientActiveTexture = tex - GL_TEXTURE0; + m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture]; +} + +GLEScmContext::~GLEScmContext(){ + if(m_texCoords){ + delete[] m_texCoords; + m_texCoords = NULL; + } + m_map[GL_TEXTURE_COORD_ARRAY] = NULL; +} + + +//setting client side arr +void GLEScmContext::setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int index){ + if( arr == NULL) return; + switch(arrayType) { + case GL_VERTEX_ARRAY: + s_glDispatch.glVertexPointer(size,dataType,stride,arr); + break; + case GL_NORMAL_ARRAY: + s_glDispatch.glNormalPointer(dataType,stride,arr); + break; + case GL_TEXTURE_COORD_ARRAY: + s_glDispatch.glTexCoordPointer(size,dataType,stride,arr); + break; + case GL_COLOR_ARRAY: + s_glDispatch.glColorPointer(size,dataType,stride,arr); + break; + case GL_POINT_SIZE_ARRAY_OES: + m_pointsIndex = index; + break; + } +} + + +void GLEScmContext::setupArrayPointerHelper(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLenum array_id,GLESpointer* p){ + unsigned int size = p->getSize(); + GLenum dataType = p->getType(); + + if(needConvert(cArrs,first,count,type,indices,direct,p,array_id)){ + //conversion has occured + ArrayData currentArr = cArrs.getCurrentArray(); + setupArr(currentArr.data,array_id,currentArr.type,size,currentArr.stride,GL_FALSE, cArrs.getCurrentIndex()); + ++cArrs; + } else { + setupArr(p->getData(),array_id,dataType,size,p->getStride(), GL_FALSE); + } +} + +void GLEScmContext::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) { + ArraysMap::iterator it; + m_pointsIndex = -1; + + //going over all clients arrays Pointers + for ( it=m_map.begin() ; it != m_map.end(); it++ ) { + + GLenum array_id = (*it).first; + GLESpointer* p = (*it).second; + if(!isArrEnabled(array_id)) continue; + if(array_id == GL_TEXTURE_COORD_ARRAY) continue; //handling textures later + setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p); + } + + unsigned int activeTexture = m_clientActiveTexture + GL_TEXTURE0; + + s_lock.lock(); + int maxTexUnits = s_glSupport.maxTexUnits; + s_lock.unlock(); + + //converting all texture coords arrays + for(int i=0; i< maxTexUnits;i++) { + + unsigned int tex = GL_TEXTURE0+i; + setClientActiveTexture(tex); + s_glDispatch.glClientActiveTexture(tex); + + GLenum array_id = GL_TEXTURE_COORD_ARRAY; + GLESpointer* p = m_map[array_id]; + if(!isArrEnabled(array_id)) continue; + setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p); + } + + setClientActiveTexture(activeTexture); + s_glDispatch.glClientActiveTexture(activeTexture); +} + +void GLEScmContext::drawPointsData(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices_in,bool isElemsDraw) { + const char *pointsArr = NULL; + int stride = 0; + GLESpointer* p = m_map[GL_POINT_SIZE_ARRAY_OES]; + + //choosing the right points sizes array source + if(m_pointsIndex >= 0) { //point size array was converted + pointsArr = (const char*)(cArrs[m_pointsIndex].data); + stride = cArrs[m_pointsIndex].stride; + } else { + pointsArr = static_cast(p->getData()); + stride = p->getStride(); + } + + if(stride == 0){ + stride = sizeof(GLfloat); + } + + + if(isElemsDraw) { + int tSize = 0; + switch (type) { + case GL_UNSIGNED_BYTE: + tSize = 1; + break; + case GL_UNSIGNED_SHORT: + tSize = 2; + break; + case GL_UNSIGNED_INT: + tSize = 4; + break; + }; + + int i = 0; + while(i(indices_in)[i]: \ + type == GL_UNSIGNED_SHORT ? \ + static_cast(indices_in)[i]: \ + static_cast(indices_in)[i]) + + GLfloat pSize = *((GLfloat*)(pointsArr+(INDEX*stride))); + i++; + + while(i < count && pSize == *((GLfloat*)(pointsArr+(INDEX*stride)))) + { + sCount++; + i++; + } + + s_glDispatch.glPointSize(pSize); + s_glDispatch.glDrawElements(GL_POINTS, sCount, type, (char*)indices_in+sStart*tSize); + } + } else { + int i = 0; + while(iisVBO(); + GLenum arrType = p->getType(); + /* + conversion is not necessary in the following cases: + (*) array type is byte but it is not vertex or texture array + (*) array type is not fixed + */ + if((arrType != GL_FIXED) && (arrType != GL_BYTE)) return false; + if((arrType == GL_BYTE && (array_id != GL_VERTEX_ARRAY)) && + (arrType == GL_BYTE && (array_id != GL_TEXTURE_COORD_ARRAY)) ) return false; + + + bool byteVBO = (arrType == GL_BYTE) && usingVBO; + if(byteVBO){ + p->redirectPointerData(); + } + + if(!usingVBO || byteVBO) { + if (direct) { + convertDirect(cArrs,first,count,array_id,p); + } else { + convertIndirect(cArrs,count,type,indices,array_id,p); + } + } else { + if (direct) { + convertDirectVBO(cArrs,first,count,array_id,p) ; + } else { + convertIndirectVBO(cArrs,count,type,indices,array_id,p); + } + } + return true; +} + +const GLESpointer* GLEScmContext::getPointer(GLenum arrType) { + GLenum type = + arrType == GL_VERTEX_ARRAY_POINTER ? GL_VERTEX_ARRAY : + arrType == GL_NORMAL_ARRAY_POINTER ? GL_NORMAL_ARRAY : + arrType == GL_TEXTURE_COORD_ARRAY_POINTER ? GL_TEXTURE_COORD_ARRAY : + arrType == GL_COLOR_ARRAY_POINTER ? GL_COLOR_ARRAY : + arrType == GL_POINT_SIZE_ARRAY_POINTER_OES ? GL_POINT_SIZE_ARRAY_OES : + 0; + if(type != 0) + { + return GLEScontext::getPointer(type); + } + return NULL; +} + +void GLEScmContext::initExtensionString() { + *s_glExtensions = "GL_OES_blend_func_separate GL_OES_blend_equation_separate GL_OES_blend_subtract " + "GL_OES_byte_coordinates GL_OES_compressed_paletted_texture GL_OES_point_size_array " + "GL_OES_point_sprite GL_OES_single_precision GL_OES_stencil_wrap GL_OES_texture_env_crossbar " + "GL_OES_texture_mirored_repeat GL_OES_EGL_image GL_OES_element_index_uint GL_OES_draw_texture " + "GL_OES_texture_cube_map GL_OES_draw_texture "; + if (s_glSupport.GL_OES_READ_FORMAT) + *s_glExtensions+="GL_OES_read_format "; + if (s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT) { + *s_glExtensions+="GL_OES_framebuffer_object GL_OES_depth24 GL_OES_depth32 GL_OES_fbo_render_mipmap " + "GL_OES_rgb8_rgba8 GL_OES_stencil1 GL_OES_stencil4 GL_OES_stencil8 "; + } + if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL) + *s_glExtensions+="GL_OES_packed_depth_stencil "; + if (s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888) + *s_glExtensions+="GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 "; + if (s_glSupport.GL_ARB_MATRIX_PALETTE && s_glSupport.GL_ARB_VERTEX_BLEND) { + *s_glExtensions+="GL_OES_matrix_palette "; + GLint max_palette_matrices=0; + GLint max_vertex_units=0; + dispatcher().glGetIntegerv(GL_MAX_PALETTE_MATRICES_OES,&max_palette_matrices); + dispatcher().glGetIntegerv(GL_MAX_VERTEX_UNITS_OES,&max_vertex_units); + if (max_palette_matrices>=32 && max_vertex_units>=4) + *s_glExtensions+="GL_OES_extended_matrix_palette "; + } + *s_glExtensions+="GL_OES_compressed_ETC1_RGB8_texture "; +} + +int GLEScmContext::getMaxTexUnits() { + return getCaps()->maxTexUnits; +} + +bool GLEScmContext::glGetBooleanv(GLenum pname, GLboolean *params) +{ + GLint iParam; + + if(glGetIntegerv(pname, &iParam)) + { + *params = (iParam != 0); + return true; + } + + return false; +} + +bool GLEScmContext::glGetFixedv(GLenum pname, GLfixed *params) +{ + GLint iParam; + + if(glGetIntegerv(pname, &iParam)) + { + *params = I2X(iParam); + return true; + } + + return false; +} + +bool GLEScmContext::glGetFloatv(GLenum pname, GLfloat *params) +{ + GLint iParam; + + if(glGetIntegerv(pname, &iParam)) + { + *params = (GLfloat)iParam; + return true; + } + + return false; +} + +bool GLEScmContext::glGetIntegerv(GLenum pname, GLint *params) +{ + if(GLEScontext::glGetIntegerv(pname, params)) + return true; + + const GLESpointer* ptr = NULL; + + switch(pname){ + case GL_VERTEX_ARRAY_BUFFER_BINDING: + case GL_VERTEX_ARRAY_SIZE: + case GL_VERTEX_ARRAY_STRIDE: + case GL_VERTEX_ARRAY_TYPE: + ptr = getPointer(GL_VERTEX_ARRAY_POINTER); + break; + + case GL_NORMAL_ARRAY_BUFFER_BINDING: + case GL_NORMAL_ARRAY_STRIDE: + case GL_NORMAL_ARRAY_TYPE: + ptr = getPointer(GL_NORMAL_ARRAY_POINTER); + break; + + case GL_COLOR_ARRAY_BUFFER_BINDING: + case GL_COLOR_ARRAY_SIZE: + case GL_COLOR_ARRAY_STRIDE: + case GL_COLOR_ARRAY_TYPE: + ptr = getPointer(GL_COLOR_ARRAY_POINTER); + break; + + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: + case GL_TEXTURE_COORD_ARRAY_SIZE: + case GL_TEXTURE_COORD_ARRAY_STRIDE: + case GL_TEXTURE_COORD_ARRAY_TYPE: + ptr = getPointer(GL_TEXTURE_COORD_ARRAY_POINTER); + break; + + case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: + case GL_POINT_SIZE_ARRAY_STRIDE_OES: + case GL_POINT_SIZE_ARRAY_TYPE_OES: + ptr = getPointer(GL_POINT_SIZE_ARRAY_POINTER_OES); + break; + + default: + return false; + } + + switch(pname) + { + case GL_VERTEX_ARRAY_BUFFER_BINDING: + case GL_NORMAL_ARRAY_BUFFER_BINDING: + case GL_COLOR_ARRAY_BUFFER_BINDING: + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: + case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: + *params = ptr ? ptr->getBufferName() : 0; + break; + + case GL_VERTEX_ARRAY_STRIDE: + case GL_NORMAL_ARRAY_STRIDE: + case GL_COLOR_ARRAY_STRIDE: + case GL_TEXTURE_COORD_ARRAY_STRIDE: + case GL_POINT_SIZE_ARRAY_STRIDE_OES: + *params = ptr ? ptr->getStride() : 0; + break; + + case GL_VERTEX_ARRAY_SIZE: + case GL_COLOR_ARRAY_SIZE: + case GL_TEXTURE_COORD_ARRAY_SIZE: + *params = ptr ? ptr->getSize() : 0; + break; + + case GL_VERTEX_ARRAY_TYPE: + case GL_NORMAL_ARRAY_TYPE: + case GL_COLOR_ARRAY_TYPE: + case GL_TEXTURE_COORD_ARRAY_TYPE: + case GL_POINT_SIZE_ARRAY_TYPE_OES: + *params = ptr ? ptr->getType() : 0; + break; + } + + return true; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.h b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.h new file mode 100644 index 0000000..ef03586 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmContext.h @@ -0,0 +1,71 @@ +/* +* 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 GLES_CM_CONTEX_H +#define GLES_CM_CONTEX_H + +#include +#include +#include +#include + +#include +#include +#include + + +typedef std::map > PointSizeIndices; + +class GlLibrary; + +class GLEScmContext: public GLEScontext +{ +public: + virtual void init(GlLibrary* glLib); + GLEScmContext(); + + void setActiveTexture(GLenum tex); + void setClientActiveTexture(GLenum tex); + GLenum getActiveTexture() { return GL_TEXTURE0 + m_activeTexture;}; + GLenum getClientActiveTexture() { return GL_TEXTURE0 + m_clientActiveTexture;}; + void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct); + void drawPointsArrs(GLESConversionArrays& arrs,GLint first,GLsizei count); + void drawPointsElems(GLESConversionArrays& arrs,GLsizei count,GLenum type,const GLvoid* indices); + virtual const GLESpointer* getPointer(GLenum arrType); + int getMaxTexUnits(); + + virtual bool glGetIntegerv(GLenum pname, GLint *params); + virtual bool glGetBooleanv(GLenum pname, GLboolean *params); + virtual bool glGetFloatv(GLenum pname, GLfloat *params); + virtual bool glGetFixedv(GLenum pname, GLfixed *params); + + ~GLEScmContext(); +protected: + + bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id); +private: + void setupArrayPointerHelper(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLenum array_id,GLESpointer* p); + void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1); + void drawPoints(PointSizeIndices* points); + void drawPointsData(GLESConversionArrays& arrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices_in,bool isElemsDraw); + void initExtensionString(); + + GLESpointer* m_texCoords; + int m_pointsIndex; + unsigned int m_clientActiveTexture; +}; + +#endif + diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmImp.cpp b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmImp.cpp new file mode 100644 index 0000000..c9b2c22 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmImp.cpp @@ -0,0 +1,2367 @@ +/* +* 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. +*/ + +#ifdef _WIN32 +#undef GL_API +#define GL_API __declspec(dllexport) +#define GL_APICALL __declspec(dllexport) +#endif +#define GL_GLEXT_PROTOTYPES +#include "GLEScmContext.h" +#include "GLEScmValidate.h" +#include "GLEScmUtils.h" +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +extern "C" { + +//decleration +static void initGLESx(); +static void initContext(GLEScontext* ctx,ShareGroupPtr grp); +static void deleteGLESContext(GLEScontext* ctx); +static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp); +static GLEScontext* createGLESContext(); +static __translatorMustCastToProperFunctionPointerType getProcAddress(const char* procName); + +} + +/************************************** GLES EXTENSIONS *********************************************************/ +//extentions descriptor +typedef std::map ProcTableMap; +ProcTableMap *s_glesExtensions = NULL; +/****************************************************************************************************************/ + +static EGLiface* s_eglIface = NULL; +static GLESiface s_glesIface = { + .initGLESx = initGLESx, + .createGLESContext = createGLESContext, + .initContext = initContext, + .deleteGLESContext = deleteGLESContext, + .flush = (FUNCPTR)glFlush, + .finish = (FUNCPTR)glFinish, + .setShareGroup = setShareGroup, + .getProcAddress = getProcAddress +}; + +#include + +extern "C" { + +static void initGLESx() { + DBG("No special initialization necessary for GLES_CM\n"); + return; +} + +static void initContext(GLEScontext* ctx,ShareGroupPtr grp) { + if (!ctx->isInitialized()) { + ctx->setShareGroup(grp); + ctx->init(s_eglIface->eglGetGlLibrary()); + glBindTexture(GL_TEXTURE_2D,0); + glBindTexture(GL_TEXTURE_CUBE_MAP_OES,0); + } +} + +static GLEScontext* createGLESContext() { + return new GLEScmContext(); +} + +static void deleteGLESContext(GLEScontext* ctx) { + if(ctx) delete ctx; +} + +static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp) { + if(ctx) { + ctx->setShareGroup(grp); + } +} +static __translatorMustCastToProperFunctionPointerType getProcAddress(const char* procName) { + GET_CTX_RET(NULL) + ctx->getGlobalLock(); + static bool proc_table_initialized = false; + if (!proc_table_initialized) { + proc_table_initialized = true; + if (!s_glesExtensions) + s_glesExtensions = new ProcTableMap(); + else + s_glesExtensions->clear(); + (*s_glesExtensions)["glEGLImageTargetTexture2DOES"] = (__translatorMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES; + (*s_glesExtensions)["glEGLImageTargetRenderbufferStorageOES"]=(__translatorMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES; + (*s_glesExtensions)["glBlendEquationSeparateOES"] = (__translatorMustCastToProperFunctionPointerType)glBlendEquationSeparateOES; + (*s_glesExtensions)["glBlendFuncSeparateOES"] = (__translatorMustCastToProperFunctionPointerType)glBlendFuncSeparateOES; + (*s_glesExtensions)["glBlendEquationOES"] = (__translatorMustCastToProperFunctionPointerType)glBlendEquationOES; + + if (ctx->getCaps()->GL_ARB_MATRIX_PALETTE && ctx->getCaps()->GL_ARB_VERTEX_BLEND) { + (*s_glesExtensions)["glCurrentPaletteMatrixOES"] = (__translatorMustCastToProperFunctionPointerType)glCurrentPaletteMatrixOES; + (*s_glesExtensions)["glLoadPaletteFromModelViewMatrixOES"]=(__translatorMustCastToProperFunctionPointerType)glLoadPaletteFromModelViewMatrixOES; + (*s_glesExtensions)["glMatrixIndexPointerOES"] = (__translatorMustCastToProperFunctionPointerType)glMatrixIndexPointerOES; + (*s_glesExtensions)["glWeightPointerOES"] = (__translatorMustCastToProperFunctionPointerType)glWeightPointerOES; + } + (*s_glesExtensions)["glDepthRangefOES"] = (__translatorMustCastToProperFunctionPointerType)glDepthRangef; + (*s_glesExtensions)["glFrustumfOES"] = (__translatorMustCastToProperFunctionPointerType)glFrustumf; + (*s_glesExtensions)["glOrthofOES"] = (__translatorMustCastToProperFunctionPointerType)glOrthof; + (*s_glesExtensions)["glClipPlanefOES"] = (__translatorMustCastToProperFunctionPointerType)glClipPlanef; + (*s_glesExtensions)["glGetClipPlanefOES"] = (__translatorMustCastToProperFunctionPointerType)glGetClipPlanef; + (*s_glesExtensions)["glClearDepthfOES"] = (__translatorMustCastToProperFunctionPointerType)glClearDepthf; + (*s_glesExtensions)["glPointSizePointerOES"] = (__translatorMustCastToProperFunctionPointerType)glPointSizePointerOES; + (*s_glesExtensions)["glTexGenfOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGenfOES; + (*s_glesExtensions)["glTexGenfvOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGenfvOES; + (*s_glesExtensions)["glTexGeniOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGeniOES; + (*s_glesExtensions)["glTexGenivOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGenivOES; + (*s_glesExtensions)["glTexGenxOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGenxOES; + (*s_glesExtensions)["glTexGenxvOES"] = (__translatorMustCastToProperFunctionPointerType)glTexGenxvOES; + (*s_glesExtensions)["glGetTexGenfvOES"] = (__translatorMustCastToProperFunctionPointerType)glGetTexGenfvOES; + (*s_glesExtensions)["glGetTexGenivOES"] = (__translatorMustCastToProperFunctionPointerType)glGetTexGenivOES; + (*s_glesExtensions)["glGetTexGenxvOES"] = (__translatorMustCastToProperFunctionPointerType)glGetTexGenxvOES; + if (ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT) { + (*s_glesExtensions)["glIsRenderbufferOES"] = (__translatorMustCastToProperFunctionPointerType)glIsRenderbufferOES; + (*s_glesExtensions)["glBindRenderbufferOES"] = (__translatorMustCastToProperFunctionPointerType)glBindRenderbufferOES; + (*s_glesExtensions)["glDeleteRenderbuffersOES"] = (__translatorMustCastToProperFunctionPointerType)glDeleteRenderbuffersOES; + (*s_glesExtensions)["glGenRenderbuffersOES"] = (__translatorMustCastToProperFunctionPointerType)glGenRenderbuffersOES; + (*s_glesExtensions)["glRenderbufferStorageOES"] = (__translatorMustCastToProperFunctionPointerType)glRenderbufferStorageOES; + (*s_glesExtensions)["glGetRenderbufferParameterivOES"] = (__translatorMustCastToProperFunctionPointerType)glGetRenderbufferParameterivOES; + (*s_glesExtensions)["glIsFramebufferOES"] = (__translatorMustCastToProperFunctionPointerType)glIsFramebufferOES; + (*s_glesExtensions)["glBindFramebufferOES"] = (__translatorMustCastToProperFunctionPointerType)glBindFramebufferOES; + (*s_glesExtensions)["glDeleteFramebuffersOES"] = (__translatorMustCastToProperFunctionPointerType)glDeleteFramebuffersOES; + (*s_glesExtensions)["glGenFramebuffersOES"] = (__translatorMustCastToProperFunctionPointerType)glGenFramebuffersOES; + (*s_glesExtensions)["glCheckFramebufferStatusOES"] = (__translatorMustCastToProperFunctionPointerType)glCheckFramebufferStatusOES; + (*s_glesExtensions)["glFramebufferTexture2DOES"] = (__translatorMustCastToProperFunctionPointerType)glFramebufferTexture2DOES; + (*s_glesExtensions)["glFramebufferRenderbufferOES"] = (__translatorMustCastToProperFunctionPointerType)glFramebufferRenderbufferOES; + (*s_glesExtensions)["glGetFramebufferAttachmentParameterivOES"] = (__translatorMustCastToProperFunctionPointerType)glGetFramebufferAttachmentParameterivOES; + (*s_glesExtensions)["glGenerateMipmapOES"] = (__translatorMustCastToProperFunctionPointerType)glGenerateMipmapOES; + } + (*s_glesExtensions)["glDrawTexsOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexsOES; + (*s_glesExtensions)["glDrawTexiOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexiOES; + (*s_glesExtensions)["glDrawTexfOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexfOES; + (*s_glesExtensions)["glDrawTexxOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexxOES; + (*s_glesExtensions)["glDrawTexsvOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexsvOES; + (*s_glesExtensions)["glDrawTexivOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexivOES; + (*s_glesExtensions)["glDrawTexfvOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexfvOES; + (*s_glesExtensions)["glDrawTexxvOES"] = (__translatorMustCastToProperFunctionPointerType)glDrawTexxvOES; + } + __translatorMustCastToProperFunctionPointerType ret=NULL; + ProcTableMap::iterator val = s_glesExtensions->find(procName); + if (val!=s_glesExtensions->end()) + ret = val->second; + ctx->releaseGlobalLock(); + + return ret; +} + +GL_APICALL GLESiface* GL_APIENTRY __translator_getIfaces(EGLiface* eglIface); + +GLESiface* __translator_getIfaces(EGLiface* eglIface) { + s_eglIface = eglIface; + return &s_glesIface; +} + +} + +static ObjectLocalName TextureLocalName(GLenum target, unsigned int tex) { + GET_CTX_RET(0); + return (tex!=0? tex : ctx->getDefaultTextureName(target)); +} + +static TextureData* getTextureData(ObjectLocalName tex){ + GET_CTX_RET(NULL); + + if(!ctx->shareGroup()->isObject(TEXTURE,tex)) + { + return NULL; + } + + TextureData *texData = NULL; + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(TEXTURE,tex); + if(!objData.Ptr()){ + texData = new TextureData(); + ctx->shareGroup()->setObjectData(TEXTURE, tex, ObjectDataPtr(texData)); + } else { + texData = (TextureData*)objData.Ptr(); + } + return texData; +} + +static TextureData* getTextureTargetData(GLenum target){ + GET_CTX_RET(NULL); + unsigned int tex = ctx->getBindedTexture(target); + return getTextureData(TextureLocalName(target,tex)); +} + +GL_API GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) { + GET_CTX_RET(GL_FALSE) + + if(buffer && ctx->shareGroup().Ptr()) { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(VERTEXBUFFER,buffer); + return objData.Ptr() ? ((GLESbuffer*)objData.Ptr())->wasBinded():GL_FALSE; + } + return GL_FALSE; +} + +GL_API GLboolean GL_APIENTRY glIsEnabled( GLenum cap) { + GET_CTX_CM_RET(GL_FALSE) + RET_AND_SET_ERROR_IF(!GLEScmValidate::capability(cap,ctx->getMaxLights(),ctx->getMaxClipPlanes()),GL_INVALID_ENUM,GL_FALSE); + + if (cap == GL_POINT_SIZE_ARRAY_OES) + return ctx->isArrEnabled(cap); + else if (cap==GL_TEXTURE_GEN_STR_OES) + return (ctx->dispatcher().glIsEnabled(GL_TEXTURE_GEN_S) && + ctx->dispatcher().glIsEnabled(GL_TEXTURE_GEN_T) && + ctx->dispatcher().glIsEnabled(GL_TEXTURE_GEN_R)); + else + return ctx->dispatcher().glIsEnabled(cap); +} + +GL_API GLboolean GL_APIENTRY glIsTexture( GLuint texture) { + GET_CTX_RET(GL_FALSE) + + if(texture == 0) // Special case + return GL_FALSE; + + TextureData* tex = getTextureData(texture); + return tex ? tex->wasBound : GL_FALSE; +} + +GL_API GLenum GL_APIENTRY glGetError(void) { + GET_CTX_RET(GL_NO_ERROR) + GLenum err = ctx->getGLerror(); + if(err != GL_NO_ERROR) { + ctx->setGLerror(GL_NO_ERROR); + return err; + } + + return ctx->dispatcher().glGetError(); +} + +GL_API const GLubyte * GL_APIENTRY glGetString( GLenum name) { + + GET_CTX_RET(NULL) + switch(name) { + case GL_VENDOR: + return (const GLubyte*)ctx->getVendorString(); + case GL_RENDERER: + return (const GLubyte*)ctx->getRendererString(); + case GL_VERSION: + return (const GLubyte*)ctx->getVersionString(); + case GL_EXTENSIONS: + return (const GLubyte*)ctx->getExtensionString(); + default: + RET_AND_SET_ERROR_IF(true,GL_INVALID_ENUM,NULL); + } +} + +GL_API void GL_APIENTRY glActiveTexture( GLenum texture) { + GET_CTX_CM() + SET_ERROR_IF(!GLEScmValidate::textureEnum(texture,ctx->getMaxTexUnits()),GL_INVALID_ENUM); + ctx->setActiveTexture(texture); + ctx->dispatcher().glActiveTexture(texture); +} + +GL_API void GL_APIENTRY glAlphaFunc( GLenum func, GLclampf ref) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::alphaFunc(func),GL_INVALID_ENUM); + ctx->dispatcher().glAlphaFunc(func,ref); +} + + +GL_API void GL_APIENTRY glAlphaFuncx( GLenum func, GLclampx ref) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::alphaFunc(func),GL_INVALID_ENUM); + ctx->dispatcher().glAlphaFunc(func,X2F(ref)); +} + + +GL_API void GL_APIENTRY glBindBuffer( GLenum target, GLuint buffer) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::bufferTarget(target),GL_INVALID_ENUM); + + //if buffer wasn't generated before,generate one + if(buffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(VERTEXBUFFER,buffer)){ + ctx->shareGroup()->genName(VERTEXBUFFER,buffer); + ctx->shareGroup()->setObjectData(VERTEXBUFFER,buffer,ObjectDataPtr(new GLESbuffer())); + } + ctx->bindBuffer(target,buffer); + if (buffer) { + GLESbuffer* vbo = (GLESbuffer*)ctx->shareGroup()->getObjectData(VERTEXBUFFER,buffer).Ptr(); + vbo->setBinded(); + } +} + + +GL_API void GL_APIENTRY glBindTexture( GLenum target, GLuint texture) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::textureTarget(target),GL_INVALID_ENUM) + + //for handling default texture (0) + ObjectLocalName localTexName = TextureLocalName(target,texture); + + GLuint globalTextureName = localTexName; + if(ctx->shareGroup().Ptr()){ + globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,localTexName); + //if texture wasn't generated before,generate one + if(!globalTextureName){ + ctx->shareGroup()->genName(TEXTURE,localTexName); + globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,localTexName); + } + + TextureData* texData = getTextureData(localTexName); + if (texData->target==0) + texData->target = target; + //if texture was already bound to another target + SET_ERROR_IF(ctx->GLTextureTargetToLocal(texData->target) != ctx->GLTextureTargetToLocal(target), GL_INVALID_OPERATION); + texData->wasBound = true; + } + + ctx->setBindedTexture(target,texture); + ctx->dispatcher().glBindTexture(target,globalTextureName); +} + +GL_API void GL_APIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::blendSrc(sfactor) || !GLEScmValidate::blendDst(dfactor),GL_INVALID_ENUM) + ctx->dispatcher().glBlendFunc(sfactor,dfactor); +} + +GL_API void GL_APIENTRY glBufferData( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::bufferTarget(target),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + ctx->setBufferData(target,size,data,usage); +} + +GL_API void GL_APIENTRY glBufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { + GET_CTX() + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::bufferTarget(target),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->setBufferSubData(target,offset,size,data),GL_INVALID_VALUE); +} + +GL_API void GL_APIENTRY glClear( GLbitfield mask) { + GET_CTX() + ctx->drawValidate(); + + ctx->dispatcher().glClear(mask); +} + +GL_API void GL_APIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + GET_CTX() + ctx->dispatcher().glClearColor(red,green,blue,alpha); +} + +GL_API void GL_APIENTRY glClearColorx( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { + GET_CTX() + ctx->dispatcher().glClearColor(X2F(red),X2F(green),X2F(blue),X2F(alpha)); +} + + +GL_API void GL_APIENTRY glClearDepthf( GLclampf depth) { + GET_CTX() + ctx->dispatcher().glClearDepth(depth); +} + +GL_API void GL_APIENTRY glClearDepthx( GLclampx depth) { + GET_CTX() + ctx->dispatcher().glClearDepth(X2F(depth)); +} + +GL_API void GL_APIENTRY glClearStencil( GLint s) { + GET_CTX() + ctx->dispatcher().glClearStencil(s); +} + +GL_API void GL_APIENTRY glClientActiveTexture( GLenum texture) { + GET_CTX_CM() + SET_ERROR_IF(!GLEScmValidate::textureEnum(texture,ctx->getMaxTexUnits()),GL_INVALID_ENUM); + ctx->setClientActiveTexture(texture); + ctx->dispatcher().glClientActiveTexture(texture); + +} + +GL_API void GL_APIENTRY glClipPlanef( GLenum plane, const GLfloat *equation) { + GET_CTX() + GLdouble tmpEquation[4]; + + for(int i = 0; i < 4; i++) { + tmpEquation[i] = static_cast(equation[i]); + } + ctx->dispatcher().glClipPlane(plane,tmpEquation); +} + +GL_API void GL_APIENTRY glClipPlanex( GLenum plane, const GLfixed *equation) { + GET_CTX() + GLdouble tmpEquation[4]; + for(int i = 0; i < 4; i++) { + tmpEquation[i] = X2D(equation[i]); + } + ctx->dispatcher().glClipPlane(plane,tmpEquation); +} + +GL_API void GL_APIENTRY glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + GET_CTX() + ctx->dispatcher().glColor4f(red,green,blue,alpha); +} + +GL_API void GL_APIENTRY glColor4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { + GET_CTX() + ctx->dispatcher().glColor4ub(red,green,blue,alpha); +} + +GL_API void GL_APIENTRY glColor4x( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { + GET_CTX() + ctx->dispatcher().glColor4f(X2F(red),X2F(green),X2F(blue),X2F(alpha)); +} + +GL_API void GL_APIENTRY glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { + GET_CTX() + ctx->dispatcher().glColorMask(red,green,blue,alpha); +} + +GL_API void GL_APIENTRY glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::colorPointerParams(size,stride),GL_INVALID_VALUE); + SET_ERROR_IF(!GLEScmValidate::colorPointerType(type),GL_INVALID_ENUM); + ctx->setPointer(GL_COLOR_ARRAY,size,type,stride,pointer); +} + +GL_API void GL_APIENTRY glCompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) { + GET_CTX_CM() + SET_ERROR_IF(!GLEScmValidate::textureTargetEx(target),GL_INVALID_ENUM); + SET_ERROR_IF(!data,GL_INVALID_OPERATION); + + doCompressedTexImage2D(ctx, target, level, internalformat, + width, height, border, + imageSize, data, (void*)glTexImage2D); +} + +GL_API void GL_APIENTRY glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) { + GET_CTX_CM() + SET_ERROR_IF(!(GLEScmValidate::texCompImgFrmt(format) && GLEScmValidate::textureTargetEx(target)),GL_INVALID_ENUM); + SET_ERROR_IF(level < 0 || level > log2(ctx->getMaxTexSize()),GL_INVALID_VALUE) + SET_ERROR_IF(!data,GL_INVALID_OPERATION); + + GLenum uncompressedFrmt; + unsigned char* uncompressed = uncompressTexture(format,uncompressedFrmt,width,height,imageSize,data,level); + ctx->dispatcher().glTexSubImage2D(target,level,xoffset,yoffset,width,height,uncompressedFrmt,GL_UNSIGNED_BYTE,uncompressed); + delete uncompressed; +} + +GL_API void GL_APIENTRY glCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::pixelFrmt(ctx,internalformat) && GLEScmValidate::textureTargetEx(target)),GL_INVALID_ENUM); + SET_ERROR_IF(border != 0,GL_INVALID_VALUE); + ctx->dispatcher().glCopyTexImage2D(target,level,internalformat,x,y,width,height,border); +} + +GL_API void GL_APIENTRY glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::textureTargetEx(target),GL_INVALID_ENUM); + ctx->dispatcher().glCopyTexSubImage2D(target,level,xoffset,yoffset,x,y,width,height); +} + +GL_API void GL_APIENTRY glCullFace( GLenum mode) { + GET_CTX() + ctx->dispatcher().glCullFace(mode); +} + +GL_API void GL_APIENTRY glDeleteBuffers( GLsizei n, const GLuint *buffers) { + GET_CTX() + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + ctx->shareGroup()->deleteName(VERTEXBUFFER,buffers[i]); + ctx->unbindBuffer(buffers[i]); + } + } +} + +GL_API void GL_APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures) { + GET_CTX() + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + if(textures[i] != 0) + { + TextureData* tData = getTextureData(textures[i]); + // delete the underlying OpenGL texture but only if this + // texture is not a target of EGLImage. + if (!tData || tData->sourceEGLImage == 0) { + const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]); + ctx->dispatcher().glDeleteTextures(1,&globalTextureName); + } + ctx->shareGroup()->deleteName(TEXTURE,textures[i]); + + if(ctx->getBindedTexture(GL_TEXTURE_2D) == textures[i]) + ctx->setBindedTexture(GL_TEXTURE_2D,0); + if (ctx->getBindedTexture(GL_TEXTURE_CUBE_MAP) == textures[i]) + ctx->setBindedTexture(GL_TEXTURE_CUBE_MAP,0); + } + } + } +} + +GL_API void GL_APIENTRY glDepthFunc( GLenum func) { + GET_CTX() + ctx->dispatcher().glDepthFunc(func); +} + +GL_API void GL_APIENTRY glDepthMask( GLboolean flag) { + GET_CTX() + ctx->dispatcher().glDepthMask(flag); +} + +GL_API void GL_APIENTRY glDepthRangef( GLclampf zNear, GLclampf zFar) { + GET_CTX() + ctx->dispatcher().glDepthRange(zNear,zFar); +} + +GL_API void GL_APIENTRY glDepthRangex( GLclampx zNear, GLclampx zFar) { + GET_CTX() + ctx->dispatcher().glDepthRange(X2F(zNear),X2F(zFar)); +} + +GL_API void GL_APIENTRY glDisable( GLenum cap) { + GET_CTX() + if (cap==GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glDisable(GL_TEXTURE_GEN_S); + ctx->dispatcher().glDisable(GL_TEXTURE_GEN_T); + ctx->dispatcher().glDisable(GL_TEXTURE_GEN_R); + } + else ctx->dispatcher().glDisable(cap); + if (cap==GL_TEXTURE_2D || cap==GL_TEXTURE_CUBE_MAP_OES) + ctx->setTextureEnabled(cap,false); +} + +GL_API void GL_APIENTRY glDisableClientState( GLenum array) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::supportedArrays(array),GL_INVALID_ENUM) + + ctx->enableArr(array,false); + if(array != GL_POINT_SIZE_ARRAY_OES) ctx->dispatcher().glDisableClientState(array); +} + + +GL_API void GL_APIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count) { + GET_CTX_CM() + SET_ERROR_IF(count < 0,GL_INVALID_VALUE) + SET_ERROR_IF(!GLEScmValidate::drawMode(mode),GL_INVALID_ENUM) + + ctx->drawValidate(); + + if(!ctx->isArrEnabled(GL_VERTEX_ARRAY)) return; + + GLESConversionArrays tmpArrs; + ctx->setupArraysPointers(tmpArrs,first,count,0,NULL,true); + if(mode == GL_POINTS && ctx->isArrEnabled(GL_POINT_SIZE_ARRAY_OES)){ + ctx->drawPointsArrs(tmpArrs,first,count); + } + else + { + ctx->dispatcher().glDrawArrays(mode,first,count); + } +} + +GL_API void GL_APIENTRY glDrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *elementsIndices) { + GET_CTX_CM() + SET_ERROR_IF(count < 0,GL_INVALID_VALUE) + SET_ERROR_IF((!GLEScmValidate::drawMode(mode) || !GLEScmValidate::drawType(type)),GL_INVALID_ENUM) + if(!ctx->isArrEnabled(GL_VERTEX_ARRAY)) return; + + ctx->drawValidate(); + + const GLvoid* indices = elementsIndices; + GLESConversionArrays tmpArrs; + if(ctx->isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)) { // if vbo is binded take the indices from the vbo + const unsigned char* buf = static_cast(ctx->getBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)); + indices = buf + SafeUIntFromPointer(elementsIndices); + } + + ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false); + if(mode == GL_POINTS && ctx->isArrEnabled(GL_POINT_SIZE_ARRAY_OES)){ + ctx->drawPointsElems(tmpArrs,count,type,indices); + } + else{ + ctx->dispatcher().glDrawElements(mode,count,type,indices); + } +} + +GL_API void GL_APIENTRY glEnable( GLenum cap) { + GET_CTX() + if (cap==GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glEnable(GL_TEXTURE_GEN_S); + ctx->dispatcher().glEnable(GL_TEXTURE_GEN_T); + ctx->dispatcher().glEnable(GL_TEXTURE_GEN_R); + } + else + ctx->dispatcher().glEnable(cap); + if (cap==GL_TEXTURE_2D || cap==GL_TEXTURE_CUBE_MAP_OES) + ctx->setTextureEnabled(cap,true); +} + +GL_API void GL_APIENTRY glEnableClientState( GLenum array) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::supportedArrays(array),GL_INVALID_ENUM) + + ctx->enableArr(array,true); + if(array != GL_POINT_SIZE_ARRAY_OES) ctx->dispatcher().glEnableClientState(array); +} + +GL_API void GL_APIENTRY glFinish( void) { + GET_CTX() + ctx->dispatcher().glFinish(); +} + +GL_API void GL_APIENTRY glFlush( void) { + GET_CTX() + ctx->dispatcher().glFlush(); +} + +GL_API void GL_APIENTRY glFogf( GLenum pname, GLfloat param) { + GET_CTX() + ctx->dispatcher().glFogf(pname,param); +} + +GL_API void GL_APIENTRY glFogfv( GLenum pname, const GLfloat *params) { + GET_CTX() + ctx->dispatcher().glFogfv(pname,params); +} + +GL_API void GL_APIENTRY glFogx( GLenum pname, GLfixed param) { + GET_CTX() + ctx->dispatcher().glFogf(pname,(pname == GL_FOG_MODE)? static_cast(param):X2F(param)); +} + +GL_API void GL_APIENTRY glFogxv( GLenum pname, const GLfixed *params) { + GET_CTX() + if(pname == GL_FOG_MODE) { + GLfloat tmpParam = static_cast(params[0]); + ctx->dispatcher().glFogfv(pname,&tmpParam); + } else { + GLfloat tmpParams[4]; + for(int i=0; i< 4; i++) { + tmpParams[i] = X2F(params[i]); + } + ctx->dispatcher().glFogfv(pname,tmpParams); + } + +} + +GL_API void GL_APIENTRY glFrontFace( GLenum mode) { + GET_CTX() + ctx->dispatcher().glFrontFace(mode); +} + +GL_API void GL_APIENTRY glFrustumf( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + GET_CTX() + ctx->dispatcher().glFrustum(left,right,bottom,top,zNear,zFar); +} + +GL_API void GL_APIENTRY glFrustumx( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { + GET_CTX() + ctx->dispatcher().glFrustum(X2F(left),X2F(right),X2F(bottom),X2F(top),X2F(zNear),X2F(zFar)); +} + +GL_API void GL_APIENTRY glGenBuffers( GLsizei n, GLuint *buffers) { + GET_CTX() + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(VERTEXBUFFER, 0, true); + //generating vbo object related to this buffer name + ctx->shareGroup()->setObjectData(VERTEXBUFFER,buffers[i],ObjectDataPtr(new GLESbuffer())); + } + } +} + +GL_API void GL_APIENTRY glGenTextures( GLsizei n, GLuint *textures) { + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(TEXTURE, 0, true); + } + } +} + +GL_API void GL_APIENTRY glGetBooleanv( GLenum pname, GLboolean *params) { + GET_CTX() + + if(ctx->glGetBooleanv(pname, params)) + { + return; + } + + switch(pname) + { + case GL_FRAMEBUFFER_BINDING_OES: + case GL_RENDERBUFFER_BINDING_OES: + { + GLint name; + glGetIntegerv(pname,&name); + *params = name!=0 ? GL_TRUE: GL_FALSE; + } + break; + case GL_TEXTURE_GEN_STR_OES: + { + GLboolean state_s = GL_FALSE; + GLboolean state_t = GL_FALSE; + GLboolean state_r = GL_FALSE; + ctx->dispatcher().glGetBooleanv(GL_TEXTURE_GEN_S,&state_s); + ctx->dispatcher().glGetBooleanv(GL_TEXTURE_GEN_T,&state_t); + ctx->dispatcher().glGetBooleanv(GL_TEXTURE_GEN_R,&state_r); + *params = state_s && state_t && state_r ? GL_TRUE: GL_FALSE; + } + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = (GLboolean)getCompressedFormats(NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + { + int nparams = getCompressedFormats(NULL); + if (nparams>0) { + int * iparams = new int[nparams]; + getCompressedFormats(iparams); + for (int i=0; idispatcher().glGetBooleanv(pname,params); + } +} + +GL_API void GL_APIENTRY glGetBufferParameteriv( GLenum target, GLenum pname, GLint *params) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::bufferTarget(target) && GLEScmValidate::bufferParam(pname)),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + switch(pname) { + case GL_BUFFER_SIZE: + ctx->getBufferSize(target,params); + break; + case GL_BUFFER_USAGE: + ctx->getBufferUsage(target,params); + break; + } + +} + +GL_API void GL_APIENTRY glGetClipPlanef( GLenum pname, GLfloat eqn[4]) { + GET_CTX() + GLdouble tmpEqn[4]; + + ctx->dispatcher().glGetClipPlane(pname,tmpEqn); + for(int i =0 ;i < 4; i++){ + eqn[i] = static_cast(tmpEqn[i]); + } +} + +GL_API void GL_APIENTRY glGetClipPlanex( GLenum pname, GLfixed eqn[4]) { + GET_CTX() + GLdouble tmpEqn[4]; + + ctx->dispatcher().glGetClipPlane(pname,tmpEqn); + for(int i =0 ;i < 4; i++){ + eqn[i] = F2X(tmpEqn[i]); + } +} + +GL_API void GL_APIENTRY glGetFixedv( GLenum pname, GLfixed *params) { + GET_CTX() + + if(ctx->glGetFixedv(pname, params)) + { + return; + } + + size_t nParams = glParamSize(pname); + GLfloat fParams[16]; + + switch(pname) + { + case GL_FRAMEBUFFER_BINDING_OES: + case GL_RENDERBUFFER_BINDING_OES: + case GL_TEXTURE_GEN_STR_OES: + glGetFloatv(pname,&fParams[0]); + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = I2X(getCompressedFormats(NULL)); + return; + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + { + int nparams = getCompressedFormats(NULL); + if (nparams>0) { + int * iparams = new int[nparams]; + getCompressedFormats(iparams); + for (int i=0; idispatcher().glGetFloatv(pname,fParams); + } + + if (nParams) + { + for(size_t i =0 ; i < nParams;i++) { + params[i] = F2X(fParams[i]); + } + } +} + +GL_API void GL_APIENTRY glGetFloatv( GLenum pname, GLfloat *params) { + GET_CTX() + + if(ctx->glGetFloatv(pname, params)) + { + return; + } + + GLint i; + + switch (pname) { + case GL_FRAMEBUFFER_BINDING_OES: + case GL_RENDERBUFFER_BINDING_OES: + case GL_TEXTURE_GEN_STR_OES: + glGetIntegerv(pname,&i); + *params = (GLfloat)i; + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = (GLfloat)getCompressedFormats(NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + { + int nparams = getCompressedFormats(NULL); + if (nparams>0) { + int * iparams = new int[nparams]; + getCompressedFormats(iparams); + for (int i=0; idispatcher().glGetFloatv(pname,params); + } +} + +GL_API void GL_APIENTRY glGetIntegerv( GLenum pname, GLint *params) { + GET_CTX() + + if(ctx->glGetIntegerv(pname, params)) + { + return; + } + + GLint i; + GLfloat f; + + switch(pname) + { + case GL_TEXTURE_GEN_STR_OES: + ctx->dispatcher().glGetIntegerv(GL_TEXTURE_GEN_S,¶ms[0]); + break; + case GL_FRAMEBUFFER_BINDING_OES: + if (ctx->shareGroup().Ptr()) { + ctx->dispatcher().glGetIntegerv(pname,&i); + *params = ctx->shareGroup()->getLocalName(FRAMEBUFFER,i); + } + break; + case GL_RENDERBUFFER_BINDING_OES: + if (ctx->shareGroup().Ptr()) { + ctx->dispatcher().glGetIntegerv(pname,&i); + *params = ctx->shareGroup()->getLocalName(RENDERBUFFER,i); + } + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = getCompressedFormats(NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + getCompressedFormats(params); + break; + case GL_MAX_CLIP_PLANES: + ctx->dispatcher().glGetIntegerv(pname,params); + if(*params > 6) + { + // GLES spec requires only 6, and the ATI driver erronously + // returns 8 (although it supports only 6). This WAR is simple, + // compliant and good enough for developers. + *params = 6; + } + break; + case GL_ALPHA_TEST_REF: + // Both the ATI and nVidia OpenGL drivers return the wrong answer + // here. So return the right one. + ctx->dispatcher().glGetFloatv(pname,&f); + *params = (int)(f * (float)0x7fffffff); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + ctx->dispatcher().glGetIntegerv(pname,params); + if(*params > 16) + { + // GLES spec requires only 2, and the ATI driver erronously + // returns 32 (although it supports only 16). This WAR is simple, + // compliant and good enough for developers. + *params = 16; + } + break; + + default: + ctx->dispatcher().glGetIntegerv(pname,params); + } +} + +GL_API void GL_APIENTRY glGetLightfv( GLenum light, GLenum pname, GLfloat *params) { + GET_CTX() + ctx->dispatcher().glGetLightfv(light,pname,params); +} + +GL_API void GL_APIENTRY glGetLightxv( GLenum light, GLenum pname, GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + + ctx->dispatcher().glGetLightfv(light,pname,tmpParams); + switch (pname){ + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_POSITION: + params[3] = F2X(tmpParams[3]); + case GL_SPOT_DIRECTION: + params[2] = F2X(tmpParams[2]); + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + params[1] = F2X(tmpParams[1]); + break; + default:{ + ctx->setGLerror(GL_INVALID_ENUM); + return; + } + + } + params[0] = F2X(tmpParams[0]); +} + +GL_API void GL_APIENTRY glGetMaterialfv( GLenum face, GLenum pname, GLfloat *params) { + GET_CTX() + ctx->dispatcher().glGetMaterialfv(face,pname,params); +} + +GL_API void GL_APIENTRY glGetMaterialxv( GLenum face, GLenum pname, GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + ctx->dispatcher().glGetMaterialfv(face,pname,tmpParams); + switch(pname){ + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + case GL_AMBIENT_AND_DIFFUSE: + params[3] = tmpParams[3]; + params[2] = tmpParams[2]; + params[1] = tmpParams[1]; + case GL_SHININESS: + params[0] = tmpParams[0]; + break; + default:{ + ctx->setGLerror(GL_INVALID_ENUM); + return; + } + } +} + +GL_API void GL_APIENTRY glGetPointerv( GLenum pname, void **params) { + GET_CTX() + const GLESpointer* p = ctx->getPointer(pname); + if(p) { + if(p->isVBO()) + { + *params = SafePointerFromUInt(p->getBufferOffset()); + }else{ + *params = const_cast(p->getArrayData()); + } + } else { + ctx->setGLerror(GL_INVALID_ENUM); + } + +} + +GL_API void GL_APIENTRY glGetTexEnvfv( GLenum env, GLenum pname, GLfloat *params) { + GET_CTX() + ctx->dispatcher().glGetTexEnvfv(env,pname,params); +} + +GL_API void GL_APIENTRY glGetTexEnviv( GLenum env, GLenum pname, GLint *params) { + GET_CTX() + ctx->dispatcher().glGetTexEnviv(env,pname,params); +} + +GL_API void GL_APIENTRY glGetTexEnvxv( GLenum env, GLenum pname, GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + + ctx->dispatcher().glGetTexEnvfv(env,pname,tmpParams); + if(pname == GL_TEXTURE_ENV_MODE) { + params[0] = static_cast(tmpParams[0]); + } else { + for(int i=0 ; i < 4 ; i++) + params[i] = F2X(tmpParams[i]); + } +} + +GL_API void GL_APIENTRY glGetTexParameterfv( GLenum target, GLenum pname, GLfloat *params) { + GET_CTX() + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + params[i] = texData->crop_rect[i]; + } + else { + ctx->dispatcher().glGetTexParameterfv(target,pname,params); + } +} + +GL_API void GL_APIENTRY glGetTexParameteriv( GLenum target, GLenum pname, GLint *params) { + GET_CTX() + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + params[i] = texData->crop_rect[i]; + } + else { + ctx->dispatcher().glGetTexParameteriv(target,pname,params); + } +} + +GL_API void GL_APIENTRY glGetTexParameterxv( GLenum target, GLenum pname, GLfixed *params) { + GET_CTX() + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + params[i] = F2X(texData->crop_rect[i]); + } + else { + GLfloat tmpParam; + ctx->dispatcher().glGetTexParameterfv(target,pname,&tmpParam); + params[0] = static_cast(tmpParam); + } +} + +GL_API void GL_APIENTRY glHint( GLenum target, GLenum mode) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::hintTargetMode(target,mode),GL_INVALID_ENUM); + ctx->dispatcher().glHint(target,mode); +} + +GL_API void GL_APIENTRY glLightModelf( GLenum pname, GLfloat param) { + GET_CTX() + ctx->dispatcher().glLightModelf(pname,param); +} + +GL_API void GL_APIENTRY glLightModelfv( GLenum pname, const GLfloat *params) { + GET_CTX() + ctx->dispatcher().glLightModelfv(pname,params); +} + +GL_API void GL_APIENTRY glLightModelx( GLenum pname, GLfixed param) { + GET_CTX() + GLfloat tmpParam = static_cast(param); + ctx->dispatcher().glLightModelf(pname,tmpParam); +} + +GL_API void GL_APIENTRY glLightModelxv( GLenum pname, const GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + if(pname == GL_LIGHT_MODEL_TWO_SIDE) { + tmpParams[0] = X2F(params[0]); + } else if (pname == GL_LIGHT_MODEL_AMBIENT) { + for(int i=0;i<4;i++) { + tmpParams[i] = X2F(params[i]); + } + } + + ctx->dispatcher().glLightModelfv(pname,tmpParams); +} + +GL_API void GL_APIENTRY glLightf( GLenum light, GLenum pname, GLfloat param) { + GET_CTX() + ctx->dispatcher().glLightf(light,pname,param); +} + +GL_API void GL_APIENTRY glLightfv( GLenum light, GLenum pname, const GLfloat *params) { + GET_CTX() + ctx->dispatcher().glLightfv(light,pname,params); +} + +GL_API void GL_APIENTRY glLightx( GLenum light, GLenum pname, GLfixed param) { + GET_CTX() + ctx->dispatcher().glLightf(light,pname,X2F(param)); +} + +GL_API void GL_APIENTRY glLightxv( GLenum light, GLenum pname, const GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + case GL_POSITION: + tmpParams[3] = X2F(params[3]); + case GL_SPOT_DIRECTION: + tmpParams[2] = X2F(params[2]); + tmpParams[1] = X2F(params[1]); + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + tmpParams[0] = X2F(params[0]); + break; + default: { + ctx->setGLerror(GL_INVALID_ENUM); + return; + } + } + ctx->dispatcher().glLightfv(light,pname,tmpParams); +} + +GL_API void GL_APIENTRY glLineWidth( GLfloat width) { + GET_CTX() + ctx->dispatcher().glLineWidth(width); +} + +GL_API void GL_APIENTRY glLineWidthx( GLfixed width) { + GET_CTX() + ctx->dispatcher().glLineWidth(X2F(width)); +} + +GL_API void GL_APIENTRY glLoadIdentity( void) { + GET_CTX() + ctx->dispatcher().glLoadIdentity(); +} + +GL_API void GL_APIENTRY glLoadMatrixf( const GLfloat *m) { + GET_CTX() + ctx->dispatcher().glLoadMatrixf(m); +} + +GL_API void GL_APIENTRY glLoadMatrixx( const GLfixed *m) { + GET_CTX() + GLfloat mat[16]; + for(int i=0; i< 16 ; i++) { + mat[i] = X2F(m[i]); + } + ctx->dispatcher().glLoadMatrixf(mat); +} + +GL_API void GL_APIENTRY glLogicOp( GLenum opcode) { + GET_CTX() + ctx->dispatcher().glLogicOp(opcode); +} + +GL_API void GL_APIENTRY glMaterialf( GLenum face, GLenum pname, GLfloat param) { + GET_CTX() + ctx->dispatcher().glMaterialf(face,pname,param); +} + +GL_API void GL_APIENTRY glMaterialfv( GLenum face, GLenum pname, const GLfloat *params) { + GET_CTX() + ctx->dispatcher().glMaterialfv(face,pname,params); +} + +GL_API void GL_APIENTRY glMaterialx( GLenum face, GLenum pname, GLfixed param) { + GET_CTX() + ctx->dispatcher().glMaterialf(face,pname,X2F(param)); +} + +GL_API void GL_APIENTRY glMaterialxv( GLenum face, GLenum pname, const GLfixed *params) { + GET_CTX() + GLfloat tmpParams[4]; + + for(int i=0; i< 4; i++) { + tmpParams[i] = X2F(params[i]); + } + ctx->dispatcher().glMaterialfv(face,pname,tmpParams); +} + +GL_API void GL_APIENTRY glMatrixMode( GLenum mode) { + GET_CTX() + ctx->dispatcher().glMatrixMode(mode); +} + +GL_API void GL_APIENTRY glMultMatrixf( const GLfloat *m) { + GET_CTX() + ctx->dispatcher().glMultMatrixf(m); +} + +GL_API void GL_APIENTRY glMultMatrixx( const GLfixed *m) { + GET_CTX() + GLfloat mat[16]; + for(int i=0; i< 16 ; i++) { + mat[i] = X2F(m[i]); + } + ctx->dispatcher().glMultMatrixf(mat); +} + +GL_API void GL_APIENTRY glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + GET_CTX_CM() + SET_ERROR_IF(!GLEScmValidate::textureEnum(target,ctx->getMaxTexUnits()),GL_INVALID_ENUM); + ctx->dispatcher().glMultiTexCoord4f(target,s,t,r,q); +} + +GL_API void GL_APIENTRY glMultiTexCoord4x( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { + GET_CTX_CM() + SET_ERROR_IF(!GLEScmValidate::textureEnum(target,ctx->getMaxTexUnits()),GL_INVALID_ENUM); + ctx->dispatcher().glMultiTexCoord4f(target,X2F(s),X2F(t),X2F(r),X2F(q)); +} + +GL_API void GL_APIENTRY glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz) { + GET_CTX() + ctx->dispatcher().glNormal3f(nx,ny,nz); +} + +GL_API void GL_APIENTRY glNormal3x( GLfixed nx, GLfixed ny, GLfixed nz) { + GET_CTX() + ctx->dispatcher().glNormal3f(X2F(nx),X2F(ny),X2F(nz)); +} + +GL_API void GL_APIENTRY glNormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(stride < 0,GL_INVALID_VALUE); + SET_ERROR_IF(!GLEScmValidate::normalPointerType(type),GL_INVALID_ENUM); + ctx->setPointer(GL_NORMAL_ARRAY,3,type,stride,pointer);//3 normal verctor +} + +GL_API void GL_APIENTRY glOrthof( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + GET_CTX() + ctx->dispatcher().glOrtho(left,right,bottom,top,zNear,zFar); +} + +GL_API void GL_APIENTRY glOrthox( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { + GET_CTX() + ctx->dispatcher().glOrtho(X2F(left),X2F(right),X2F(bottom),X2F(top),X2F(zNear),X2F(zFar)); +} + +GL_API void GL_APIENTRY glPixelStorei( GLenum pname, GLint param) { + GET_CTX() + SET_ERROR_IF(!(pname == GL_PACK_ALIGNMENT || pname == GL_UNPACK_ALIGNMENT),GL_INVALID_ENUM); + SET_ERROR_IF(!((param==1)||(param==2)||(param==4)||(param==8)), GL_INVALID_VALUE); + ctx->setUnpackAlignment(param); + ctx->dispatcher().glPixelStorei(pname,param); +} + +GL_API void GL_APIENTRY glPointParameterf( GLenum pname, GLfloat param) { + GET_CTX() + ctx->dispatcher().glPointParameterf(pname,param); +} + +GL_API void GL_APIENTRY glPointParameterfv( GLenum pname, const GLfloat *params) { + GET_CTX() + ctx->dispatcher().glPointParameterfv(pname,params); +} + +GL_API void GL_APIENTRY glPointParameterx( GLenum pname, GLfixed param) +{ + GET_CTX() + ctx->dispatcher().glPointParameterf(pname,X2F(param)); +} + +GL_API void GL_APIENTRY glPointParameterxv( GLenum pname, const GLfixed *params) { + GET_CTX() + + GLfloat tmpParam = X2F(*params) ; + ctx->dispatcher().glPointParameterfv(pname,&tmpParam); +} + +GL_API void GL_APIENTRY glPointSize( GLfloat size) { + GET_CTX() + ctx->dispatcher().glPointSize(size); +} + +GL_API void GL_APIENTRY glPointSizePointerOES( GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(stride < 0,GL_INVALID_VALUE); + SET_ERROR_IF(!GLEScmValidate::pointPointerType(type),GL_INVALID_ENUM); + ctx->setPointer(GL_POINT_SIZE_ARRAY_OES,1,type,stride,pointer); +} + +GL_API void GL_APIENTRY glPointSizex( GLfixed size) { + GET_CTX() + ctx->dispatcher().glPointSize(X2F(size)); +} + +GL_API void GL_APIENTRY glPolygonOffset( GLfloat factor, GLfloat units) { + GET_CTX() + ctx->dispatcher().glPolygonOffset(factor,units); +} + +GL_API void GL_APIENTRY glPolygonOffsetx( GLfixed factor, GLfixed units) { + GET_CTX() + ctx->dispatcher().glPolygonOffset(X2F(factor),X2F(units)); +} + +GL_API void GL_APIENTRY glPopMatrix(void) { + GET_CTX() + ctx->dispatcher().glPopMatrix(); +} + +GL_API void GL_APIENTRY glPushMatrix(void) { + GET_CTX() + ctx->dispatcher().glPushMatrix(); +} + +GL_API void GL_APIENTRY glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::pixelFrmt(ctx,format) && GLEScmValidate::pixelType(ctx,type)),GL_INVALID_ENUM); + SET_ERROR_IF(!(GLEScmValidate::pixelOp(format,type)),GL_INVALID_OPERATION); + + ctx->dispatcher().glReadPixels(x,y,width,height,format,type,pixels); +} + +GL_API void GL_APIENTRY glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + GET_CTX() + ctx->dispatcher().glRotatef(angle,x,y,z); +} + +GL_API void GL_APIENTRY glRotatex( GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { + GET_CTX() + ctx->dispatcher().glRotatef(angle,X2F(x),X2F(y),X2F(z)); +} + +GL_API void GL_APIENTRY glSampleCoverage( GLclampf value, GLboolean invert) { + GET_CTX() + ctx->dispatcher().glSampleCoverage(value,invert); +} + +GL_API void GL_APIENTRY glSampleCoveragex( GLclampx value, GLboolean invert) { + GET_CTX() + ctx->dispatcher().glSampleCoverage(X2F(value),invert); +} + +GL_API void GL_APIENTRY glScalef( GLfloat x, GLfloat y, GLfloat z) { + GET_CTX() + ctx->dispatcher().glScalef(x,y,z); +} + +GL_API void GL_APIENTRY glScalex( GLfixed x, GLfixed y, GLfixed z) { + GET_CTX() + ctx->dispatcher().glScalef(X2F(x),X2F(y),X2F(z)); +} + +GL_API void GL_APIENTRY glScissor( GLint x, GLint y, GLsizei width, GLsizei height) { + GET_CTX() + ctx->dispatcher().glScissor(x,y,width,height); +} + +GL_API void GL_APIENTRY glShadeModel( GLenum mode) { + GET_CTX() + ctx->dispatcher().glShadeModel(mode); +} + +GL_API void GL_APIENTRY glStencilFunc( GLenum func, GLint ref, GLuint mask) { + GET_CTX() + ctx->dispatcher().glStencilFunc(func,ref,mask); +} + +GL_API void GL_APIENTRY glStencilMask( GLuint mask) { + GET_CTX() + ctx->dispatcher().glStencilMask(mask); +} + +GL_API void GL_APIENTRY glStencilOp( GLenum fail, GLenum zfail, GLenum zpass) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::stencilOp(fail) && GLEScmValidate::stencilOp(zfail) && GLEScmValidate::stencilOp(zpass)),GL_INVALID_ENUM); + ctx->dispatcher().glStencilOp(fail,zfail,zpass); +} + +GL_API void GL_APIENTRY glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texCoordPointerParams(size,stride),GL_INVALID_VALUE); + SET_ERROR_IF(!GLEScmValidate::texCoordPointerType(type),GL_INVALID_ENUM); + ctx->setPointer(GL_TEXTURE_COORD_ARRAY,size,type,stride,pointer); +} + +GL_API void GL_APIENTRY glTexEnvf( GLenum target, GLenum pname, GLfloat param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + ctx->dispatcher().glTexEnvf(target,pname,param); +} + +GL_API void GL_APIENTRY glTexEnvfv( GLenum target, GLenum pname, const GLfloat *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + ctx->dispatcher().glTexEnvfv(target,pname,params); +} + +GL_API void GL_APIENTRY glTexEnvi( GLenum target, GLenum pname, GLint param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + ctx->dispatcher().glTexEnvi(target,pname,param); +} + +GL_API void GL_APIENTRY glTexEnviv( GLenum target, GLenum pname, const GLint *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + ctx->dispatcher().glTexEnviv(target,pname,params); +} + +GL_API void GL_APIENTRY glTexEnvx( GLenum target, GLenum pname, GLfixed param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + GLfloat tmpParam = static_cast(param); + ctx->dispatcher().glTexEnvf(target,pname,tmpParam); +} + +GL_API void GL_APIENTRY glTexEnvxv( GLenum target, GLenum pname, const GLfixed *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texEnv(target,pname),GL_INVALID_ENUM); + + GLfloat tmpParams[4]; + if(pname == GL_TEXTURE_ENV_COLOR) { + for(int i =0;i<4;i++) { + tmpParams[i] = X2F(params[i]); + } + } else { + tmpParams[0] = static_cast(params[0]); + } + ctx->dispatcher().glTexEnvfv(target,pname,tmpParams); +} + +GL_API void GL_APIENTRY glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + GET_CTX() + + SET_ERROR_IF(!(GLEScmValidate::textureTargetEx(target) && + GLEScmValidate::pixelFrmt(ctx,internalformat) && + GLEScmValidate::pixelFrmt(ctx,format) && + GLEScmValidate::pixelType(ctx,type)),GL_INVALID_ENUM); + + SET_ERROR_IF(!(GLEScmValidate::pixelOp(format,type) && internalformat == ((GLint)format)),GL_INVALID_OPERATION); + + bool needAutoMipmap = false; + + if (ctx->shareGroup().Ptr()){ + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + if(texData) { + texData->width = width; + texData->height = height; + texData->border = border; + texData->internalFormat = internalformat; + texData->target = target; + + if (texData->sourceEGLImage != 0) { + // + // This texture was a target of EGLImage, + // but now it is re-defined so we need to detach + // from the EGLImage and re-generate global texture name + // for it. + // + if (texData->eglImageDetach) { + (*texData->eglImageDetach)(texData->sourceEGLImage); + } + unsigned int tex = ctx->getBindedTexture(target); + ctx->shareGroup()->replaceGlobalName(TEXTURE, + tex, + texData->oldGlobal); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, texData->oldGlobal); + texData->sourceEGLImage = 0; + texData->oldGlobal = 0; + } + + needAutoMipmap = texData->requiresAutoMipmap; + } + } + + ctx->dispatcher().glTexImage2D(target,level, + internalformat,width,height, + border,format,type,pixels); + + if(needAutoMipmap) + { + ctx->dispatcher().glGenerateMipmapEXT(target); + } +} + +static bool handleMipmapGeneration(GLenum target, GLenum pname, bool param) +{ + GET_CTX_RET(false) + + if(pname == GL_GENERATE_MIPMAP && !ctx->isAutoMipmapSupported()) + { + TextureData *texData = getTextureTargetData(target); + if(texData) + { + texData->requiresAutoMipmap = param; + } + return true; + } + + return false; +} + +GL_API void GL_APIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)param)) + return; + + ctx->dispatcher().glTexParameterf(target,pname,param); +} + +GL_API void GL_APIENTRY glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)(*params))) + return; + + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + texData->crop_rect[i] = params[i]; + } + else { + ctx->dispatcher().glTexParameterfv(target,pname,params); + } +} + +GL_API void GL_APIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)param)) + return; + + ctx->dispatcher().glTexParameteri(target,pname,param); +} + +GL_API void GL_APIENTRY glTexParameteriv( GLenum target, GLenum pname, const GLint *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)(*params))) + return; + + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + texData->crop_rect[i] = params[i]; + } + else { + ctx->dispatcher().glTexParameteriv(target,pname,params); + } +} + +GL_API void GL_APIENTRY glTexParameterx( GLenum target, GLenum pname, GLfixed param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)param)) + return; + + ctx->dispatcher().glTexParameterf(target,pname,static_cast(param)); +} + +GL_API void GL_APIENTRY glTexParameterxv( GLenum target, GLenum pname, const GLfixed *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texParams(target,pname),GL_INVALID_ENUM); + + if(handleMipmapGeneration(target, pname, (bool)(*params))) + return; + + if (pname==GL_TEXTURE_CROP_RECT_OES) { + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + for (int i=0;i<4;++i) + texData->crop_rect[i] = X2F(params[i]); + } + else { + GLfloat param = static_cast(params[0]); + ctx->dispatcher().glTexParameterfv(target,pname,¶m); + } +} + +GL_API void GL_APIENTRY glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::textureTargetEx(target) && + GLEScmValidate::pixelFrmt(ctx,format)&& + GLEScmValidate::pixelType(ctx,type)),GL_INVALID_ENUM); + SET_ERROR_IF(!GLEScmValidate::pixelOp(format,type),GL_INVALID_OPERATION); + SET_ERROR_IF(!pixels,GL_INVALID_OPERATION); + + ctx->dispatcher().glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels); + + if (ctx->shareGroup().Ptr()){ + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + if(texData && texData->requiresAutoMipmap) + { + ctx->dispatcher().glGenerateMipmapEXT(target); + } + } +} + +GL_API void GL_APIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z) { + GET_CTX() + ctx->dispatcher().glTranslatef(x,y,z); +} + +GL_API void GL_APIENTRY glTranslatex( GLfixed x, GLfixed y, GLfixed z) { + GET_CTX() + ctx->dispatcher().glTranslatef(X2F(x),X2F(y),X2F(z)); +} + +GL_API void GL_APIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::vertexPointerParams(size,stride),GL_INVALID_VALUE); + SET_ERROR_IF(!GLEScmValidate::vertexPointerType(type),GL_INVALID_ENUM); + ctx->setPointer(GL_VERTEX_ARRAY,size,type,stride,pointer); +} + +GL_API void GL_APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height) { + GET_CTX() + ctx->dispatcher().glViewport(x,y,width,height); +} + +GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + GET_CTX(); + SET_ERROR_IF(!GLEScmValidate::textureTargetLimited(target),GL_INVALID_ENUM); + unsigned int imagehndl = SafeUIntFromPointer(image); + EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); + if (img) { + // Create the texture object in the underlying EGL implementation, + // flag to the OpenGL layer to skip the image creation and map the + // current binded texture object to the existing global object. + if (ctx->shareGroup().Ptr()) { + ObjectLocalName tex = TextureLocalName(target,ctx->getBindedTexture(target)); + unsigned int oldGlobal = ctx->shareGroup()->getGlobalName(TEXTURE, tex); + // Delete old texture object but only if it is not a target of a EGLImage + if (oldGlobal) { + TextureData* oldTexData = getTextureData(tex); + if (!oldTexData || oldTexData->sourceEGLImage == 0) { + ctx->dispatcher().glDeleteTextures(1, &oldGlobal); + } + } + // replace mapping and bind the new global object + ctx->shareGroup()->replaceGlobalName(TEXTURE, tex,img->globalTexName); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, img->globalTexName); + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + texData->width = img->width; + texData->height = img->height; + texData->border = img->border; + texData->internalFormat = img->internalFormat; + texData->sourceEGLImage = imagehndl; + texData->eglImageDetach = s_eglIface->eglDetachEGLImage; + texData->oldGlobal = oldGlobal; + } + } +} + +GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + GET_CTX(); + SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM); + unsigned int imagehndl = SafeUIntFromPointer(image); + EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); + SET_ERROR_IF(!img,GL_INVALID_VALUE); + SET_ERROR_IF(!ctx->shareGroup().Ptr(),GL_INVALID_OPERATION); + + // Get current bounded renderbuffer + // raise INVALID_OPERATIOn if no renderbuffer is bounded + GLuint rb = ctx->getRenderbufferBinding(); + SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + SET_ERROR_IF(!rbData,GL_INVALID_OPERATION); + + // + // flag in the renderbufferData that it is an eglImage target + // + rbData->sourceEGLImage = imagehndl; + rbData->eglImageDetach = s_eglIface->eglDetachEGLImage; + rbData->eglImageGlobalTexName = img->globalTexName; + + // + // if the renderbuffer is attached to a framebuffer + // change the framebuffer attachment in the undelying OpenGL + // to point to the eglImage texture object. + // + if (rbData->attachedFB) { + // update the framebuffer attachment point to the + // underlying texture of the img + GLuint prevFB = ctx->getFramebufferBinding(); + if (prevFB != rbData->attachedFB) { + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + rbData->attachedFB); + } + ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + rbData->attachedPoint, + GL_TEXTURE_2D, + img->globalTexName,0); + if (prevFB != rbData->attachedFB) { + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + prevFB); + } + } +} + +/* GL_OES_blend_subtract*/ +GL_API void GL_APIENTRY glBlendEquationOES(GLenum mode) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::blendEquationMode(mode)), GL_INVALID_ENUM); + ctx->dispatcher().glBlendEquation(mode); +} + +/* GL_OES_blend_equation_separate */ +GL_API void GL_APIENTRY glBlendEquationSeparateOES (GLenum modeRGB, GLenum modeAlpha) { + GET_CTX() + SET_ERROR_IF(!(GLEScmValidate::blendEquationMode(modeRGB) && GLEScmValidate::blendEquationMode(modeAlpha)), GL_INVALID_ENUM); + ctx->dispatcher().glBlendEquationSeparate(modeRGB,modeAlpha); +} + +/* GL_OES_blend_func_separate */ +GL_API void GL_APIENTRY glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::blendSrc(srcRGB) || !GLEScmValidate::blendDst(dstRGB) || + !GLEScmValidate::blendSrc(srcAlpha) || ! GLEScmValidate::blendDst(dstAlpha) ,GL_INVALID_ENUM); + ctx->dispatcher().glBlendFuncSeparate(srcRGB,dstRGB,srcAlpha,dstAlpha); +} + +/* GL_OES_framebuffer_object */ +GL_API GLboolean GL_APIENTRY glIsRenderbufferOES(GLuint renderbuffer) { + GET_CTX_RET(GL_FALSE) + RET_AND_SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION,GL_FALSE); + if(renderbuffer && ctx->shareGroup().Ptr()){ + return ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer) ? GL_TRUE :GL_FALSE; + } + return ctx->dispatcher().glIsRenderbufferEXT(renderbuffer); +} + +GL_API void GLAPIENTRY glBindRenderbufferOES(GLenum target, GLuint renderbuffer) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::renderbufferTarget(target),GL_INVALID_ENUM); + + //if buffer wasn't generated before,generate one + if(renderbuffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)){ + ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffer, + ObjectDataPtr(new RenderbufferData())); + } + + int globalBufferName = (renderbuffer != 0) ? ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer) : 0; + ctx->dispatcher().glBindRenderbufferEXT(target,globalBufferName); + + // update renderbuffer binding state + ctx->setRenderbufferBinding(renderbuffer); +} + +GL_API void GLAPIENTRY glDeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffers) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + for (int i=0;ishareGroup()->getGlobalName(RENDERBUFFER,renderbuffers[i]); + ctx->dispatcher().glDeleteRenderbuffersEXT(1,&globalBufferName); + } +} + +GL_API void GLAPIENTRY glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(RENDERBUFFER, 0, true); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffers[i], + ObjectDataPtr(new RenderbufferData())); + } + } +} + +GL_API void GLAPIENTRY glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height){ + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::renderbufferTarget(target) || !GLEScmValidate::renderbufferInternalFrmt(ctx,internalformat) ,GL_INVALID_ENUM); + if (internalformat==GL_RGB565_OES) //RGB565 not supported by GL + internalformat = GL_RGB8_OES; + + // Get current bounded renderbuffer + // raise INVALID_OPERATIOn if no renderbuffer is bounded + GLuint rb = ctx->getRenderbufferBinding(); + SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + SET_ERROR_IF(!rbData,GL_INVALID_OPERATION); + + // + // if the renderbuffer was an eglImage target, detach from + // the eglImage. + // + if (rbData->sourceEGLImage != 0) { + if (rbData->eglImageDetach) { + (*rbData->eglImageDetach)(rbData->sourceEGLImage); + } + rbData->sourceEGLImage = 0; + rbData->eglImageGlobalTexName = 0; + } + + ctx->dispatcher().glRenderbufferStorageEXT(target,internalformat,width,height); +} + +GL_API void GLAPIENTRY glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::renderbufferTarget(target) || !GLEScmValidate::renderbufferParams(pname) ,GL_INVALID_ENUM); + + // + // If this is a renderbuffer which is eglimage's target, we + // should query the underlying eglimage's texture object instead. + // + GLuint rb = ctx->getRenderbufferBinding(); + if (rb) { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + if (rbData && rbData->sourceEGLImage != 0) { + GLenum texPname; + switch(pname) { + case GL_RENDERBUFFER_WIDTH_OES: + texPname = GL_TEXTURE_WIDTH; + break; + case GL_RENDERBUFFER_HEIGHT_OES: + texPname = GL_TEXTURE_HEIGHT; + break; + case GL_RENDERBUFFER_INTERNAL_FORMAT_OES: + texPname = GL_TEXTURE_INTERNAL_FORMAT; + break; + case GL_RENDERBUFFER_RED_SIZE_OES: + texPname = GL_TEXTURE_RED_SIZE; + break; + case GL_RENDERBUFFER_GREEN_SIZE_OES: + texPname = GL_TEXTURE_GREEN_SIZE; + break; + case GL_RENDERBUFFER_BLUE_SIZE_OES: + texPname = GL_TEXTURE_BLUE_SIZE; + break; + case GL_RENDERBUFFER_ALPHA_SIZE_OES: + texPname = GL_TEXTURE_ALPHA_SIZE; + break; + case GL_RENDERBUFFER_DEPTH_SIZE_OES: + texPname = GL_TEXTURE_DEPTH_SIZE; + break; + case GL_RENDERBUFFER_STENCIL_SIZE_OES: + default: + *params = 0; //XXX + return; + break; + } + + GLint prevTex; + ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, + rbData->eglImageGlobalTexName); + ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, + texPname, + params); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prevTex); + return; + } + } + + ctx->dispatcher().glGetRenderbufferParameterivEXT(target,pname,params); +} + +GL_API GLboolean GLAPIENTRY glIsFramebufferOES(GLuint framebuffer) { + GET_CTX_RET(GL_FALSE) + RET_AND_SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION,GL_FALSE); + if (framebuffer && ctx->shareGroup().Ptr()) { + return ctx->shareGroup()->isObject(FRAMEBUFFER,framebuffer) ? GL_TRUE : GL_FALSE; + } + return ctx->dispatcher().glIsFramebufferEXT(framebuffer); +} + +GL_API void GLAPIENTRY glBindFramebufferOES(GLenum target, GLuint framebuffer) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) ,GL_INVALID_ENUM); + if (framebuffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(FRAMEBUFFER,framebuffer)) { + ctx->shareGroup()->genName(FRAMEBUFFER,framebuffer); + ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffer, + ObjectDataPtr(new FramebufferData(framebuffer))); + } + int globalBufferName = (framebuffer!=0) ? ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffer) : 0; + ctx->dispatcher().glBindFramebufferEXT(target,globalBufferName); + + // update framebuffer binding state + ctx->setFramebufferBinding(framebuffer); +} + +GL_API void GLAPIENTRY glDeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + for (int i=0;ishareGroup()->getGlobalName(FRAMEBUFFER,framebuffers[i]); + ctx->dispatcher().glDeleteFramebuffersEXT(1,&globalBufferName); + } +} + +GL_API void GLAPIENTRY glGenFramebuffersOES(GLsizei n, GLuint *framebuffers) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if (ctx->shareGroup().Ptr()) { + for (int i=0;ishareGroup()->genName(FRAMEBUFFER, 0, true); + ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffers[i], + ObjectDataPtr(new FramebufferData(framebuffers[i]))); + } + } +} + +GL_API GLenum GLAPIENTRY glCheckFramebufferStatusOES(GLenum target) { + GET_CTX_RET(0) + RET_AND_SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION,0); + RET_AND_SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) ,GL_INVALID_ENUM,0); + return ctx->dispatcher().glCheckFramebufferStatusEXT(target); +} + +GL_API void GLAPIENTRY glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || !GLEScmValidate::framebufferAttachment(attachment) || + !GLEScmValidate::textureTargetEx(textarget),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION); + + GLuint globalTexName = 0; + if(texture) { + if (!ctx->shareGroup()->isObject(TEXTURE,texture)) { + ctx->shareGroup()->genName(TEXTURE,texture); + } + ObjectLocalName texname = TextureLocalName(textarget,texture); + globalTexName = ctx->shareGroup()->getGlobalName(TEXTURE,texname); + } + + ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,globalTexName,level); + + // Update the the current framebuffer object attachment state + GLuint fbName = ctx->getFramebufferBinding(); + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + fbData->setAttachment(attachment, textarget, + texture, ObjectDataPtr(NULL)); + } +} + +GL_API void GLAPIENTRY glFramebufferRenderbufferOES(GLenum target, GLenum attachment,GLenum renderbuffertarget, GLuint renderbuffer) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || + !GLEScmValidate::framebufferAttachment(attachment) || + !GLEScmValidate::renderbufferTarget(renderbuffertarget), GL_INVALID_ENUM); + + SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION); + + GLuint globalBufferName = 0; + ObjectDataPtr obj; + + // generate the renderbuffer object if not yet exist + if (renderbuffer) { + if (!ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)) { + ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer); + obj = ObjectDataPtr(new RenderbufferData()); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffer, + ObjectDataPtr(new RenderbufferData())); + } + else { + obj = ctx->shareGroup()->getObjectData(RENDERBUFFER,renderbuffer); + } + globalBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer); + } + + // Update the the current framebuffer object attachment state + GLuint fbName = ctx->getFramebufferBinding(); + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + fbData->setAttachment(attachment, renderbuffertarget, renderbuffer, obj); + } + + if (renderbuffer && obj.Ptr() != NULL) { + RenderbufferData *rbData = (RenderbufferData *)obj.Ptr(); + if (rbData->sourceEGLImage != 0) { + // + // This renderbuffer object is an eglImage target + // attach the eglimage's texture instead the renderbuffer. + // + ctx->dispatcher().glFramebufferTexture2DEXT(target, + attachment, + GL_TEXTURE_2D, + rbData->eglImageGlobalTexName,0); + return; + } + } + + ctx->dispatcher().glFramebufferRenderbufferEXT(target,attachment,renderbuffertarget,globalBufferName); +} + +GL_API void GLAPIENTRY glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint *params) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || !GLEScmValidate::framebufferAttachment(attachment) || + !GLEScmValidate::framebufferAttachmentParams(pname), GL_INVALID_ENUM); + + // + // Take the attachment attribute from our state - if available + // + GLuint fbName = ctx->getFramebufferBinding(); + if (fbName) { + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + GLenum target; + GLuint name = fbData->getAttachment(attachment, &target, NULL); + if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES) { + *params = target; + return; + } + else if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES) { + *params = name; + return; + } + } + } + + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(target,attachment,pname,params); +} + +GL_API void GL_APIENTRY glGenerateMipmapOES(GLenum target) { + GET_CTX() + SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION); + SET_ERROR_IF(!GLEScmValidate::textureTargetLimited(target),GL_INVALID_ENUM); + ctx->dispatcher().glGenerateMipmapEXT(target); +} + +GL_API void GL_APIENTRY glCurrentPaletteMatrixOES(GLuint index) { + GET_CTX() + SET_ERROR_IF(!(ctx->getCaps()->GL_ARB_MATRIX_PALETTE && ctx->getCaps()->GL_ARB_VERTEX_BLEND),GL_INVALID_OPERATION); + ctx->dispatcher().glCurrentPaletteMatrixARB(index); +} + +GL_API void GL_APIENTRY glLoadPaletteFromModelViewMatrixOES() { + GET_CTX() + SET_ERROR_IF(!(ctx->getCaps()->GL_ARB_MATRIX_PALETTE && ctx->getCaps()->GL_ARB_VERTEX_BLEND),GL_INVALID_OPERATION); + GLint matrix[16]; + ctx->dispatcher().glGetIntegerv(GL_MODELVIEW_MATRIX,matrix); + ctx->dispatcher().glMatrixIndexuivARB(1,(GLuint*)matrix); + +} + +GL_API void GL_APIENTRY glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(!(ctx->getCaps()->GL_ARB_MATRIX_PALETTE && ctx->getCaps()->GL_ARB_VERTEX_BLEND),GL_INVALID_OPERATION); + ctx->dispatcher().glMatrixIndexPointerARB(size,type,stride,pointer); +} + +GL_API void GL_APIENTRY glWeightPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + GET_CTX() + SET_ERROR_IF(!(ctx->getCaps()->GL_ARB_MATRIX_PALETTE && ctx->getCaps()->GL_ARB_VERTEX_BLEND),GL_INVALID_OPERATION); + ctx->dispatcher().glWeightPointerARB(size,type,stride,pointer); + +} + +GL_API void GL_APIENTRY glTexGenfOES (GLenum coord, GLenum pname, GLfloat param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGenf(GL_S,pname,param); + ctx->dispatcher().glTexGenf(GL_T,pname,param); + ctx->dispatcher().glTexGenf(GL_R,pname,param); + } + else + ctx->dispatcher().glTexGenf(coord,pname,param); +} + +GL_API void GL_APIENTRY glTexGenfvOES (GLenum coord, GLenum pname, const GLfloat *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGenfv(GL_S,pname,params); + ctx->dispatcher().glTexGenfv(GL_T,pname,params); + ctx->dispatcher().glTexGenfv(GL_R,pname,params); + } + else + ctx->dispatcher().glTexGenfv(coord,pname,params); +} +GL_API void GL_APIENTRY glTexGeniOES (GLenum coord, GLenum pname, GLint param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGeni(GL_S,pname,param); + ctx->dispatcher().glTexGeni(GL_T,pname,param); + ctx->dispatcher().glTexGeni(GL_R,pname,param); + } + else + ctx->dispatcher().glTexGeni(coord,pname,param); +} +GL_API void GL_APIENTRY glTexGenivOES (GLenum coord, GLenum pname, const GLint *params) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGeniv(GL_S,pname,params); + ctx->dispatcher().glTexGeniv(GL_T,pname,params); + ctx->dispatcher().glTexGeniv(GL_R,pname,params); + } + else + ctx->dispatcher().glTexGeniv(coord,pname,params); +} +GL_API void GL_APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param) { + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGenf(GL_S,pname,X2F(param)); + ctx->dispatcher().glTexGenf(GL_T,pname,X2F(param)); + ctx->dispatcher().glTexGenf(GL_R,pname,X2F(param)); + } + else + ctx->dispatcher().glTexGenf(coord,pname,X2F(param)); +} +GL_API void GL_APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params) { + GLfloat tmpParams[1]; + GET_CTX() + SET_ERROR_IF(!GLEScmValidate::texGen(coord,pname),GL_INVALID_ENUM); + tmpParams[0] = X2F(params[0]); + if (coord == GL_TEXTURE_GEN_STR_OES) { + ctx->dispatcher().glTexGenfv(GL_S,pname,tmpParams); + ctx->dispatcher().glTexGenfv(GL_T,pname,tmpParams); + ctx->dispatcher().glTexGenfv(GL_R,pname,tmpParams); + } + else + ctx->dispatcher().glTexGenfv(coord,pname,tmpParams); +} + +GL_API void GL_APIENTRY glGetTexGenfvOES (GLenum coord, GLenum pname, GLfloat *params) { + GET_CTX() + if (coord == GL_TEXTURE_GEN_STR_OES) + { + GLfloat state_s = GL_FALSE; + GLfloat state_t = GL_FALSE; + GLfloat state_r = GL_FALSE; + ctx->dispatcher().glGetTexGenfv(GL_S,pname,&state_s); + ctx->dispatcher().glGetTexGenfv(GL_T,pname,&state_t); + ctx->dispatcher().glGetTexGenfv(GL_R,pname,&state_r); + *params = state_s && state_t && state_r ? GL_TRUE: GL_FALSE; + } + else + ctx->dispatcher().glGetTexGenfv(coord,pname,params); + +} +GL_API void GL_APIENTRY glGetTexGenivOES (GLenum coord, GLenum pname, GLint *params) { + GET_CTX() + if (coord == GL_TEXTURE_GEN_STR_OES) + { + GLint state_s = GL_FALSE; + GLint state_t = GL_FALSE; + GLint state_r = GL_FALSE; + ctx->dispatcher().glGetTexGeniv(GL_S,pname,&state_s); + ctx->dispatcher().glGetTexGeniv(GL_T,pname,&state_t); + ctx->dispatcher().glGetTexGeniv(GL_R,pname,&state_r); + *params = state_s && state_t && state_r ? GL_TRUE: GL_FALSE; + } + else + ctx->dispatcher().glGetTexGeniv(coord,pname,params); +} + +GL_API void GL_APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params) { + GET_CTX() + GLfloat tmpParams[1]; + + if (coord == GL_TEXTURE_GEN_STR_OES) + { + GLfloat state_s = GL_FALSE; + GLfloat state_t = GL_FALSE; + GLfloat state_r = GL_FALSE; + ctx->dispatcher().glGetTexGenfv(GL_TEXTURE_GEN_S,pname,&state_s); + ctx->dispatcher().glGetTexGenfv(GL_TEXTURE_GEN_T,pname,&state_t); + ctx->dispatcher().glGetTexGenfv(GL_TEXTURE_GEN_R,pname,&state_r); + tmpParams[0] = state_s && state_t && state_r ? GL_TRUE: GL_FALSE; + } + else + ctx->dispatcher().glGetTexGenfv(coord,pname,tmpParams); + + params[0] = F2X(tmpParams[1]); +} + +template +void glDrawTexOES (T x, T y, T z, T width, T height) { + GET_CTX() + + SET_ERROR_IF((width<=0 || height<=0),GL_INVALID_VALUE); + + ctx->drawValidate(); + + int numClipPlanes; + + GLint viewport[4] = {}; + z = (z>1 ? 1 : (z<0 ? 0 : z)); + + T vertices[4*3] = { + x , y, z, + x , static_cast(y+height), z, + static_cast(x+width), static_cast(y+height), z, + static_cast(x+width), y, z + }; + GLfloat texels[ctx->getMaxTexUnits()][4*2]; + memset((void*)texels, 0, ctx->getMaxTexUnits()*4*2*sizeof(GLfloat)); + + ctx->dispatcher().glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + ctx->dispatcher().glPushAttrib(GL_TRANSFORM_BIT); + + //setup projection matrix to draw in viewport aligned coordinates + ctx->dispatcher().glMatrixMode(GL_PROJECTION); + ctx->dispatcher().glPushMatrix(); + ctx->dispatcher().glLoadIdentity(); + ctx->dispatcher().glGetIntegerv(GL_VIEWPORT,viewport); + ctx->dispatcher().glOrtho(viewport[0],viewport[0] + viewport[2],viewport[1],viewport[1]+viewport[3],0,-1); + //setup texture matrix + ctx->dispatcher().glMatrixMode(GL_TEXTURE); + ctx->dispatcher().glPushMatrix(); + ctx->dispatcher().glLoadIdentity(); + //setup modelview matrix + ctx->dispatcher().glMatrixMode(GL_MODELVIEW); + ctx->dispatcher().glPushMatrix(); + ctx->dispatcher().glLoadIdentity(); + //backup vbo's + int array_buffer,element_array_buffer; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING,&array_buffer); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,&element_array_buffer); + ctx->dispatcher().glBindBuffer(GL_ARRAY_BUFFER,0); + ctx->dispatcher().glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + + //disable clip planes + ctx->dispatcher().glGetIntegerv(GL_MAX_CLIP_PLANES,&numClipPlanes); + for (int i=0;idispatcher().glDisable(GL_CLIP_PLANE0+i); + + int nTexPtrs = 0; + for (int i=0;igetMaxTexUnits();++i) { + if (ctx->isTextureUnitEnabled(GL_TEXTURE0+i)) { + TextureData * texData = NULL; + unsigned int texname = ctx->getBindedTexture(GL_TEXTURE0+i,GL_TEXTURE_2D); + ObjectLocalName tex = TextureLocalName(GL_TEXTURE_2D,texname); + ctx->dispatcher().glClientActiveTexture(GL_TEXTURE0+i); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(TEXTURE,tex); + if (objData.Ptr()) { + texData = (TextureData*)objData.Ptr(); + //calculate texels + texels[i][0] = (float)(texData->crop_rect[0])/(float)(texData->width); + texels[i][1] = (float)(texData->crop_rect[1])/(float)(texData->height); + + texels[i][2] = (float)(texData->crop_rect[0])/(float)(texData->width); + texels[i][3] = (float)(texData->crop_rect[3]+texData->crop_rect[1])/(float)(texData->height); + + texels[i][4] = (float)(texData->crop_rect[2]+texData->crop_rect[0])/(float)(texData->width); + texels[i][5] = (float)(texData->crop_rect[3]+texData->crop_rect[1])/(float)(texData->height); + + texels[i][6] = (float)(texData->crop_rect[2]+texData->crop_rect[0])/(float)(texData->width); + texels[i][7] = (float)(texData->crop_rect[1])/(float)(texData->height); + + ctx->dispatcher().glTexCoordPointer(2,GL_FLOAT,0,texels[i]); + nTexPtrs++; + } + } + } + + if (nTexPtrs>0) { + //draw rectangle - only if we have some textures enabled & ready + ctx->dispatcher().glEnableClientState(GL_VERTEX_ARRAY); + ctx->dispatcher().glVertexPointer(3,TypeName,0,vertices); + ctx->dispatcher().glEnableClientState(GL_TEXTURE_COORD_ARRAY); + ctx->dispatcher().glDrawArrays(GL_TRIANGLE_FAN,0,4); + } + + //restore vbo's + ctx->dispatcher().glBindBuffer(GL_ARRAY_BUFFER,array_buffer); + ctx->dispatcher().glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,element_array_buffer); + + //restore matrix state + + ctx->dispatcher().glMatrixMode(GL_MODELVIEW); + ctx->dispatcher().glPopMatrix(); + ctx->dispatcher().glMatrixMode(GL_TEXTURE); + ctx->dispatcher().glPopMatrix(); + ctx->dispatcher().glMatrixMode(GL_PROJECTION); + ctx->dispatcher().glPopMatrix(); + + ctx->dispatcher().glPopAttrib(); + ctx->dispatcher().glPopClientAttrib(); +} + +GL_API void GL_APIENTRY glDrawTexsOES (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) { + glDrawTexOES(x,y,z,width,height); +} + +GL_API void GL_APIENTRY glDrawTexiOES (GLint x, GLint y, GLint z, GLint width, GLint height) { + glDrawTexOES(x,y,z,width,height); +} + +GL_API void GL_APIENTRY glDrawTexfOES (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) { + glDrawTexOES(x,y,z,width,height); +} + +GL_API void GL_APIENTRY glDrawTexxOES (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) { + glDrawTexOES(X2F(x),X2F(y),X2F(z),X2F(width),X2F(height)); +} + +GL_API void GL_APIENTRY glDrawTexsvOES (const GLshort * coords) { + glDrawTexOES(coords[0],coords[1],coords[2],coords[3],coords[4]); +} + +GL_API void GL_APIENTRY glDrawTexivOES (const GLint * coords) { + glDrawTexOES(coords[0],coords[1],coords[2],coords[3],coords[4]); +} + +GL_API void GL_APIENTRY glDrawTexfvOES (const GLfloat * coords) { + glDrawTexOES(coords[0],coords[1],coords[2],coords[3],coords[4]); +} + +GL_API void GL_APIENTRY glDrawTexxvOES (const GLfixed * coords) { + glDrawTexOES(X2F(coords[0]),X2F(coords[1]),X2F(coords[2]),X2F(coords[3]),X2F(coords[4])); +} diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.cpp b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.cpp new file mode 100644 index 0000000..891b4e3 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.cpp @@ -0,0 +1,101 @@ +/* +* 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 "GLEScmUtils.h" + + +size_t glParamSize(GLenum param) +{ + size_t s = 0; + + switch(param) + { + case GL_MAX_TEXTURE_SIZE: + //case GL_TEXTURE_GEN_MODE_OES: + case GL_TEXTURE_ENV_MODE: + case GL_FOG_MODE: + case GL_FOG_DENSITY: + case GL_FOG_START: + case GL_FOG_END: + case GL_SPOT_EXPONENT: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + case GL_SHININESS: + case GL_LIGHT_MODEL_TWO_SIDE: + case GL_POINT_SIZE: + case GL_POINT_SIZE_MIN: + case GL_POINT_SIZE_MAX: + case GL_POINT_FADE_THRESHOLD_SIZE: + case GL_CULL_FACE_MODE: + case GL_FRONT_FACE: + case GL_SHADE_MODEL: + case GL_DEPTH_WRITEMASK: + case GL_DEPTH_CLEAR_VALUE: + case GL_STENCIL_FAIL: + case GL_STENCIL_PASS_DEPTH_FAIL: + case GL_STENCIL_PASS_DEPTH_PASS: + case GL_STENCIL_REF: + case GL_STENCIL_WRITEMASK: + case GL_MATRIX_MODE: + case GL_MODELVIEW_STACK_DEPTH: + case GL_PROJECTION_STACK_DEPTH: + case GL_TEXTURE_STACK_DEPTH: + case GL_ALPHA_TEST_FUNC: + case GL_ALPHA_TEST_REF: + case GL_BLEND_DST: + case GL_BLEND_SRC: + case GL_LOGIC_OP_MODE: + case GL_SCISSOR_TEST: + case GL_MAX_TEXTURE_UNITS: + s = 1; + break; + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_DEPTH_RANGE: + case GL_MAX_VIEWPORT_DIMS: + case GL_SMOOTH_POINT_SIZE_RANGE: + case GL_SMOOTH_LINE_WIDTH_RANGE: + s= 2; + break; + case GL_SPOT_DIRECTION: + case GL_POINT_DISTANCE_ATTENUATION: + case GL_CURRENT_NORMAL: + s = 3; + break; + case GL_CURRENT_TEXTURE_COORDS: + case GL_CURRENT_COLOR: + case GL_FOG_COLOR: + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + case GL_POSITION: + case GL_LIGHT_MODEL_AMBIENT: + case GL_TEXTURE_ENV_COLOR: + case GL_SCISSOR_BOX: + case GL_VIEWPORT: + //case GL_TEXTURE_CROP_RECT_OES: + s = 4; + break; + case GL_MODELVIEW_MATRIX: + case GL_PROJECTION_MATRIX: + case GL_TEXTURE_MATRIX: + s = 16; + default: + s = 1; // assume 1 + } + return s; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.h b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.h new file mode 100644 index 0000000..38ad6bc --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmUtils.h @@ -0,0 +1,22 @@ +/* +* 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 GLES_UTILS_H +#define GLES_UTILS_H +#include +#include + +size_t glParamSize(GLenum param); +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.cpp b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.cpp new file mode 100644 index 0000000..24e4dcf --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.cpp @@ -0,0 +1,306 @@ +/* +* 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 "GLEScmValidate.h" +#include +#include +#include +#include +#include "GLEScmValidate.h" + + +bool GLEScmValidate::lightEnum(GLenum e,unsigned int maxLights) { + return e >=GL_LIGHT0 && e <= (GL_LIGHT0+maxLights); +} + +bool GLEScmValidate::clipPlaneEnum(GLenum e,unsigned int maxClipPlanes) { + return e >=GL_CLIP_PLANE0 && e <= (GL_CLIP_PLANE0+maxClipPlanes); +} + +bool GLEScmValidate::alphaFunc(GLenum f) { + switch(f) { + case GL_NEVER: + case GL_LESS: + case GL_EQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_GEQUAL: + case GL_ALWAYS: + return true; + } + return false; +} + +bool GLEScmValidate::blendSrc(GLenum s) { + switch(s) { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + return true; + } + return false; +} + +bool GLEScmValidate::vertexPointerParams(GLint size,GLsizei stride) { + return ((size >=2) && (size <= 4)) && (stride >=0) ; +} + +bool GLEScmValidate::colorPointerParams(GLint size,GLsizei stride) { + return (size == 4) && (stride >=0) ; +} + +bool GLEScmValidate::texCoordPointerParams(GLint size,GLsizei stride) { + return ((size >=2) && (size <= 4)) && (stride >=0) ; +} + +bool GLEScmValidate::supportedArrays(GLenum arr) { + switch(arr) { + case GL_COLOR_ARRAY: + case GL_NORMAL_ARRAY: + case GL_POINT_SIZE_ARRAY_OES: + case GL_TEXTURE_COORD_ARRAY: + case GL_VERTEX_ARRAY: + return true; + } + return false; +} + +bool GLEScmValidate::hintTargetMode(GLenum target,GLenum mode) { + switch(target) { + case GL_FOG_HINT: + case GL_GENERATE_MIPMAP_HINT: + case GL_LINE_SMOOTH_HINT: + case GL_PERSPECTIVE_CORRECTION_HINT: + case GL_POINT_SMOOTH_HINT: + break; + default: return false; + } + switch(mode) { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: return false; + } + return true; +} + +bool GLEScmValidate::texParams(GLenum target,GLenum pname) { + switch(pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_CROP_RECT_OES: + case GL_GENERATE_MIPMAP: + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + break; + default: + return false; + } + return (target == GL_TEXTURE_2D)||(target == GL_TEXTURE_CUBE_MAP_OES); +} + +bool GLEScmValidate::texEnv(GLenum target,GLenum pname) { + switch(pname) { + case GL_TEXTURE_ENV_MODE: + case GL_TEXTURE_ENV_COLOR: + case GL_COMBINE_RGB: + case GL_COMBINE_ALPHA: + case GL_SRC0_RGB: + case GL_SRC1_RGB: + case GL_SRC2_RGB: + case GL_SRC0_ALPHA: + case GL_SRC1_ALPHA: + case GL_SRC2_ALPHA: + case GL_OPERAND0_RGB: + case GL_OPERAND1_RGB: + case GL_OPERAND2_RGB: + case GL_OPERAND0_ALPHA: + case GL_OPERAND1_ALPHA: + case GL_OPERAND2_ALPHA: + case GL_RGB_SCALE: + case GL_ALPHA_SCALE: + case GL_COORD_REPLACE_OES: + break; + default: + return false; + } + return (target == GL_TEXTURE_ENV || target == GL_POINT_SPRITE_OES); +} + +bool GLEScmValidate::capability(GLenum cap,int maxLights,int maxClipPlanes) { + switch(cap) { + case GL_ALPHA_TEST: + case GL_BLEND: + case GL_COLOR_ARRAY: + case GL_COLOR_LOGIC_OP: + case GL_COLOR_MATERIAL: + case GL_CULL_FACE: + case GL_DEPTH_TEST: + case GL_DITHER: + case GL_FOG: + case GL_LIGHTING: + case GL_LINE_SMOOTH: + case GL_MULTISAMPLE: + case GL_NORMAL_ARRAY: + case GL_NORMALIZE: + case GL_POINT_SIZE_ARRAY_OES: + case GL_POINT_SMOOTH: + case GL_POINT_SPRITE_OES: + case GL_POLYGON_OFFSET_FILL: + case GL_RESCALE_NORMAL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_ALPHA_TO_ONE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_TEXTURE_2D: + case GL_TEXTURE_COORD_ARRAY: + case GL_VERTEX_ARRAY: + return true; + } + return GLEScmValidate::lightEnum(cap,maxLights) || GLEScmValidate::clipPlaneEnum(cap,maxClipPlanes); +} + + +bool GLEScmValidate::texCompImgFrmt(GLenum format) { + switch(format) { + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + return true; + } + return false; +} + +bool GLEScmValidate::blendDst(GLenum d) { + switch(d) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + return true; + } + return false; +} + +bool GLEScmValidate::renderbufferInternalFrmt(GLEScontext* ctx, GLenum internalformat) +{ + switch (internalformat) { + case GL_DEPTH_COMPONENT16_OES: + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGB565_OES: + case GL_STENCIL_INDEX1_OES: + case GL_STENCIL_INDEX4_OES: + case GL_STENCIL_INDEX8_OES: + case GL_RGB8_OES: + case GL_RGBA8_OES: + case GL_DEPTH_COMPONENT24_OES: + case GL_DEPTH_COMPONENT32_OES: + return true; + } + if (ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL && internalformat==GL_DEPTH24_STENCIL8_OES) + return true; + + return false; +} + +bool GLEScmValidate::stencilOp(GLenum param) { + switch (param) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_OES: + case GL_DECR_WRAP_OES: + return true; + } + return false; +} + +bool GLEScmValidate::texGen(GLenum coord, GLenum pname) { + return (coord == GL_TEXTURE_GEN_STR_OES && pname == GL_TEXTURE_GEN_MODE_OES); +} + +bool GLEScmValidate::colorPointerType(GLenum type){ + switch(type){ + case GL_UNSIGNED_BYTE: + case GL_FIXED: + case GL_FLOAT: + return true; + } + return false; +} + +bool GLEScmValidate::normalPointerType(GLenum type){ + + switch(type){ + case GL_BYTE: + case GL_SHORT: + case GL_FLOAT: + case GL_FIXED: + return true; + } + return false; +} + +bool GLEScmValidate::pointPointerType(GLenum type){ + return type == GL_FIXED || type == GL_FLOAT; +} + +bool GLEScmValidate::texCoordPointerType(GLenum type){ + switch(type){ + case GL_BYTE: + case GL_SHORT: + case GL_FLOAT: + case GL_FIXED: + return true; + } + return false; +} + +bool GLEScmValidate::vertexPointerType(GLenum type){ + switch(type){ + case GL_BYTE: + case GL_SHORT: + case GL_FLOAT: + case GL_FIXED: + return true; + } + return false; +} + diff --git a/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.h b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.h new file mode 100644 index 0000000..9bc3393 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_CM/GLEScmValidate.h @@ -0,0 +1,50 @@ +/* +* 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 GLES_CM_VALIDATE_H +#define GLES_CM_VALIDATE_H + +#include +#include +struct GLEScmValidate : public GLESvalidate +{ +static bool blendSrc(GLenum s); +static bool blendDst(GLenum d); +static bool lightEnum(GLenum e,unsigned int maxLIghts); +static bool clipPlaneEnum(GLenum e,unsigned int maxClipPlanes); +static bool alphaFunc(GLenum f); +static bool vertexPointerParams(GLint size,GLsizei stride); +static bool colorPointerParams(GLint size,GLsizei stride); +static bool supportedArrays(GLenum arr); +static bool hintTargetMode(GLenum target,GLenum mode); +static bool capability(GLenum cap,int maxLights,int maxClipPlanes); +static bool texParams(GLenum target,GLenum pname); +static bool texCoordPointerParams(GLint size,GLsizei stride); + +static bool texEnv(GLenum target,GLenum pname); +static bool texCompImgFrmt(GLenum format); + +static bool renderbufferInternalFrmt(GLEScontext * ctx, GLenum internalformat); +static bool stencilOp(GLenum param); +static bool texGen(GLenum coord,GLenum pname); + +static bool colorPointerType(GLenum type); +static bool normalPointerType(GLenum type); +static bool pointPointerType(GLenum type); +static bool texCoordPointerType(GLenum type); +static bool vertexPointerType(GLenum type); +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp b/external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..8102470c466227658d4ea2ddf8c32b58a732f10d GIT binary patch literal 16384 zcmeHNS&Sn`8E&qG1#&0>lsrIcy%N}i$DVZ}j%;Ry$I~;h@Yu%3&Mv#bX}8Os-n6?r z-R+rKuJ8aMZ#6 z7l{a^t^L-X{{Q;>udn_({;KLP9jR`xcNDHs@VQh`w8t8om%q(#+n? zd^{-*49|Cs{B2NLqXN_k((-}I_@`M*ec$lomq`JWTzA56&qB;|&* zzkEU5{^L^KlJYMku9FmC@3QXcyM)r9;}DL*dl?|XH;{Anpa zBISdGTsDW2m-2fOa``y@N*PEQNEt{ONEt{ONEt{ONEt{ONE!IQWk5qhwh!JvOo=Sc z|HJ(MnM)MqKH$f|$AJ~#3gC^v>5CQR_rP7i4Zvl<{TC_9SAZ`8Uj#k_+zM#GJAs41 z67YK9nb#@G?||O|_W+*)c7YSX3XlUX0DkjYMR^3cANVQo1K|6>*MK{KV?Y)-{TfBN z7tnz|a3jzI9z(@`0qg)x;9=x+4*}l=ZU=4#RNyM$3FMRa0iOeWpaxWd>w&idZvn0Z zt^l4z?s_lqE#Mo#*8vY`0SAHSkURep_%d)ea2K!xYyw@N17v{9fJ=c(fS)6u{}J$c z;IqJ|fjfbB0SAD6z^{;`eh2s@-~h|O60i^W5cVsm4Ic_OBq$=8{A3rr-pJ&hic1xi zXV{jPJDwSt>Uym@)<(Rexg+kkxHaHze=;0$w~d<=5H!?w=7!~LujfziS8Pl?zoL15 z$8Nf|!`-!srTehhv<(Y4Hae#qo_k@I51pHP9oz_+xV*F~oMOxDzjiBXapnwBmSk)3 zux@hA&E{rm-1PXg0(+H#hZf&qU`g+2eUoo!PPDu+WZC`6_vEG)9Te;NRIX=OhHq%5 z@c}-7P2ZjHzzbnvZ@nD*ps?imns4Z=Z`&r@TN4(C8mbbQ)cxJX!w7|S)9!0#&DL)U zU0zo^y-Me3ucdaf^=_?}Q>5*4j130sL`iutaJlDYb;P32^exR@5FXaGF(>bp4~q%} z{}a8!HIMsksPc8!o;cZ&>&ON%hFQp|ob+lNSBqF&o9+eSZ9c+ifvn|cmYTlH$k^2GessyI8NwX0nE=RyxA__=ryA+mz*V4~;X_sq0j~XXqNg_t(ieU|8 z?Beykj(W7yZK=IVcSY@Ol$-gbNSK~cyR;h96ZBG~WxXCBnbo1D^TosXwNBAcGy1OP zp33GTmPLs;#nA>qbO$!Q>MVX?Akjwj%8-^g8E0vsfZQN#S69}vnYzt9hwJDmY}#WG z{Wdj#j!=XD3^&Udy#@EfPFR^)Gl+1ZQY75XiZ%=`ps`FPLt$~iuyk`W;Ox5fnr@GA zFHT%A8*932dxfpT2-v`vLOj4Jbe9uBuh7Fnj5>M(z1Xw7LJtc=_~mWU&+vnxZ>?Le zG&?Pfv}-~f>Y9_dDr`n|Ni0?8A{nZ4&!jFfBO6Kjuq-&1&!m=~3}0BBdls=MxDM+C z-6{Y1Xzws662lQ$ge6p`{TwrxP*@<1Fm9nhL)0NfDK7kvKShNGw{W~?bJOnBH6Qcj zfDf7H53ap-tU1?-A9Tsl8s*tJ4yuP^v&!DEK`zs;9e#g9-hG(jmGC!>FRx z+to(B&CZ*|B8}r=Yo24J5}ju6nc@Wxq*KN7n;GK8=laR~ED$dc=|FR;d(1=gh2^+J zO*`ONi@0KBQl;oo0{u!x3CqJkpJ7IBUr@@Fvaa9lVeFtG#hJY_j|<<5O?UhhQqCqS+PM) zB^aAk*R|c6J({CHZI_B8vjpCf)s_@ zrZF~XNk{#fO1KP{rdiFl@t;+bp+Q<$9;8wppXaDvkPTwIc?E#u_WvkFobu>#KRj4Z69_ zP+wZnF-)<>*f9-0Acy3|?TL@Y>zv2T!0;5@>=p``t2K*d%57F{XV^-)U2W%KqiZ2` z@tDhRo)|9d^iMI(!5eg19-~G(^iFN$a>#re^9b8T(Q;sx6s;r_T_&nwod6%2UlVyUns)Q{N{Hr7rtyYFkTsWIJl@YgU#u;#2pbA_G`~>;@ZNO1r6KDb#0~Z31Acwyj zxCuB3=)l{6N0GDN1AG&>9XJk@fTxkOKLFeYyc>8s@Hq1JyMY^lHvp&M=Uo5?jssnQ zd~X5iCuJaIAY~wBAY~wB;6-B~xnnik#G7XOXa9l4W@(ug3 zgKWLax^!Mm zoAm8PZ|3#d1cw*cf2NSb7L8yB`*;yXXwMZHMYtVKtywGv8I5_0vM3)ZC5|V;`~cA~ zC5aRr%6rA4e>ls&SrBz&Y}GJ_&QB1vdr`2hnk=`KcGCKT2ovjGn;t(xX*)|SM)K;s}>Q&dW`-3Xv(YdSjBjs9kwby8>tukfQ za+r&rz=>Ba1ZCiAc3zgV`zJ}Ofa8lWE*qk)=_#FQNCgxZ5$(;6PIBUyXQrKPsr6O0 z6%3epw=W%vRlx1D?0O4O0tJcKEQ>iN zjK8cwy_BL)mY(2bc4T1>g9d`B5N6uikaw#Vh9i3{k6DAld$p1;!jPsm1X{FJdpI|Z LI + +void GLESv2Context::init(GlLibrary* glLib) { + emugl::Mutex::AutoLock mutex(s_lock); + if(!m_initialized) { + s_glDispatch.dispatchFuncs(GLES_2_0, glLib); + GLEScontext::init(glLib); + for(int i=0; i < s_glSupport.maxVertexAttribs;i++){ + m_map[i] = new GLESpointer(); + } + setAttribute0value(0.0, 0.0, 0.0, 1.0); + + buildStrings((const char*)dispatcher().glGetString(GL_VENDOR), + (const char*)dispatcher().glGetString(GL_RENDERER), + (const char*)dispatcher().glGetString(GL_VERSION), + "OpenGL ES 2.0"); + } + m_initialized = true; +} + +GLESv2Context::GLESv2Context():GLEScontext(), m_att0Array(NULL), m_att0ArrayLength(0), m_att0NeedsDisable(false){}; + +GLESv2Context::~GLESv2Context() +{ + delete[] m_att0Array; +} + +void GLESv2Context::setAttribute0value(float x, float y, float z, float w) +{ + m_attribute0value[0] = x; + m_attribute0value[1] = y; + m_attribute0value[2] = z; + m_attribute0value[3] = w; +} + +void GLESv2Context::validateAtt0PreDraw(unsigned int count) +{ + m_att0NeedsDisable = false; + + if(count == 0) + return; + + int enabled = 0; + s_glDispatch.glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled); + if(enabled) + return; + + if(count > m_att0ArrayLength) + { + delete [] m_att0Array; + m_att0Array = new GLfloat[4*count]; + m_att0ArrayLength = count; + } + + for(unsigned int i=0; igetSize(); + + if(needConvert(cArrs,first,count,type,indices,direct,p,array_id)){ + //conversion has occured + ArrayData currentArr = cArrs.getCurrentArray(); + setupArr(currentArr.data,array_id,currentArr.type,size,currentArr.stride, p->getNormalized()); + ++cArrs; + } else { + setupArr(p->getData(),array_id,p->getType(), + size,p->getStride(), p->getNormalized()); + } + } +} + +//setting client side arr +void GLESv2Context::setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int index){ + if(arr == NULL) return; + s_glDispatch.glVertexAttribPointer(arrayType,size,dataType,normalized,stride,arr); +} + +bool GLESv2Context::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) { + + bool usingVBO = p->isVBO(); + GLenum arrType = p->getType(); + /* + conversion is not necessary in the following cases: + (*) array type is not fixed + */ + if(arrType != GL_FIXED) return false; + + if(!usingVBO) { + if (direct) { + convertDirect(cArrs,first,count,array_id,p); + } else { + convertIndirect(cArrs,count,type,indices,array_id,p); + } + } else { + if (direct) { + convertDirectVBO(cArrs,first,count,array_id,p) ; + } else { + convertIndirectVBO(cArrs,count,type,indices,array_id,p); + } + } + return true; +} + +void GLESv2Context::initExtensionString() { + *s_glExtensions = "GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_depth24 GL_OES_depth32 GL_OES_element_index_uint " + "GL_OES_texture_float GL_OES_texture_float_linear " + "GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture "; + if (s_glSupport.GL_ARB_HALF_FLOAT_PIXEL || s_glSupport.GL_NV_HALF_FLOAT) + *s_glExtensions+="GL_OES_texture_half_float GL_OES_texture_half_float_linear "; + if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL) + *s_glExtensions+="GL_OES_packed_depth_stencil "; + if (s_glSupport.GL_ARB_HALF_FLOAT_VERTEX) + *s_glExtensions+="GL_OES_vertex_half_float "; + if (s_glSupport.GL_OES_STANDARD_DERIVATIVES) + *s_glExtensions+="GL_OES_standard_derivatives "; + if (s_glSupport.GL_OES_TEXTURE_NPOT) + *s_glExtensions+="GL_OES_texture_npot "; + if (s_glSupport.GL_OES_RGB8_RGBA8) { + *s_glExtensions+="GL_OES_rgb8_rgba8 "; + } +} + +int GLESv2Context::getMaxTexUnits() { + return getCaps()->maxTexImageUnits; +} + +int GLESv2Context::getMaxCombinedTexUnits() { + // GLES spec requires only 2, and the ATI driver erronously + // returns 32 (although it supports only 16). This WAR is simple, + // compliant and good enough for developers. + if (getCaps()->maxCombinedTexImageUnits > 16) + return 16; + return getCaps()->maxCombinedTexImageUnits; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Context.h b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Context.h new file mode 100644 index 0000000..daacb0d --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Context.h @@ -0,0 +1,54 @@ +/* +* Copyright 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 GLES_V2_CONTEXT_H +#define GLES_V2_CONTEXT_H + +#include +#include +#include + +class GLESv2Context : public GLEScontext{ +public: + virtual void init(GlLibrary* glLib); + GLESv2Context(); + virtual ~GLESv2Context(); + void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct); + int getMaxCombinedTexUnits(); + int getMaxTexUnits(); + + // This whole att0 thing is about a incompatibility between GLES and OpenGL. + // GLES allows a vertex shader attribute to be in location 0 and have a + // current value, while OpenGL is not very clear about this, which results + // in each implementation doing something different. + void setAttribute0value(float x, float y, float z, float w); + void validateAtt0PreDraw(unsigned int count); + void validateAtt0PostDraw(void); + const float* getAtt0(void) {return m_attribute0value;} + +protected: + bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id); +private: + void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1); + void initExtensionString(); + + float m_attribute0value[4]; + GLfloat* m_att0Array; + unsigned int m_att0ArrayLength; + bool m_att0NeedsDisable; +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp new file mode 100644 index 0000000..3e24516 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp @@ -0,0 +1,2277 @@ +/* +* 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. +*/ + +#ifdef _WIN32 +#undef GL_APICALL +#define GL_API __declspec(dllexport) +#define GL_APICALL __declspec(dllexport) +#endif + +#define GL_GLEXT_PROTOTYPES +#include +#include + +#include +#include +#include "GLESv2Context.h" +#include "GLESv2Validate.h" +#include "ShaderParser.h" +#include "ProgramData.h" +#include +#include + +#include + +extern "C" { + +//decleration +static void initGLESx(); +static void initContext(GLEScontext* ctx,ShareGroupPtr grp); +static void deleteGLESContext(GLEScontext* ctx); +static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp); +static GLEScontext* createGLESContext(); +static __translatorMustCastToProperFunctionPointerType getProcAddress(const char* procName); + +} + +/************************************** GLES EXTENSIONS *********************************************************/ +//extentions descriptor +typedef std::map ProcTableMap; +ProcTableMap *s_glesExtensions = NULL; +/****************************************************************************************************************/ + +static EGLiface* s_eglIface = NULL; +static GLESiface s_glesIface = { + .initGLESx = initGLESx, + .createGLESContext = createGLESContext, + .initContext = initContext, + .deleteGLESContext = deleteGLESContext, + .flush = (FUNCPTR)glFlush, + .finish = (FUNCPTR)glFinish, + .setShareGroup = setShareGroup, + .getProcAddress = getProcAddress +}; + +#include + +extern "C" { + +static void initGLESx() { + DBG("No special initialization necessary for GLES_V2\n"); + return; +} + +static void initContext(GLEScontext* ctx,ShareGroupPtr grp) { + if (!ctx->isInitialized()) { + ctx->setShareGroup(grp); + ctx->init(s_eglIface->eglGetGlLibrary()); + glBindTexture(GL_TEXTURE_2D,0); + glBindTexture(GL_TEXTURE_CUBE_MAP,0); + } +} +static GLEScontext* createGLESContext() { + return new GLESv2Context(); +} + +static void deleteGLESContext(GLEScontext* ctx) { + delete ctx; +} + +static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp) { + if(ctx) { + ctx->setShareGroup(grp); + } +} + +static __translatorMustCastToProperFunctionPointerType getProcAddress(const char* procName) { + GET_CTX_RET(NULL) + ctx->getGlobalLock(); + static bool proc_table_initialized = false; + if (!proc_table_initialized) { + proc_table_initialized = true; + if (!s_glesExtensions) + s_glesExtensions = new ProcTableMap(); + else + s_glesExtensions->clear(); + (*s_glesExtensions)["glEGLImageTargetTexture2DOES"] = (__translatorMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES; + (*s_glesExtensions)["glEGLImageTargetRenderbufferStorageOES"]=(__translatorMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES; + } + __translatorMustCastToProperFunctionPointerType ret=NULL; + ProcTableMap::iterator val = s_glesExtensions->find(procName); + if (val!=s_glesExtensions->end()) + ret = val->second; + ctx->releaseGlobalLock(); + + return ret; +} + +GL_APICALL GLESiface* GL_APIENTRY __translator_getIfaces(EGLiface* eglIface); + +GLESiface* __translator_getIfaces(EGLiface* eglIface) { + s_eglIface = eglIface; + return & s_glesIface; +} + +} // extern "C" + +static void s_attachShader(GLEScontext* ctx, GLuint program, GLuint shader) { + if (ctx && program && shader && ctx->shareGroup().Ptr()) { + ObjectDataPtr shaderData = ctx->shareGroup()->getObjectData(SHADER,shader); + if (!shaderData.Ptr()) return; + ShaderParser* shaderParser = (ShaderParser*)shaderData.Ptr(); + shaderParser->setAttachedProgram(program); + } +} + +static void s_detachShader(GLEScontext* ctx, GLuint shader) { + if (ctx && shader && ctx->shareGroup().Ptr()) { + ObjectDataPtr shaderData = ctx->shareGroup()->getObjectData(SHADER,shader); + if (!shaderData.Ptr()) return; + ShaderParser* shaderParser = (ShaderParser*)shaderData.Ptr(); + shaderParser->setAttachedProgram(0); + if (shaderParser->getDeleteStatus()) { + ctx->shareGroup()->deleteName(SHADER, shader); + } + } +} + +static ObjectLocalName TextureLocalName(GLenum target,unsigned int tex) { + GET_CTX_RET(0); + return (tex!=0? tex : ctx->getDefaultTextureName(target)); +} + +static TextureData* getTextureData(ObjectLocalName tex) { + GET_CTX_RET(NULL); + TextureData *texData = NULL; + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(TEXTURE,tex); + if(!objData.Ptr()){ + texData = new TextureData(); + ctx->shareGroup()->setObjectData(TEXTURE, tex, ObjectDataPtr(texData)); + } else { + texData = (TextureData*)objData.Ptr(); + } + return texData; +} + +static TextureData* getTextureTargetData(GLenum target){ + GET_CTX_RET(NULL); + unsigned int tex = ctx->getBindedTexture(target); + return getTextureData(TextureLocalName(target,tex)); +} + +GL_APICALL void GL_APIENTRY glActiveTexture(GLenum texture){ + GET_CTX_V2(); + SET_ERROR_IF (!GLESv2Validate::textureEnum(texture,ctx->getMaxCombinedTexUnits()),GL_INVALID_ENUM); + ctx->setActiveTexture(texture); + ctx->dispatcher().glActiveTexture(texture); +} + +GL_APICALL void GL_APIENTRY glAttachShader(GLuint program, GLuint shader){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + + ObjectDataPtr programData = ctx->shareGroup()->getObjectData(SHADER,program); + ObjectDataPtr shaderData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!shaderData.Ptr() || !programData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(!(shaderData.Ptr()->getDataType() ==SHADER_DATA) || + !(programData.Ptr()->getDataType()==PROGRAM_DATA) ,GL_INVALID_OPERATION); + + GLenum shaderType = ((ShaderParser*)shaderData.Ptr())->getType(); + ProgramData* pData = (ProgramData*)programData.Ptr(); + SET_ERROR_IF((pData->getAttachedShader(shaderType)!=0), GL_INVALID_OPERATION); + pData->attachShader(shader,shaderType); + s_attachShader(ctx, program, shader); + ctx->dispatcher().glAttachShader(globalProgramName,globalShaderName); + } +} + +GL_APICALL void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::attribName(name),GL_INVALID_OPERATION); + SET_ERROR_IF(!GLESv2Validate::attribIndex(index),GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + + ctx->dispatcher().glBindAttribLocation(globalProgramName,index,name); + } +} + +GL_APICALL void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::bufferTarget(target),GL_INVALID_ENUM); + //if buffer wasn't generated before,generate one + if(buffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(VERTEXBUFFER,buffer)){ + ctx->shareGroup()->genName(VERTEXBUFFER,buffer); + ctx->shareGroup()->setObjectData(VERTEXBUFFER,buffer,ObjectDataPtr(new GLESbuffer())); + } + ctx->bindBuffer(target,buffer); + if (buffer) { + GLESbuffer* vbo = (GLESbuffer*)ctx->shareGroup()->getObjectData(VERTEXBUFFER,buffer).Ptr(); + vbo->setBinded(); + } +} + +GL_APICALL void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::framebufferTarget(target),GL_INVALID_ENUM); + + GLuint globalFrameBufferName = framebuffer; + if(framebuffer && ctx->shareGroup().Ptr()){ + globalFrameBufferName = ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffer); + //if framebuffer wasn't generated before,generate one + if(!globalFrameBufferName){ + ctx->shareGroup()->genName(FRAMEBUFFER,framebuffer); + ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffer, + ObjectDataPtr(new FramebufferData(framebuffer))); + globalFrameBufferName = ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffer); + } + } + ctx->dispatcher().glBindFramebufferEXT(target,globalFrameBufferName); + + // update framebuffer binding state + ctx->setFramebufferBinding(framebuffer); +} + +GL_APICALL void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::renderbufferTarget(target),GL_INVALID_ENUM); + + GLuint globalRenderBufferName = renderbuffer; + if(renderbuffer && ctx->shareGroup().Ptr()){ + globalRenderBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer); + //if renderbuffer wasn't generated before,generate one + if(!globalRenderBufferName){ + ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffer, + ObjectDataPtr(new RenderbufferData())); + globalRenderBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer); + } + } + ctx->dispatcher().glBindRenderbufferEXT(target,globalRenderBufferName); + + // update renderbuffer binding state + ctx->setRenderbufferBinding(renderbuffer); +} + +GL_APICALL void GL_APIENTRY glBindTexture(GLenum target, GLuint texture){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::textureTarget(target),GL_INVALID_ENUM) + + //for handling default texture (0) + ObjectLocalName localTexName = TextureLocalName(target,texture); + + GLuint globalTextureName = localTexName; + if(ctx->shareGroup().Ptr()){ + globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,localTexName); + //if texture wasn't generated before,generate one + if(!globalTextureName){ + ctx->shareGroup()->genName(TEXTURE,localTexName); + globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,localTexName); + } + + TextureData* texData = getTextureData(localTexName); + if (texData->target==0) + texData->target = target; + //if texture was already bound to another target + SET_ERROR_IF(ctx->GLTextureTargetToLocal(texData->target) != ctx->GLTextureTargetToLocal(target), GL_INVALID_OPERATION); + texData->wasBound = true; + } + + ctx->setBindedTexture(target,texture); + ctx->dispatcher().glBindTexture(target,globalTextureName); +} + +GL_APICALL void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha){ + GET_CTX(); + ctx->dispatcher().glBlendColor(red,green,blue,alpha); +} + +GL_APICALL void GL_APIENTRY glBlendEquation( GLenum mode ){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::blendEquationMode(mode),GL_INVALID_ENUM) + ctx->dispatcher().glBlendEquation(mode); +} + +GL_APICALL void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::blendEquationMode(modeRGB) && GLESv2Validate::blendEquationMode(modeAlpha)),GL_INVALID_ENUM); + ctx->dispatcher().glBlendEquationSeparate(modeRGB,modeAlpha); +} + +GL_APICALL void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::blendSrc(sfactor) || !GLESv2Validate::blendDst(dfactor),GL_INVALID_ENUM) + ctx->dispatcher().glBlendFunc(sfactor,dfactor); +} + +GL_APICALL void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha){ + GET_CTX(); + SET_ERROR_IF( +!(GLESv2Validate::blendSrc(srcRGB) && GLESv2Validate::blendDst(dstRGB) && GLESv2Validate::blendSrc(srcAlpha) && GLESv2Validate::blendDst(dstAlpha)),GL_INVALID_ENUM); + ctx->dispatcher().glBlendFuncSeparate(srcRGB,dstRGB,srcAlpha,dstAlpha); +} + +GL_APICALL void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::bufferTarget(target),GL_INVALID_ENUM); + SET_ERROR_IF(!GLESv2Validate::bufferUsage(usage),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + ctx->setBufferData(target,size,data,usage); +} + +GL_APICALL void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data){ + GET_CTX(); + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + SET_ERROR_IF(!GLESv2Validate::bufferTarget(target),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->setBufferSubData(target,offset,size,data),GL_INVALID_VALUE); +} + + +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target){ + GET_CTX_RET(GL_FRAMEBUFFER_COMPLETE); + RET_AND_SET_ERROR_IF(!GLESv2Validate::framebufferTarget(target),GL_INVALID_ENUM,GL_FRAMEBUFFER_COMPLETE); + ctx->drawValidate(); + return ctx->dispatcher().glCheckFramebufferStatusEXT(target); +} + +GL_APICALL void GL_APIENTRY glClear(GLbitfield mask){ + GET_CTX(); + GLbitfield allowed_bits = GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + GLbitfield has_disallowed_bits = (mask & ~allowed_bits); + SET_ERROR_IF(has_disallowed_bits, GL_INVALID_VALUE); + ctx->drawValidate(); + + ctx->dispatcher().glClear(mask); +} +GL_APICALL void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha){ + GET_CTX(); + ctx->dispatcher().glClearColor(red,green,blue,alpha); +} +GL_APICALL void GL_APIENTRY glClearDepthf(GLclampf depth){ + GET_CTX(); + ctx->dispatcher().glClearDepth(depth); +} +GL_APICALL void GL_APIENTRY glClearStencil(GLint s){ + GET_CTX(); + ctx->dispatcher().glClearStencil(s); +} +GL_APICALL void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha){ + GET_CTX(); + ctx->dispatcher().glColorMask(red,green,blue,alpha); +} + +GL_APICALL void GL_APIENTRY glCompileShader(GLuint shader){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(objData.Ptr()->getDataType()!= SHADER_DATA,GL_INVALID_OPERATION); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + ctx->dispatcher().glCompileShader(globalShaderName); + + GLsizei infoLogLength=0; + GLchar* infoLog; + ctx->dispatcher().glGetShaderiv(globalShaderName,GL_INFO_LOG_LENGTH,&infoLogLength); + infoLog = new GLchar[infoLogLength+1]; + ctx->dispatcher().glGetShaderInfoLog(globalShaderName,infoLogLength,NULL,infoLog); + sp->setInfoLog(infoLog); + } +} + +GL_APICALL void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::textureTargetEx(target),GL_INVALID_ENUM); + SET_ERROR_IF(level < 0 || imageSize < 0, GL_INVALID_VALUE); + SET_ERROR_IF(!data,GL_INVALID_OPERATION); + + doCompressedTexImage2D(ctx, target, level, internalformat, + width, height, border, + imageSize, data, (void*)glTexImage2D); +} + +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::textureTargetEx(target),GL_INVALID_ENUM); + SET_ERROR_IF(!data,GL_INVALID_OPERATION); + ctx->dispatcher().glCompressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data); +} + +GL_APICALL void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::pixelFrmt(ctx,internalformat) && GLESv2Validate::textureTargetEx(target)),GL_INVALID_ENUM); + SET_ERROR_IF((GLESv2Validate::textureIsCubeMap(target) && width != height), GL_INVALID_VALUE); + SET_ERROR_IF(border != 0,GL_INVALID_VALUE); + ctx->dispatcher().glCopyTexImage2D(target,level,internalformat,x,y,width,height,border); +} + +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::textureTargetEx(target),GL_INVALID_ENUM); + ctx->dispatcher().glCopyTexSubImage2D(target,level,xoffset,yoffset,x,y,width,height); +} + +GL_APICALL GLuint GL_APIENTRY glCreateProgram(void){ + GET_CTX_RET(0); + const GLuint globalProgramName = ctx->dispatcher().glCreateProgram(); + if(ctx->shareGroup().Ptr() && globalProgramName) { + ProgramData* programInfo = new ProgramData(); + const GLuint localProgramName = ctx->shareGroup()->genName(SHADER, 0, true); + ctx->shareGroup()->replaceGlobalName(SHADER,localProgramName,globalProgramName); + ctx->shareGroup()->setObjectData(SHADER,localProgramName,ObjectDataPtr(programInfo)); + return localProgramName; + } + if(globalProgramName){ + ctx->dispatcher().glDeleteProgram(globalProgramName); + } + return 0; +} + +GL_APICALL GLuint GL_APIENTRY glCreateShader(GLenum type){ + GET_CTX_V2_RET(0); + RET_AND_SET_ERROR_IF(!GLESv2Validate::shaderType(type),GL_INVALID_ENUM,0); + const GLuint globalShaderName = ctx->dispatcher().glCreateShader(type); + if(ctx->shareGroup().Ptr() && globalShaderName) { + const GLuint localShaderName = ctx->shareGroup()->genName(SHADER, 0, true); + ShaderParser* sp = new ShaderParser(type); + ctx->shareGroup()->replaceGlobalName(SHADER,localShaderName,globalShaderName); + ctx->shareGroup()->setObjectData(SHADER,localShaderName,ObjectDataPtr(sp)); + return localShaderName; + } + if(globalShaderName){ + ctx->dispatcher().glDeleteShader(globalShaderName); + } + return 0; +} + +GL_APICALL void GL_APIENTRY glCullFace(GLenum mode){ + GET_CTX(); + ctx->dispatcher().glCullFace(mode); +} + +GL_APICALL void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + ctx->shareGroup()->deleteName(VERTEXBUFFER,buffers[i]); + } + } +} + +GL_APICALL void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + const GLuint globalFrameBufferName = ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffers[i]); + ctx->shareGroup()->deleteName(FRAMEBUFFER,framebuffers[i]); + ctx->dispatcher().glDeleteFramebuffersEXT(1,&globalFrameBufferName); + } + } +} + +static void s_detachFromFramebuffer(GLuint bufferType, GLuint texture) { + GET_CTX(); + GLuint fbName = ctx->getFramebufferBinding(); + if (!fbName) return; + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() == NULL) return; + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + GLenum target; + const GLenum kAttachments[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + const size_t sizen = sizeof(kAttachments)/sizeof(GLenum); + for (size_t i = 0; i < sizen; ++i ) { + GLuint name = fbData->getAttachment(kAttachments[i], &target, NULL); + if (name != texture) continue; + if (TEXTURE == bufferType && GLESv2Validate::textureTargetEx(target)) { + glFramebufferTexture2D(GL_FRAMEBUFFER, kAttachments[i], target, 0, 0); + } else if (RENDERBUFFER == bufferType && GLESv2Validate::renderbufferTarget(target)) { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, kAttachments[i], target, 0); + } + } +} + +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + const GLuint globalRenderBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffers[i]); + ctx->shareGroup()->deleteName(RENDERBUFFER,renderbuffers[i]); + ctx->dispatcher().glDeleteRenderbuffersEXT(1,&globalRenderBufferName); + s_detachFromFramebuffer(RENDERBUFFER, renderbuffers[i]); + } + } +} + +GL_APICALL void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; i < n; i++){ + if (textures[i]!=0) { + TextureData* tData = getTextureData(textures[i]); + // delete the underlying OpenGL texture but only if this + // texture is not a target of EGLImage. + if (!tData || tData->sourceEGLImage == 0) { + const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]); + ctx->dispatcher().glDeleteTextures(1,&globalTextureName); + } + ctx->shareGroup()->deleteName(TEXTURE,textures[i]); + + if (ctx->getBindedTexture(GL_TEXTURE_2D) == textures[i]) + ctx->setBindedTexture(GL_TEXTURE_2D,0); + if (ctx->getBindedTexture(GL_TEXTURE_CUBE_MAP) == textures[i]) + ctx->setBindedTexture(GL_TEXTURE_CUBE_MAP,0); + s_detachFromFramebuffer(TEXTURE, textures[i]); + } + } + } +} + +GL_APICALL void GL_APIENTRY glDeleteProgram(GLuint program){ + GET_CTX(); + if(program && ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(!globalProgramName, GL_INVALID_VALUE); + + ObjectDataPtr programData = ctx->shareGroup()->getObjectData(SHADER,program); + ProgramData* pData = (ProgramData*)programData.Ptr(); + if (pData && pData->isInUse()) { + pData->setDeleteStatus(true); + return; + } + s_detachShader(ctx, pData->getAttachedVertexShader()); + s_detachShader(ctx, pData->getAttachedFragmentShader()); + + ctx->shareGroup()->deleteName(SHADER,program); + ctx->dispatcher().glDeleteProgram(globalProgramName); + } +} + +GL_APICALL void GL_APIENTRY glDeleteShader(GLuint shader){ + GET_CTX(); + if(shader && ctx->shareGroup().Ptr()) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(!globalShaderName, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + if (sp->getAttachedProgram()) { + sp->setDeleteStatus(true); + } else { + ctx->shareGroup()->deleteName(SHADER,shader); + } + ctx->dispatcher().glDeleteShader(globalShaderName); + } + +} + +GL_APICALL void GL_APIENTRY glDepthFunc(GLenum func){ + GET_CTX(); + ctx->dispatcher().glDepthFunc(func); +} +GL_APICALL void GL_APIENTRY glDepthMask(GLboolean flag){ + GET_CTX(); + ctx->dispatcher().glDepthMask(flag); +} +GL_APICALL void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar){ + GET_CTX(); + ctx->dispatcher().glDepthRange(zNear,zFar); +} + +GL_APICALL void GL_APIENTRY glDetachShader(GLuint program, GLuint shader){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr(),GL_INVALID_OPERATION); + SET_ERROR_IF(!(objData.Ptr()->getDataType()==PROGRAM_DATA) ,GL_INVALID_OPERATION); + + ProgramData* programData = (ProgramData*)objData.Ptr(); + SET_ERROR_IF(!programData->isAttached(shader),GL_INVALID_OPERATION); + programData->detachShader(shader); + + s_detachShader(ctx, shader); + + ctx->dispatcher().glDetachShader(globalProgramName,globalShaderName); + } +} + +GL_APICALL void GL_APIENTRY glDisable(GLenum cap){ + GET_CTX(); + ctx->dispatcher().glDisable(cap); +} + +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray(GLuint index){ + GET_CTX(); + SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); + ctx->enableArr(index,false); + ctx->dispatcher().glDisableVertexAttribArray(index); +} + +GL_APICALL void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count){ + GET_CTX_V2(); + SET_ERROR_IF(count < 0,GL_INVALID_VALUE) + SET_ERROR_IF(!GLESv2Validate::drawMode(mode),GL_INVALID_ENUM); + + ctx->drawValidate(); + + GLESConversionArrays tmpArrs; + ctx->setupArraysPointers(tmpArrs,first,count,0,NULL,true); + + ctx->validateAtt0PreDraw(count); + + //Enable texture generation for GL_POINTS and gl_PointSize shader variable + //GLES2 assumes this is enabled by default, we need to set this state for GL + if (mode==GL_POINTS) { + ctx->dispatcher().glEnable(GL_POINT_SPRITE); + ctx->dispatcher().glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + } + + ctx->dispatcher().glDrawArrays(mode,first,count); + + if (mode==GL_POINTS) { + ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); + ctx->dispatcher().glDisable(GL_POINT_SPRITE); + } + + ctx->validateAtt0PostDraw(); +} + +GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* elementsIndices){ + GET_CTX_V2(); + SET_ERROR_IF(count < 0,GL_INVALID_VALUE) + SET_ERROR_IF(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM); + + ctx->drawValidate(); + + const GLvoid* indices = elementsIndices; + if(ctx->isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)) { // if vbo is binded take the indices from the vbo + const unsigned char* buf = static_cast(ctx->getBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)); + indices = buf + SafeUIntFromPointer(elementsIndices); + } + + GLESConversionArrays tmpArrs; + ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false); + + unsigned int maxIndex = ctx->findMaxIndex(count, type, indices); + ctx->validateAtt0PreDraw(maxIndex); + + //See glDrawArrays + if (mode==GL_POINTS) { + ctx->dispatcher().glEnable(GL_POINT_SPRITE); + ctx->dispatcher().glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + } + + ctx->dispatcher().glDrawElements(mode,count,type,indices); + + if (mode==GL_POINTS) { + ctx->dispatcher().glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); + ctx->dispatcher().glDisable(GL_POINT_SPRITE); + } + + ctx->validateAtt0PostDraw(); +} + +GL_APICALL void GL_APIENTRY glEnable(GLenum cap){ + GET_CTX(); + ctx->dispatcher().glEnable(cap); +} + +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray(GLuint index){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); + ctx->enableArr(index,true); + ctx->dispatcher().glEnableVertexAttribArray(index); +} + +GL_APICALL void GL_APIENTRY glFinish(void){ + GET_CTX(); + ctx->dispatcher().glFinish(); +} +GL_APICALL void GL_APIENTRY glFlush(void){ + GET_CTX(); + ctx->dispatcher().glFlush(); +} + + +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(target) && + GLESv2Validate::renderbufferTarget(renderbuffertarget) && + GLESv2Validate::framebufferAttachment(attachment)),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION); + + GLuint globalRenderbufferName = 0; + ObjectDataPtr obj; + + // generate the renderbuffer object if not yet exist + if(renderbuffer) { + if (!ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)) { + ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer); + obj = ObjectDataPtr(new RenderbufferData()); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffer, obj); + } + else { + obj = ctx->shareGroup()->getObjectData(RENDERBUFFER, renderbuffer); + } + + globalRenderbufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer); + } + + // Update the the current framebuffer object attachment state + GLuint fbName = ctx->getFramebufferBinding(); + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + fbData->setAttachment(attachment, renderbuffertarget, renderbuffer, obj); + } + + if (renderbuffer && obj.Ptr() != NULL) { + RenderbufferData *rbData = (RenderbufferData *)obj.Ptr(); + if (rbData->sourceEGLImage != 0) { + // + // This renderbuffer object is an eglImage target + // attach the eglimage's texture instead the renderbuffer. + // + ctx->dispatcher().glFramebufferTexture2DEXT(target, + attachment, + GL_TEXTURE_2D, + rbData->eglImageGlobalTexName,0); + return; + } + } + + ctx->dispatcher().glFramebufferRenderbufferEXT(target,attachment,renderbuffertarget,globalRenderbufferName); +} + +GL_APICALL void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(target) && + GLESv2Validate::textureTargetEx(textarget) && + GLESv2Validate::framebufferAttachment(attachment)),GL_INVALID_ENUM); + SET_ERROR_IF(level != 0, GL_INVALID_VALUE); + SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION); + + GLuint globalTextureName = 0; + + if(texture) { + if (!ctx->shareGroup()->isObject(TEXTURE,texture)) { + ctx->shareGroup()->genName(TEXTURE,texture); + } + ObjectLocalName texname = TextureLocalName(textarget,texture); + globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,texname); + } + + ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,globalTextureName,level); + + // Update the the current framebuffer object attachment state + GLuint fbName = ctx->getFramebufferBinding(); + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + fbData->setAttachment(attachment, textarget, + texture, ObjectDataPtr(NULL)); + } +} + + +GL_APICALL void GL_APIENTRY glFrontFace(GLenum mode){ + GET_CTX(); + ctx->dispatcher().glFrontFace(mode); +} + +GL_APICALL void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(VERTEXBUFFER, 0, true); + //generating vbo object related to this buffer name + ctx->shareGroup()->setObjectData(VERTEXBUFFER,buffers[i],ObjectDataPtr(new GLESbuffer())); + } + } +} + +GL_APICALL void GL_APIENTRY glGenerateMipmap(GLenum target){ + GET_CTX(); + SET_ERROR_IF(!GLESvalidate::textureTarget(target), GL_INVALID_ENUM); + ctx->dispatcher().glGenerateMipmapEXT(target); +} + +GL_APICALL void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(FRAMEBUFFER, 0 ,true); + ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffers[i], + ObjectDataPtr(new FramebufferData(framebuffers[i]))); + } + } +} + +GL_APICALL void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(RENDERBUFFER, 0, true); + ctx->shareGroup()->setObjectData(RENDERBUFFER, + renderbuffers[i], + ObjectDataPtr(new RenderbufferData())); + } + } +} + +GL_APICALL void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures){ + GET_CTX(); + SET_ERROR_IF(n<0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()) { + for(int i=0; ishareGroup()->genName(TEXTURE, 0, true); + } + } +} + +GL_APICALL void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ctx->dispatcher().glGetActiveAttrib(globalProgramName,index,bufsize,length,size,type,name); + } +} + +GL_APICALL void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ctx->dispatcher().glGetActiveUniform(globalProgramName,index,bufsize,length,size,type,name); + } +} + +GL_APICALL void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ctx->dispatcher().glGetAttachedShaders(globalProgramName,maxcount,count,shaders); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + GLint numShaders=0; + ctx->dispatcher().glGetProgramiv(globalProgramName,GL_ATTACHED_SHADERS,&numShaders); + for(int i=0 ; i < maxcount && ishareGroup()->getLocalName(SHADER,shaders[i]); + } + } +} + +GL_APICALL int GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name){ + GET_CTX_RET(-1); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + RET_AND_SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE,-1); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + RET_AND_SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION,-1); + ProgramData* pData = (ProgramData *)objData.Ptr(); + RET_AND_SET_ERROR_IF(pData->getLinkStatus() != GL_TRUE,GL_INVALID_OPERATION,-1); + return ctx->dispatcher().glGetAttribLocation(globalProgramName,name); + } + return -1; +} + +GL_APICALL void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params){ + GET_CTX(); + + if (ctx->glGetBooleanv(pname,params)) + { + return; + } + + switch(pname) + { + case GL_SHADER_COMPILER: + case GL_SHADER_BINARY_FORMATS: + case GL_NUM_SHADER_BINARY_FORMATS: + case GL_MAX_VERTEX_UNIFORM_VECTORS: + case GL_MAX_VARYING_VECTORS: + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + if(ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY) + ctx->dispatcher().glGetBooleanv(pname,params); + else + { + GLint iparam; + glGetIntegerv(pname,&iparam); + *params = (iparam != 0); + } + break; + + default: + ctx->dispatcher().glGetBooleanv(pname,params); + } +} + +GL_APICALL void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::bufferTarget(target) && GLESv2Validate::bufferParam(pname)),GL_INVALID_ENUM); + SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); + switch(pname) { + case GL_BUFFER_SIZE: + ctx->getBufferSize(target,params); + break; + case GL_BUFFER_USAGE: + ctx->getBufferUsage(target,params); + break; + } +} + + +GL_APICALL GLenum GL_APIENTRY glGetError(void){ + GET_CTX_RET(GL_NO_ERROR) + GLenum err = ctx->getGLerror(); + if(err != GL_NO_ERROR) { + ctx->setGLerror(GL_NO_ERROR); + return err; + } + return ctx->dispatcher().glGetError(); +} + +GL_APICALL void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params){ + GET_CTX(); + + if (ctx->glGetFloatv(pname,params)) { + return; + } + + GLint i; + + switch (pname) { + case GL_CURRENT_PROGRAM: + case GL_FRAMEBUFFER_BINDING: + case GL_RENDERBUFFER_BINDING: + glGetIntegerv(pname,&i); + *params = (GLfloat)i; + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = (GLfloat)getCompressedFormats(NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + { + int nparams = getCompressedFormats(NULL); + if (nparams>0) { + int * iparams = new int[nparams]; + getCompressedFormats(iparams); + for (int i=0; igetCaps()->GL_ARB_ES2_COMPATIBILITY) + ctx->dispatcher().glGetFloatv(pname,params); + else + { + glGetIntegerv(pname,&i); + *params = (GLfloat)i; + } + break; + + case GL_STENCIL_BACK_VALUE_MASK: + case GL_STENCIL_BACK_WRITEMASK: + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_WRITEMASK: + { + GLint myint = 0; + glGetIntegerv(pname, &myint); + // Two casts are used: since mask is unsigned integer, + // the first cast converts to unsigned integer; + // the second cast converts to float. + *params = (GLfloat)((GLuint)(myint)); + } + break; + + default: + ctx->dispatcher().glGetFloatv(pname,params); + } +} + +GL_APICALL void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params){ + int destroyCtx = 0; + GET_CTX(); + + if (!ctx) { + ctx = createGLESContext(); + if (ctx) + destroyCtx = 1; + } + if (ctx->glGetIntegerv(pname,params)) + { + if (destroyCtx) + deleteGLESContext(ctx); + return; + } + + bool es2 = ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY; + GLint i; + + switch (pname) { + case GL_CURRENT_PROGRAM: + if (ctx->shareGroup().Ptr()) { + ctx->dispatcher().glGetIntegerv(pname,&i); + *params = ctx->shareGroup()->getLocalName(SHADER,i); + } + break; + case GL_FRAMEBUFFER_BINDING: + if (ctx->shareGroup().Ptr()) { + ctx->dispatcher().glGetIntegerv(pname,&i); + *params = ctx->shareGroup()->getLocalName(FRAMEBUFFER,i); + } + break; + case GL_RENDERBUFFER_BINDING: + if (ctx->shareGroup().Ptr()) { + ctx->dispatcher().glGetIntegerv(pname,&i); + *params = ctx->shareGroup()->getLocalName(RENDERBUFFER,i); + } + break; + + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = getCompressedFormats(NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + getCompressedFormats(params); + break; + + case GL_SHADER_COMPILER: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + else + *params = 1; + break; + + case GL_SHADER_BINARY_FORMATS: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + break; + + case GL_NUM_SHADER_BINARY_FORMATS: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + else + *params = 0; + break; + + case GL_MAX_VERTEX_UNIFORM_VECTORS: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + else + *params = 128; + break; + + case GL_MAX_VARYING_VECTORS: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + else + *params = 8; + break; + + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + if(es2) + ctx->dispatcher().glGetIntegerv(pname,params); + else + *params = 16; + break; + + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + ctx->dispatcher().glGetIntegerv(pname,params); + if(*params > 16) + { + // GLES spec requires only 2, and the ATI driver erronously + // returns 32 (although it supports only 16). This WAR is simple, + // compliant and good enough for developers. + *params = 16; + } + break; + default: + ctx->dispatcher().glGetIntegerv(pname,params); + } + if (destroyCtx) + deleteGLESContext(ctx); +} + +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(target) && + GLESv2Validate::framebufferAttachment(attachment) && + GLESv2Validate::framebufferAttachmentParams(pname)),GL_INVALID_ENUM); + + // + // Take the attachment attribute from our state - if available + // + GLuint fbName = ctx->getFramebufferBinding(); + SET_ERROR_IF (!fbName, GL_INVALID_OPERATION); + if (fbName) { + ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName); + if (fbObj.Ptr() != NULL) { + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + GLenum target; + GLuint name = fbData->getAttachment(attachment, &target, NULL); + if (!name) { + SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE && + pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, GL_INVALID_ENUM); + } + if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) { + if (target == GL_TEXTURE_2D) { + *params = GL_TEXTURE; + return; + } + else if (target == GL_RENDERBUFFER) { + *params = GL_RENDERBUFFER; + return; + } else { + *params = GL_NONE; + } + } + else if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) { + *params = name; + return; + } + } + } + + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(target,attachment,pname,params); +} + +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::renderbufferTarget(target) && GLESv2Validate::renderbufferParams(pname)),GL_INVALID_ENUM); + + // + // If this is a renderbuffer which is eglimage's target, we + // should query the underlying eglimage's texture object instead. + // + GLuint rb = ctx->getRenderbufferBinding(); + if (rb) { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + if (rbData && rbData->sourceEGLImage != 0) { + GLenum texPname; + switch(pname) { + case GL_RENDERBUFFER_WIDTH: + texPname = GL_TEXTURE_WIDTH; + break; + case GL_RENDERBUFFER_HEIGHT: + texPname = GL_TEXTURE_HEIGHT; + break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: + texPname = GL_TEXTURE_INTERNAL_FORMAT; + break; + case GL_RENDERBUFFER_RED_SIZE: + texPname = GL_TEXTURE_RED_SIZE; + break; + case GL_RENDERBUFFER_GREEN_SIZE: + texPname = GL_TEXTURE_GREEN_SIZE; + break; + case GL_RENDERBUFFER_BLUE_SIZE: + texPname = GL_TEXTURE_BLUE_SIZE; + break; + case GL_RENDERBUFFER_ALPHA_SIZE: + texPname = GL_TEXTURE_ALPHA_SIZE; + break; + case GL_RENDERBUFFER_DEPTH_SIZE: + texPname = GL_TEXTURE_DEPTH_SIZE; + break; + case GL_RENDERBUFFER_STENCIL_SIZE: + default: + *params = 0; //XXX + return; + break; + } + + GLint prevTex; + ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, + rbData->eglImageGlobalTexName); + ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, + texPname, + params); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prevTex); + return; + } + } + + ctx->dispatcher().glGetRenderbufferParameterivEXT(target,pname,params); +} + + +GL_APICALL void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::programParam(pname),GL_INVALID_ENUM); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + switch(pname) { + case GL_DELETE_STATUS: + { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + params[0] = programData->getDeleteStatus() ? GL_TRUE : GL_FALSE; + } + break; + case GL_LINK_STATUS: + { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + params[0] = programData->getLinkStatus(); + } + break; + //validate status should not return GL_TRUE if link failed + case GL_VALIDATE_STATUS: + { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + if (programData->getLinkStatus()==GL_TRUE) + ctx->dispatcher().glGetProgramiv(globalProgramName,pname,params); + else + params[0] = GL_FALSE; + } + break; + case GL_INFO_LOG_LENGTH: + { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + GLint logLength = strlen(programData->getInfoLog()); + params[0] = (logLength>0) ? logLength+1 : 0; + } + break; + default: + ctx->dispatcher().glGetProgramiv(globalProgramName,pname,params); + } + } +} + +GL_APICALL void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + + if (bufsize==0) { + if (length) { + *length = 0; + } + return; + } + + GLsizei logLength; + logLength = strlen(programData->getInfoLog()); + + GLsizei returnLength=0; + if (infolog) { + returnLength = bufsize-1 < logLength ? bufsize-1 : logLength; + strncpy(infolog,programData->getInfoLog(),returnLength+1); + infolog[returnLength] = '\0'; + } + if (length) { + *length = returnLength; + } + } +} + +GL_APICALL void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + if (pname == GL_DELETE_STATUS) { + SET_ERROR_IF(globalShaderName == 0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_VALUE); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_VALUE); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + params[0] = (sp->getDeleteStatus()) ? GL_TRUE : GL_FALSE; + return; + } + SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + switch(pname) { + case GL_INFO_LOG_LENGTH: + { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + GLint logLength = strlen(sp->getInfoLog()); + params[0] = (logLength>0) ? logLength+1 : 0; + } + break; + default: + ctx->dispatcher().glGetShaderiv(globalShaderName,pname,params); + } + } +} + + +GL_APICALL void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + + if (bufsize==0) { + if (length) { + *length = 0; + } + return; + } + + GLsizei logLength; + logLength = strlen(sp->getInfoLog()); + + GLsizei returnLength=0; + if (infolog) { + returnLength = bufsize-1 getInfoLog(),returnLength+1); + infolog[returnLength] = '\0'; + } + if (length) { + *length = returnLength; + } + } +} + +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision){ + GET_CTX_V2(); + SET_ERROR_IF(!(GLESv2Validate::shaderType(shadertype) && GLESv2Validate::precisionType(precisiontype)),GL_INVALID_ENUM); + + switch (precisiontype) { + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + range[0] = range[1] = 16; + *precision = 0; + break; + + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + if(ctx->dispatcher().glGetShaderPrecisionFormat != NULL) { + ctx->dispatcher().glGetShaderPrecisionFormat(shadertype,precisiontype,range,precision); + } else { + range[0] = range[1] = 127; + *precision = 24; + } + break; + } +} + +GL_APICALL void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName == 0,GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr(),GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); + const char* src = ((ShaderParser*)objData.Ptr())->getOriginalSrc(); + int srcLength = 0; + if (src) { + srcLength = strlen(src); + } + + int returnLength = bufsizegetVendorString(); + case GL_RENDERER: + return (const GLubyte*)ctx->getRendererString(); + case GL_VERSION: + return (const GLubyte*)ctx->getVersionString(); + case GL_SHADING_LANGUAGE_VERSION: + return SHADING; + case GL_EXTENSIONS: + return (const GLubyte*)ctx->getExtensionString(); + default: + RET_AND_SET_ERROR_IF(true,GL_INVALID_ENUM,NULL); + } +} + +GL_APICALL void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glGetTexParameterfv(target,pname,params); + +} +GL_APICALL void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glGetTexParameteriv(target,pname,params); +} + +GL_APICALL void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params){ + GET_CTX(); + SET_ERROR_IF(location < 0,GL_INVALID_OPERATION); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* pData = (ProgramData *)objData.Ptr(); + SET_ERROR_IF(pData->getLinkStatus() != GL_TRUE,GL_INVALID_OPERATION); + ctx->dispatcher().glGetUniformfv(globalProgramName,location,params); + } +} + +GL_APICALL void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params){ + GET_CTX(); + SET_ERROR_IF(location < 0,GL_INVALID_OPERATION); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* pData = (ProgramData *)objData.Ptr(); + SET_ERROR_IF(pData->getLinkStatus() != GL_TRUE,GL_INVALID_OPERATION); + ctx->dispatcher().glGetUniformiv(globalProgramName,location,params); + } +} + +GL_APICALL int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name){ + GET_CTX_RET(-1); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + RET_AND_SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE,-1); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + RET_AND_SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION,-1); + ProgramData* pData = (ProgramData *)objData.Ptr(); + RET_AND_SET_ERROR_IF(pData->getLinkStatus() != GL_TRUE,GL_INVALID_OPERATION,-1); + return ctx->dispatcher().glGetUniformLocation(globalProgramName,name); + } + return -1; +} + +static bool s_invalidVertexAttribIndex(GLuint index) { + GLint param=0; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, ¶m); + return (param < 0 || index >= (GLuint)param); +} + +GL_APICALL void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params){ + GET_CTX_V2(); + SET_ERROR_IF(s_invalidVertexAttribIndex(index), GL_INVALID_VALUE); + const GLESpointer* p = ctx->getPointer(index); + if(p) { + switch(pname){ + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + *params = 0; + break; + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + *params = p->isEnable(); + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + *params = p->getSize(); + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + *params = p->getStride(); + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + *params = p->getType(); + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + *params = p->isNormalize(); + break; + case GL_CURRENT_VERTEX_ATTRIB: + if(index == 0) + { + const float* att0 = ctx->getAtt0(); + for(int i=0; i<4; i++) + params[i] = att0[i]; + } + else + ctx->dispatcher().glGetVertexAttribfv(index,pname,params); + break; + default: + ctx->setGLerror(GL_INVALID_ENUM); + } + } else { + ctx->setGLerror(GL_INVALID_VALUE); + } +} + +GL_APICALL void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params){ + GET_CTX_V2(); + SET_ERROR_IF(s_invalidVertexAttribIndex(index), GL_INVALID_VALUE); + const GLESpointer* p = ctx->getPointer(index); + if(p) { + switch(pname){ + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + *params = 0; + break; + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + *params = p->isEnable(); + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + *params = p->getSize(); + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + *params = p->getStride(); + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + *params = p->getType(); + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + *params = p->isNormalize(); + break; + case GL_CURRENT_VERTEX_ATTRIB: + if(index == 0) + { + const float* att0 = ctx->getAtt0(); + for(int i=0; i<4; i++) + params[i] = (GLint)att0[i]; + } + else + ctx->dispatcher().glGetVertexAttribiv(index,pname,params); + break; + default: + ctx->setGLerror(GL_INVALID_ENUM); + } + } else { + ctx->setGLerror(GL_INVALID_VALUE); + } +} + +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer){ + GET_CTX(); + SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER,GL_INVALID_ENUM); + SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); + + const GLESpointer* p = ctx->getPointer(index); + if(p) { + *pointer = const_cast( p->getBufferData()); + } else { + ctx->setGLerror(GL_INVALID_VALUE); + } +} + +GL_APICALL void GL_APIENTRY glHint(GLenum target, GLenum mode){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::hintTargetMode(target,mode),GL_INVALID_ENUM); + ctx->dispatcher().glHint(target,mode); +} + +GL_APICALL GLboolean GL_APIENTRY glIsEnabled(GLenum cap){ + GET_CTX_RET(GL_FALSE); + RET_AND_SET_ERROR_IF(!GLESv2Validate::capability(cap),GL_INVALID_ENUM,GL_FALSE); + return ctx->dispatcher().glIsEnabled(cap); +} + +GL_APICALL GLboolean GL_APIENTRY glIsBuffer(GLuint buffer){ + GET_CTX_RET(GL_FALSE) + if(buffer && ctx->shareGroup().Ptr()) { + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(VERTEXBUFFER,buffer); + return objData.Ptr() ? ((GLESbuffer*)objData.Ptr())->wasBinded():GL_FALSE; + } + return GL_FALSE; +} + +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer){ + GET_CTX_RET(GL_FALSE) + if(framebuffer && ctx->shareGroup().Ptr()){ + return (ctx->shareGroup()->isObject(FRAMEBUFFER,framebuffer) && + ctx->getFramebufferBinding() == framebuffer) ? GL_TRUE :GL_FALSE; + } + return GL_FALSE; +} + +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer){ + GET_CTX_RET(GL_FALSE) + if(renderbuffer && ctx->shareGroup().Ptr()){ + return (ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer) && + ctx->getRenderbufferBinding() == renderbuffer) ? GL_TRUE :GL_FALSE; + } + return GL_FALSE; +} + +GL_APICALL GLboolean GL_APIENTRY glIsTexture(GLuint texture){ + GET_CTX_RET(GL_FALSE) + if (texture==0) + return GL_FALSE; + TextureData* tex = getTextureData(texture); + return tex ? tex->wasBound : GL_FALSE; +} + +GL_APICALL GLboolean GL_APIENTRY glIsProgram(GLuint program){ + GET_CTX_RET(GL_FALSE) + if(program && ctx->shareGroup().Ptr() && + ctx->shareGroup()->isObject(SHADER,program)) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + return ctx->dispatcher().glIsProgram(globalProgramName); + } + return GL_FALSE; +} + +GL_APICALL GLboolean GL_APIENTRY glIsShader(GLuint shader){ + GET_CTX_RET(GL_FALSE) + if(shader && ctx->shareGroup().Ptr() && + ctx->shareGroup()->isObject(SHADER,shader)) { + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + return ctx->dispatcher().glIsShader(globalShaderName); + } + return GL_FALSE; +} + +GL_APICALL void GL_APIENTRY glLineWidth(GLfloat width){ + GET_CTX(); + ctx->dispatcher().glLineWidth(width); +} + +GL_APICALL void GL_APIENTRY glLinkProgram(GLuint program){ + GET_CTX(); + GLint linkStatus = GL_FALSE; + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr(), GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA, GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + GLint fragmentShader = programData->getAttachedFragmentShader(); + GLint vertexShader = programData->getAttachedVertexShader(); + if (vertexShader != 0 && fragmentShader!=0) { + /* validating that the fragment & vertex shaders were compiled successfuly*/ + GLint fCompileStatus = GL_FALSE; + GLint vCompileStatus = GL_FALSE; + GLuint fragmentShaderGlobal = ctx->shareGroup()->getGlobalName(SHADER,fragmentShader); + GLuint vertexShaderGlobal = ctx->shareGroup()->getGlobalName(SHADER,vertexShader); + ctx->dispatcher().glGetShaderiv(fragmentShaderGlobal,GL_COMPILE_STATUS,&fCompileStatus); + ctx->dispatcher().glGetShaderiv(vertexShaderGlobal,GL_COMPILE_STATUS,&vCompileStatus); + + if(fCompileStatus != 0 && vCompileStatus != 0){ + ctx->dispatcher().glLinkProgram(globalProgramName); + ctx->dispatcher().glGetProgramiv(globalProgramName,GL_LINK_STATUS,&linkStatus); + } + } + programData->setLinkStatus(linkStatus); + + GLsizei infoLogLength=0; + GLchar* infoLog; + ctx->dispatcher().glGetProgramiv(globalProgramName,GL_INFO_LOG_LENGTH,&infoLogLength); + infoLog = new GLchar[infoLogLength+1]; + ctx->dispatcher().glGetProgramInfoLog(globalProgramName,infoLogLength,NULL,infoLog); + programData->setInfoLog(infoLog); + } +} + +GL_APICALL void GL_APIENTRY glPixelStorei(GLenum pname, GLint param){ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::pixelStoreParam(pname),GL_INVALID_ENUM); + SET_ERROR_IF(!((param==1)||(param==2)||(param==4)||(param==8)), GL_INVALID_VALUE); + ctx->setUnpackAlignment(param); + ctx->dispatcher().glPixelStorei(pname,param); +} + +GL_APICALL void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units){ + GET_CTX(); + ctx->dispatcher().glPolygonOffset(factor,units); +} + +GL_APICALL void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::readPixelFrmt(format) && GLESv2Validate::pixelType(ctx,type)),GL_INVALID_ENUM); + SET_ERROR_IF((width < 0 || height < 0),GL_INVALID_VALUE); + SET_ERROR_IF(!(GLESv2Validate::pixelOp(format,type)),GL_INVALID_OPERATION); + SET_ERROR_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION); + ctx->dispatcher().glReadPixels(x,y,width,height,format,type,pixels); +} + + +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler(void){ +// this function doesn't work on Mac OS with MacOSX10.9sdk +#ifndef __APPLE__ + + /* Use this function with mesa will cause potential bug. Specifically, + * calling this function between glCompileShader() and glLinkProgram() will + * release resources that would be potentially used by glLinkProgram, + * resulting in a segmentation fault. + */ + const char* env = ::getenv("ANDROID_GL_LIB"); + if (env && !strcmp(env, "mesa")) { + return; + } + + GET_CTX(); + + if(ctx->dispatcher().glReleaseShaderCompiler != NULL) + { + ctx->dispatcher().glReleaseShaderCompiler(); + } +#endif // !__APPLE__ +} + +GL_APICALL void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height){ + GET_CTX(); + GLenum internal = internalformat; + switch (internalformat) { + case GL_RGB565: + internal = GL_RGB; + break; + case GL_RGB5_A1: + internal = GL_RGBA; + break; + default: + internal = internalformat; + break; + } + + // Get current bounded renderbuffer + // raise INVALID_OPERATIOn if no renderbuffer is bounded + GLuint rb = ctx->getRenderbufferBinding(); + SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + SET_ERROR_IF(!rbData,GL_INVALID_OPERATION); + + // + // if the renderbuffer was an eglImage target, detach from + // the eglImage. + // + if (rbData->sourceEGLImage != 0) { + if (rbData->eglImageDetach) { + (*rbData->eglImageDetach)(rbData->sourceEGLImage); + } + rbData->sourceEGLImage = 0; + rbData->eglImageGlobalTexName = 0; + } + + ctx->dispatcher().glRenderbufferStorageEXT(target,internal,width,height); +} + +GL_APICALL void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert){ + GET_CTX(); + ctx->dispatcher().glSampleCoverage(value,invert); +} + +GL_APICALL void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height){ + GET_CTX(); + ctx->dispatcher().glScissor(x,y,width,height); +} + +GL_APICALL void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length){ + GET_CTX(); + + SET_ERROR_IF( (ctx->dispatcher().glShaderBinary == NULL), GL_INVALID_OPERATION); + + if(ctx->shareGroup().Ptr()){ + for(int i=0; i < n ; i++){ + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shaders[i]); + SET_ERROR_IF(globalShaderName == 0,GL_INVALID_VALUE); + ctx->dispatcher().glShaderBinary(1,&globalShaderName,binaryformat,binary,length); + } + } +} + +GL_APICALL void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length){ + GET_CTX_V2(); + SET_ERROR_IF(count < 0,GL_INVALID_VALUE); + if(ctx->shareGroup().Ptr()){ + const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader); + SET_ERROR_IF(globalShaderName == 0,GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader); + SET_ERROR_IF(!objData.Ptr(),GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); + ShaderParser* sp = (ShaderParser*)objData.Ptr(); + sp->setSrc(ctx->glslVersion(),count,string,length); + ctx->dispatcher().glShaderSource(globalShaderName,1,sp->parsedLines(),NULL); + } +} + +GL_APICALL void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask){ + GET_CTX(); + ctx->dispatcher().glStencilFunc(func,ref,mask); +} +GL_APICALL void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask){ + GET_CTX(); + ctx->dispatcher().glStencilFuncSeparate(face,func,ref,mask); +} +GL_APICALL void GL_APIENTRY glStencilMask(GLuint mask){ + GET_CTX(); + ctx->dispatcher().glStencilMask(mask); +} + +GL_APICALL void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask){ + GET_CTX(); + ctx->dispatcher().glStencilMaskSeparate(face,mask); +} + +GL_APICALL void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass){ + GET_CTX(); + ctx->dispatcher().glStencilOp(fail,zfail,zpass); +} + +GL_APICALL void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass){ + GET_CTX(); + switch (face) { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + SET_ERROR_IF(1, GL_INVALID_ENUM); + } + ctx->dispatcher().glStencilOpSeparate(face, fail,zfail,zpass); +} + +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +GL_APICALL void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTargetEx(target) && + GLESv2Validate::pixelFrmt(ctx,format)&& + GLESv2Validate::pixelType(ctx,type)),GL_INVALID_ENUM); + + SET_ERROR_IF(!GLESv2Validate::pixelFrmt(ctx,internalformat), GL_INVALID_VALUE); + SET_ERROR_IF((GLESv2Validate::textureIsCubeMap(target) && width != height), GL_INVALID_VALUE); + SET_ERROR_IF((format == GL_DEPTH_COMPONENT || internalformat == GL_DEPTH_COMPONENT) && + (type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT), GL_INVALID_OPERATION); + + SET_ERROR_IF((type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) && + (format != GL_DEPTH_COMPONENT || internalformat != GL_DEPTH_COMPONENT), GL_INVALID_OPERATION); + + SET_ERROR_IF(!(GLESv2Validate::pixelOp(format,type) && internalformat == ((GLint)format)),GL_INVALID_OPERATION); + SET_ERROR_IF(border != 0,GL_INVALID_VALUE); + + if (ctx->shareGroup().Ptr()){ + TextureData *texData = getTextureTargetData(target); + if(texData) { + texData->width = width; + texData->height = height; + texData->border = border; + texData->internalFormat = internalformat; + texData->target = target; + + if (texData->sourceEGLImage != 0) { + // + // This texture was a target of EGLImage, + // but now it is re-defined so we need to detach + // from the EGLImage and re-generate global texture name + // for it. + // + if (texData->eglImageDetach) { + (*texData->eglImageDetach)(texData->sourceEGLImage); + } + unsigned int tex = ctx->getBindedTexture(target); + ctx->shareGroup()->replaceGlobalName(TEXTURE, + tex, + texData->oldGlobal); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, texData->oldGlobal); + texData->sourceEGLImage = 0; + texData->oldGlobal = 0; + } + } + } + + if (type==GL_HALF_FLOAT_OES) + type = GL_HALF_FLOAT_NV; + if (pixels==NULL && type==GL_UNSIGNED_SHORT_5_5_5_1) + type = GL_UNSIGNED_SHORT; + if (type == GL_FLOAT) + internalformat = (format == GL_RGBA) ? GL_RGBA32F : GL_RGB32F; + ctx->dispatcher().glTexImage2D(target,level,internalformat,width,height,border,format,type,pixels); +} + + +GL_APICALL void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glTexParameterf(target,pname,param); +} +GL_APICALL void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glTexParameterfv(target,pname,params); +} +GL_APICALL void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glTexParameteri(target,pname,param); +} +GL_APICALL void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTarget(target) && GLESv2Validate::textureParams(pname)),GL_INVALID_ENUM); + ctx->dispatcher().glTexParameteriv(target,pname,params); +} + +GL_APICALL void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels){ + GET_CTX(); + SET_ERROR_IF(!(GLESv2Validate::textureTargetEx(target)), GL_INVALID_ENUM); + SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); + SET_ERROR_IF(!(GLESv2Validate::pixelFrmt(ctx,format)&& + GLESv2Validate::pixelType(ctx,type)),GL_INVALID_ENUM); + SET_ERROR_IF(!GLESv2Validate::pixelOp(format,type),GL_INVALID_OPERATION); + SET_ERROR_IF(!pixels,GL_INVALID_OPERATION); + if (type==GL_HALF_FLOAT_OES) + type = GL_HALF_FLOAT_NV; + + ctx->dispatcher().glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels); + +} + +GL_APICALL void GL_APIENTRY glUniform1f(GLint location, GLfloat x){ + GET_CTX(); + ctx->dispatcher().glUniform1f(location,x); +} +GL_APICALL void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v){ + GET_CTX(); + ctx->dispatcher().glUniform1fv(location,count,v); +} + +GL_APICALL void GL_APIENTRY glUniform1i(GLint location, GLint x){ + GET_CTX(); + ctx->dispatcher().glUniform1i(location,x); +} +GL_APICALL void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v){ + GET_CTX(); + ctx->dispatcher().glUniform1iv(location,count,v); +} +GL_APICALL void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y){ + GET_CTX(); + ctx->dispatcher().glUniform2f(location,x,y); +} +GL_APICALL void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v){ + GET_CTX(); + ctx->dispatcher().glUniform2fv(location,count,v); +} +GL_APICALL void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y){ + GET_CTX(); + ctx->dispatcher().glUniform2i(location,x,y); +} +GL_APICALL void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v){ + GET_CTX(); + ctx->dispatcher().glUniform2iv(location,count,v); +} +GL_APICALL void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z){ + GET_CTX(); + ctx->dispatcher().glUniform3f(location,x,y,z); +} +GL_APICALL void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v){ + GET_CTX(); + ctx->dispatcher().glUniform3fv(location,count,v); +} +GL_APICALL void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z){ + GET_CTX(); + ctx->dispatcher().glUniform3i(location,x,y,z); +} + +GL_APICALL void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v){ + GET_CTX(); + ctx->dispatcher().glUniform3iv(location,count,v); +} + +GL_APICALL void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w){ + GET_CTX(); + ctx->dispatcher().glUniform4f(location,x,y,z,w); +} + +GL_APICALL void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v){ + GET_CTX(); + ctx->dispatcher().glUniform4fv(location,count,v); +} + +GL_APICALL void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w){ + GET_CTX(); + ctx->dispatcher().glUniform4i(location,x,y,z,w); +} + +GL_APICALL void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v){ + GET_CTX(); + ctx->dispatcher().glUniform4iv(location,count,v); +} + +GL_APICALL void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value){ + GET_CTX(); + SET_ERROR_IF(transpose != GL_FALSE,GL_INVALID_VALUE); + ctx->dispatcher().glUniformMatrix2fv(location,count,transpose,value); +} + +GL_APICALL void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value){ + GET_CTX(); + SET_ERROR_IF(transpose != GL_FALSE,GL_INVALID_VALUE); + ctx->dispatcher().glUniformMatrix3fv(location,count,transpose,value); +} + +GL_APICALL void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value){ + GET_CTX(); + SET_ERROR_IF(transpose != GL_FALSE,GL_INVALID_VALUE); + ctx->dispatcher().glUniformMatrix4fv(location,count,transpose,value); +} + +static void s_unUseCurrentProgram() { + GET_CTX(); + GLint localCurrentProgram = 0; + glGetIntegerv(GL_CURRENT_PROGRAM, &localCurrentProgram); + if (!localCurrentProgram) return; + + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,localCurrentProgram); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + programData->setInUse(false); + if (programData->getDeleteStatus()) { glDeleteProgram(localCurrentProgram); } +} + +GL_APICALL void GL_APIENTRY glUseProgram(GLuint program){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(program!=0 && globalProgramName==0,GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr() && (objData.Ptr()->getDataType()!=PROGRAM_DATA),GL_INVALID_OPERATION); + + s_unUseCurrentProgram(); + + ProgramData* programData = (ProgramData*)objData.Ptr(); + if (programData) programData->setInUse(true); + + ctx->dispatcher().glUseProgram(globalProgramName); + } +} + +GL_APICALL void GL_APIENTRY glValidateProgram(GLuint program){ + GET_CTX(); + if(ctx->shareGroup().Ptr()) { + const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program); + SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + ctx->dispatcher().glValidateProgram(globalProgramName); + + GLsizei infoLogLength=0; + GLchar* infoLog; + ctx->dispatcher().glGetProgramiv(globalProgramName,GL_INFO_LOG_LENGTH,&infoLogLength); + infoLog = new GLchar[infoLogLength+1]; + ctx->dispatcher().glGetProgramInfoLog(globalProgramName,infoLogLength,NULL,infoLog); + programData->setInfoLog(infoLog); + } +} + +GL_APICALL void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib1f(indx,x); + if(indx == 0) + ctx->setAttribute0value(x, 0.0, 0.0, 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib1fv(indx,values); + if(indx == 0) + ctx->setAttribute0value(values[0], 0.0, 0.0, 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib2f(indx,x,y); + if(indx == 0) + ctx->setAttribute0value(x, y, 0.0, 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib2fv(indx,values); + if(indx == 0) + ctx->setAttribute0value(values[0], values[1], 0.0, 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib3f(indx,x,y,z); + if(indx == 0) + ctx->setAttribute0value(x, y, z, 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib3fv(indx,values); + if(indx == 0) + ctx->setAttribute0value(values[0], values[1], values[2], 1.0); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib4f(indx,x,y,z,w); + if(indx == 0) + ctx->setAttribute0value(x, y, z, w); +} + +GL_APICALL void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values){ + GET_CTX_V2(); + ctx->dispatcher().glVertexAttrib4fv(indx,values); + if(indx == 0) + ctx->setAttribute0value(values[0], values[1], values[2], values[3]); +} + +GL_APICALL void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr){ + GET_CTX(); + SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,indx)),GL_INVALID_VALUE); + if (type == GL_HALF_FLOAT_OES) type = GL_HALF_FLOAT; + ctx->setPointer(indx,size,type,stride,ptr,normalized); +} + +GL_APICALL void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height){ + GET_CTX(); + ctx->dispatcher().glViewport(x,y,width,height); +} + +GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + GET_CTX(); + SET_ERROR_IF(!GLESv2Validate::textureTargetLimited(target),GL_INVALID_ENUM); + unsigned int imagehndl = SafeUIntFromPointer(image); + EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); + if (img) { + // Create the texture object in the underlying EGL implementation, + // flag to the OpenGL layer to skip the image creation and map the + // current binded texture object to the existing global object. + if (ctx->shareGroup().Ptr()) { + ObjectLocalName tex = TextureLocalName(target,ctx->getBindedTexture(target)); + unsigned int oldGlobal = ctx->shareGroup()->getGlobalName(TEXTURE, tex); + // Delete old texture object but only if it is not a target of a EGLImage + if (oldGlobal) { + TextureData* oldTexData = getTextureData(tex); + if (!oldTexData || oldTexData->sourceEGLImage == 0) { + ctx->dispatcher().glDeleteTextures(1, &oldGlobal); + } + } + // replace mapping and bind the new global object + ctx->shareGroup()->replaceGlobalName(TEXTURE, tex,img->globalTexName); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, img->globalTexName); + TextureData *texData = getTextureTargetData(target); + SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION); + texData->width = img->width; + texData->height = img->height; + texData->border = img->border; + texData->internalFormat = img->internalFormat; + texData->sourceEGLImage = imagehndl; + texData->eglImageDetach = s_eglIface->eglDetachEGLImage; + texData->oldGlobal = oldGlobal; + } + } +} + +GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + GET_CTX(); + SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM); + unsigned int imagehndl = SafeUIntFromPointer(image); + EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); + SET_ERROR_IF(!img,GL_INVALID_VALUE); + SET_ERROR_IF(!ctx->shareGroup().Ptr(),GL_INVALID_OPERATION); + + // Get current bounded renderbuffer + // raise INVALID_OPERATIOn if no renderbuffer is bounded + GLuint rb = ctx->getRenderbufferBinding(); + SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION); + ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb); + RenderbufferData *rbData = (RenderbufferData *)objData.Ptr(); + SET_ERROR_IF(!rbData,GL_INVALID_OPERATION); + + // + // flag in the renderbufferData that it is an eglImage target + // + rbData->sourceEGLImage = imagehndl; + rbData->eglImageDetach = s_eglIface->eglDetachEGLImage; + rbData->eglImageGlobalTexName = img->globalTexName; + + // + // if the renderbuffer is attached to a framebuffer + // change the framebuffer attachment in the undelying OpenGL + // to point to the eglImage texture object. + // + if (rbData->attachedFB) { + // update the framebuffer attachment point to the + // underlying texture of the img + GLuint prevFB = ctx->getFramebufferBinding(); + if (prevFB != rbData->attachedFB) { + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + rbData->attachedFB); + } + ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + rbData->attachedPoint, + GL_TEXTURE_2D, + img->globalTexName,0); + if (prevFB != rbData->attachedFB) { + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + prevFB); + } + } +} diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp new file mode 100644 index 0000000..b3555a8 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp @@ -0,0 +1,198 @@ +/* +* 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 "GLESv2Validate.h" +#include + +bool GLESv2Validate::blendEquationMode(GLenum mode){ + return mode == GL_FUNC_ADD || + mode == GL_FUNC_SUBTRACT || + mode == GL_FUNC_REVERSE_SUBTRACT; +} + +bool GLESv2Validate::blendSrc(GLenum s) { + switch(s) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + return true; + } + return false; +} + + +bool GLESv2Validate::blendDst(GLenum d) { + switch(d) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + return true; + } + return false; +} + +bool GLESv2Validate::textureParams(GLenum param){ + switch(param) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + return true; + default: + return false; + } +} + +bool GLESv2Validate::hintTargetMode(GLenum target,GLenum mode){ + + switch(mode) { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: return false; + } + return target == GL_GENERATE_MIPMAP_HINT || target == GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES; +} + +bool GLESv2Validate::capability(GLenum cap){ + switch(cap){ + case GL_BLEND: + case GL_CULL_FACE: + case GL_DEPTH_TEST: + case GL_DITHER: + case GL_POLYGON_OFFSET_FILL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + return true; + } + return false; +} + +bool GLESv2Validate::pixelStoreParam(GLenum param){ + return param == GL_PACK_ALIGNMENT || param == GL_UNPACK_ALIGNMENT; +} + +bool GLESv2Validate::readPixelFrmt(GLenum format){ + switch(format) { + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_RGB: + case GL_RGBA: + return true; + } + return false; +} + + +bool GLESv2Validate::shaderType(GLenum type){ + return type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER; +} + +bool GLESv2Validate::precisionType(GLenum type){ + switch(type){ + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + return true; + } + return false; +} + +bool GLESv2Validate::arrayIndex(GLEScontext * ctx,GLuint index) { + return index < (GLuint)ctx->getCaps()->maxVertexAttribs; +} + +bool GLESv2Validate::pixelType(GLEScontext * ctx,GLenum type) { + if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) + return true; + + return GLESvalidate::pixelType(ctx, type); +} + +bool GLESv2Validate::pixelFrmt(GLEScontext* ctx,GLenum format) { + if(format == GL_DEPTH_COMPONENT) + return true; + + return GLESvalidate::pixelFrmt(ctx, format); +} + +bool GLESv2Validate::attribName(const GLchar* name){ + const GLchar* found = strstr(name,"gl_"); + return (!found) || + (found != name) ; // attrib name does not start with gl_ +} + +bool GLESv2Validate::attribIndex(int index){ + return index >=0 && index < GL_MAX_VERTEX_ATTRIBS; +} + +bool GLESv2Validate::programParam(GLenum pname){ + switch(pname){ + case GL_DELETE_STATUS: + case GL_LINK_STATUS: + case GL_VALIDATE_STATUS: + case GL_INFO_LOG_LENGTH: + case GL_ATTACHED_SHADERS: + case GL_ACTIVE_ATTRIBUTES: + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + case GL_ACTIVE_UNIFORMS: + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + return true; + } + return false; +} + +bool GLESv2Validate::textureIsCubeMap(GLenum target){ + switch(target){ + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return true; + } + return false; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.h b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.h new file mode 100644 index 0000000..6678778 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Validate.h @@ -0,0 +1,44 @@ +/* +* Copyright 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 GLES_V2_VALIDATE_H +#define GLES_V2_VALIDATE_H + +#include +#include +#include + +struct GLESv2Validate:public GLESvalidate{ +static bool blendEquationMode(GLenum mode); +static bool blendSrc(GLenum s); +static bool blendDst(GLenum d); +static bool textureParams(GLenum param); +static bool hintTargetMode(GLenum target,GLenum mode); +static bool capability(GLenum cap); +static bool pixelStoreParam(GLenum param); +static bool readPixelFrmt(GLenum format); +static bool shaderType(GLenum type); +static bool precisionType(GLenum type); +static bool arrayIndex(GLEScontext * ctx,GLuint index); +static bool pixelType(GLEScontext * ctx,GLenum type); +static bool pixelFrmt(GLEScontext* ctx,GLenum format); +static bool attribName(const GLchar* name); +static bool attribIndex(int index); +static bool programParam(GLenum pname); +static bool textureIsCubeMap(GLenum target); +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.cpp b/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.cpp new file mode 100644 index 0000000..b008e91 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.cpp @@ -0,0 +1,98 @@ +/* +* 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 +#include +#include "ProgramData.h" + +ProgramData::ProgramData() : ObjectData(PROGRAM_DATA), + AttachedVertexShader(0), + AttachedFragmentShader(0), + LinkStatus(GL_FALSE), + IsInUse(false), + DeleteStatus(false) { + infoLog = new GLchar[1]; + infoLog[0] = '\0'; +} + +ProgramData::~ProgramData () { + delete[] infoLog; +}; + +void ProgramData::setInfoLog(GLchar* log) { + delete[] infoLog; + infoLog = log; +} + +GLchar* ProgramData::getInfoLog() { + return infoLog; +} + +GLuint ProgramData::getAttachedVertexShader() { + return AttachedVertexShader; +} + +GLuint ProgramData::getAttachedFragmentShader() { + return AttachedFragmentShader; +} + +GLuint ProgramData::getAttachedShader(GLenum type) { + GLuint shader = 0; + switch (type) { + case GL_VERTEX_SHADER: + shader = AttachedVertexShader; + break; + case GL_FRAGMENT_SHADER: + shader = AttachedFragmentShader; + break; + } + return shader; +} + +bool ProgramData::attachShader(GLuint shader,GLenum type) { + if (type==GL_VERTEX_SHADER && AttachedVertexShader==0) { + AttachedVertexShader=shader; + return true; + } + else if (type==GL_FRAGMENT_SHADER && AttachedFragmentShader==0) { + AttachedFragmentShader=shader; + return true; + } + return false; +} + +bool ProgramData::isAttached(GLuint shader) { + return (AttachedFragmentShader==shader || AttachedVertexShader==shader); +} + +bool ProgramData::detachShader(GLuint shader) { + if (AttachedVertexShader==shader) { + AttachedVertexShader = 0; + return true; + } + else if (AttachedFragmentShader==shader) { + AttachedFragmentShader = 0; + return true; + } + return false; +} + +void ProgramData::setLinkStatus(GLint status) { + LinkStatus = status; +} + +GLint ProgramData::getLinkStatus() { + return LinkStatus; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.h b/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.h new file mode 100644 index 0000000..7ce5801 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/ProgramData.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 PROGRAM_DATA_H +#define PROGRAM_DATA_H + +class ProgramData:public ObjectData{ +public: + ProgramData(); + virtual ~ProgramData(); + + GLuint getAttachedVertexShader(); + GLuint getAttachedFragmentShader(); + GLuint getAttachedShader(GLenum type); + + bool attachShader(GLuint shader,GLenum type); + bool isAttached(GLuint shader); + bool detachShader(GLuint shader); + + void setLinkStatus(GLint status); + GLint getLinkStatus(); + + void setInfoLog(GLchar *log); + GLchar* getInfoLog(); + + bool isInUse() const { return IsInUse; } + void setInUse(bool inUse) { IsInUse = inUse; } + + bool getDeleteStatus() const { return DeleteStatus; } + void setDeleteStatus(bool status) { DeleteStatus = status; } +private: + GLuint AttachedVertexShader; + GLuint AttachedFragmentShader; + GLint LinkStatus; + GLchar* infoLog; + bool IsInUse; + bool DeleteStatus; +}; +#endif diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.cpp new file mode 100644 index 0000000..39b23a5 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.cpp @@ -0,0 +1,350 @@ +/* +* Copyright 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 "ShaderParser.h" +#include +#include + +ShaderParser::ShaderParser():ObjectData(SHADER_DATA), + m_type(0), + m_originalSrc(NULL), + m_parsedLines(NULL), + m_deleteStatus(false), + m_program(0) { + m_infoLog = new GLchar[1]; + m_infoLog[0] = '\0'; +}; + +ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA), + m_type(type), + m_originalSrc(NULL), + m_parsedLines(NULL), + m_deleteStatus(false), + m_program(0) { + + m_infoLog = new GLchar[1]; + m_infoLog[0] = '\0'; +}; + +void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar* const* strings,const GLint* length){ + m_src.clear(); + for(int i = 0;i (&m_parsedLines); +}; + +const char* ShaderParser::getOriginalSrc(){ + return m_originalSrc; +} + +void ShaderParser::parseLineNumbers() +{ + m_parsedSrc += "#line 1\n"; +} + +void ShaderParser::parseOriginalSrc() { + m_parsedSrc+=m_src; +} + +void ShaderParser::parseGLSLversion() { + + // + // find in shader the #version token if exist. + // That token should be the first non-comment or blank token + // + const char *src = m_src.c_str(); + const int minGLSLVersion = 120; + int glslVersion = minGLSLVersion; + enum { + PARSE_NONE, + PARSE_IN_C_COMMENT, + PARSE_IN_LINE_COMMENT + } parseState = PARSE_NONE; + const char *c = src; + + #define IS_VALID_VERSION(v) ( (v) == 100 || (v) == 300 || (v) == 310 ) + + while( c && *c != '\0') { + if (parseState == PARSE_IN_C_COMMENT) { + if (*c == '*' && *(c+1) == '/') { + parseState = PARSE_NONE; + c += 2; + } + else c++; + } + else if (parseState == PARSE_IN_LINE_COMMENT) { + if (*c == '\n') { + parseState = PARSE_NONE; + } + c++; + } + else if (*c == '/' && *(c+1) == '/') { + parseState = PARSE_IN_LINE_COMMENT; + c += 2; + } + else if (*c == '/' && *(c+1) == '*') { + parseState = PARSE_IN_C_COMMENT; + c += 2; + } + else if (*c == ' ' || *c == '\t' || *c == '\r' || *c == '\n') { + c++; + } + else { + // + // We have reached the first non-blank character outside + // a comment, this must be a #version token or else #version + // token does not exist in this shader source. + // + if (!strncmp(c,"#version",8)) { + int ver; + if (sscanf(c+8,"%d",&ver) == 1) { + // + // parsed version string correctly, blank out the + // version token from the source, we will add it later at + // the begining of the shader. + // + char *cc = (char *)c; + for (int i=0; i<8; i++,cc++) *cc = ' '; + while (*cc < '0' || *cc > '9') { *cc = ' '; cc++; } + while (*cc >= '0' && *cc <= '9') { *cc = ' '; cc++; } + + // Use the version from the source but only if + // it is larger than our minGLSLVersion + if (!IS_VALID_VERSION(ver) || ver > minGLSLVersion) glslVersion = ver; + } + } + + // + // break the loop, no need to go further on the source. + break; + } + } + + // + // allow to force GLSL version through environment variable + // + const char *forceVersion = getenv("GOOGLE_GLES_FORCE_GLSL_VERSION"); + if (forceVersion) { + int ver; + if (sscanf(forceVersion,"%d",&ver) == 1) { + glslVersion = ver; + } + } + + // + // if glslVersion is defined, add it to the parsed source + // + if (glslVersion > 0) { + char vstr[16]; + sprintf(vstr,"%d",glslVersion); + m_parsedSrc += std::string("#version ") + + std::string(vstr) + + std::string("\n"); + } +} + +void ShaderParser::parseBuiltinConstants() +{ + m_parsedSrc += + "const int _translator_gl_MaxVertexUniformVectors = 256;\n" + "const int _translator_gl_MaxFragmentUniformVectors = 256;\n" + "const int _translator_gl_MaxVaryingVectors = 15;\n" + "#define gl_MaxVertexUniformVectors _translator_gl_MaxVertexUniformVectors\n" + "#define gl_MaxFragmentUniformVectors _translator_gl_MaxFragmentUniformVectors\n" + "#define gl_MaxVaryingVectors _translator_gl_MaxVaryingVectors\n"; + +} + +void ShaderParser::parseOmitPrecision(){ + + //defines we need to add in order to Omit precisions qualifiers + static const GLchar defines[] = { + "#define GLES 1\n" + "#define lowp \n" + "#define mediump \n" + "#define highp \n" + }; + m_parsedSrc+=defines; + + // + // parse the source and blank out precision statements + // which has the following syntax: + // precision {qualifier} {type}; + // where {qualifier} is one of lowp,mediump or hightp + // type is any valid GLES defined type (we do not check that here!) + // NOTE: This is needed in order to workaround driver bug in + // Intel/Linux where the compiler does not get statement like + // "float;", otherwise we could just define a macro named + // precision to be empty. + // + const char *src = m_src.c_str(); + + enum { + PRECISION, + QUALIFIER, + SEMICOLON + } statementState = PRECISION; + const char *precision = NULL; + + enum { + PARSE_NONE, + PARSE_IN_C_COMMENT, + PARSE_IN_LINE_COMMENT + } parseState = PARSE_NONE; + const char *c = src; + const char *t = NULL; + + #define IS_DELIMITER(c) ( (c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' ) + #define IS_TOKEN_START(c) ( ((c) >= 'a' && (c) <='z') || ((c) >= 'A' && (c) <= 'Z') ) + #define IS_TOKEN_DELIMITER(c) ( IS_DELIMITER(c) || (c) == ';' ) + + while( c && *c != '\0') { + if (parseState == PARSE_IN_C_COMMENT) { + if (*c == '*' && *(c+1) == '/') { + parseState = PARSE_NONE; + c += 2; + } + else c++; + } + else if (parseState == PARSE_IN_LINE_COMMENT) { + if (*c == '\n') { + parseState = PARSE_NONE; + } + c++; + } + else if (*c == '/' && *(c+1) == '/') { + parseState = PARSE_IN_LINE_COMMENT; + c += 2; + } + else if (*c == '/' && *(c+1) == '*') { + parseState = PARSE_IN_C_COMMENT; + c += 2; + } + else if (t && IS_TOKEN_DELIMITER(*c)) { + int tokenLen = c - t; + switch (statementState) { + case PRECISION: + if (tokenLen == 9 && !strncmp(t,"precision",9)) { + statementState = QUALIFIER; + precision = t; + } + break; + case QUALIFIER: + if ((tokenLen == 4 && !strncmp(t,"lowp",4)) || + (tokenLen == 7 && !strncmp(t,"mediump",7)) || + (tokenLen == 5 && !strncmp(t,"highp",5))) { + statementState = SEMICOLON; + } + else { + statementState = PRECISION; + } + break; + case SEMICOLON: + if (*c == ';') { + for (char *r = (char *)precision; r<=c ; ++r) { + *r = ' '; //blank the character + } + } + statementState = PRECISION; //search for the next precision line + break; + default: + break; + } + c++; + t = NULL; + } + else if (IS_DELIMITER(*c)) { + c++; + } + else { + if (!t && IS_TOKEN_START(*c)) { + t = c; + } + c++; + } + } +} + +void ShaderParser::parseExtendDefaultPrecision(){ + + //the precision lines which we need to add to the shader + static const GLchar extend[] = { + "#define GLES 1\n" + "precision lowp sampler2D;\n" + "precision lowp samplerCube;\n" + }; + + m_parsedSrc+=extend; +} + +void ShaderParser::clearParsedSrc(){ + m_parsedSrc.clear(); +} + +GLenum ShaderParser::getType() { + return m_type; +} + +void ShaderParser::setInfoLog(GLchar* infoLog) +{ + delete[] m_infoLog; + m_infoLog = infoLog; +} + +GLchar* ShaderParser::getInfoLog() +{ + return m_infoLog; +} + +ShaderParser::~ShaderParser(){ + clearParsedSrc(); + if (m_originalSrc) + free(m_originalSrc); + delete[] m_infoLog; +} diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.h b/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.h new file mode 100644 index 0000000..8cd3940 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLES_V2/ShaderParser.h @@ -0,0 +1,61 @@ +/* +* Copyright 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 SHADER_PARSER_H +#define SHADER_PARSER_H + +#include "GLESv2Context.h" +#include +#include +#include + +class ShaderParser:public ObjectData{ +public: + ShaderParser(); + ShaderParser(GLenum type); + void setSrc(const Version& ver,GLsizei count,const GLchar* const* strings,const GLint* length); + const char* getOriginalSrc(); + const GLchar** parsedLines(); + GLenum getType(); + ~ShaderParser(); + + void setInfoLog(GLchar * infoLog); + GLchar* getInfoLog(); + + void setDeleteStatus(bool val) { m_deleteStatus = val; } + bool getDeleteStatus() const { return m_deleteStatus; } + + void setAttachedProgram(GLuint program) { m_program = program; } + GLuint getAttachedProgram() const { return m_program; } +private: + void parseOriginalSrc(); + void parseGLSLversion(); + void parseBuiltinConstants(); + void parseOmitPrecision(); + void parseExtendDefaultPrecision(); + void parseLineNumbers(); + void clearParsedSrc(); + + GLenum m_type; + char* m_originalSrc; + std::string m_src; + std::string m_parsedSrc; + GLchar* m_parsedLines; + GLchar* m_infoLog; + bool m_deleteStatus; + GLuint m_program; +}; +#endif diff --git a/external/android-emugl/host/libs/Translator/GLcommon/Android.mk b/external/android-emugl/host/libs/Translator/GLcommon/Android.mk new file mode 100644 index 0000000..93cc30d --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/Android.mk @@ -0,0 +1,43 @@ +LOCAL_PATH := $(call my-dir) + +host_common_SRC_FILES := \ + GLDispatch.cpp \ + GLutils.cpp \ + GLEScontext.cpp \ + GLESvalidate.cpp \ + GLESpointer.cpp \ + GLESbuffer.cpp \ + RangeManip.cpp \ + TextureUtils.cpp \ + PaletteTexture.cpp \ + etc1.cpp \ + objectNameManager.cpp \ + FramebufferData.cpp + +host_GL_COMMON_LINKER_FLAGS := +host_common_LDLIBS := +host_common_LDFLAGS := + +ifeq ($(BUILD_TARGET_OS),linux) +# host_common_LDFLAGS += -Wl,--whole-archive + host_common_LDLIBS += -ldl + host_common_LDFLAGS += -Wl,-Bsymbolic +endif + +ifeq ($(BUILD_TARGET_OS),windows) + host_common_LDLIBS += -lgdi32 + host_common_LDFLAGS += -Wl,--add-stdcall-alias +endif + +### EGL host implementation ######################## + +$(call emugl-begin-host-static-library,libGLcommon) + +LOCAL_SRC_FILES := $(host_common_SRC_FILES) +$(call emugl-export,LDLIBS,$(host_common_LDLIBS)) +$(call emugl-export,LDFLAGS,$(host_common_LDFLAGS)) +$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/../include $(EMUGL_PATH)/shared) +$(call emugl-export,STATIC_LIBRARIES, libemugl_common) + +$(call emugl-end-module) + diff --git a/external/android-emugl/host/libs/Translator/GLcommon/CMakeLists.txt b/external/android-emugl/host/libs/Translator/GLcommon/CMakeLists.txt new file mode 100644 index 0000000..79339f6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/CMakeLists.txt @@ -0,0 +1,17 @@ +set(SOURCES + GLDispatch.cpp + GLutils.cpp + GLEScontext.cpp + GLESvalidate.cpp + GLESpointer.cpp + GLESbuffer.cpp + RangeManip.cpp + TextureUtils.cpp + PaletteTexture.cpp + etc1.cpp + objectNameManager.cpp + FramebufferData.cpp) + +add_library(GLcommon ${SOURCES}) +target_link_libraries(GLcommon + emugl_common) diff --git a/external/android-emugl/host/libs/Translator/GLcommon/FramebufferData.cpp b/external/android-emugl/host/libs/Translator/GLcommon/FramebufferData.cpp new file mode 100644 index 0000000..2e35c8d --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/FramebufferData.cpp @@ -0,0 +1,215 @@ +/* +* 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 +#include +#include +#include + +RenderbufferData::RenderbufferData() : sourceEGLImage(0), + eglImageDetach(NULL), + attachedFB(0), + attachedPoint(0), + eglImageGlobalTexName(0) { +} + +RenderbufferData::~RenderbufferData() { + if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage); +} + + +FramebufferData::FramebufferData(GLuint name):m_dirty(false) { + m_fbName = name; + for (int i=0; iattachedFB = m_fbName; + rbData->attachedPoint = attachment; + } + + m_dirty = true; + } +} + +GLuint FramebufferData::getAttachment(GLenum attachment, + GLenum *outTarget, + ObjectDataPtr *outObj) { + int idx = attachmentPointIndex(attachment); + if (outTarget) *outTarget = m_attachPoints[idx].target; + if (outObj) *outObj = m_attachPoints[idx].obj; + return m_attachPoints[idx].name; +} + +int FramebufferData::attachmentPointIndex(GLenum attachment) +{ + switch(attachment) { + case GL_COLOR_ATTACHMENT0_OES: + return 0; + case GL_DEPTH_ATTACHMENT_OES: + return 1; + case GL_STENCIL_ATTACHMENT_OES: + return 2; + default: + return MAX_ATTACH_POINTS; + } +} + +void FramebufferData::detachObject(int idx) { + if (m_attachPoints[idx].target == GL_RENDERBUFFER_OES && m_attachPoints[idx].obj.Ptr() != NULL) { + RenderbufferData *rbData = (RenderbufferData *)m_attachPoints[idx].obj.Ptr(); + rbData->attachedFB = 0; + rbData->attachedPoint = 0; + } + + if(m_attachPoints[idx].owned) + { + switch(m_attachPoints[idx].target) + { + case GL_RENDERBUFFER_OES: + GLEScontext::dispatcher().glDeleteRenderbuffersEXT(1, &(m_attachPoints[idx].name)); + break; + case GL_TEXTURE_2D: + GLEScontext::dispatcher().glDeleteTextures(1, &(m_attachPoints[idx].name)); + break; + } + } + + m_attachPoints[idx].target = 0; + m_attachPoints[idx].name = 0; + m_attachPoints[idx].obj = ObjectDataPtr(NULL); + m_attachPoints[idx].owned = false; +} + +void FramebufferData::validate(GLEScontext* ctx) +{ + if(!getAttachment(GL_COLOR_ATTACHMENT0_OES, NULL, NULL)) + { + // GLES does not require the framebuffer to have a color attachment. + // OpenGL does. Therefore, if no color is attached, create a dummy + // color texture and attach it. + // This dummy color texture will is owned by the FramebufferObject, + // and will be released by it when its object is detached. + + GLint type = GL_NONE; + GLint name = 0; + + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); + if(type != GL_NONE) + { + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name); + } + else + { + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); + if(type != GL_NONE) + { + ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name); + } + else + { + // No color, depth or stencil attachments - do nothing + return; + } + } + + // Find the existing attachment(s) dimensions + GLint width = 0; + GLint height = 0; + + if(type == GL_RENDERBUFFER) + { + GLint prev; + ctx->dispatcher().glGetIntegerv(GL_RENDERBUFFER_BINDING, &prev); + ctx->dispatcher().glBindRenderbufferEXT(GL_RENDERBUFFER, name); + ctx->dispatcher().glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); + ctx->dispatcher().glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); + ctx->dispatcher().glBindRenderbufferEXT(GL_RENDERBUFFER, prev); + } + else if(type == GL_TEXTURE) + { + GLint prev; + ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, name); + ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prev); + } + + // Create the color attachment and attch it + unsigned int tex = ctx->shareGroup()->genGlobalName(TEXTURE); + GLint prev; + ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev); + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, tex); + + ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + ctx->dispatcher().glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex, 0); + setAttachment(GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex, ObjectDataPtr(NULL), true); + + ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prev); + } + + if(m_dirty) + { + // This is a workaround for a bug found in several OpenGL + // drivers (e.g. ATI's) - after the framebuffer attachments + // have changed, and before the next draw, unbind and rebind + // the framebuffer to sort things out. + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER,0); + ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER,ctx->shareGroup()->getGlobalName(FRAMEBUFFER,m_fbName)); + + m_dirty = false; + } +} + diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLDispatch.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLDispatch.cpp new file mode 100644 index 0000000..ff491a5 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLDispatch.cpp @@ -0,0 +1,117 @@ +/* +* 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 "GLcommon/GLDispatch.h" +#include "GLcommon/GLLibrary.h" + +#include "emugl/common/lazy_instance.h" +#include "emugl/common/shared_library.h" + +#include "OpenglCodecCommon/ErrorLog.h" + +#ifdef __linux__ +#include +#elif defined(WIN32) +#include +#endif + +#include + +typedef GlLibrary::GlFunctionPointer GL_FUNC_PTR; + +static GL_FUNC_PTR getGLFuncAddress(const char *funcName, GlLibrary* glLib) { + return glLib->findSymbol(funcName); +} + +#define LOAD_GL_FUNC(return_type, func_name, signature, args) do { \ + if (!func_name) { \ + void* address = (void *)getGLFuncAddress(#func_name, glLib); \ + if (address) { \ + func_name = (__typeof__(func_name))(address); \ + } else { \ + fprintf(stderr, "Could not load func %s\n", #func_name); \ + func_name = (__typeof__(func_name))(dummy_##func_name); \ + } \ + } \ + } while (0); + +#define LOAD_GLEXT_FUNC(return_type, func_name, signature, args) do { \ + if (!func_name) { \ + void* address = (void *)getGLFuncAddress(#func_name, glLib); \ + if (address) { \ + func_name = (__typeof__(func_name))(address); \ + } \ + } \ + } while (0); + + +// Define dummy functions, only for non-extensions. + +#define RETURN_void return +#define RETURN_GLboolean return GL_FALSE +#define RETURN_GLint return 0 +#define RETURN_GLuint return 0U +#define RETURN_GLenum return 0 +#define RETURN_int return 0 +#define RETURN_GLconstubyteptr return NULL + +#define RETURN_(x) RETURN_ ## x + +#define DEFINE_DUMMY_FUNCTION(return_type, func_name, signature, args) \ +static return_type dummy_##func_name signature { \ + RETURN_(return_type); \ +} + +#define DEFINE_DUMMY_EXTENSION_FUNCTION(return_type, func_name, signature, args) \ + // nothing here + +LIST_GLES_FUNCTIONS(DEFINE_DUMMY_FUNCTION, DEFINE_DUMMY_EXTENSION_FUNCTION) + +// Initializing static GLDispatch members*/ + +emugl::Mutex GLDispatch::s_lock; + +#define GL_DISPATCH_DEFINE_POINTER(return_type, function_name, signature, args) \ + GL_APICALL return_type (GL_APIENTRY *GLDispatch::function_name) signature = NULL; + +LIST_GLES_FUNCTIONS(GL_DISPATCH_DEFINE_POINTER, GL_DISPATCH_DEFINE_POINTER) + +// Constructor. +GLDispatch::GLDispatch() : m_isLoaded(false) {} + +void GLDispatch::dispatchFuncs(GLESVersion version, GlLibrary* glLib) { + emugl::Mutex::AutoLock mutex(s_lock); + if(m_isLoaded) + return; + + /* Loading OpenGL functions which are needed for implementing BOTH GLES 1.1 & GLES 2.0*/ + LIST_GLES_COMMON_FUNCTIONS(LOAD_GL_FUNC) + LIST_GLES_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC) + + /* Loading OpenGL functions which are needed ONLY for implementing GLES 1.1*/ + if(version == GLES_1_1){ + LIST_GLES1_ONLY_FUNCTIONS(LOAD_GL_FUNC) + LIST_GLES1_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC) + } else if (version == GLES_2_0){ + LIST_GLES2_ONLY_FUNCTIONS(LOAD_GL_FUNC) + LIST_GLES2_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC) + } + + /* Load glGetStringi() if it is available, so use LOAD_GLEXT_FUNC */ + LIST_GLES3_ONLY_FUNCTIONS(LOAD_GLEXT_FUNC) + + m_isLoaded = true; +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLESbuffer.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLESbuffer.cpp new file mode 100644 index 0000000..5dcdd65 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLESbuffer.cpp @@ -0,0 +1,55 @@ +/* +* 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 +#include + +bool GLESbuffer::setBuffer(GLuint size,GLuint usage,const GLvoid* data) { + m_size = size; + m_usage = usage; + if(m_data) { + delete [] m_data; + m_data = NULL; + } + m_data = new unsigned char[size]; + if(m_data) { + if(data) { + memcpy(m_data,data,size); + } + m_conversionManager.clear(); + m_conversionManager.addRange(Range(0,m_size)); + return true; + } + return false; +} + +bool GLESbuffer::setSubBuffer(GLint offset,GLuint size,const GLvoid* data) { + if(offset + size > m_size) return false; + memcpy(m_data+offset,data,size); + m_conversionManager.addRange(Range(offset,size)); + m_conversionManager.merge(); + return true; +} + +void GLESbuffer::getConversions(const RangeList& rIn,RangeList& rOut) { + m_conversionManager.delRanges(rIn,rOut); + rOut.merge(); +} + +GLESbuffer::~GLESbuffer() { + if(m_data) { + delete [] m_data; + } +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLEScontext.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLEScontext.cpp new file mode 100644 index 0000000..9cdc427 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLEScontext.cpp @@ -0,0 +1,865 @@ +/* +* Copyright 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//decleration +static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize); +static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize); +static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize); +static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize); + +GLESConversionArrays::~GLESConversionArrays() { + for(std::map::iterator it = m_arrays.begin(); it != m_arrays.end();it++) { + if((*it).second.allocated){ + if((*it).second.type == GL_FLOAT){ + GLfloat* p = (GLfloat *)((*it).second.data); + if(p) delete[] p; + } else if((*it).second.type == GL_SHORT){ + GLshort* p = (GLshort *)((*it).second.data); + if(p) delete[] p; + } + } + } +} + +void GLESConversionArrays::allocArr(unsigned int size,GLenum type){ + if(type == GL_FIXED){ + m_arrays[m_current].data = new GLfloat[size]; + m_arrays[m_current].type = GL_FLOAT; + } else if(type == GL_BYTE){ + m_arrays[m_current].data = new GLshort[size]; + m_arrays[m_current].type = GL_SHORT; + } + m_arrays[m_current].stride = 0; + m_arrays[m_current].allocated = true; +} + +void GLESConversionArrays::setArr(void* data,unsigned int stride,GLenum type){ + m_arrays[m_current].type = type; + m_arrays[m_current].data = data; + m_arrays[m_current].stride = stride; + m_arrays[m_current].allocated = false; +} + +void* GLESConversionArrays::getCurrentData(){ + return m_arrays[m_current].data; +} + +ArrayData& GLESConversionArrays::getCurrentArray(){ + return m_arrays[m_current]; +} + +unsigned int GLESConversionArrays::getCurrentIndex(){ + return m_current; +} + +ArrayData& GLESConversionArrays::operator[](int i){ + return m_arrays[i]; +} + +void GLESConversionArrays::operator++(){ + m_current++; +} + +GLDispatch GLEScontext::s_glDispatch; +emugl::Mutex GLEScontext::s_lock; +std::string* GLEScontext::s_glExtensions= NULL; +std::string GLEScontext::s_glVendor; +std::string GLEScontext::s_glRenderer; +std::string GLEScontext::s_glVersion; +GLSupport GLEScontext::s_glSupport; + +Version::Version():m_major(0), + m_minor(0), + m_release(0){}; + +Version::Version(int major,int minor,int release):m_major(major), + m_minor(minor), + m_release(release){}; + +Version::Version(const Version& ver):m_major(ver.m_major), + m_minor(ver.m_minor), + m_release(ver.m_release){} + +Version::Version(const char* versionString){ + m_release = 0; + if((!versionString) || + ((!(sscanf(versionString,"%d.%d" ,&m_major,&m_minor) == 2)) && + (!(sscanf(versionString,"%d.%d.%d",&m_major,&m_minor,&m_release) == 3)))){ + m_major = m_minor = 0; // the version is not in the right format + } +} + +Version& Version::operator=(const Version& ver){ + m_major = ver.m_major; + m_minor = ver.m_minor; + m_release = ver.m_release; + return *this; +} + +bool Version::operator<(const Version& ver) const{ + if(m_major < ver.m_major) return true; + if(m_major == ver.m_major){ + if(m_minor < ver.m_minor) return true; + if(m_minor == ver.m_minor){ + return m_release < ver.m_release; + } + } + return false; +} + +static std::string getHostExtensionsString(GLDispatch* dispatch) { + // glGetString(GL_EXTENSIONS) is deprecated in GL 3.0, one has to use + // glGetStringi(GL_EXTENSIONS, index) instead to get individual extension + // names. Recent desktop drivers implement glGetStringi() but have a + // version of glGetString() that returns NULL, so deal with this by + // doing the following: + // + // - If glGetStringi() is available, and glGetIntegerv(GL_NUM_EXTENSIONS &num_exts) + // gives a nonzero value, use it to build the extensions + // string, using simple spaces to separate the names. + // + // - Otherwise, fallback to getGetString(). If it returns NULL, return + // an empty string. + // + + std::string result; + int num_exts = 0; + + if (dispatch->glGetStringi) { + dispatch->glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts); + GLenum err = dispatch->glGetError(); + if (err == GL_NO_ERROR) { + for (int n = 0; n < num_exts; n++) { + const char* ext = reinterpret_cast( + dispatch->glGetStringi(GL_EXTENSIONS, n)); + if (ext != NULL) { + if (!result.empty()) { + result += " "; + } + result += ext; + } + } + } + } + + // If glGetIntegerv does not affect the value, + // our system does not actually support + // GL 3.0 style extension getting. + if (!dispatch->glGetStringi || num_exts == 0) { + const char* extensions = reinterpret_cast( + dispatch->glGetString(GL_EXTENSIONS)); + if (extensions) { + result = extensions; + } + } + + // For the sake of initCapsLocked() add a starting and trailing space. + if (!result.empty()) { + if (result[0] != ' ') { + result.insert(0, 1, ' '); + } + if (result[result.size() - 1U] != ' ') { + result += ' '; + } + } + return result; +} + +static GLuint getIndex(GLenum indices_type, const GLvoid* indices, unsigned int i) { + switch (indices_type) { + case GL_UNSIGNED_BYTE: + return static_cast(indices)[i]; + case GL_UNSIGNED_SHORT: + return static_cast(indices)[i]; + case GL_UNSIGNED_INT: + return static_cast(indices)[i]; + default: + ERR("**** ERROR unknown type 0x%x (%s,%d)\n", indices_type, __FUNCTION__,__LINE__); + return 0; + } +} + +void GLEScontext::init(GlLibrary* glLib) { + + if (!s_glExtensions) { + initCapsLocked(reinterpret_cast( + getHostExtensionsString(&s_glDispatch).c_str())); + // NOTE: the string below corresponds to the extensions reported + // by this context, which is initialized in each GLESv1 or GLESv2 + // context implementation, based on the parsing of the host + // extensions string performed by initCapsLocked(). I.e. it will + // be populated after calling this ::init() method. + s_glExtensions = new std::string(""); + } + + if (!m_initialized) { + initExtensionString(); + + int maxTexUnits = getMaxTexUnits(); + m_texState = new textureUnitState[maxTexUnits]; + for (int i=0;i(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + m_map[arrType]->setBuffer(size,type,stride,vbo,bufferName,offset,normalize); + return static_cast(vbo->getData()) + offset; + } + m_map[arrType]->setArray(size,type,stride,data,normalize); + return data; +} + +void GLEScontext::enableArr(GLenum arr,bool enable) { + m_map[arr]->enable(enable); +} + +bool GLEScontext::isArrEnabled(GLenum arr) { + return m_map[arr]->isEnable(); +} + +const GLESpointer* GLEScontext::getPointer(GLenum arrType) { + if (m_map.find(arrType) != m_map.end()) return m_map[arrType]; + return NULL; +} + +static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) { + + for(unsigned int i = 0; i < nBytes;i+=strideOut) { + const GLfixed* fixed_data = (const GLfixed *)dataIn; + //filling attrib + for(int j=0;j(&static_cast(dataOut)[i])[j] = X2F(fixed_data[j]); + } + dataIn += strideIn; + } +} + +static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) { + for(int i = 0 ;i < count ;i++) { + GLuint index = getIndex(indices_type, indices, i); + + const GLfixed* fixed_data = (GLfixed *)(dataIn + index*strideIn); + GLfloat* float_data = reinterpret_cast(static_cast(dataOut) + index*strideOut); + + for(int j=0;j(&static_cast(dataOut)[i])[j] = B2S(byte_data[j]); + } + dataIn += strideIn; + } +} + +static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) { + for(int i = 0 ;i < count ;i++) { + GLuint index = getIndex(indices_type, indices, i); + const GLbyte* bytes_data = (GLbyte *)(dataIn + index*strideIn); + GLshort* short_data = reinterpret_cast(static_cast(dataOut) + index*strideOut); + + for(int j=0;jgetSize()*4; //4 is the sizeof GLfixed or GLfloat in bytes + int stride = p->getStride()?p->getStride():attribSize; + int start = p->getBufferOffset()+first*attribSize; + if(!p->getStride()) { + list.addRange(Range(start,count*attribSize)); + } else { + for(int i = 0 ;i < count; i++,start+=stride) { + list.addRange(Range(start,attribSize)); + } + } +} + +static void indirectToBytesRanges(const GLvoid* indices,GLenum indices_type,GLsizei count,GLESpointer* p,RangeList& list) { + + int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes + int stride = p->getStride()?p->getStride():attribSize; + int start = p->getBufferOffset(); + for(int i=0 ; i < count; i++) { + GLuint index = getIndex(indices_type, indices, i); + list.addRange(Range(start+index*stride,attribSize)); + + } +} + +int bytesRangesToIndices(RangeList& ranges,GLESpointer* p,GLuint* indices) { + + int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes + int stride = p->getStride()?p->getStride():attribSize; + int offset = p->getBufferOffset(); + + int n = 0; + for(int i=0;igetType(); + int attribSize = p->getSize(); + unsigned int size = attribSize*count + first; + unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte); + cArrs.allocArr(size,type); + int stride = p->getStride()?p->getStride():bytes*attribSize; + const char* data = (const char*)p->getArrayData() + (first*stride); + + if(type == GL_FIXED) { + convertFixedDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLfloat),attribSize*sizeof(GLfloat),attribSize); + } else if(type == GL_BYTE) { + convertByteDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLshort),attribSize*sizeof(GLshort),attribSize); + } +} + +void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) { + + RangeList ranges; + RangeList conversions; + GLuint* indices = NULL; + int attribSize = p->getSize(); + int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize; + char* data = (char*)p->getBufferData() + (first*stride); + + if(p->bufferNeedConversion()) { + directToBytesRanges(first,count,p,ranges); //converting indices range to buffer bytes ranges by offset + p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted + + if(conversions.size()) { // there are some elements to convert + indices = new GLuint[count]; + int nIndices = bytesRangesToIndices(conversions,p,indices); //converting bytes ranges by offset to indices in this array + convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,indices,stride,attribSize); + } + } + if(indices) delete[] indices; + cArrs.setArr(data,p->getStride(),GL_FLOAT); +} + +unsigned int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) { + //finding max index + unsigned int max = 0; + if(type == GL_UNSIGNED_BYTE) { + GLubyte* b_indices =(GLubyte *)indices; + for(int i=0;i max) max = b_indices[i]; + } + } else if (type == GL_UNSIGNED_SHORT) { + GLushort* us_indices =(GLushort *)indices; + for(int i=0;i max) max = us_indices[i]; + } + } else { // type == GL_UNSIGNED_INT + GLuint* ui_indices =(GLuint *)indices; + for(int i=0;i max) max = ui_indices[i]; + } + } + return max; +} + +void GLEScontext::convertIndirect(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) { + GLenum type = p->getType(); + int maxElements = findMaxIndex(count,indices_type,indices) + 1; + + int attribSize = p->getSize(); + int size = attribSize * maxElements; + unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte); + cArrs.allocArr(size,type); + int stride = p->getStride()?p->getStride():bytes*attribSize; + + const char* data = (const char*)p->getArrayData(); + if(type == GL_FIXED) { + convertFixedIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLfloat),attribSize); + } else if(type == GL_BYTE){ + convertByteIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLshort),attribSize); + } +} + +void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) { + RangeList ranges; + RangeList conversions; + GLuint* conversionIndices = NULL; + int attribSize = p->getSize(); + int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize; + char* data = static_cast(p->getBufferData()); + if(p->bufferNeedConversion()) { + indirectToBytesRanges(indices,indices_type,count,p,ranges); //converting indices range to buffer bytes ranges by offset + p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted + if(conversions.size()) { // there are some elements to convert + conversionIndices = new GLuint[count]; + int nIndices = bytesRangesToIndices(conversions,p,conversionIndices); //converting bytes ranges by offset to indices in this array + convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,conversionIndices,stride,attribSize); + } + } + if(conversionIndices) delete[] conversionIndices; + cArrs.setArr(data,p->getStride(),GL_FLOAT); +} + + + +void GLEScontext::bindBuffer(GLenum target,GLuint buffer) { + if(target == GL_ARRAY_BUFFER) { + m_arrayBuffer = buffer; + } else { + m_elementBuffer = buffer; + } +} + +void GLEScontext::unbindBuffer(GLuint buffer) { + if(m_arrayBuffer == buffer) + { + m_arrayBuffer = 0; + } + if(m_elementBuffer == buffer) + { + m_elementBuffer = 0; + } +} + +//checks if any buffer is binded to target +bool GLEScontext::isBindedBuffer(GLenum target) { + if(target == GL_ARRAY_BUFFER) { + return m_arrayBuffer != 0; + } else { + return m_elementBuffer != 0; + } +} + +GLuint GLEScontext::getBuffer(GLenum target) { + return target == GL_ARRAY_BUFFER ? m_arrayBuffer:m_elementBuffer; +} + +GLvoid* GLEScontext::getBindedBuffer(GLenum target) { + GLuint bufferName = getBuffer(target); + if(!bufferName) return NULL; + + GLESbuffer* vbo = static_cast(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + return vbo->getData(); +} + +void GLEScontext::getBufferSize(GLenum target,GLint* param) { + GLuint bufferName = getBuffer(target); + GLESbuffer* vbo = static_cast(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + *param = vbo->getSize(); +} + +void GLEScontext::getBufferUsage(GLenum target,GLint* param) { + GLuint bufferName = getBuffer(target); + GLESbuffer* vbo = static_cast(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + *param = vbo->getUsage(); +} + +bool GLEScontext::setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage) { + GLuint bufferName = getBuffer(target); + if(!bufferName) return false; + GLESbuffer* vbo = static_cast(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + return vbo->setBuffer(size,usage,data); +} + +bool GLEScontext::setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data) { + + GLuint bufferName = getBuffer(target); + if(!bufferName) return false; + GLESbuffer* vbo = static_cast(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); + return vbo->setSubBuffer(offset,size,data); +} + +const char * GLEScontext::getExtensionString() { + const char * ret; + s_lock.lock(); + if (s_glExtensions) + ret = s_glExtensions->c_str(); + else + ret=""; + s_lock.unlock(); + return ret; +} + +const char * GLEScontext::getVendorString() const { + return s_glVendor.c_str(); +} + +const char * GLEScontext::getRendererString() const { + return s_glRenderer.c_str(); +} + +const char * GLEScontext::getVersionString() const { + return s_glVersion.c_str(); +} + +void GLEScontext::getGlobalLock() { + s_lock.lock(); +} + +void GLEScontext::releaseGlobalLock() { + s_lock.unlock(); +} + + +void GLEScontext::initCapsLocked(const GLubyte * extensionString) +{ + const char* cstring = (const char*)extensionString; + + s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&s_glSupport.maxVertexAttribs); + s_glDispatch.glGetIntegerv(GL_MAX_CLIP_PLANES,&s_glSupport.maxClipPlane); + s_glDispatch.glGetIntegerv(GL_MAX_LIGHTS,&s_glSupport.maxLights); + s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_glSupport.maxTexSize); + s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_UNITS,&s_glSupport.maxTexUnits); + s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&s_glSupport.maxTexImageUnits); + s_glDispatch.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &s_glSupport.maxCombinedTexImageUnits); + const GLubyte* glslVersion = s_glDispatch.glGetString(GL_SHADING_LANGUAGE_VERSION); + s_glSupport.glslVersion = Version((const char*)(glslVersion)); + const GLubyte* glVersion = s_glDispatch.glGetString(GL_VERSION); + + if (strstr(cstring,"GL_EXT_bgra ")!=NULL) + s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888 = true; + + if (strstr(cstring,"GL_EXT_framebuffer_object ")!=NULL) + s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT = true; + + if (strstr(cstring,"GL_ARB_vertex_blend ")!=NULL) + s_glSupport.GL_ARB_VERTEX_BLEND = true; + + if (strstr(cstring,"GL_ARB_matrix_palette ")!=NULL) + s_glSupport.GL_ARB_MATRIX_PALETTE = true; + + if (strstr(cstring,"GL_EXT_packed_depth_stencil ")!=NULL ) + s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL = true; + + if (strstr(cstring,"GL_OES_read_format ")!=NULL) + s_glSupport.GL_OES_READ_FORMAT = true; + + if (strstr(cstring,"GL_ARB_half_float_pixel ")!=NULL) + s_glSupport.GL_ARB_HALF_FLOAT_PIXEL = true; + + if (strstr(cstring,"GL_NV_half_float ")!=NULL) + s_glSupport.GL_NV_HALF_FLOAT = true; + + if (strstr(cstring,"GL_ARB_half_float_vertex ")!=NULL) + s_glSupport.GL_ARB_HALF_FLOAT_VERTEX = true; + + if (strstr(cstring,"GL_SGIS_generate_mipmap ")!=NULL) + s_glSupport.GL_SGIS_GENERATE_MIPMAP = true; + + if (strstr(cstring,"GL_ARB_ES2_compatibility ")!=NULL) + s_glSupport.GL_ARB_ES2_COMPATIBILITY = true; + + if (strstr(cstring,"GL_OES_standard_derivatives ")!=NULL) + s_glSupport.GL_OES_STANDARD_DERIVATIVES = true; + + if (strstr(cstring,"GL_ARB_texture_non_power_of_two")!=NULL) + s_glSupport.GL_OES_TEXTURE_NPOT = true; + + if (!(Version((const char*)glVersion) < Version("3.0")) || strstr(cstring,"GL_OES_rgb8_rgba8")!=NULL) + s_glSupport.GL_OES_RGB8_RGBA8 = true; + +} + +void GLEScontext::buildStrings(const char* baseVendor, + const char* baseRenderer, const char* baseVersion, const char* version) +{ + static const char VENDOR[] = {"Google ("}; + static const char RENDERER[] = {"Android Emulator OpenGL ES Translator ("}; + const size_t VENDOR_LEN = sizeof(VENDOR) - 1; + const size_t RENDERER_LEN = sizeof(RENDERER) - 1; + + // Sanitize the strings as some OpenGL implementations return NULL + // when asked the basic questions (this happened at least once on a client + // machine) + if (!baseVendor) { + baseVendor = "N/A"; + } + if (!baseRenderer) { + baseRenderer = "N/A"; + } + if (!baseVersion) { + baseVersion = "N/A"; + } + if (!version) { + version = "N/A"; + } + + size_t baseVendorLen = strlen(baseVendor); + s_glVendor.clear(); + s_glVendor.reserve(baseVendorLen + VENDOR_LEN + 1); + s_glVendor.append(VENDOR, VENDOR_LEN); + s_glVendor.append(baseVendor, baseVendorLen); + s_glVendor.append(")", 1); + + size_t baseRendererLen = strlen(baseRenderer); + s_glRenderer.clear(); + s_glRenderer.reserve(baseRendererLen + RENDERER_LEN + 1); + s_glRenderer.append(RENDERER, RENDERER_LEN); + s_glRenderer.append(baseRenderer, baseRendererLen); + s_glRenderer.append(")", 1); + + size_t baseVersionLen = strlen(baseVersion); + size_t versionLen = strlen(version); + s_glVersion.clear(); + s_glVersion.reserve(baseVersionLen + versionLen + 3); + s_glVersion.append(version, versionLen); + s_glVersion.append(" (", 2); + s_glVersion.append(baseVersion, baseVersionLen); + s_glVersion.append(")", 1); +} + +bool GLEScontext::isTextureUnitEnabled(GLenum unit) { + for (int i=0;i0 && glGetIntegerv(pname,iParams)) { + while(numParams >= 0) + { + params[numParams] = I2X(iParams[numParams]); + numParams--; + } + result = true; + } + delete [] iParams; + + return result; +} + +bool GLEScontext::glGetFloatv(GLenum pname, GLfloat *params) +{ + bool result = false; + GLint numParams = 1; + + GLint* iParams = new GLint[numParams]; + if (numParams>0 && glGetIntegerv(pname,iParams)) { + while(numParams >= 0) + { + params[numParams] = (GLfloat)iParams[numParams]; + numParams--; + } + result = true; + } + delete [] iParams; + + return result; +} + +bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params) +{ + switch(pname) + { + case GL_ARRAY_BUFFER_BINDING: + *params = m_arrayBuffer; + break; + + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + *params = m_elementBuffer; + break; + + case GL_TEXTURE_BINDING_CUBE_MAP: + *params = m_texState[m_activeTexture][TEXTURE_CUBE_MAP].texture; + break; + + case GL_TEXTURE_BINDING_2D: + *params = m_texState[m_activeTexture][TEXTURE_2D].texture; + break; + + case GL_ACTIVE_TEXTURE: + *params = m_activeTexture+GL_TEXTURE0; + break; + + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + *params = GL_UNSIGNED_BYTE; + break; + + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + *params = GL_RGBA; + break; + + case GL_MAX_TEXTURE_SIZE: + *params = getMaxTexSize(); + break; + default: + return false; + } + + return true; +} + +TextureTarget GLEScontext::GLTextureTargetToLocal(GLenum target) { + TextureTarget value=TEXTURE_2D; + switch (target) { + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + value = TEXTURE_CUBE_MAP; + break; + case GL_TEXTURE_2D: + value = TEXTURE_2D; + break; + } + return value; +} + +unsigned int GLEScontext::getBindedTexture(GLenum target) { + TextureTarget pos = GLTextureTargetToLocal(target); + return m_texState[m_activeTexture][pos].texture; +} + +unsigned int GLEScontext::getBindedTexture(GLenum unit, GLenum target) { + TextureTarget pos = GLTextureTargetToLocal(target); + return m_texState[unit-GL_TEXTURE0][pos].texture; +} + +void GLEScontext::setBindedTexture(GLenum target, unsigned int tex) { + TextureTarget pos = GLTextureTargetToLocal(target); + m_texState[m_activeTexture][pos].texture = tex; +} + +void GLEScontext::setTextureEnabled(GLenum target, GLenum enable) { + TextureTarget pos = GLTextureTargetToLocal(target); + m_texState[m_activeTexture][pos].enabled = enable; +} + +#define INTERNAL_NAME(x) (x +0x100000000ll); + +ObjectLocalName GLEScontext::getDefaultTextureName(GLenum target) { + ObjectLocalName name = 0; + switch (GLTextureTargetToLocal(target)) { + case TEXTURE_2D: + name = INTERNAL_NAME(0); + break; + case TEXTURE_CUBE_MAP: + name = INTERNAL_NAME(1); + break; + default: + name = 0; + break; + } + return name; +} + +void GLEScontext::drawValidate(void) +{ + if(m_framebuffer == 0) + return; + + ObjectDataPtr fbObj = m_shareGroup->getObjectData(FRAMEBUFFER,m_framebuffer); + if (fbObj.Ptr() == NULL) + return; + + FramebufferData *fbData = (FramebufferData *)fbObj.Ptr(); + + fbData->validate(this); +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLESpointer.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLESpointer.cpp new file mode 100644 index 0000000..372257e --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLESpointer.cpp @@ -0,0 +1,109 @@ +/* +* 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 +#include + +GLESpointer::GLESpointer():m_size(4), + m_type(GL_FLOAT), + m_stride(0), + m_enabled(false), + m_normalize(false), + m_data(NULL), + m_buffer(NULL), + m_bufferName(0), + m_buffOffset(0), + m_isVBO(false){}; + + +GLenum GLESpointer:: getType() const { + return m_type; +} + +GLint GLESpointer::getSize() const { + return m_size; +} + +GLsizei GLESpointer::getStride() const { + return m_stride; +} + +const GLvoid* GLESpointer::getArrayData() const { + return m_data; +} + +GLvoid* GLESpointer::getBufferData() const { + return m_buffer ? static_cast(m_buffer->getData()) + m_buffOffset : NULL; +} + +const GLvoid* GLESpointer::getData() const{ + return m_isVBO ? getBufferData():getArrayData(); +} + +void GLESpointer::redirectPointerData(){ + m_data = getBufferData(); +} + +GLuint GLESpointer::getBufferName() const { + return m_bufferName; +} + +unsigned int GLESpointer::getBufferOffset() const { + + return m_buffOffset; +} + +bool GLESpointer::isEnable() const { + return m_enabled; +} + +bool GLESpointer::isNormalize() const { + return m_normalize; +} + +bool GLESpointer::isVBO() const { + return m_isVBO; +} + +void GLESpointer::enable(bool b) { + m_enabled = b; +} + +void GLESpointer::setArray(GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) { + m_size = size; + m_type = type; + m_stride = stride; + m_data = data; + m_buffer = NULL; + m_bufferName = 0; + m_normalize = normalize; + m_isVBO = false; +} + +void GLESpointer::setBuffer(GLint size,GLenum type,GLsizei stride,GLESbuffer* buf,GLuint bufferName,int offset,bool normalize) { + m_size = size; + m_type = type; + m_stride = stride; + m_data = NULL; + m_buffer = buf; + m_bufferName = bufferName; + m_buffOffset = offset; + m_normalize = normalize; + m_isVBO = true; +} + +void GLESpointer::getBufferConversions(const RangeList& rl,RangeList& rlOut) { + m_buffer->getConversions(rl,rlOut); +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLESvalidate.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLESvalidate.cpp new file mode 100644 index 0000000..a6d99f7 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLESvalidate.cpp @@ -0,0 +1,194 @@ +/* +* Copyright 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 +#include +#include +#include +#include +#include + + +bool GLESvalidate::textureEnum(GLenum e,unsigned int maxTex) { + return e >= GL_TEXTURE0 && e < (GL_TEXTURE0 + maxTex); +} + +bool GLESvalidate::pixelType(GLEScontext * ctx, GLenum type) { + if ((ctx && ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL) && + (type == GL_UNSIGNED_INT_24_8_OES) ) + return true; + + if (ctx && + (ctx->getCaps()->GL_ARB_HALF_FLOAT_PIXEL || ctx->getCaps()->GL_NV_HALF_FLOAT) && + (type == GL_HALF_FLOAT_OES)) + return true; + + switch(type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_FLOAT: + return true; + } + return false; +} + +bool GLESvalidate::pixelOp(GLenum format,GLenum type) { + switch(type) { + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + return format == GL_RGBA; + case GL_UNSIGNED_SHORT_5_6_5: + return format == GL_RGB; + } + return true; +} + +bool GLESvalidate::pixelFrmt(GLEScontext* ctx ,GLenum format) { + if (ctx && ctx->getCaps()->GL_EXT_TEXTURE_FORMAT_BGRA8888 && format == GL_BGRA_EXT) + return true; + if (ctx && ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL && format == GL_DEPTH_STENCIL_OES) + return true; + switch(format) { + case GL_ALPHA: + case GL_RGB: + case GL_RGBA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + return true; + } + return false; +} + +bool GLESvalidate::bufferTarget(GLenum target) { + return target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER; +} + +bool GLESvalidate::bufferUsage(GLenum usage) { + switch(usage) { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + return true; + } + return false; +} + +bool GLESvalidate::bufferParam(GLenum param) { + return (param == GL_BUFFER_SIZE) || (param == GL_BUFFER_USAGE); +} + +bool GLESvalidate::drawMode(GLenum mode) { + switch(mode) { + case GL_POINTS: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_LINES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_TRIANGLES: + return true; + } + return false; +} + +bool GLESvalidate::drawType(GLenum mode) { + return mode == GL_UNSIGNED_BYTE || + mode == GL_UNSIGNED_SHORT || + mode == GL_UNSIGNED_INT; +} + +bool GLESvalidate::textureTarget(GLenum target) { + return target==GL_TEXTURE_2D || target==GL_TEXTURE_CUBE_MAP; +} + +bool GLESvalidate::textureTargetLimited(GLenum target) { + return target==GL_TEXTURE_2D; +} + +bool GLESvalidate::textureTargetEx(GLenum target) { + switch(target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: + case GL_TEXTURE_2D: + return true; + } + return false; +} + +bool GLESvalidate::blendEquationMode(GLenum mode){ + return mode == GL_FUNC_ADD || + mode == GL_FUNC_SUBTRACT || + mode == GL_FUNC_REVERSE_SUBTRACT; +} + +bool GLESvalidate::framebufferTarget(GLenum target){ + return target == GL_FRAMEBUFFER; +} + +bool GLESvalidate::framebufferAttachment(GLenum attachment){ + switch(attachment){ + case GL_COLOR_ATTACHMENT0: + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + return true; + } + return false; +} + +bool GLESvalidate::framebufferAttachmentParams(GLenum pname){ + switch(pname){ + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + return true; + } + return false; +} + +bool GLESvalidate::renderbufferTarget(GLenum target){ + return target == GL_RENDERBUFFER; +} + +bool GLESvalidate::renderbufferParams(GLenum pname){ + switch(pname){ + case GL_RENDERBUFFER_WIDTH: + case GL_RENDERBUFFER_HEIGHT: + case GL_RENDERBUFFER_INTERNAL_FORMAT: + case GL_RENDERBUFFER_RED_SIZE: + case GL_RENDERBUFFER_GREEN_SIZE: + case GL_RENDERBUFFER_BLUE_SIZE: + case GL_RENDERBUFFER_ALPHA_SIZE: + case GL_RENDERBUFFER_DEPTH_SIZE: + case GL_RENDERBUFFER_STENCIL_SIZE: + return true; + } + return false; +} + +bool GLESvalidate::texImgDim(GLsizei width,GLsizei height,int maxTexSize) { + + if( width < 0 || height < 0 || width > maxTexSize || height > maxTexSize) + return false; + return isPowerOf2(width) && isPowerOf2(height); +} + diff --git a/external/android-emugl/host/libs/Translator/GLcommon/GLutils.cpp b/external/android-emugl/host/libs/Translator/GLcommon/GLutils.cpp new file mode 100644 index 0000000..46e292c --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/GLutils.cpp @@ -0,0 +1,20 @@ +/* +* 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 + +bool isPowerOf2(int num) { + return (num & (num -1)) == 0; +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/PaletteTexture.cpp b/external/android-emugl/host/libs/Translator/GLcommon/PaletteTexture.cpp new file mode 100644 index 0000000..c99ed07 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/PaletteTexture.cpp @@ -0,0 +1,170 @@ +/* +* 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 "GLcommon/PaletteTexture.h" +#include + + + +struct Color +{ + Color(unsigned char r, unsigned char g,unsigned char b, unsigned char a):red(r),green(g),blue(b),alpha(a){}; + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; +}; + +void getPaletteInfo(GLenum internalFormat,unsigned int& indexSizeBits,unsigned int& colorSizeBytes,GLenum& colorFrmt) { + + colorFrmt = GL_RGB; + switch(internalFormat) + { + case GL_PALETTE4_RGB8_OES: + indexSizeBits = 4; + colorSizeBytes = 3; + break; + + case GL_PALETTE4_RGBA8_OES: + indexSizeBits = 4; + colorSizeBytes = 4; + colorFrmt = GL_RGBA; + break; + + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + colorFrmt = GL_RGBA; + /* fall-through */ + case GL_PALETTE4_R5_G6_B5_OES: + indexSizeBits = 4; + colorSizeBytes = 2; + break; + + case GL_PALETTE8_RGB8_OES: + indexSizeBits = 8; + colorSizeBytes = 3; + break; + + case GL_PALETTE8_RGBA8_OES: + indexSizeBits = 8; + colorSizeBytes = 4; + colorFrmt = GL_RGBA; + break; + + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + colorFrmt = GL_RGBA; + /* fall-through */ + case GL_PALETTE8_R5_G6_B5_OES: + indexSizeBits = 8; + colorSizeBytes = 2; + break; + } +} + + +Color paletteColor(const unsigned char* pallete,unsigned int index,GLenum format) +{ + short s; + switch(format) { + //RGB + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE8_RGB8_OES: + return Color(pallete[index],pallete[index+1],pallete[index+2],0); + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE4_R5_G6_B5_OES: + s = *((short *)(pallete+index)); + return Color((s >> 11)*255/31,((s >> 5) & 0x3f)*255/63 ,(s & 0x1f)*255/31,0); + + //RGBA + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE8_RGBA8_OES: + return Color(pallete[index],pallete[index+1],pallete[index+2],pallete[index+3]); + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE8_RGBA4_OES: + s = *((short *)(pallete+index)); + return Color(((s >> 12) & 0xf)*255/15,((s >> 8) & 0xf)*255/15,((s >> 4) & 0xf)*255/15 ,(s & 0xf)*255/15); + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB5_A1_OES: + s = *((short *)(pallete+index)); + return Color(((s >> 11) & 0x1f)*255/31,((s >> 6) & 0x1f)*255/31,((s >> 1) & 0x1f)*255/31 ,(s & 0x1) * 255); + default: + return Color(255,255,255,255); + } +} + +unsigned char* uncompressTexture(GLenum internalformat,GLenum& formatOut,GLsizei width,GLsizei height,GLsizei imageSize, const GLvoid* data,GLint level) { + + unsigned int indexSizeBits; //the size of the color index in the pallete + unsigned int colorSizeBytes; //the size of each color cell in the pallete + + getPaletteInfo(internalformat,indexSizeBits,colorSizeBytes,formatOut); + if(!data) + { + return NULL; + } + + const unsigned char* palette = static_cast(data); + + //the pallete positioned in the begininng of the data + // so we jump over it to get to the colos indices in the palette + + int nColors = 2 << (indexSizeBits -1); //2^indexSizeBits + int paletteSizeBytes = nColors*colorSizeBytes; + const unsigned char* imageIndices = palette + paletteSizeBytes; + + //jumping to the the correct mipmap level + for(int i=0;i> 1; + height = height >> 1; + } + + int colorSizeOut = (formatOut == GL_RGB? 3:4); + int nPixels = width*height; + unsigned char* pixelsOut = new unsigned char[nPixels*colorSizeOut]; + if(!pixelsOut) return NULL; + + int leftBytes = ((palette + imageSize) /* the end of data pointer*/ + - imageIndices); + int leftPixels = (leftBytes * 8 )/indexSizeBits; + + int maxIndices = (leftPixels < nPixels) ? leftPixels:nPixels; + + //filling the pixels array + for(int i =0 ; i < maxIndices ; i++) { + int paletteIndex = 0; + int indexOut = i*colorSizeOut; + if(indexSizeBits == 4) { + paletteIndex = (i%2) == 0 ? + imageIndices[i/2] >> 4: //upper bits + imageIndices[i/2] & 0xf; //lower bits + } else { + paletteIndex = imageIndices[i]; + } + + paletteIndex*=colorSizeBytes; + Color c = paletteColor(palette,paletteIndex,internalformat); + + pixelsOut[indexOut] = c.red; + pixelsOut[indexOut+1] = c.green; + pixelsOut[indexOut+2] = c.blue; + if(formatOut == GL_RGBA) { + pixelsOut[indexOut+3] = c.alpha; + } + } + return pixelsOut; +} + diff --git a/external/android-emugl/host/libs/Translator/GLcommon/RangeManip.cpp b/external/android-emugl/host/libs/Translator/GLcommon/RangeManip.cpp new file mode 100644 index 0000000..2d6f119 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/RangeManip.cpp @@ -0,0 +1,127 @@ +/* +* 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 + + +bool Range::rangeIntersection(const Range& r,Range& rOut) const { + if(m_start > r.getEnd() || r.getStart() > m_end) return false; + int max_start = (m_start > r.getStart())? m_start:r.getStart(); + int min_end = (m_end < r.getEnd())?m_end:r.getEnd(); + int size = min_end - max_start; + if(size) { + rOut.setRange(max_start,min_end-max_start); + return true; + } + return false; +} + +bool Range::rangeUnion(const Range& r,Range& rOut) const { + if(m_start > r.getEnd() || r.getStart() > m_end) return false; + int min_start = (m_start < r.getStart())?m_start:r.getStart(); + int max_end = (m_end > r.getEnd())?m_end:r.getEnd(); + int size = max_end - min_start; + if(size) { + rOut.setRange(min_start,max_end-min_start); + return true; + } + return false; +} + +void RangeList::addRange(const Range& r) { + if(r.getSize()) + list.push_back(r); +} + +void RangeList::addRanges(const RangeList& rl) { + for(int i =0; i< rl.size();i++) { + addRange(rl.list[i]); + } +} + +void RangeList::delRanges(const RangeList& rl,RangeList& deleted) { + for(int i =0; i< rl.size();i++) { + delRange(rl.list[i],deleted); + } +} + +bool RangeList::empty() const{ + return list.empty(); +} + +int RangeList::size() const{ + return list.size(); +} +void RangeList::clear() { + return list.clear(); +} + +void RangeList::erase(unsigned int i) { + if(i > list.size()) return; + list.erase(list.begin() +i); +} + +void RangeList::delRange(const Range& r,RangeList& deleted) { + if(r.getSize() == 0) return; + + Range intersection; + Range temp; + // compare new rect to each and any of the rects on the list + for (int i=0;i<(int)list.size();i++) { // i must be signed for i-- below + // if there is intersection + if (r.rangeIntersection(list[i],intersection)) { + Range old=list[i]; + // remove old as it is about to be split + erase(i); + i--; + if (intersection!=old) { // otherwise split: + //intersection on right side + if(old.getStart() != intersection.getStart()) { + list.insert(list.begin(),Range(old.getStart(),intersection.getStart() - old.getStart())); + } + + //intersection on left side + if(old.getEnd() != intersection.getEnd()) { + list.insert(list.begin(),Range(intersection.getEnd(),old.getEnd() - intersection.getEnd())); + } + } + deleted.addRange(intersection); + } + } +} + +void RangeList::merge() { + if(list.empty()) return; + + Range temp; + bool changed; + + do { // re-run if changed in last run + changed=0; + // run for each combinations of two rects in the list + for (int i=0;i<(((int)list.size())-1) && !changed ;i++) + { + for (int j=i+1;j<(int)list.size() && !changed ;j++) + { + if (list[i].rangeUnion(list[j],temp)) { + // are them exactly one on left of the other + list[i] = temp; + erase(j); + changed=1; + } + } + } + } while (changed); +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/TextureUtils.cpp b/external/android-emugl/host/libs/Translator/GLcommon/TextureUtils.cpp new file mode 100644 index 0000000..81152f6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/TextureUtils.cpp @@ -0,0 +1,109 @@ +/* +* 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 +#include +#include +#include +#include +#include + +int getCompressedFormats(int* formats){ + if(formats){ + //Palette + formats[0] = GL_PALETTE4_RGBA8_OES; + formats[1] = GL_PALETTE4_RGBA4_OES; + formats[2] = GL_PALETTE8_RGBA8_OES; + formats[3] = GL_PALETTE8_RGBA4_OES; + formats[4] = GL_PALETTE4_RGB8_OES; + formats[5] = GL_PALETTE8_RGB8_OES; + formats[6] = GL_PALETTE4_RGB5_A1_OES; + formats[7] = GL_PALETTE8_RGB5_A1_OES; + formats[8] = GL_PALETTE4_R5_G6_B5_OES; + formats[9] = GL_PALETTE8_R5_G6_B5_OES; + //ETC + formats[MAX_SUPPORTED_PALETTE] = GL_ETC1_RGB8_OES; + } + return MAX_SUPPORTED_PALETTE + MAX_ETC_SUPPORTED; +} + +void doCompressedTexImage2D(GLEScontext * ctx, GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLint border, + GLsizei imageSize, const GLvoid* data, void * funcPtr) +{ + /* XXX: This is just a hack to fix the resolve of glTexImage2D problem + It will be removed when we'll no longer link against ligGL */ + typedef void (GLAPIENTRY *glTexImage2DPtr_t ) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + glTexImage2DPtr_t glTexImage2DPtr; + glTexImage2DPtr = (glTexImage2DPtr_t)funcPtr; + + switch (internalformat) { + case GL_ETC1_RGB8_OES: + { + GLint format = GL_RGB; + GLint type = GL_UNSIGNED_BYTE; + + GLsizei compressedSize = etc1_get_encoded_data_size(width, height); + SET_ERROR_IF((compressedSize > imageSize), GL_INVALID_VALUE); + + const int32_t align = ctx->getUnpackAlignment()-1; + const int32_t bpr = ((width * 3) + align) & ~align; + const size_t size = bpr * height; + + etc1_byte* pOut = new etc1_byte[size]; + int res = etc1_decode_image((const etc1_byte*)data, pOut, width, height, 3, bpr); + SET_ERROR_IF(res!=0, GL_INVALID_VALUE); + glTexImage2DPtr(target,level,format,width,height,border,format,type,pOut); + delete [] pOut; + } + break; + + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + { + SET_ERROR_IF(level > log2(ctx->getMaxTexSize()) || + border !=0 || level > 0 || + !GLESvalidate::texImgDim(width,height,ctx->getMaxTexSize()+2),GL_INVALID_VALUE) + + int nMipmaps = -level + 1; + GLsizei tmpWidth = width; + GLsizei tmpHeight = height; + + for(int i = 0; i < nMipmaps ; i++) + { + GLenum uncompressedFrmt; + unsigned char* uncompressed = uncompressTexture(internalformat,uncompressedFrmt,width,height,imageSize,data,i); + glTexImage2DPtr(target,i,uncompressedFrmt,tmpWidth,tmpHeight,border,uncompressedFrmt,GL_UNSIGNED_BYTE,uncompressed); + tmpWidth/=2; + tmpHeight/=2; + delete[] uncompressed; + } + } + break; + + default: + SET_ERROR_IF(1, GL_INVALID_ENUM); + break; + } +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/etc1.cpp b/external/android-emugl/host/libs/Translator/GLcommon/etc1.cpp new file mode 100644 index 0000000..97d1085 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/etc1.cpp @@ -0,0 +1,670 @@ +// Copyright 2009 Google Inc. +// +// 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 + +#include + +/* From http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt + + The number of bits that represent a 4x4 texel block is 64 bits if + is given by ETC1_RGB8_OES. + + The data for a block is a number of bytes, + + {q0, q1, q2, q3, q4, q5, q6, q7} + + where byte q0 is located at the lowest memory address and q7 at + the highest. The 64 bits specifying the block is then represented + by the following 64 bit integer: + + int64bit = 256*(256*(256*(256*(256*(256*(256*q0+q1)+q2)+q3)+q4)+q5)+q6)+q7; + + ETC1_RGB8_OES: + + a) bit layout in bits 63 through 32 if diffbit = 0 + + 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 + ----------------------------------------------- + | base col1 | base col2 | base col1 | base col2 | + | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| + ----------------------------------------------- + + 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + --------------------------------------------------- + | base col1 | base col2 | table | table |diff|flip| + | B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + --------------------------------------------------- + + + b) bit layout in bits 63 through 32 if diffbit = 1 + + 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 + ----------------------------------------------- + | base col1 | dcol 2 | base col1 | dcol 2 | + | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | + ----------------------------------------------- + + 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + --------------------------------------------------- + | base col 1 | dcol 2 | table | table |diff|flip| + | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + --------------------------------------------------- + + + c) bit layout in bits 31 through 0 (in both cases) + + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 + ----------------------------------------------- + | most significant pixel index bits | + | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| + ----------------------------------------------- + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + -------------------------------------------------- + | least significant pixel index bits | + | p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + -------------------------------------------------- + + + Add table 3.17.2: Intensity modifier sets for ETC1 compressed textures: + + table codeword modifier table + ------------------ ---------------------- + 0 -8 -2 2 8 + 1 -17 -5 5 17 + 2 -29 -9 9 29 + 3 -42 -13 13 42 + 4 -60 -18 18 60 + 5 -80 -24 24 80 + 6 -106 -33 33 106 + 7 -183 -47 47 183 + + + Add table 3.17.3 Mapping from pixel index values to modifier values for + ETC1 compressed textures: + + pixel index value + --------------- + msb lsb resulting modifier value + ----- ----- ------------------------- + 1 1 -b (large negative value) + 1 0 -a (small negative value) + 0 0 a (small positive value) + 0 1 b (large positive value) + + + */ + +static const int kModifierTable[] = { +/* 0 */2, 8, -2, -8, +/* 1 */5, 17, -5, -17, +/* 2 */9, 29, -9, -29, +/* 3 */13, 42, -13, -42, +/* 4 */18, 60, -18, -60, +/* 5 */24, 80, -24, -80, +/* 6 */33, 106, -33, -106, +/* 7 */47, 183, -47, -183 }; + +static const int kLookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; + +static inline etc1_byte clamp(int x) { + return (etc1_byte) (x >= 0 ? (x < 255 ? x : 255) : 0); +} + +static +inline int convert4To8(int b) { + int c = b & 0xf; + return (c << 4) | c; +} + +static +inline int convert5To8(int b) { + int c = b & 0x1f; + return (c << 3) | (c >> 2); +} + +static +inline int convert6To8(int b) { + int c = b & 0x3f; + return (c << 2) | (c >> 4); +} + +static +inline int divideBy255(int d) { + return (d + 128 + (d >> 8)) >> 8; +} + +static +inline int convert8To4(int b) { + int c = b & 0xff; + return divideBy255(c * 15); +} + +static +inline int convert8To5(int b) { + int c = b & 0xff; + return divideBy255(c * 31); +} + +static +inline int convertDiff(int base, int diff) { + return convert5To8((0x1f & base) + kLookup[0x7 & diff]); +} + +static +void decode_subblock(etc1_byte* pOut, int r, int g, int b, const int* table, + etc1_uint32 low, bool second, bool flipped) { + int baseX = 0; + int baseY = 0; + if (second) { + if (flipped) { + baseY = 2; + } else { + baseX = 2; + } + } + for (int i = 0; i < 8; i++) { + int x, y; + if (flipped) { + x = baseX + (i >> 1); + y = baseY + (i & 1); + } else { + x = baseX + (i >> 2); + y = baseY + (i & 3); + } + int k = y + (x * 4); + int offset = ((low >> k) & 1) | ((low >> (k + 15)) & 2); + int delta = table[offset]; + etc1_byte* q = pOut + 3 * (x + 4 * y); + *q++ = clamp(r + delta); + *q++ = clamp(g + delta); + *q++ = clamp(b + delta); + } +} + +// Input is an ETC1 compressed version of the data. +// Output is a 4 x 4 square of 3-byte pixels in form R, G, B + +void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut) { + etc1_uint32 high = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; + etc1_uint32 low = (pIn[4] << 24) | (pIn[5] << 16) | (pIn[6] << 8) | pIn[7]; + int r1, r2, g1, g2, b1, b2; + if (high & 2) { + // differential + int rBase = high >> 27; + int gBase = high >> 19; + int bBase = high >> 11; + r1 = convert5To8(rBase); + r2 = convertDiff(rBase, high >> 24); + g1 = convert5To8(gBase); + g2 = convertDiff(gBase, high >> 16); + b1 = convert5To8(bBase); + b2 = convertDiff(bBase, high >> 8); + } else { + // not differential + r1 = convert4To8(high >> 28); + r2 = convert4To8(high >> 24); + g1 = convert4To8(high >> 20); + g2 = convert4To8(high >> 16); + b1 = convert4To8(high >> 12); + b2 = convert4To8(high >> 8); + } + int tableIndexA = 7 & (high >> 5); + int tableIndexB = 7 & (high >> 2); + const int* tableA = kModifierTable + tableIndexA * 4; + const int* tableB = kModifierTable + tableIndexB * 4; + bool flipped = (high & 1) != 0; + decode_subblock(pOut, r1, g1, b1, tableA, low, false, flipped); + decode_subblock(pOut, r2, g2, b2, tableB, low, true, flipped); +} + +typedef struct { + etc1_uint32 high; + etc1_uint32 low; + etc1_uint32 score; // Lower is more accurate +} etc_compressed; + +static +inline void take_best(etc_compressed* a, const etc_compressed* b) { + if (a->score > b->score) { + *a = *b; + } +} + +static +void etc_average_colors_subblock(const etc1_byte* pIn, etc1_uint32 inMask, + etc1_byte* pColors, bool flipped, bool second) { + int r = 0; + int g = 0; + int b = 0; + + if (flipped) { + int by = 0; + if (second) { + by = 2; + } + for (int y = 0; y < 2; y++) { + int yy = by + y; + for (int x = 0; x < 4; x++) { + int i = x + 4 * yy; + if (inMask & (1 << i)) { + const etc1_byte* p = pIn + i * 3; + r += *(p++); + g += *(p++); + b += *(p++); + } + } + } + } else { + int bx = 0; + if (second) { + bx = 2; + } + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 2; x++) { + int xx = bx + x; + int i = xx + 4 * y; + if (inMask & (1 << i)) { + const etc1_byte* p = pIn + i * 3; + r += *(p++); + g += *(p++); + b += *(p++); + } + } + } + } + pColors[0] = (etc1_byte)((r + 4) >> 3); + pColors[1] = (etc1_byte)((g + 4) >> 3); + pColors[2] = (etc1_byte)((b + 4) >> 3); +} + +static +inline int square(int x) { + return x * x; +} + +static etc1_uint32 chooseModifier(const etc1_byte* pBaseColors, + const etc1_byte* pIn, etc1_uint32 *pLow, int bitIndex, + const int* pModifierTable) { + etc1_uint32 bestScore = ~0; + int bestIndex = 0; + int pixelR = pIn[0]; + int pixelG = pIn[1]; + int pixelB = pIn[2]; + int r = pBaseColors[0]; + int g = pBaseColors[1]; + int b = pBaseColors[2]; + for (int i = 0; i < 4; i++) { + int modifier = pModifierTable[i]; + int decodedG = clamp(g + modifier); + etc1_uint32 score = (etc1_uint32) (6 * square(decodedG - pixelG)); + if (score >= bestScore) { + continue; + } + int decodedR = clamp(r + modifier); + score += (etc1_uint32) (3 * square(decodedR - pixelR)); + if (score >= bestScore) { + continue; + } + int decodedB = clamp(b + modifier); + score += (etc1_uint32) square(decodedB - pixelB); + if (score < bestScore) { + bestScore = score; + bestIndex = i; + } + } + etc1_uint32 lowMask = (((bestIndex >> 1) << 16) | (bestIndex & 1)) + << bitIndex; + *pLow |= lowMask; + return bestScore; +} + +static +void etc_encode_subblock_helper(const etc1_byte* pIn, etc1_uint32 inMask, + etc_compressed* pCompressed, bool flipped, bool second, + const etc1_byte* pBaseColors, const int* pModifierTable) { + int score = pCompressed->score; + if (flipped) { + int by = 0; + if (second) { + by = 2; + } + for (int y = 0; y < 2; y++) { + int yy = by + y; + for (int x = 0; x < 4; x++) { + int i = x + 4 * yy; + if (inMask & (1 << i)) { + score += chooseModifier(pBaseColors, pIn + i * 3, + &pCompressed->low, yy + x * 4, pModifierTable); + } + } + } + } else { + int bx = 0; + if (second) { + bx = 2; + } + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 2; x++) { + int xx = bx + x; + int i = xx + 4 * y; + if (inMask & (1 << i)) { + score += chooseModifier(pBaseColors, pIn + i * 3, + &pCompressed->low, y + xx * 4, pModifierTable); + } + } + } + } + pCompressed->score = score; +} + +static bool inRange4bitSigned(int color) { + return color >= -4 && color <= 3; +} + +static void etc_encodeBaseColors(etc1_byte* pBaseColors, + const etc1_byte* pColors, etc_compressed* pCompressed) { + int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks + bool differential; + { + int r51 = convert8To5(pColors[0]); + int g51 = convert8To5(pColors[1]); + int b51 = convert8To5(pColors[2]); + int r52 = convert8To5(pColors[3]); + int g52 = convert8To5(pColors[4]); + int b52 = convert8To5(pColors[5]); + + r1 = convert5To8(r51); + g1 = convert5To8(g51); + b1 = convert5To8(b51); + + int dr = r52 - r51; + int dg = g52 - g51; + int db = b52 - b51; + + differential = inRange4bitSigned(dr) && inRange4bitSigned(dg) + && inRange4bitSigned(db); + if (differential) { + r2 = convert5To8(r51 + dr); + g2 = convert5To8(g51 + dg); + b2 = convert5To8(b51 + db); + pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19) + | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2; + } + } + + if (!differential) { + int r41 = convert8To4(pColors[0]); + int g41 = convert8To4(pColors[1]); + int b41 = convert8To4(pColors[2]); + int r42 = convert8To4(pColors[3]); + int g42 = convert8To4(pColors[4]); + int b42 = convert8To4(pColors[5]); + r1 = convert4To8(r41); + g1 = convert4To8(g41); + b1 = convert4To8(b41); + r2 = convert4To8(r42); + g2 = convert4To8(g42); + b2 = convert4To8(b42); + pCompressed->high |= (r41 << 28) | (r42 << 24) | (g41 << 20) | (g42 + << 16) | (b41 << 12) | (b42 << 8); + } + pBaseColors[0] = r1; + pBaseColors[1] = g1; + pBaseColors[2] = b1; + pBaseColors[3] = r2; + pBaseColors[4] = g2; + pBaseColors[5] = b2; +} + +static +void etc_encode_block_helper(const etc1_byte* pIn, etc1_uint32 inMask, + const etc1_byte* pColors, etc_compressed* pCompressed, bool flipped) { + pCompressed->score = ~0; + pCompressed->high = (flipped ? 1 : 0); + pCompressed->low = 0; + + etc1_byte pBaseColors[6]; + + etc_encodeBaseColors(pBaseColors, pColors, pCompressed); + + int originalHigh = pCompressed->high; + + const int* pModifierTable = kModifierTable; + for (int i = 0; i < 8; i++, pModifierTable += 4) { + etc_compressed temp; + temp.score = 0; + temp.high = originalHigh | (i << 5); + temp.low = 0; + etc_encode_subblock_helper(pIn, inMask, &temp, flipped, false, + pBaseColors, pModifierTable); + take_best(pCompressed, &temp); + } + pModifierTable = kModifierTable; + etc_compressed firstHalf = *pCompressed; + for (int i = 0; i < 8; i++, pModifierTable += 4) { + etc_compressed temp; + temp.score = firstHalf.score; + temp.high = firstHalf.high | (i << 2); + temp.low = firstHalf.low; + etc_encode_subblock_helper(pIn, inMask, &temp, flipped, true, + pBaseColors + 3, pModifierTable); + if (i == 0) { + *pCompressed = temp; + } else { + take_best(pCompressed, &temp); + } + } +} + +static void writeBigEndian(etc1_byte* pOut, etc1_uint32 d) { + pOut[0] = (etc1_byte)(d >> 24); + pOut[1] = (etc1_byte)(d >> 16); + pOut[2] = (etc1_byte)(d >> 8); + pOut[3] = (etc1_byte) d; +} + +// Input is a 4 x 4 square of 3-byte pixels in form R, G, B +// inmask is a 16-bit mask where bit (1 << (x + y * 4)) tells whether the corresponding (x,y) +// pixel is valid or not. Invalid pixel color values are ignored when compressing. +// Output is an ETC1 compressed version of the data. + +void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 inMask, + etc1_byte* pOut) { + etc1_byte colors[6]; + etc1_byte flippedColors[6]; + etc_average_colors_subblock(pIn, inMask, colors, false, false); + etc_average_colors_subblock(pIn, inMask, colors + 3, false, true); + etc_average_colors_subblock(pIn, inMask, flippedColors, true, false); + etc_average_colors_subblock(pIn, inMask, flippedColors + 3, true, true); + + etc_compressed a, b; + etc_encode_block_helper(pIn, inMask, colors, &a, false); + etc_encode_block_helper(pIn, inMask, flippedColors, &b, true); + take_best(&a, &b); + writeBigEndian(pOut, a.high); + writeBigEndian(pOut + 4, a.low); +} + +// Return the size of the encoded image data (does not include size of PKM header). + +etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height) { + return (((width + 3) & ~3) * ((height + 3) & ~3)) >> 1; +} + +// Encode an entire image. +// pIn - pointer to the image data. Formatted such that the Red component of +// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset; +// pOut - pointer to encoded data. Must be large enough to store entire encoded image. + +int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height, + etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut) { + if (pixelSize < 2 || pixelSize > 3) { + return -1; + } + static const unsigned short kYMask[] = { 0x0, 0xf, 0xff, 0xfff, 0xffff }; + static const unsigned short kXMask[] = { 0x0, 0x1111, 0x3333, 0x7777, + 0xffff }; + etc1_byte block[ETC1_DECODED_BLOCK_SIZE]; + etc1_byte encoded[ETC1_ENCODED_BLOCK_SIZE]; + + etc1_uint32 encodedWidth = (width + 3) & ~3; + etc1_uint32 encodedHeight = (height + 3) & ~3; + + for (etc1_uint32 y = 0; y < encodedHeight; y += 4) { + etc1_uint32 yEnd = height - y; + if (yEnd > 4) { + yEnd = 4; + } + int ymask = kYMask[yEnd]; + for (etc1_uint32 x = 0; x < encodedWidth; x += 4) { + etc1_uint32 xEnd = width - x; + if (xEnd > 4) { + xEnd = 4; + } + int mask = ymask & kXMask[xEnd]; + for (etc1_uint32 cy = 0; cy < yEnd; cy++) { + etc1_byte* q = block + (cy * 4) * 3; + const etc1_byte* p = pIn + pixelSize * x + stride * (y + cy); + if (pixelSize == 3) { + memcpy(q, p, xEnd * 3); + } else { + for (etc1_uint32 cx = 0; cx < xEnd; cx++) { + int pixel = (p[1] << 8) | p[0]; + *q++ = convert5To8(pixel >> 11); + *q++ = convert6To8(pixel >> 5); + *q++ = convert5To8(pixel); + p += pixelSize; + } + } + } + etc1_encode_block(block, mask, encoded); + memcpy(pOut, encoded, sizeof(encoded)); + pOut += sizeof(encoded); + } + } + return 0; +} + +// Decode an entire image. +// pIn - pointer to encoded data. +// pOut - pointer to the image data. Will be written such that the Red component of +// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset. Must be +// large enough to store entire image. + + +int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut, + etc1_uint32 width, etc1_uint32 height, + etc1_uint32 pixelSize, etc1_uint32 stride) { + if (pixelSize < 2 || pixelSize > 3) { + return -1; + } + etc1_byte block[ETC1_DECODED_BLOCK_SIZE]; + + etc1_uint32 encodedWidth = (width + 3) & ~3; + etc1_uint32 encodedHeight = (height + 3) & ~3; + + for (etc1_uint32 y = 0; y < encodedHeight; y += 4) { + etc1_uint32 yEnd = height - y; + if (yEnd > 4) { + yEnd = 4; + } + for (etc1_uint32 x = 0; x < encodedWidth; x += 4) { + etc1_uint32 xEnd = width - x; + if (xEnd > 4) { + xEnd = 4; + } + etc1_decode_block(pIn, block); + pIn += ETC1_ENCODED_BLOCK_SIZE; + for (etc1_uint32 cy = 0; cy < yEnd; cy++) { + const etc1_byte* q = block + (cy * 4) * 3; + etc1_byte* p = pOut + pixelSize * x + stride * (y + cy); + if (pixelSize == 3) { + memcpy(p, q, xEnd * 3); + } else { + for (etc1_uint32 cx = 0; cx < xEnd; cx++) { + etc1_byte r = *q++; + etc1_byte g = *q++; + etc1_byte b = *q++; + etc1_uint32 pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); + *p++ = (etc1_byte) pixel; + *p++ = (etc1_byte) (pixel >> 8); + } + } + } + } + } + return 0; +} + +static const char kMagic[] = { 'P', 'K', 'M', ' ', '1', '0' }; + +static const etc1_uint32 ETC1_PKM_FORMAT_OFFSET = 6; +static const etc1_uint32 ETC1_PKM_ENCODED_WIDTH_OFFSET = 8; +static const etc1_uint32 ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10; +static const etc1_uint32 ETC1_PKM_WIDTH_OFFSET = 12; +static const etc1_uint32 ETC1_PKM_HEIGHT_OFFSET = 14; + +static const etc1_uint32 ETC1_RGB_NO_MIPMAPS = 0; + +static void writeBEUint16(etc1_byte* pOut, etc1_uint32 data) { + pOut[0] = (etc1_byte) (data >> 8); + pOut[1] = (etc1_byte) data; +} + +static etc1_uint32 readBEUint16(const etc1_byte* pIn) { + return (pIn[0] << 8) | pIn[1]; +} + +// Format a PKM header + +void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height) { + memcpy(pHeader, kMagic, sizeof(kMagic)); + etc1_uint32 encodedWidth = (width + 3) & ~3; + etc1_uint32 encodedHeight = (height + 3) & ~3; + writeBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET, ETC1_RGB_NO_MIPMAPS); + writeBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET, encodedWidth); + writeBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET, encodedHeight); + writeBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET, width); + writeBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET, height); +} + +// Check if a PKM header is correctly formatted. + +etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader) { + if (memcmp(pHeader, kMagic, sizeof(kMagic))) { + return false; + } + etc1_uint32 format = readBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET); + etc1_uint32 encodedWidth = readBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET); + etc1_uint32 encodedHeight = readBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET); + etc1_uint32 width = readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET); + etc1_uint32 height = readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET); + return format == ETC1_RGB_NO_MIPMAPS && + encodedWidth >= width && encodedWidth - width < 4 && + encodedHeight >= height && encodedHeight - height < 4; +} + +// Read the image width from a PKM header + +etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader) { + return readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET); +} + +// Read the image height from a PKM header + +etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader){ + return readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET); +} diff --git a/external/android-emugl/host/libs/Translator/GLcommon/objectNameManager.cpp b/external/android-emugl/host/libs/Translator/GLcommon/objectNameManager.cpp new file mode 100644 index 0000000..3612211 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/GLcommon/objectNameManager.cpp @@ -0,0 +1,369 @@ +/* +* 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 +#include +#include + + +NameSpace::NameSpace(NamedObjectType p_type, + GlobalNameSpace *globalNameSpace) : + m_nextName(0), + m_type(p_type), + m_globalNameSpace(globalNameSpace) {} + +NameSpace::~NameSpace() +{ + for (NamesMap::iterator n = m_localToGlobalMap.begin(); + n != m_localToGlobalMap.end(); + n++) { + m_globalNameSpace->deleteName(m_type, (*n).second); + } +} + +ObjectLocalName +NameSpace::genName(ObjectLocalName p_localName, + bool genGlobal, bool genLocal) +{ + ObjectLocalName localName = p_localName; + if (genLocal) { + do { + localName = ++m_nextName; + } while(localName == 0 || + m_localToGlobalMap.find(localName) != + m_localToGlobalMap.end() ); + } + + if (genGlobal) { + unsigned int globalName = m_globalNameSpace->genName(m_type); + m_localToGlobalMap[localName] = globalName; + } + + return localName; +} + + +unsigned int +NameSpace::genGlobalName(void) +{ + return m_globalNameSpace->genName(m_type); +} + +unsigned int +NameSpace::getGlobalName(ObjectLocalName p_localName) +{ + NamesMap::iterator n( m_localToGlobalMap.find(p_localName) ); + if (n != m_localToGlobalMap.end()) { + // object found - return its global name map + return (*n).second; + } + + // object does not exist; + return 0; +} + +ObjectLocalName +NameSpace::getLocalName(unsigned int p_globalName) +{ + for(NamesMap::iterator it = m_localToGlobalMap.begin(); it != m_localToGlobalMap.end();it++){ + if((*it).second == p_globalName){ + // object found - return its local name + return (*it).first; + } + } + + // object does not exist; + return 0; +} + +void +NameSpace::deleteName(ObjectLocalName p_localName) +{ + NamesMap::iterator n( m_localToGlobalMap.find(p_localName) ); + if (n != m_localToGlobalMap.end()) { + m_globalNameSpace->deleteName(m_type, (*n).second); + m_localToGlobalMap.erase(p_localName); + } +} + +bool +NameSpace::isObject(ObjectLocalName p_localName) +{ + return (m_localToGlobalMap.find(p_localName) != m_localToGlobalMap.end() ); +} + +void +NameSpace::replaceGlobalName(ObjectLocalName p_localName, unsigned int p_globalName) +{ + NamesMap::iterator n( m_localToGlobalMap.find(p_localName) ); + if (n != m_localToGlobalMap.end()) { + m_globalNameSpace->deleteName(m_type, (*n).second); + (*n).second = p_globalName; + } +} + + +GlobalNameSpace::GlobalNameSpace() : m_lock() {} + +GlobalNameSpace::~GlobalNameSpace() {} + +unsigned int +GlobalNameSpace::genName(NamedObjectType p_type) +{ + if ( p_type >= NUM_OBJECT_TYPES ) return 0; + unsigned int name = 0; + + emugl::Mutex::AutoLock _lock(m_lock); + switch (p_type) { + case VERTEXBUFFER: + GLEScontext::dispatcher().glGenBuffers(1,&name); + break; + case TEXTURE: + GLEScontext::dispatcher().glGenTextures(1,&name); + break; + case RENDERBUFFER: + GLEScontext::dispatcher().glGenRenderbuffersEXT(1,&name); + break; + case FRAMEBUFFER: + GLEScontext::dispatcher().glGenFramebuffersEXT(1,&name); + break; + case SHADER: //objects in shader namepace are not handled + default: + name = 0; + } + return name; +} + +void +GlobalNameSpace::deleteName(NamedObjectType p_type, unsigned int p_name) +{ +} + +typedef std::pair ObjectIDPair; +typedef std::map ObjectDataMap; + +ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) : m_lock() { + for (int i=0; i < NUM_OBJECT_TYPES; i++) { + m_nameSpace[i] = new NameSpace((NamedObjectType)i, globalNameSpace); + } + + m_objectsData = NULL; +} + +ShareGroup::~ShareGroup() +{ + emugl::Mutex::AutoLock _lock(m_lock); + for (int t = 0; t < NUM_OBJECT_TYPES; t++) { + delete m_nameSpace[t]; + } + + delete (ObjectDataMap *)m_objectsData; +} + +ObjectLocalName +ShareGroup::genName(NamedObjectType p_type, + ObjectLocalName p_localName, + bool genLocal) +{ + if (p_type >= NUM_OBJECT_TYPES) return 0; + + emugl::Mutex::AutoLock _lock(m_lock); + ObjectLocalName localName = + m_nameSpace[p_type]->genName(p_localName, true, genLocal); + return localName; +} + +unsigned int +ShareGroup::genGlobalName(NamedObjectType p_type) +{ + if (p_type >= NUM_OBJECT_TYPES) return 0; + + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->genGlobalName(); +} + +unsigned int +ShareGroup::getGlobalName(NamedObjectType p_type, + ObjectLocalName p_localName) +{ + if (p_type >= NUM_OBJECT_TYPES) return 0; + + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->getGlobalName(p_localName); +} + +ObjectLocalName +ShareGroup::getLocalName(NamedObjectType p_type, + unsigned int p_globalName) +{ + if (p_type >= NUM_OBJECT_TYPES) return 0; + + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->getLocalName(p_globalName); +} + +void +ShareGroup::deleteName(NamedObjectType p_type, ObjectLocalName p_localName) +{ + if (p_type >= NUM_OBJECT_TYPES) return; + + emugl::Mutex::AutoLock _lock(m_lock); + m_nameSpace[p_type]->deleteName(p_localName); + ObjectDataMap *map = (ObjectDataMap *)m_objectsData; + if (map) { + map->erase( ObjectIDPair(p_type, p_localName) ); + } +} + +bool +ShareGroup::isObject(NamedObjectType p_type, ObjectLocalName p_localName) +{ + if (p_type >= NUM_OBJECT_TYPES) return 0; + + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->isObject(p_localName); +} + +void +ShareGroup::replaceGlobalName(NamedObjectType p_type, + ObjectLocalName p_localName, + unsigned int p_globalName) +{ + if (p_type >= NUM_OBJECT_TYPES) return; + + emugl::Mutex::AutoLock _lock(m_lock); + m_nameSpace[p_type]->replaceGlobalName(p_localName, p_globalName); +} + +void +ShareGroup::setObjectData(NamedObjectType p_type, + ObjectLocalName p_localName, + ObjectDataPtr data) +{ + if (p_type >= NUM_OBJECT_TYPES) return; + + emugl::Mutex::AutoLock _lock(m_lock); + + ObjectDataMap *map = (ObjectDataMap *)m_objectsData; + if (!map) { + map = new ObjectDataMap(); + m_objectsData = map; + } + + ObjectIDPair id( p_type, p_localName ); + map->insert( std::pair(id, data) ); +} + +ObjectDataPtr +ShareGroup::getObjectData(NamedObjectType p_type, + ObjectLocalName p_localName) +{ + ObjectDataPtr ret; + + if (p_type >= NUM_OBJECT_TYPES) return ret; + + emugl::Mutex::AutoLock _lock(m_lock); + + ObjectDataMap *map = (ObjectDataMap *)m_objectsData; + if (map) { + ObjectDataMap::iterator i = + map->find( ObjectIDPair(p_type, p_localName) ); + if (i != map->end()) ret = (*i).second; + } + return ret; +} + +ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) : + m_lock(), m_globalNameSpace(globalNameSpace) {} + +ObjectNameManager::~ObjectNameManager() {} + +ShareGroupPtr +ObjectNameManager::createShareGroup(void *p_groupName) +{ + emugl::Mutex::AutoLock _lock(m_lock); + + ShareGroupPtr shareGroupReturn; + + ShareGroupsMap::iterator s( m_groups.find(p_groupName) ); + if (s != m_groups.end()) { + shareGroupReturn = (*s).second; + } + else { + // + // Group does not exist, create new group + // + shareGroupReturn = ShareGroupPtr(new ShareGroup(m_globalNameSpace)); + m_groups.insert( + std::pair( + p_groupName, shareGroupReturn)); + } + + return shareGroupReturn; +} + +ShareGroupPtr +ObjectNameManager::getShareGroup(void *p_groupName) +{ + emugl::Mutex::AutoLock _lock(m_lock); + + ShareGroupPtr shareGroupReturn(NULL); + + ShareGroupsMap::iterator s( m_groups.find(p_groupName) ); + if (s != m_groups.end()) { + shareGroupReturn = (*s).second; + } + + return shareGroupReturn; +} + +ShareGroupPtr +ObjectNameManager::attachShareGroup(void *p_groupName, + void *p_existingGroupName) +{ + emugl::Mutex::AutoLock _lock(m_lock); + + ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) ); + if (s == m_groups.end()) { + // ShareGroup did not found !!! + return ShareGroupPtr(NULL); + } + + ShareGroupPtr shareGroupReturn((*s).second); + if (m_groups.find(p_groupName) == m_groups.end()) { + m_groups.insert( + std::pair( + p_groupName, shareGroupReturn)); + } + return shareGroupReturn; +} + +void +ObjectNameManager::deleteShareGroup(void *p_groupName) +{ + emugl::Mutex::AutoLock _lock(m_lock); + + ShareGroupsMap::iterator s( m_groups.find(p_groupName) ); + if (s != m_groups.end()) { + m_groups.erase(s); + } +} + +void *ObjectNameManager::getGlobalContext() +{ + emugl::Mutex::AutoLock _lock(m_lock); + return (m_groups.size() > 0) ? (*m_groups.begin()).first : NULL; +} + diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/FramebufferData.h b/external/android-emugl/host/libs/Translator/include/GLcommon/FramebufferData.h new file mode 100644 index 0000000..46cb651 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/FramebufferData.h @@ -0,0 +1,72 @@ +/* +* 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 _FRAMEBUFFER_DATA_H +#define _FRAMEBUFFER_DATA_H + +#include "objectNameManager.h" +#include +#include + +class RenderbufferData : public ObjectData +{ +public: + RenderbufferData(); + ~RenderbufferData(); + + unsigned int sourceEGLImage; + void (*eglImageDetach)(unsigned int imageId); + GLuint attachedFB; + GLenum attachedPoint; + GLuint eglImageGlobalTexName; + +}; + +const int MAX_ATTACH_POINTS = 3; + +class FramebufferData : public ObjectData +{ +public: + explicit FramebufferData(GLuint name); + ~FramebufferData(); + + void setAttachment(GLenum attachment, + GLenum target, + GLuint name, + ObjectDataPtr obj, + bool takeOwnership = false); + + GLuint getAttachment(GLenum attachment, + GLenum *outTarget, + ObjectDataPtr *outObj); + + void validate(class GLEScontext* ctx); + +private: + inline int attachmentPointIndex(GLenum attachment); + void detachObject(int idx); + +private: + GLuint m_fbName; + struct attachPoint { + GLenum target; // OGL if owned, GLES otherwise + GLuint name; // OGL if owned, GLES otherwise + ObjectDataPtr obj; + bool owned; + } m_attachPoints[MAX_ATTACH_POINTS+1]; + bool m_dirty; +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLDispatch.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLDispatch.h new file mode 100644 index 0000000..4ee08cd --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLDispatch.h @@ -0,0 +1,50 @@ +/* +* 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 GL_DISPATCHH +#define GL_DISPATCHH + +#include +#include + +#include "OpenGLESDispatch/gldefs.h" +#include "OpenGLESDispatch/gles_functions.h" +#include "GLutils.h" + +#include "emugl/common/mutex.h" + +#define GLAPIENTRY GL_APIENTRY +typedef void(*FUNCPTR)(); + +class GlLibrary; + +#define GLES_DECLARE_METHOD(return_type, function_name, signature, args) \ + static GL_APICALL return_type (GL_APIENTRY *function_name) signature; + +class GLDispatch { +public: + // Constructor. + GLDispatch(); + + void dispatchFuncs(GLESVersion version, GlLibrary* glLib); + + LIST_GLES_FUNCTIONS(GLES_DECLARE_METHOD, GLES_DECLARE_METHOD) + +private: + bool m_isLoaded; + static emugl::Mutex s_lock; +}; + +#endif // GL_DISPATCH_H diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESbuffer.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESbuffer.h new file mode 100644 index 0000000..38429d1 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESbuffer.h @@ -0,0 +1,47 @@ +/* +* 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 GLES_BUFFER_H +#define GLES_BUFFER_H + +#include +#include +#include +#include + +class GLESbuffer: public ObjectData { +public: + GLESbuffer():ObjectData(BUFFER_DATA),m_size(0),m_usage(GL_STATIC_DRAW),m_data(NULL),m_wasBound(false){} + GLuint getSize(){return m_size;}; + GLuint getUsage(){return m_usage;}; + GLvoid* getData(){ return m_data;} + bool setBuffer(GLuint size,GLuint usage,const GLvoid* data); + bool setSubBuffer(GLint offset,GLuint size,const GLvoid* data); + void getConversions(const RangeList& rIn,RangeList& rOut); + bool fullyConverted(){return m_conversionManager.size() == 0;}; + void setBinded(){m_wasBound = true;}; + bool wasBinded(){return m_wasBound;}; + ~GLESbuffer(); + +private: + GLuint m_size; + GLuint m_usage; + unsigned char* m_data; + RangeList m_conversionManager; + bool m_wasBound; +}; + +typedef emugl::SmartPtr GLESbufferPtr; +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLEScontext.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLEScontext.h new file mode 100644 index 0000000..037f902 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLEScontext.h @@ -0,0 +1,222 @@ +/* +* Copyright 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 GLES_CONTEXT_H +#define GLES_CONTEXT_H + +#include "GLDispatch.h" +#include "GLESpointer.h" +#include "objectNameManager.h" +#include "emugl/common/mutex.h" +#include + +typedef std::map ArraysMap; + +enum TextureTarget { +TEXTURE_2D, +TEXTURE_CUBE_MAP, +NUM_TEXTURE_TARGETS +}; + +typedef struct _textureTargetState { + GLuint texture; + GLboolean enabled; +} textureTargetState; + +typedef textureTargetState textureUnitState[NUM_TEXTURE_TARGETS]; + +class Version{ +public: + Version(); + Version(int major,int minor,int release); + Version(const char* versionString); + Version(const Version& ver); + bool operator<(const Version& ver) const; + Version& operator=(const Version& ver); +private: + int m_major; + int m_minor; + int m_release; +}; + +struct GLSupport { + GLSupport():maxLights(0),maxVertexAttribs(0),maxClipPlane(0),maxTexUnits(0), \ + maxTexImageUnits(0),maxTexSize(0) , maxCombinedTexImageUnits(0), \ + GL_EXT_TEXTURE_FORMAT_BGRA8888(false), GL_EXT_FRAMEBUFFER_OBJECT(false), \ + GL_ARB_VERTEX_BLEND(false), GL_ARB_MATRIX_PALETTE(false), \ + GL_EXT_PACKED_DEPTH_STENCIL(false) , GL_OES_READ_FORMAT(false), \ + GL_ARB_HALF_FLOAT_PIXEL(false), GL_NV_HALF_FLOAT(false), \ + GL_ARB_HALF_FLOAT_VERTEX(false),GL_SGIS_GENERATE_MIPMAP(false), + GL_ARB_ES2_COMPATIBILITY(false),GL_OES_STANDARD_DERIVATIVES(false), + GL_OES_TEXTURE_NPOT(false), GL_OES_RGB8_RGBA8(false) {} ; + int maxLights; + int maxVertexAttribs; + int maxClipPlane; + int maxTexUnits; + int maxTexImageUnits; + int maxTexSize; + int maxCombinedTexImageUnits; + Version glslVersion; + bool GL_EXT_TEXTURE_FORMAT_BGRA8888; + bool GL_EXT_FRAMEBUFFER_OBJECT; + bool GL_ARB_VERTEX_BLEND; + bool GL_ARB_MATRIX_PALETTE; + bool GL_EXT_PACKED_DEPTH_STENCIL; + bool GL_OES_READ_FORMAT; + bool GL_ARB_HALF_FLOAT_PIXEL; + bool GL_NV_HALF_FLOAT; + bool GL_ARB_HALF_FLOAT_VERTEX; + bool GL_SGIS_GENERATE_MIPMAP; + bool GL_ARB_ES2_COMPATIBILITY; + bool GL_OES_STANDARD_DERIVATIVES; + bool GL_OES_TEXTURE_NPOT; + bool GL_OES_RGB8_RGBA8; + +}; + +struct ArrayData{ + ArrayData():data(NULL), + type(0), + stride(0), + allocated(false){}; + + void* data; + GLenum type; + unsigned int stride; + bool allocated; +}; + +class GLESConversionArrays +{ +public: + GLESConversionArrays():m_current(0){}; + void setArr(void* data,unsigned int stride,GLenum type); + void allocArr(unsigned int size,GLenum type); + ArrayData& operator[](int i); + void* getCurrentData(); + ArrayData& getCurrentArray(); + unsigned int getCurrentIndex(); + void operator++(); + + ~GLESConversionArrays(); +private: + std::map m_arrays; + unsigned int m_current; +}; + +class GLEScontext{ +public: + virtual void init(GlLibrary* glLib); + GLEScontext(); + GLenum getGLerror(); + void setGLerror(GLenum err); + void setShareGroup(ShareGroupPtr grp){m_shareGroup = grp;}; + ShareGroupPtr shareGroup() const { return m_shareGroup; } + virtual void setActiveTexture(GLenum tex); + unsigned int getBindedTexture(GLenum target); + unsigned int getBindedTexture(GLenum unit,GLenum target); + void setBindedTexture(GLenum target,unsigned int tex); + bool isTextureUnitEnabled(GLenum unit); + void setTextureEnabled(GLenum target, GLenum enable); + ObjectLocalName getDefaultTextureName(GLenum target); + bool isInitialized() { return m_initialized; }; + void setUnpackAlignment(GLint param){ m_unpackAlignment = param; }; + GLint getUnpackAlignment(){ return m_unpackAlignment; }; + + bool isArrEnabled(GLenum); + void enableArr(GLenum arr,bool enable); + const GLvoid* setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize = false); + virtual const GLESpointer* getPointer(GLenum arrType); + virtual void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) = 0; + void bindBuffer(GLenum target,GLuint buffer); + void unbindBuffer(GLuint buffer); + bool isBuffer(GLuint buffer); + bool isBindedBuffer(GLenum target); + GLvoid* getBindedBuffer(GLenum target); + void getBufferSize(GLenum target,GLint* param); + void getBufferUsage(GLenum target,GLint* param); + bool setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage); + bool setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data); + const char * getExtensionString(); + const char * getVendorString() const; + const char * getRendererString() const; + const char * getVersionString() const; + void getGlobalLock(); + void releaseGlobalLock(); + virtual GLSupport* getCaps(){return &s_glSupport;}; + virtual ~GLEScontext(); + virtual int getMaxTexUnits() = 0; + virtual void drawValidate(void); + + void setRenderbufferBinding(GLuint rb) { m_renderbuffer = rb; } + GLuint getRenderbufferBinding() const { return m_renderbuffer; } + void setFramebufferBinding(GLuint fb) { m_framebuffer = fb; } + GLuint getFramebufferBinding() const { return m_framebuffer; } + + static GLDispatch& dispatcher(){return s_glDispatch;}; + + static int getMaxLights(){return s_glSupport.maxLights;} + static int getMaxClipPlanes(){return s_glSupport.maxClipPlane;} + static int getMaxTexSize(){return s_glSupport.maxTexSize;} + static Version glslVersion(){return s_glSupport.glslVersion;} + static bool isAutoMipmapSupported(){return s_glSupport.GL_SGIS_GENERATE_MIPMAP;} + static TextureTarget GLTextureTargetToLocal(GLenum target); + static unsigned int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices); + + virtual bool glGetIntegerv(GLenum pname, GLint *params); + virtual bool glGetBooleanv(GLenum pname, GLboolean *params); + virtual bool glGetFloatv(GLenum pname, GLfloat *params); + virtual bool glGetFixedv(GLenum pname, GLfixed *params); + +protected: + static void buildStrings(const char* baseVendor, const char* baseRenderer, const char* baseVersion, const char* version); + virtual bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) = 0; + void convertDirect(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p); + void convertDirectVBO(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p); + void convertIndirect(GLESConversionArrays& fArrs,GLsizei count,GLenum type,const GLvoid* indices,GLenum array_id,GLESpointer* p); + void convertIndirectVBO(GLESConversionArrays& fArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p); + void initCapsLocked(const GLubyte * extensionString); + virtual void initExtensionString() =0; + + static emugl::Mutex s_lock; + static GLDispatch s_glDispatch; + bool m_initialized; + unsigned int m_activeTexture; + GLint m_unpackAlignment; + ArraysMap m_map; + static std::string* s_glExtensions; + static GLSupport s_glSupport; + +private: + + virtual void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride, GLboolean normalized, int pointsIndex = -1) = 0 ; + GLuint getBuffer(GLenum target); + + ShareGroupPtr m_shareGroup; + GLenum m_glError; + textureUnitState* m_texState; + unsigned int m_arrayBuffer; + unsigned int m_elementBuffer; + GLuint m_renderbuffer; + GLuint m_framebuffer; + + static std::string s_glVendor; + static std::string s_glRenderer; + static std::string s_glVersion; +}; + +#endif + diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h new file mode 100644 index 0000000..15e5d04 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h @@ -0,0 +1,48 @@ +#ifndef GLES_MACROS_H +#define GLES_MACROS_H + +#define GET_CTX() \ + if(!s_eglIface) return; \ + GLEScontext *ctx = s_eglIface->getGLESContext(); \ + if(!ctx) return; + +#define GET_CTX_CM() \ + if(!s_eglIface) return; \ + GLEScmContext *ctx = static_cast(s_eglIface->getGLESContext()); \ + if(!ctx) return; + +#define GET_CTX_V2() \ + if(!s_eglIface) return; \ + GLESv2Context *ctx = static_cast(s_eglIface->getGLESContext()); \ + if(!ctx) return; + +#define GET_CTX_RET(failure_ret) \ + if(!s_eglIface) return failure_ret; \ + GLEScontext *ctx = s_eglIface->getGLESContext(); \ + if(!ctx) return failure_ret; + +#define GET_CTX_CM_RET(failure_ret) \ + if(!s_eglIface) return failure_ret; \ + GLEScmContext *ctx = static_cast(s_eglIface->getGLESContext()); \ + if(!ctx) return failure_ret; + +#define GET_CTX_V2_RET(failure_ret) \ + if(!s_eglIface) return failure_ret; \ + GLESv2Context *ctx = static_cast(s_eglIface->getGLESContext()); \ + if(!ctx) return failure_ret; + + +#define SET_ERROR_IF(condition,err) if((condition)) { \ + fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ + ctx->setGLerror(err); \ + return; \ + } + + +#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \ + fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ + ctx->setGLerror(err); \ + return ret; \ + } + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESpointer.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESpointer.h new file mode 100644 index 0000000..851fe45 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESpointer.h @@ -0,0 +1,58 @@ +/* +* 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 GLES_POINTER_H +#define GLES_POINTER_H + +#include +#include "GLESbuffer.h" + +class GLESpointer +{ + +public: + GLESpointer(); + GLenum getType() const; + GLint getSize() const; + GLsizei getStride() const; + const GLvoid* getArrayData() const; + GLvoid* getBufferData() const; + GLuint getBufferName() const; + GLboolean getNormalized() const { return m_normalize ? GL_TRUE : GL_FALSE; } + const GLvoid* getData() const; + unsigned int getBufferOffset() const; + void redirectPointerData(); + void getBufferConversions(const RangeList& rl,RangeList& rlOut); + bool bufferNeedConversion(){ return !m_buffer->fullyConverted();} + void setArray (GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize = false); + void setBuffer(GLint size,GLenum type,GLsizei stride,GLESbuffer* buf,GLuint bufferName,int offset,bool normalize = false); + bool isEnable() const; + bool isNormalize() const; + bool isVBO() const; + void enable(bool b); + +private: + GLint m_size; + GLenum m_type; + GLsizei m_stride; + bool m_enabled; + bool m_normalize; + const GLvoid* m_data; + GLESbuffer* m_buffer; + GLuint m_bufferName; + unsigned int m_buffOffset; + bool m_isVBO; +}; +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESvalidate.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESvalidate.h new file mode 100644 index 0000000..92c1f33 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESvalidate.h @@ -0,0 +1,44 @@ +/* +* 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 GLES_VALIDATE_H +#define GLES_VALIDATE_H + +#include +#include "GLEScontext.h" +struct GLESvalidate +{ +static bool textureEnum(GLenum e,unsigned int maxTex); +static bool pixelType(GLEScontext * ctx,GLenum type); +static bool pixelOp(GLenum format,GLenum type); +static bool pixelFrmt(GLEScontext* ctx , GLenum format); +static bool bufferTarget(GLenum target); +static bool bufferUsage(GLenum usage); +static bool bufferParam(GLenum param); +static bool drawMode(GLenum mode); +static bool drawType(GLenum mode); +static bool textureTarget(GLenum target); +static bool textureTargetLimited(GLenum target); +static bool textureTargetEx(GLenum target); +static bool texImgDim(GLsizei width,GLsizei height,int maxTexSize); +static bool blendEquationMode(GLenum mode); +static bool framebufferTarget(GLenum target); +static bool framebufferAttachment(GLenum attachment); +static bool framebufferAttachmentParams(GLenum pname); +static bool renderbufferTarget(GLenum target); +static bool renderbufferParams(GLenum pname); +}; + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLLibrary.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLLibrary.h new file mode 100644 index 0000000..0a33096 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLLibrary.h @@ -0,0 +1,36 @@ +// Copyright (C) 2015 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 GLCOMMON_GL_LIBRARY_H +#define GLCOMMON_GL_LIBRARY_H + +// An interface class used to model the desktop GL library to use at runtime. +// Use GlLibrary::getHostInstance() to retrieve the instance corresponding +// to the host's default system GL library. +class GlLibrary { +public: + // Generic pointer-to-function type. + typedef void (*GlFunctionPointer)(void); + + // Empty constructor. + GlLibrary() {} + + // Empty destructor. + virtual ~GlLibrary() {} + + // Find the function named |name| in the library and return its address. + virtual GlFunctionPointer findSymbol(const char* name) = 0; +}; + +#endif // GLCOMMON_GL_LIBRARY_H diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLconversion_macros.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLconversion_macros.h new file mode 100644 index 0000000..83e99b4 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLconversion_macros.h @@ -0,0 +1,31 @@ +/* +* 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 _GL_FIXED_OPS_H +#define _GL_FIXED_OPS_H + +#define X2F(x) (((float)(x))/65536.0f) +#define X2D(x) (((double)(x))/65536.0) +#define X2I(x) ((x) /65536) +#define B2S(x) ((short)x) + + +#define F2X(d) ((d) > 32767.65535 ? 32767 * 65536 + 65535 : \ + (d) < -32768.65535 ? -32768 * 65536 + 65535 : \ + ((GLfixed) ((d) * 65536))) + +#define I2X(d) ((d)*65536) + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLutils.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLutils.h new file mode 100644 index 0000000..28750d6 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLutils.h @@ -0,0 +1,54 @@ +/* +* 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 GL_UTILS_H +#define GL_UTILS_H + +#include +#include +#include + +typedef enum { + GLES_1_1 = 1, + GLES_2_0 = 2, + MAX_GLES_VERSION //Must be last +} GLESVersion; + +bool isPowerOf2(int num); + +// defines many types as 'void*' while they're really +// implemented as unsigned integers. These convenience template functions +// help casting between them safely without generating compiler warnings. +inline void* SafePointerFromUInt(unsigned int handle) { + return (void*)(uintptr_t)(handle); +} + +inline unsigned int SafeUIntFromPointer(const void* ptr) { +#if 1 + // Ignore the assert below to avoid crashing when running older + // system images, which might have buggy encoder libraries. Print + // an error message though. + if ((uintptr_t)(ptr) != (unsigned int)(uintptr_t)(ptr)) { + fprintf(stderr, "EmuGL:WARNING: bad generic pointer %p\n", ptr); + } +#else + // Assertion error if the pointer contains a value that does not fit + // in an unsigned integer! + assert((uintptr_t)(ptr) == (unsigned int)(uintptr_t)(ptr)); +#endif + return (unsigned int)(uintptr_t)(ptr); +} + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/PaletteTexture.h b/external/android-emugl/host/libs/Translator/include/GLcommon/PaletteTexture.h new file mode 100644 index 0000000..90b206d --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/PaletteTexture.h @@ -0,0 +1,25 @@ +/* +* 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 __PALETTE_TEXTURE_H__ +#define __PALETTE_TEXTURE_H__ + +#include + +#define MAX_SUPPORTED_PALETTE 10 + +unsigned char* uncompressTexture(GLenum internalformat,GLenum& formatOut,GLsizei width,GLsizei height,GLsizei imageSize, const GLvoid* data,GLint level); + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/RangeManip.h b/external/android-emugl/host/libs/Translator/include/GLcommon/RangeManip.h new file mode 100644 index 0000000..e3162b8 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/RangeManip.h @@ -0,0 +1,69 @@ +/* +* 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 RANGE_H +#define RANGE_H + +#include + +class Range { + +public: + Range():m_start(0),m_end(0),m_size(0){}; + Range(int start,int size):m_start(start),m_end(start+size),m_size(size){}; + Range(const Range& r):m_start(r.m_start),m_end(r.m_end),m_size(r.m_size){}; + void setRange(int start,int size){m_start = start; m_end = start+size; m_size = size;}; + inline int getStart() const{return m_start;}; + inline int getEnd() const{return m_end;}; + inline int getSize() const{return m_size;}; + Range& operator=(const Range& r) { + m_start = r.m_start; + m_end = r.m_end; + m_size = r.m_size; + return *this; + } + bool operator ==(const Range& r) const { + return m_start == r.m_start && m_size == r.m_size && m_end == r.m_end; + } + bool operator !=(const Range& r) const {return !((*this) == r);}; + bool rangeIntersection(const Range& r,Range& rOut) const ; + bool rangeUnion(const Range& r,Range& rOut) const ; + +private: + int m_start; + int m_end; + int m_size; +}; + +class RangeList { +public: + void addRange(const Range& r); + void addRanges(const RangeList& rl); + void delRange(const Range& r,RangeList& deleted); + void delRanges(const RangeList& rl,RangeList& deleted); + bool empty() const; + void merge(); + int size() const; + void clear(); + Range& operator[](unsigned int i){return list[i];}; +private: + void erase(unsigned int i); + std::vector list; +}; + + + + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/TextureUtils.h b/external/android-emugl/host/libs/Translator/include/GLcommon/TextureUtils.h new file mode 100644 index 0000000..9b0c4ea --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/TextureUtils.h @@ -0,0 +1,31 @@ +/* +* 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 _TEXTURE_UTILS_H +#define _TEXTURE_UTILS_H + +#include +#include +#include "GLEScontext.h" +#include "PaletteTexture.h" +#include "etc1.h" + +int getCompressedFormats(int* formats); +void doCompressedTexImage2D(GLEScontext * ctx, GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLint border, + GLsizei imageSize, const GLvoid* data, void * funcPtr); + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h b/external/android-emugl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h new file mode 100644 index 0000000..4beffaa --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h @@ -0,0 +1,120 @@ +/* +* 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 TRANSLATOR_IFACES_H +#define TRANSLATOR_IFACES_H + +#include "GLcommon/objectNameManager.h" + +#include +#include + +extern "C" { + +/* This is a generic function pointer type, whose name indicates it must + * be cast to the proper type *and calling convention* before use. + */ +typedef void (*__translatorMustCastToProperFunctionPointerType)(void); + +typedef struct { + const char* name; + __translatorMustCastToProperFunctionPointerType address; +}ExtentionDescriptor; + +class TextureData : public ObjectData +{ +public: + ~TextureData() { + if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage); + } + TextureData(): ObjectData(TEXTURE_DATA), + width(0), + height(0), + border(0), + internalFormat(GL_RGBA), + sourceEGLImage(0), + wasBound(false), + requiresAutoMipmap(false), + target(0), + oldGlobal(0) { + memset(crop_rect,0,4*sizeof(int)); + }; + + unsigned int width; + unsigned int height; + unsigned int border; + unsigned int internalFormat; + unsigned int sourceEGLImage; + bool wasBound; + bool requiresAutoMipmap; + int crop_rect[4]; + void (*eglImageDetach)(unsigned int imageId); + GLenum target; + GLuint oldGlobal; +}; + +struct EglImage +{ + ~EglImage(){}; + unsigned int imageId; + unsigned int globalTexName; + unsigned int width; + unsigned int height; + unsigned int internalFormat; + unsigned int border; +}; + +typedef emugl::SmartPtr ImagePtr; +typedef std::map< unsigned int, ImagePtr> ImagesHndlMap; + +class GLEScontext; + +typedef struct { + void (*initGLESx)(); + GLEScontext* (*createGLESContext)(); + void (*initContext)(GLEScontext*,ShareGroupPtr); + void (*deleteGLESContext)(GLEScontext*); + void (*flush)(); + void (*finish)(); + void (*setShareGroup)(GLEScontext*,ShareGroupPtr); + __translatorMustCastToProperFunctionPointerType (*getProcAddress)(const char*); +}GLESiface; + +class GlLibrary; + +// A structure containing function pointers implemented by the EGL +// translator library, and called from the GLES 1.x and 2.0 translator +// libraries. +struct EGLiface { + // Get the current GLESContext instance for the current thread. + GLEScontext* (*getGLESContext)(); + + // Create a new global EglImage object named |imageId| and return a + // pointer to its new instance. + EglImage* (*eglAttachEGLImage)(unsigned int imageId); + + // Release a global EglImage instance named |imageId|. + void (*eglDetachEGLImage)(unsigned int imageId); + + // Return instance of GlLibrary class to use for dispatch. + // at runtime. This is implemented in the EGL library because on Windows + // all functions returned by wglGetProcAddress() are context-dependent! + GlLibrary* (*eglGetGlLibrary)(); +}; + +typedef GLESiface* (*__translator_getGLESIfaceFunc)(const EGLiface*); + +} +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/etc1.h b/external/android-emugl/host/libs/Translator/include/GLcommon/etc1.h new file mode 100644 index 0000000..15ee9ac --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/etc1.h @@ -0,0 +1,108 @@ +// Copyright 2009 Google Inc. +// +// 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 __etc1_h__ +#define __etc1_h__ + +#define MAX_ETC_SUPPORTED 1 + +#define ETC1_ENCODED_BLOCK_SIZE 8 +#define ETC1_DECODED_BLOCK_SIZE 48 + +#ifndef ETC1_RGB8_OES +#define ETC1_RGB8_OES 0x8D64 +#endif + +typedef unsigned char etc1_byte; +typedef int etc1_bool; +typedef unsigned int etc1_uint32; + +#ifdef __cplusplus +extern "C" { +#endif + +// Encode a block of pixels. +// +// pIn is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a +// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R +// value of pixel (x, y). +// +// validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether +// the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing. +// +// pOut is an ETC1 compressed version of the data. + +void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 validPixelMask, etc1_byte* pOut); + +// Decode a block of pixels. +// +// pIn is an ETC1 compressed version of the data. +// +// pOut is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a +// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R +// value of pixel (x, y). + +void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut); + +// Return the size of the encoded image data (does not include size of PKM header). + +etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height); + +// Encode an entire image. +// pIn - pointer to the image data. Formatted such that +// pixel (x,y) is at pIn + pixelSize * x + stride * y; +// pOut - pointer to encoded data. Must be large enough to store entire encoded image. +// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image. +// returns non-zero if there is an error. + +int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height, + etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut); + +// Decode an entire image. +// pIn - pointer to encoded data. +// pOut - pointer to the image data. Will be written such that +// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be +// large enough to store entire image. +// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image. +// returns non-zero if there is an error. + +int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut, + etc1_uint32 width, etc1_uint32 height, + etc1_uint32 pixelSize, etc1_uint32 stride); + +// Size of a PKM header, in bytes. + +#define ETC_PKM_HEADER_SIZE 16 + +// Format a PKM header + +void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height); + +// Check if a PKM header is correctly formatted. + +etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader); + +// Read the image width from a PKM header + +etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader); + +// Read the image height from a PKM header + +etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/objectNameManager.h b/external/android-emugl/host/libs/Translator/include/GLcommon/objectNameManager.h new file mode 100644 index 0000000..4d4d038 --- /dev/null +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/objectNameManager.h @@ -0,0 +1,269 @@ +/* +* 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 _OBJECT_NAME_MANAGER_H +#define _OBJECT_NAME_MANAGER_H + +#include +#include "emugl/common/mutex.h" +#include "emugl/common/smart_ptr.h" + +enum NamedObjectType { + VERTEXBUFFER = 0, + TEXTURE = 1, + RENDERBUFFER = 2, + FRAMEBUFFER = 3, + SHADER = 4, + NUM_OBJECT_TYPES = 5 // Must be last +}; + +enum ObjectDataType { + SHADER_DATA, + PROGRAM_DATA, + TEXTURE_DATA, + BUFFER_DATA, + UNDEFINED_DATA +}; + +class ObjectData +{ +public: + ObjectData() : m_dataType(UNDEFINED_DATA) {}; + ObjectData(ObjectDataType type): m_dataType(type) {}; + ObjectDataType getDataType() { return m_dataType; }; + virtual ~ObjectData() {}; +private: + ObjectDataType m_dataType; +}; +typedef emugl::SmartPtr ObjectDataPtr; +typedef unsigned long long ObjectLocalName; +typedef std::map NamesMap; + +// +// Class NameSpace - this class manages allocations and deletions of objects +// from a single "local" namespace (private to context group). +// For each allocated object name, a "global" name is +// generated as well to be used in the space where all +// contexts are shared. +// +// NOTE: this class does not used by the EGL/GLES layer directly, +// the EGL/GLES layer creates objects using the ShareGroup class +// interface (see below). +class GlobalNameSpace; +class NameSpace +{ + friend class ShareGroup; + friend class GlobalNameSpace; + +private: + NameSpace(NamedObjectType p_type, GlobalNameSpace *globalNameSpace); + ~NameSpace(); + + // + // genName - creates new object in the namespace and returns its name. + // if genLocal is false then the specified p_localName will be used. + // This function also generate a global name for the object, + // the value of the global name can be retrieved using the + // getGlobalName function. + // + ObjectLocalName genName(ObjectLocalName p_localName, bool genGlobal, bool genLocal); + + // genGlobalName() - This function creates a global name + // with no associated local name, for the + // translator internal use. + unsigned int genGlobalName(void); + + // + // getGlobalName - returns the global name of an object or 0 if the object + // does not exist. + // + unsigned int getGlobalName(ObjectLocalName p_localName); + + // + // getLocaalName - returns the local name of an object or 0 if the object + // does not exist. + // + ObjectLocalName getLocalName(unsigned int p_globalName); + + // + // deleteName - deletes and object from the namespace as well as its + // global name from the global name space. + // + void deleteName(ObjectLocalName p_localName); + + // + // isObject - returns true if the named object exist. + // + bool isObject(ObjectLocalName p_localName); + + // + // replaces an object to map to an existing global object + // + void replaceGlobalName(ObjectLocalName p_localName, unsigned int p_globalName); + +private: + ObjectLocalName m_nextName; + NamesMap m_localToGlobalMap; + const NamedObjectType m_type; + GlobalNameSpace *m_globalNameSpace; +}; + +class GlobalNameSpace +{ +public: + GlobalNameSpace(); + ~GlobalNameSpace(); + unsigned int genName(NamedObjectType p_type); + void deleteName(NamedObjectType p_type, unsigned int p_name); + +private: + emugl::Mutex m_lock; +}; + +// +// class ShareGroup - +// That class manages objects of one "local" context share group, typically +// there will be one inctance of ShareGroup for each user OpenGL context +// unless the user context share with another user context. In that case they +// both will share the same ShareGroup instance. +// calls into that class gets serialized through a lock so it is thread safe. +// +class ShareGroup +{ + friend class ObjectNameManager; + friend class emugl::SmartPtr; // to allow destructing when ShareGroupPtr refcount reaches zero + +public: + + // + // genName - generates new object name and returns its name value. + // if genLocal is false, p_localName will be used as the name. + // This function also generates a "global" name for the object + // which can be queried using the getGlobalName function. + // + ObjectLocalName genName(NamedObjectType p_type, ObjectLocalName p_localName = 0, bool genLocal= false); + + // genGlobalName() - This function creates a global name + // with no associated local name, for the + // translator internal use. + unsigned int genGlobalName(NamedObjectType p_type); + + // + // getGlobalName - retrieves the "global" name of an object or 0 if the + // object does not exist. + // + unsigned int getGlobalName(NamedObjectType p_type, ObjectLocalName p_localName); + + // + // getLocalName - retrieves the "local" name of an object or 0 if the + // object does not exist. + // + ObjectLocalName getLocalName(NamedObjectType p_type, unsigned int p_globalName); + + // + // deleteName - deletes and object from the namespace as well as its + // global name from the global name space. + // + void deleteName(NamedObjectType p_type, ObjectLocalName p_localName); + + // + // replaceGlobalName - replaces an object to map to an existing global + // named object. (used when creating EGLImage siblings) + // + void replaceGlobalName(NamedObjectType p_type, ObjectLocalName p_localName, unsigned int p_globalName); + + // + // isObject - returns true if the named object exist. + // + bool isObject(NamedObjectType p_type, ObjectLocalName p_localName); + + // + // Assign object global data to a names object + // + void setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, ObjectDataPtr data); + + // + // Retrieve object global data + // + ObjectDataPtr getObjectData(NamedObjectType p_type, ObjectLocalName p_localName); + +private: + explicit ShareGroup(GlobalNameSpace *globalNameSpace); + ~ShareGroup(); + +private: + emugl::Mutex m_lock; + NameSpace *m_nameSpace[NUM_OBJECT_TYPES]; + void *m_objectsData; +}; + +typedef emugl::SmartPtr ShareGroupPtr; +typedef std::multimap ShareGroupsMap; + +// +// ObjectNameManager - +// This class manages the set of all ShareGroups instances, +// each ShareGroup instance can be accessed through one or more 'groupName' +// values. the type of 'groupName' is void *, the intent is that the EGL +// layer will use the user context handle as the name for its ShareGroup +// object. Multiple names can be attached to a ShareGroup object to support +// user context sharing. +// +class ObjectNameManager +{ +public: + explicit ObjectNameManager(GlobalNameSpace *globalNameSpace); + ~ObjectNameManager(); + + // + // createShareGroup - create a new ShareGroup object and attach it with + // the "name" specified by p_groupName. + // + ShareGroupPtr createShareGroup(void *p_groupName); + + // + // attachShareGroup - find the ShareGroup object attached to the name + // specified in p_existingGroupName and attach p_groupName to the same + // ShareGroup instance. + // + ShareGroupPtr attachShareGroup(void *p_groupName, void *p_existingGroupName); + + // + // getShareGroup - retreive a ShareGroup object based on its "name" + // + ShareGroupPtr getShareGroup(void *p_groupName); + + // + // deleteShareGroup - deletes the attachment of the p_groupName to its + // attached ShareGroup. When the last name of ShareGroup is + // deleted the ShareGroup object is destroyed. + // + void deleteShareGroup(void *p_groupName); + + // + // getGlobalContext() - this function returns a name of an existing + // ShareGroup. The intent is that the EGL layer will + // use that function to get the GL context which each + // new context needs to share with. + // + void *getGlobalContext(); + +private: + ShareGroupsMap m_groups; + emugl::Mutex m_lock; + GlobalNameSpace *m_globalNameSpace; +}; + +#endif diff --git a/external/android-emugl/shared/emugl/common/shared_library.h b/external/android-emugl/shared/emugl/common/shared_library.h index 62d1f0b..55304a7 100644 --- a/external/android-emugl/shared/emugl/common/shared_library.h +++ b/external/android-emugl/shared/emugl/common/shared_library.h @@ -92,14 +92,8 @@ private: // eg. // on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo" -#if defined(__x86_64__) -# define EMUGL_LIBNAME(name) "lib64" name -#elif defined(__i386__) + # define EMUGL_LIBNAME(name) "lib" name -#else -/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ -# define EMUGL_LIBNAME(name) "lib" name -#endif } // namespace emugl