diff options
Diffstat (limited to 'emulator/opengl')
112 files changed, 4401 insertions, 1164 deletions
diff --git a/emulator/opengl/Android.mk b/emulator/opengl/Android.mk index a349b96..856826a 100644 --- a/emulator/opengl/Android.mk +++ b/emulator/opengl/Android.mk @@ -1,13 +1,10 @@ # This is the top-level build file for the Android HW OpenGL ES emulation # in Android. # -# You must define BUILD_EMULATOR_OPENGL to 'true' in your environment to +# You must define BUILD_EMULATOR_HOST_OPENGL to 'true' in your environment to # build the following files. # -# Also define BUILD_EMULATOR_OPENGL_DRIVER to 'true' to build the gralloc -# stuff as well. -# -ifeq (true,$(BUILD_EMULATOR_OPENGL)) +ifeq (true,$(BUILD_EMULATOR_HOST_OPENGL)) # Top-level for all modules EMUGL_PATH := $(call my-dir) @@ -16,7 +13,19 @@ EMUGL_PATH := $(call my-dir) # This is always set to a module's LOCAL_C_INCLUDES # See the definition of emugl-begin-module in common.mk # -EMUGL_COMMON_INCLUDES := $(EMUGL_PATH)/host/include/libOpenglRender +EMUGL_COMMON_INCLUDES := \ + $(EMUGL_PATH)/host/include/libOpenglRender \ + $(EMUGL_PATH)/shared + +ifeq ($(BUILD_STANDALONE_EMULATOR),true) +EMUGL_COMMON_INCLUDES := $(EMUGL_PATH)/host/libs/Translator/include +endif + +ifeq ($(BUILD_STANDALONE_EMULATOR),true) +EMUGL_BUILD_64BITS := $(strip $(EMULATOR_BUILD_64BITS)) +else +EMUGL_BUILD_64BITS := true +endif # common cflags used by several modules # This is always set to a module's LOCAL_CFLAGS @@ -24,6 +33,12 @@ EMUGL_COMMON_INCLUDES := $(EMUGL_PATH)/host/include/libOpenglRender # EMUGL_COMMON_CFLAGS := -DWITH_GLES2 +# Define EMUGL_BUILD_DEBUG=1 in your environment to build a +# debug version of the EmuGL host binaries. +ifneq (,$(strip $(EMUGL_BUILD_DEBUG))) +EMUGL_COMMON_CFLAGS += -O0 -g -DEMUGL_DEBUG=1 +endif + # Uncomment the following line if you want to enable debug traces # in the GLES emulation libraries. # EMUGL_COMMON_CFLAGS += -DEMUGL_DEBUG=1 @@ -53,6 +68,11 @@ include $(EMUGL_PATH)/common.mk # source files (see all emugl-gen-decoder/encoder in common.mk) # include $(EMUGL_PATH)/host/tools/emugen/Android.mk + +# Required by our units test. +include $(EMUGL_PATH)/googletest.mk + +include $(EMUGL_PATH)/shared/emugl/common/Android.mk include $(EMUGL_PATH)/shared/OpenglOsUtils/Android.mk include $(EMUGL_PATH)/shared/OpenglCodecCommon/Android.mk @@ -66,6 +86,9 @@ include $(EMUGL_PATH)/host/libs/Translator/GLES_CM/Android.mk include $(EMUGL_PATH)/host/libs/Translator/GLES_V2/Android.mk include $(EMUGL_PATH)/host/libs/Translator/EGL/Android.mk +# Required to declare SDL-related flags for some host tests. +include $(EMUGL_PATH)/sdl.mk + # Host shared libraries include $(EMUGL_PATH)/host/libs/libOpenglRender/Android.mk @@ -78,4 +101,4 @@ include $(EMUGL_PATH)/tests/translator_tests/MacCommon/Android.mk include $(EMUGL_PATH)/tests/translator_tests/GLES_CM/Android.mk include $(EMUGL_PATH)/tests/translator_tests/GLES_V2/Android.mk -endif # BUILD_EMULATOR_OPENGL == true +endif # BUILD_EMULATOR_HOST_OPENGL == true diff --git a/emulator/opengl/common.mk b/emulator/opengl/common.mk index be5eaf5..255b9e3 100644 --- a/emulator/opengl/common.mk +++ b/emulator/opengl/common.mk @@ -24,10 +24,20 @@ emugl-begin-host-static-library = $(call emugl-begin-module,$1,HOST_STATIC_LIBRA emugl-begin-host-shared-library = $(call emugl-begin-module,$1,HOST_SHARED_LIBRARY,HOST) emugl-begin-host-executable = $(call emugl-begin-module,$1,HOST_EXECUTABLE,HOST) +emugl-begin-host64-static-library = $(call emugl-begin-module64,$1,HOST_STATIC_LIBRARY,HOST) +emugl-begin-host64-shared-library = $(call emugl-begin-module64,$1,HOST_SHARED_LIBRARY,HOST) +emugl-begin-host64-executable = $(call emugl-begin-module64,$1,HOST_EXECUTABLE,HOST) + # Internal list of all declared modules (used for sanity checking) _emugl_modules := _emugl_HOST_modules := +ifeq ($(BUILD_STANDALONE_EMULATOR),true) +EMUGL_LOCAL_EXTRAS = $(end-emulator-module-ev) +else # BUILD_STANDALONE_EMULATOR != true +EMUGL_LOCAL_EXTRAS = +endif # BUILD_STANDALONE_EMULATOR != true + # do not use directly, see functions above instead emugl-begin-module = \ $(eval include $(CLEAR_VARS)) \ @@ -35,14 +45,21 @@ emugl-begin-module = \ $(eval LOCAL_MODULE_TAGS := $(if $3,,debug)) \ $(eval LOCAL_MODULE_CLASS := $(patsubst HOST_%,%,$(patsubst %EXECUTABLE,%EXECUTABLES,$(patsubst %LIBRARY,%LIBRARIES,$2)))) \ $(eval LOCAL_IS_HOST_MODULE := $(if $3,true,))\ - $(eval LOCAL_C_INCLUDES := $(EMUGL_COMMON_INCLUDES)) \ - $(eval LOCAL_CFLAGS := $(EMUGL_COMMON_CFLAGS)) \ + $(eval LOCAL_C_INCLUDES += $(EMUGL_COMMON_INCLUDES)) \ + $(eval LOCAL_CFLAGS += $(EMUGL_COMMON_CFLAGS)) \ + $(eval LOCAL_LDLIBS += -lstdc++) \ $(eval LOCAL_PRELINK_MODULE := false)\ $(eval _EMUGL_INCLUDE_TYPE := $(BUILD_$2)) \ + $(eval LOCAL_MODULE_BITS := 32) \ $(call _emugl-init-module,$1,$2,$3) +emugl-begin-module64 = \ + $(call emugl-begin-module,$1,$2,$3) \ + $(eval LOCAL_MODULE_BITS := 64) \ + # Used to end a module definition, see function definitions above emugl-end-module = \ + $(eval $(EMUGL_LOCAL_EXTRAS)) \ $(eval include $(_EMUGL_INCLUDE_TYPE))\ $(eval _EMUGL_INCLUDE_TYPE :=) \ $(eval _emugl_$(_emugl_HOST)modules += $(_emugl_MODULE))\ @@ -87,6 +104,7 @@ emugl-end-module = \ # This is the list of recognized export types we support for now. EMUGL_EXPORT_TYPES := \ CFLAGS \ + CXXFLAGS \ LDLIBS \ LDFLAGS \ C_INCLUDES \ @@ -118,7 +136,7 @@ _emugl-init-module = \ # $2: Value(s) to append to the export emugl-export = \ $(eval _emugl.$(_emugl_MODULE).export.$1 += $2)\ - $(eval LOCAL_$1 := $2 $(LOCAL_$1)) + $(eval LOCAL_$1 := $(LOCAL_$1) $2) emugl-export-outer = \ $(eval _emugl.$(_emugl_MODULE).export.$1 += $2) @@ -148,7 +166,7 @@ _emugl-module-import = \ $(call _emugl-module-import,$(_sub))\ )\ $(foreach _type,$(EMUGL_EXPORT_TYPES),\ - $(eval LOCAL_$(_type) := $(_emugl.$1.export.$(_type)) $(LOCAL_$(_type)))\ + $(eval LOCAL_$(_type) := $(LOCAL_$(_type)) $(_emugl.$1.export.$(_type)))\ )\ $(if $(filter EXECUTABLE SHARED_LIBRARY,$(_emugl.$(_emugl_MODULE).type)),\ $(if $(filter STATIC_LIBRARY,$(_emugl.$1.type)),\ diff --git a/emulator/opengl/gen-encoder.sh b/emulator/opengl/gen-encoder.sh index 23ecf03..c55a170 100755 --- a/emulator/opengl/gen-encoder.sh +++ b/emulator/opengl/gen-encoder.sh @@ -12,17 +12,12 @@ if [ -z "$ANDROID_BUILD_TOP" ]; then fi cd "$ANDROID_BUILD_TOP" >/dev/null SRCDIR="sdk/emulator/opengl/host/libs" -DSTDIR="development/tools/emulator/opengl/system" +DSTDIR="device/generic/goldfish/opengl/system" +EMUGEN="external/qemu/objs/emugen" if [ ! -d "$SRCDIR" -o ! -d "$DSTDIR" ]; then echo error: can\'t find source and/or destination directory exit 1 fi - -if [ -z "$ANDROID_HOST_OUT" ]; then - echo error: ANDROID_HOST_OUT not set - exit 1 -fi -EMUGEN="$ANDROID_HOST_OUT/bin/emugen" if [ ! -x "$EMUGEN" ]; then echo error: emugen not available, did you forget to build? exit 1 diff --git a/emulator/opengl/googletest.mk b/emulator/opengl/googletest.mk new file mode 100644 index 0000000..8147874 --- /dev/null +++ b/emulator/opengl/googletest.mk @@ -0,0 +1,43 @@ +# This contains common definitions used to define a host module +# to link GoogleTest with the EmuGL test programs. +# +# This is used instead of including external/gtest/Android.mk to +# be able to build both the 32-bit and 64-bit binaries while +# building a 32-bit only SDK (sdk-eng, sdk_x86-eng, sdk_mips-eng). + + +ifeq (true,$(BUILD_STANDALONE_EMULATOR)) +LOCAL_PATH := $(EMULATOR_GTEST_SOURCES_DIR) +else +LOCAL_PATH := $(EMUGL_PATH)/../../../external/gtest +endif + +common_SRC_FILES := \ + src/gtest-all.cc \ + src/gtest_main.cc + +common_CFLAGS := -O0 + +ifneq (windows,$(HOST_OS)) + common_LDLIBS += -lpthread +endif + +$(call emugl-begin-host-static-library,libemugl_gtest) +LOCAL_SRC_FILES := $(common_SRC_FILES) +LOCAL_CFLAGS += $(common_CFLAGS) +LOCAL_CPP_EXTENSION := .cc +$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include) +$(call emugl-export,LDLIBS,$(common_LDLIBS)) +$(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64emugl_gtest) + LOCAL_SRC_FILES := $(common_SRC_FILES) + LOCAL_CFLAGS += $(common_CFLAGS) + LOCAL_C_INCLUDES += $(LOCAL_PATH)/include + LOCAL_CPP_EXTENSION := .cc + $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include) + $(call emugl-export,CFLAGS,-m64) + $(call emugl-export,LDLIBS,$(common_LDLIBS) -m64) + $(call emugl-end-module) +endif # EMUGL_BUILD_64BITS diff --git a/emulator/opengl/host/libs/GLESv1_dec/Android.mk b/emulator/opengl/host/libs/GLESv1_dec/Android.mk index a6d8670..7ab3f0a 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/Android.mk +++ b/emulator/opengl/host/libs/GLESv1_dec/Android.mk @@ -18,20 +18,24 @@ $(call emugl-gen-decoder,$(LOCAL_PATH),gl) LOCAL_SRC_FILES := GLDecoder.cpp $(call emugl-export,CFLAGS,$(host_common_debug_CFLAGS)) +$(call emugl-export,LDLIBS,-lstdc++) $(call emugl-end-module) ### host library, 64-bit #################################### -$(call emugl-begin-host-static-library,lib64GLESv1_dec) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64GLESv1_dec) -$(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) + $(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) -$(call emugl-gen-decoder,$(LOCAL_PATH),gl) + $(call emugl-gen-decoder,$(LOCAL_PATH),gl) -LOCAL_SRC_FILES := GLDecoder.cpp + LOCAL_SRC_FILES := GLDecoder.cpp -$(call emugl-export,CFLAGS,$(host_common_debug_CFLAGS) -m64) + $(call emugl-export,CFLAGS,$(host_common_debug_CFLAGS) -m64) + $(call emugl-export,LDLIBS,-lstdc++) -$(call emugl-end-module) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp index 5399445..3c5bd70 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp +++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp @@ -21,6 +21,10 @@ #include <GLES/gl.h> #include <GLES/glext.h> +static inline void* SafePointerFromUInt(GLuint value) { + return (void*)(uintptr_t)value; +} + GLDecoder::GLDecoder() { m_contextData = NULL; @@ -88,43 +92,43 @@ int GLDecoder::s_glFinishRoundTrip(void *self) void GLDecoder::s_glVertexPointerOffset(void *self, GLint size, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glVertexPointer(size, type, stride, (void *)offset); + ctx->glVertexPointer(size, type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glColorPointerOffset(void *self, GLint size, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glColorPointer(size, type, stride, (void *)offset); + ctx->glColorPointer(size, type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glTexCoordPointerOffset(void *self, GLint size, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glTexCoordPointer(size, type, stride, (void *) offset); + ctx->glTexCoordPointer(size, type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glNormalPointerOffset(void *self, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glNormalPointer(type, stride, (void *)offset); + ctx->glNormalPointer(type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glPointSizePointerOffset(void *self, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glPointSizePointerOES(type, stride, (void *)offset); + ctx->glPointSizePointerOES(type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glWeightPointerOffset(void * self, GLint size, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glWeightPointerOES(size, type, stride, (void*)offset); + ctx->glWeightPointerOES(size, type, stride, SafePointerFromUInt(offset)); } void GLDecoder::s_glMatrixIndexPointerOffset(void * self, GLint size, GLenum type, GLsizei stride, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glMatrixIndexPointerOES(size, type, stride, (void*)offset); + ctx->glMatrixIndexPointerOES(size, type, stride, SafePointerFromUInt(offset)); } @@ -204,7 +208,7 @@ void GLDecoder::s_glMatrixIndexPointerData(void * self, GLint size, GLenum type, void GLDecoder::s_glDrawElementsOffset(void *self, GLenum mode, GLsizei count, GLenum type, GLuint offset) { GLDecoder *ctx = (GLDecoder *)self; - ctx->glDrawElements(mode, count, type, (void *)offset); + ctx->glDrawElements(mode, count, type, SafePointerFromUInt(offset)); } void GLDecoder::s_glDrawElementsData(void *self, GLenum mode, GLsizei count, GLenum type, void * data, GLuint datalen) diff --git a/emulator/opengl/host/libs/GLESv2_dec/Android.mk b/emulator/opengl/host/libs/GLESv2_dec/Android.mk index 7a034ec..bc04c25 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/Android.mk +++ b/emulator/opengl/host/libs/GLESv2_dec/Android.mk @@ -22,15 +22,17 @@ LOCAL_SRC_FILES := GL2Decoder.cpp $(call emugl-end-module) ### host library, 64-bit #################################### -$(call emugl-begin-host-static-library,lib64GLESv2_dec) -$(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) -$(call emugl-gen-decoder,$(LOCAL_PATH),gl2) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64GLESv2_dec) + $(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-gen-decoder,$(LOCAL_PATH),gl2) -# For gl2_types.h ! -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) + # For gl2_types.h ! + $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) -$(call emugl-export,CFLAGS,$(host_common_debug_CFLAGS) -m64) + $(call emugl-export,CFLAGS,$(host_common_debug_CFLAGS) -m64) -LOCAL_SRC_FILES := GL2Decoder.cpp + LOCAL_SRC_FILES := GL2Decoder.cpp -$(call emugl-end-module) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp index a777c50..ccf2f06 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp +++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp @@ -19,6 +19,9 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +static inline void* SafePointerFromUInt(GLuint value) { + return (void*)(uintptr_t)value; +} GL2Decoder::GL2Decoder() { @@ -115,7 +118,7 @@ void GL2Decoder::s_glVertexAttribPointerOffset(void *self, GLuint indx, GLint si GLboolean normalized, GLsizei stride, GLuint data) { GL2Decoder *ctx = (GL2Decoder *) self; - ctx->glVertexAttribPointer(indx, size, type, normalized, stride, (GLvoid *)data); + ctx->glVertexAttribPointer(indx, size, type, normalized, stride, SafePointerFromUInt(data)); } @@ -129,7 +132,7 @@ void GL2Decoder::s_glDrawElementsData(void *self, GLenum mode, GLsizei count, GL void GL2Decoder::s_glDrawElementsOffset(void *self, GLenum mode, GLsizei count, GLenum type, GLuint offset) { GL2Decoder *ctx = (GL2Decoder *)self; - ctx->glDrawElements(mode, count, type, (void *)offset); + ctx->glDrawElements(mode, count, type, SafePointerFromUInt(offset)); } void GL2Decoder::s_glShaderString(void *self, GLuint shader, const GLchar* string, GLsizei len) diff --git a/emulator/opengl/host/libs/Translator/EGL/Android.mk b/emulator/opengl/host/libs/Translator/EGL/Android.mk index f1a6d3a..5d1c9b2 100644 --- a/emulator/opengl/host/libs/Translator/EGL/Android.mk +++ b/emulator/opengl/host/libs/Translator/EGL/Android.mk @@ -47,11 +47,12 @@ LOCAL_SRC_FILES := $(host_common_SRC_FILES) $(call emugl-end-module) ### EGL host implementation, 64-bit ######################## -$(call emugl-begin-host-shared-library,lib64EGL_translator) -$(call emugl-import,lib64GLcommon) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64EGL_translator) + $(call emugl-import,lib64GLcommon) -LOCAL_LDLIBS += $(host_common_LDLIBS) -m64 -LOCAL_SRC_FILES := $(host_common_SRC_FILES) - -$(call emugl-end-module) + LOCAL_LDLIBS += $(host_common_LDLIBS) -m64 + LOCAL_SRC_FILES := $(host_common_SRC_FILES) + $(call emugl-end-module) +endif diff --git a/emulator/opengl/host/libs/Translator/EGL/EglContext.h b/emulator/opengl/host/libs/Translator/EGL/EglContext.h index e4917c6..d8eb05e 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglContext.h +++ b/emulator/opengl/host/libs/Translator/EGL/EglContext.h @@ -19,10 +19,10 @@ #include <map> #include <EGL/egl.h> #include <GLcommon/GLutils.h> -#include <GLcommon/SmartPtr.h> #include <GLcommon/TranslatorIfaces.h> #include <GLcommon/objectNameManager.h> +#include "emugl/common/smart_ptr.h" #include "EglConfig.h" #include "EglSurface.h" @@ -30,7 +30,7 @@ class EglContext; -typedef SmartPtr<EglContext> ContextPtr; +typedef emugl::SmartPtr<EglContext> ContextPtr; class EglDisplay; diff --git a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp index 99f9d8b..24b9a0d 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp @@ -16,7 +16,6 @@ #include "EglDisplay.h" #include "EglOsApi.h" #include <GLcommon/GLutils.h> -#include <utils/threads.h> EglDisplay::EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault) : m_dpy(dpy), @@ -31,7 +30,7 @@ EglDisplay::EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault) : }; EglDisplay::~EglDisplay() { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); // // Destroy the global context if one was created. @@ -59,7 +58,7 @@ EglDisplay::~EglDisplay() { EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;} void EglDisplay::initialize(int renderableType) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); m_initialized = true; initConfigurations(renderableType); m_configInitialized = true; @@ -68,7 +67,7 @@ void EglDisplay::initialize(int renderableType) { bool EglDisplay::isInitialize() { return m_initialized;} void EglDisplay::terminate(){ - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); m_contexts.clear(); m_surfaces.clear(); m_initialized = false; @@ -128,7 +127,7 @@ void EglDisplay::initConfigurations(int renderableType) { } EglConfig* EglDisplay::getConfig(EGLConfig conf) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { if(static_cast<EGLConfig>(*it) == conf) { @@ -140,9 +139,9 @@ EglConfig* EglDisplay::getConfig(EGLConfig conf) { } SurfacePtr EglDisplay::getSurface(EGLSurface surface) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* surface is "key" in map<unsigned int, SurfacePtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)surface); + unsigned int hndl = SafeUIntFromPointer(surface); SurfacesHndlMap::iterator it = m_surfaces.find(hndl); return it != m_surfaces.end() ? (*it).second : @@ -150,9 +149,9 @@ SurfacePtr EglDisplay::getSurface(EGLSurface surface) { } ContextPtr EglDisplay::getContext(EGLContext ctx) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* ctx is "key" in map<unsigned int, ContextPtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); + unsigned int hndl = SafeUIntFromPointer(ctx); ContextsHndlMap::iterator it = m_contexts.find(hndl); return it != m_contexts.end() ? (*it).second : @@ -160,9 +159,9 @@ ContextPtr EglDisplay::getContext(EGLContext ctx) { } bool EglDisplay::removeSurface(EGLSurface s) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* s is "key" in map<unsigned int, SurfacePtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)s); + unsigned int hndl = SafeUIntFromPointer(s); SurfacesHndlMap::iterator it = m_surfaces.find(hndl); if(it != m_surfaces.end()) { m_surfaces.erase(it); @@ -172,7 +171,7 @@ bool EglDisplay::removeSurface(EGLSurface s) { } bool EglDisplay::removeSurface(SurfacePtr s) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); SurfacesHndlMap::iterator it; for(it = m_surfaces.begin(); it!= m_surfaces.end();it++) @@ -189,9 +188,9 @@ bool EglDisplay::removeSurface(SurfacePtr s) { } bool EglDisplay::removeContext(EGLContext ctx) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* ctx is "key" in map<unsigned int, ContextPtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); + unsigned int hndl = SafeUIntFromPointer(ctx); ContextsHndlMap::iterator it = m_contexts.find(hndl); if(it != m_contexts.end()) { m_contexts.erase(it); @@ -201,7 +200,7 @@ bool EglDisplay::removeContext(EGLContext ctx) { } bool EglDisplay::removeContext(ContextPtr ctx) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ContextsHndlMap::iterator it; for(it = m_contexts.begin(); it != m_contexts.end();it++) { @@ -217,7 +216,7 @@ bool EglDisplay::removeContext(ContextPtr ctx) { } EglConfig* EglDisplay::getConfig(EGLint id) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { if((*it)->id() == id) { @@ -229,7 +228,7 @@ EglConfig* EglDisplay::getConfig(EGLint id) { } int EglDisplay::getConfigs(EGLConfig* configs,int config_size) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); int i = 0; for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && i < config_size ;i++,it++) { configs[i] = static_cast<EGLConfig>(*it); @@ -238,7 +237,7 @@ int EglDisplay::getConfigs(EGLConfig* configs,int config_size) { } int EglDisplay::chooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); return doChooseConfigs(dummy, configs, config_size); } @@ -258,7 +257,7 @@ int EglDisplay::doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int co } EGLSurface EglDisplay::addSurface(SurfacePtr s ) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); unsigned int hndl = s.Ptr()->getHndl(); EGLSurface ret =reinterpret_cast<EGLSurface> (hndl); @@ -271,7 +270,7 @@ EGLSurface EglDisplay::addSurface(SurfacePtr s ) { } EGLContext EglDisplay::addContext(ContextPtr ctx ) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); unsigned int hndl = ctx.Ptr()->getHndl(); EGLContext ret = reinterpret_cast<EGLContext> (hndl); @@ -285,7 +284,7 @@ EGLContext EglDisplay::addContext(ContextPtr ctx ) { EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); do { ++m_nextEglImageId; } while(m_nextEglImageId == 0); img->imageId = m_nextEglImageId; m_eglImages[m_nextEglImageId] = img; @@ -293,17 +292,17 @@ EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) { } ImagePtr EglDisplay::getImage(EGLImageKHR img) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* img is "key" in map<unsigned int, ImagePtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); + unsigned int hndl = SafeUIntFromPointer(img); ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL); } bool EglDisplay:: destroyImageKHR(EGLImageKHR img) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); /* img is "key" in map<unsigned int, ImagePtr>. */ - unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); + unsigned int hndl = SafeUIntFromPointer(img); ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); if (i != m_eglImages.end()) { @@ -314,7 +313,7 @@ bool EglDisplay:: destroyImageKHR(EGLImageKHR img) { } EGLNativeContextType EglDisplay::getGlobalSharedContext(){ - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); #ifndef _WIN32 // find an existing OpenGL context to share with, if exist EGLNativeContextType ret = diff --git a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h index 587e92a..47a2598 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h +++ b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h @@ -20,8 +20,8 @@ #include <map> #include <EGL/egl.h> #include <EGL/eglext.h> -#include <utils/threads.h> -#include <GLcommon/SmartPtr.h> +#include "emugl/common/mutex.h" +#include "emugl/common/smart_ptr.h" #include "EglConfig.h" #include "EglContext.h" @@ -30,6 +30,7 @@ + typedef std::list<EglConfig*> ConfigsList; typedef std::map< unsigned int, ContextPtr> ContextsHndlMap; typedef std::map< unsigned int, SurfacePtr> SurfacesHndlMap; @@ -81,7 +82,7 @@ private: SurfacesHndlMap m_surfaces; GlobalNameSpace m_globalNameSpace; ObjectNameManager *m_manager[MAX_GLES_VERSION]; - android::Mutex m_lock; + emugl::Mutex m_lock; ImagesHndlMap m_eglImages; unsigned int m_nextEglImageId; EGLNativeContextType m_globalSharedContext; diff --git a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp index 8e5b462..95b696e 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp @@ -51,7 +51,7 @@ void EglGlobalInfo::delInstance() { EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy,EGLNativeInternalDisplayType idpy) { //search if it is not already exists - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) { if((*it).second == dpy) return (*it).first; } @@ -68,7 +68,7 @@ EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy,EGLNativeInternal } bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) { if(static_cast<EGLDisplay>((*it).first) == dpy) { delete (*it).first; @@ -80,7 +80,7 @@ bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) { } EglDisplay* EglGlobalInfo::getDisplay(EGLNativeDisplayType dpy) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) { if((*it).second == dpy) return (*it).first; } @@ -88,7 +88,7 @@ EglDisplay* EglGlobalInfo::getDisplay(EGLNativeDisplayType dpy) { } EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); DisplaysMap::iterator it = m_displays.find(static_cast<EglDisplay*>(dpy)); return (it != m_displays.end() ? (*it).first : NULL); } @@ -99,7 +99,7 @@ EGLNativeInternalDisplayType EglGlobalInfo::generateInternalDisplay(EGLNativeDis void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) { - android::Mutex::Autolock mutex(m_lock); + 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/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h index ec07ffe..f56b79e 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h +++ b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h @@ -16,14 +16,15 @@ #ifndef EGL_GLOBAL_INFO #define EGL_GLOBAL_INFO -#include <list> -#include <EGL/egl.h> -#include <utils/threads.h> -#include <GLcommon/TranslatorIfaces.h> #include "EglDisplay.h" #include "EglConfig.h" #include "EglContext.h" +#include <GLcommon/TranslatorIfaces.h> +#include "emugl/common/mutex.h" +#include <list> +#include <EGL/egl.h> + typedef std::map<EglDisplay*,EGLNativeDisplayType>DisplaysMap; @@ -58,7 +59,7 @@ private: EGLNativeInternalDisplayType m_default; GLESiface* m_gles_ifaces[MAX_GLES_VERSION]; bool m_gles_extFuncs_inited[MAX_GLES_VERSION]; - android::Mutex m_lock; + emugl::Mutex m_lock; }; #endif diff --git a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp index d03c9db..06dcf67 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp @@ -50,11 +50,11 @@ GLEScontext* getGLESContext(); #define tls_thread EglThreadInfo::get() EglGlobalInfo* g_eglInfo = NULL; -android::Mutex s_eglLock; +emugl::Mutex s_eglLock; void initGlobalInfo() { - android::Mutex::Autolock mutex(s_eglLock); + emugl::Mutex::AutoLock mutex(s_eglLock); if (!g_eglInfo) { g_eglInfo = EglGlobalInfo::getInstance(); } @@ -72,8 +72,8 @@ static EGLiface s_eglIface = { #define EGL_EXTENTIONS 2 //decleration -EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image); +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image); // extentions descriptors static ExtentionDescriptor s_eglExtentions[] = { @@ -273,28 +273,31 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint * } //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; + //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 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 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 sample_buffers_num = 0; EGLint samples_per_pixel = 0; EGLint stencil_size = 0; @@ -318,7 +321,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint * if(attrib_list[i+1] < 0) { RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); } - buffer_size = attrib_list[i+1]; + //buffer_size = attrib_list[i+1]; break; case EGL_RED_SIZE: if(attrib_list[i+1] < 0) { @@ -345,10 +348,10 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint * alpha_size = attrib_list[i+1]; break; case EGL_BIND_TO_TEXTURE_RGB: - bind_to_tex_rgb = attrib_list[i+1]; + //bind_to_tex_rgb = attrib_list[i+1]; break; case EGL_BIND_TO_TEXTURE_RGBA: - bind_to_tex_rgba = attrib_list[i+1]; + //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) { @@ -373,13 +376,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint * if(attrib_list[i+1] < 0) { RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); } - max_swap_interval = attrib_list[i+1]; + //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]; + //min_swap_interval = attrib_list[i+1]; break; case EGL_NATIVE_RENDERABLE: native_renderable = attrib_list[i+1]; @@ -394,7 +397,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint * RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); } case EGL_SAMPLE_BUFFERS: - sample_buffers_num = attrib_list[i+1]; + //sample_buffers_num = attrib_list[i+1]; break; if(attrib_list[i+1] < 0) { RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); @@ -635,13 +638,11 @@ EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig con } ContextPtr sharedCtxPtr; - EGLNativeContextType nativeShared = NULL; if(share_context != EGL_NO_CONTEXT) { sharedCtxPtr = dpy->getContext(share_context); if(!sharedCtxPtr.Ptr()) { RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT); } - nativeShared = sharedCtxPtr->nativeType(); } EGLNativeContextType globalSharedContext = dpy->getGlobalSharedContext(); @@ -815,7 +816,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) { 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)ctx->getHndl(); + EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl()); if(dpy->getContext(c).Ptr()) { return c; @@ -839,7 +840,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { // 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)surface->getHndl(); + EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl()); surface = dpy->getSurface(s); if(surface.Ptr()) { @@ -858,7 +859,9 @@ EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) { EGLenum api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_ES_API); - return eglWaitClient(); + EGLBoolean ret = eglWaitClient(); + eglBindAPI(api); + return ret; } EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { @@ -1012,7 +1015,6 @@ EglImage *attachEGLImage(unsigned int imageId) void detachEGLImage(unsigned int imageId) { ThreadInfo* thread = getThreadInfo(); - EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); ContextPtr ctx = thread->eglContext; if (ctx.Ptr()) { ctx->detachImage(imageId); @@ -1020,7 +1022,7 @@ void detachEGLImage(unsigned int imageId) } -EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { VALIDATE_DISPLAY(display); VALIDATE_CONTEXT(context); @@ -1033,13 +1035,13 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum ta ThreadInfo* thread = getThreadInfo(); ShareGroupPtr sg = thread->shareGroup; if (sg.Ptr() != NULL) { - unsigned int globalTexName = sg->getGlobalName(TEXTURE, (uintptr_t)buffer); + 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, (uintptr_t)buffer); + ObjectDataPtr objData = sg->getObjectData(TEXTURE, SafeUIntFromPointer(buffer)); if (!objData.Ptr()) return EGL_NO_IMAGE_KHR; TextureData *texData = (TextureData *)objData.Ptr(); @@ -1057,7 +1059,7 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum ta } -EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image) +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image) { VALIDATE_DISPLAY(display); return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE; diff --git a/emulator/opengl/host/libs/Translator/EGL/EglSurface.h b/emulator/opengl/host/libs/Translator/EGL/EglSurface.h index d65f480..ba28ae8 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglSurface.h +++ b/emulator/opengl/host/libs/Translator/EGL/EglSurface.h @@ -16,14 +16,15 @@ #ifndef EGL_SURFACE_H #define EGL_SURFACE_H +#include <map> + #include <EGL/egl.h> #include <EGL/eglinternalplatform.h> -#include <map> -#include <GLcommon/SmartPtr.h> +#include "emugl/common/smart_ptr.h" #include "EglConfig.h" class EglSurface; -typedef SmartPtr<EglSurface> SurfacePtr; +typedef emugl::SmartPtr<EglSurface> SurfacePtr; class EglDisplay; diff --git a/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp index 1b403f2..6481774 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp @@ -16,26 +16,33 @@ #include "EglThreadInfo.h" #include "EglOsApi.h" -EglThreadInfo::EglThreadInfo():m_err(EGL_SUCCESS),m_api(EGL_OPENGL_ES_API) {} +#include "emugl/common/lazy_instance.h" +#include "emugl/common/thread_store.h" -#include <cutils/threads.h> +namespace { -static thread_store_t s_tls = THREAD_STORE_INITIALIZER; - -static void tlsDestruct(void *ptr) -{ - if (ptr) { - EglThreadInfo *ti = (EglThreadInfo *)ptr; - delete ti; +class EglThreadInfoStore : public emugl::ThreadStore { +public: + EglThreadInfoStore() : emugl::ThreadStore(&destructor) {} +private: + static void destructor(void* value) { + delete static_cast<EglThreadInfo*>(value); } -} +}; + +} // namespace + +EglThreadInfo::EglThreadInfo() : + m_err(EGL_SUCCESS), m_api(EGL_OPENGL_ES_API) {} + +static emugl::LazyInstance<EglThreadInfoStore> s_tls = LAZY_INSTANCE_INIT; EglThreadInfo* EglThreadInfo::get(void) { - EglThreadInfo *ti = (EglThreadInfo *)thread_store_get(&s_tls); + EglThreadInfo *ti = static_cast<EglThreadInfo*>(s_tls->get()); if (!ti) { ti = new EglThreadInfo(); - thread_store_set(&s_tls, ti, tlsDestruct); + s_tls->set(ti); } return ti; } diff --git a/emulator/opengl/host/libs/Translator/EGL/EglWindowsApi.cpp b/emulator/opengl/host/libs/Translator/EGL/EglWindowsApi.cpp index 460c0b6..5b48fcb 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglWindowsApi.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglWindowsApi.cpp @@ -20,8 +20,7 @@ #include <stdio.h> #define IS_TRUE(a) \ - if(a != true) return false; - + if(a != true) return NULL; struct DisplayInfo{ DisplayInfo():dc(NULL),hwnd(NULL),isPixelFormatSet(false){}; @@ -48,9 +47,7 @@ static TlsData *getTLS() { class WinDisplay{ public: - typedef enum { - DEFAULT_DISPLAY = 0 - }; + enum { DEFAULT_DISPLAY = 0 }; WinDisplay(){}; DisplayInfo& getInfo(int configurationIndex){ return getTLS()->m_map[configurationIndex];} HDC getDC(int configId){return getTLS()->m_map[configId].dc;} @@ -193,7 +190,8 @@ HWND createDummyWindow(){ wcx.lpszClassName = "DummyWin"; // name of window class wcx.hIconSm = (HICON) NULL; // small class icon - ATOM winClass = RegisterClassEx(&wcx); + RegisterClassEx(&wcx); + HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "DummyWin", "Dummy", @@ -340,7 +338,7 @@ EglConfig* pixelFormatToConfig(EGLNativeInternalDisplayType display,int renderab EGLint transparentType,samples; EGLint tRed,tGreen,tBlue; EGLint pMaxWidth,pMaxHeight,pMaxPixels; - EGLint configId,level; + EGLint level; EGLint window,bitmap,pbuffer,transparent; HDC dpy = getDummyDC(display,WinDisplay::DEFAULT_DISPLAY); @@ -416,10 +414,10 @@ void queryConfigs(EGLNativeInternalDisplayType display,int renderableType,Config initPixelFormat(dpy); //quering num of formats - int nFormats = DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd); + int maxFormat = DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd); //inserting rest of formats - for(iPixelFormat;iPixelFormat < nFormats; iPixelFormat++) { + for(;iPixelFormat <= maxFormat; iPixelFormat++) { DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd); EglConfig* pConfig = pixelFormatToConfig(display,renderableType,&pfd,iPixelFormat); if(pConfig) listOut.push_back(pConfig); @@ -497,7 +495,7 @@ EGLNativeSurfaceType createPbufferSurface(EGLNativeInternalDisplayType display,E if(!s_wglExtProcs->wglCreatePbufferARB) return NULL; EGLNativePbufferType pb = s_wglExtProcs->wglCreatePbufferARB(dpy,cfg->nativeId(),width,height,pbAttribs); if(!pb) { - DWORD err = GetLastError(); + GetLastError(); return NULL; } return new SrfcInfo(pb); @@ -507,7 +505,7 @@ bool releasePbuffer(EGLNativeInternalDisplayType display,EGLNativeSurfaceType pb if (!pb) return false; if(!s_wglExtProcs->wglReleasePbufferDCARB || !s_wglExtProcs->wglDestroyPbufferARB) return false; if(!s_wglExtProcs->wglReleasePbufferDCARB(pb->getPbuffer(),pb->getDC()) || !s_wglExtProcs->wglDestroyPbufferARB(pb->getPbuffer())){ - DWORD err = GetLastError(); + GetLastError(); return false; } return true; @@ -539,7 +537,7 @@ EGLNativeContextType createContext(EGLNativeInternalDisplayType display,EglConfi bool destroyContext(EGLNativeInternalDisplayType dpy,EGLNativeContextType ctx) { if(!wglDeleteContext(ctx)) { - DWORD err = GetLastError(); + GetLastError(); return false; } return true; @@ -566,7 +564,7 @@ bool makeCurrent(EGLNativeInternalDisplayType display,EglSurface* read,EglSurfac void swapBuffers(EGLNativeInternalDisplayType display,EGLNativeSurfaceType srfc){ if(srfc && !SwapBuffers(srfc->getDC())) { - DWORD err = GetLastError(); + GetLastError(); } } diff --git a/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp b/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp index 129f244..41cf8c4 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ #include "EglOsApi.h" +#include "emugl/common/mutex.h" + #include <string.h> #include <X11/Xlib.h> #include <GL/glx.h> -#include <utils/threads.h> class ErrorHandler{ @@ -29,7 +30,7 @@ int getLastError(){ return s_lastErrorCode;}; private: static int s_lastErrorCode; int (*m_oldErrorHandler) (Display *, XErrorEvent *); -static android::Mutex s_lock; +static emugl::Mutex s_lock; static int errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event); }; @@ -50,17 +51,17 @@ private: }; int ErrorHandler::s_lastErrorCode = 0; -android::Mutex ErrorHandler::s_lock; +emugl::Mutex ErrorHandler::s_lock; ErrorHandler::ErrorHandler(EGLNativeDisplayType dpy){ - android::Mutex::Autolock mutex(s_lock); + emugl::Mutex::AutoLock mutex(s_lock); XSync(dpy,False); s_lastErrorCode = 0; m_oldErrorHandler = XSetErrorHandler(errorHandlerProc); } ErrorHandler::~ErrorHandler(){ - android::Mutex::Autolock mutex(s_lock); + emugl::Mutex::AutoLock mutex(s_lock); XSetErrorHandler(m_oldErrorHandler); s_lastErrorCode = 0; } @@ -71,7 +72,7 @@ int ErrorHandler::errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event){ } #define IS_SUCCESS(a) \ - if(a != Success) return false; + if(a != Success) return 0; namespace EglOS { @@ -193,7 +194,7 @@ bool validNativePixmap(EGLNativeDisplayType dpy,EGLNativeSurfaceType pix) { int tmp; unsigned int utmp; ErrorHandler handler(dpy); - if(!XGetGeometry(dpy,pix ? pix->srfc() : NULL,&root,&tmp,&tmp,&utmp,&utmp,&utmp,&utmp)) return false; + if(!XGetGeometry(dpy,pix ? pix->srfc() : 0,&root,&tmp,&tmp,&utmp,&utmp,&utmp,&utmp)) return false; return handler.getLastError() == 0; } @@ -260,7 +261,7 @@ bool makeCurrent(EGLNativeDisplayType dpy,EglSurface* read,EglSurface* draw,EGLN bool retval = false; if (!ctx && !read && !draw) { // unbind - retval = glXMakeContextCurrent(dpy, NULL, NULL, NULL); + retval = glXMakeContextCurrent(dpy, 0, 0, NULL); } else if (ctx && read && draw) { retval = glXMakeContextCurrent(dpy,draw->native()->srfc(),read->native()->srfc(),ctx); diff --git a/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp index 4f5d75f..1571b3a 100644 --- a/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp @@ -14,16 +14,47 @@ * limitations under the License. */ -#include <stdio.h> #include "ThreadInfo.h" -//#define TRACE_THREADINFO -#ifdef TRACE_THREADINFO +#include "emugl/common/lazy_instance.h" +#include "emugl/common/thread_store.h" + +#include <stdio.h> + +// 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<ThreadInfo*>(value); + mNumInstances--; + } + + static size_t mNumInstances; +}; + +size_t ThreadInfoStore::mNumInstances = 0; + +} // namespace + + void ThreadInfo::updateInfo(ContextPtr eglCtx, EglDisplay* dpy, GLEScontext* glesCtx, @@ -37,27 +68,16 @@ void ThreadInfo::updateInfo(ContextPtr eglCtx, objManager = manager; } -#include <cutils/threads.h> -static thread_store_t s_tls = THREAD_STORE_INITIALIZER; -static int active_instance = 0; -static void tlsDestruct(void *ptr) -{ - active_instance--; - LOG_THREADINFO("tlsDestruct EGL %lx %d\n", (long)ptr, active_instance); - if (ptr) { - ThreadInfo *ti = (ThreadInfo *)ptr; - delete ti; - } -} +static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT; ThreadInfo *getThreadInfo() { - ThreadInfo *ti = (ThreadInfo *)thread_store_get(&s_tls); + ThreadInfo *ti = static_cast<ThreadInfo*>(s_tls->get()); if (!ti) { ti = new ThreadInfo(); - thread_store_set(&s_tls, ti, tlsDestruct); - active_instance++; - LOG_THREADINFO("getThreadInfo EGL %lx %d\n", (long)ti, active_instance); + s_tls->set(ti); + LOG_THREADINFO("%s: EGL %p (%d instances)\n", __FUNCTION__, + ti, (int)ThreadInfoStore::getInstanceCount()); } return ti; } diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk b/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk index 9aa74a7..c5e7e6d 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk +++ b/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk @@ -18,11 +18,14 @@ $(call emugl-end-module) ### GLES_CM host implementation, 64-bit ######################## -$(call emugl-begin-host-shared-library,lib64GLES_CM_translator) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64GLES_CM_translator) -$(call emugl-import,lib64GLcommon) + $(call emugl-import,lib64GLcommon) -LOCAL_LDLIBS += -m64 -LOCAL_SRC_FILES := $(host_common_SRC_FILES) + LOCAL_CFLAGS += -fPIC + LOCAL_LDLIBS += -m64 + LOCAL_SRC_FILES := $(host_common_SRC_FILES) -$(call emugl-end-module) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp index af5c0d8..66adefb 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp @@ -51,7 +51,7 @@ GLDispatch::GLDispatch():m_isLoaded(false){}; void GLDispatch::dispatchFuncs() { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); if(m_isLoaded) return; LOAD_GL_FUNC(glActiveTexture); diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h index 9dc320f..ae8c9f8 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h +++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h @@ -17,7 +17,7 @@ #define GLDISPATCHH #include <GLES/gl.h> -#include <utils/threads.h> +#include "emugl/common/mutex.h" #define GLAPIENTRY GL_APIENTRY @@ -151,8 +151,8 @@ public: void (GLAPIENTRY *glVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void (GLAPIENTRY *glViewport) (GLint x, GLint y, GLsizei width, GLsizei height); private: - bool m_isLoaded; - android::Mutex m_lock; + bool m_isLoaded; + emugl::Mutex m_lock; }; #endif diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp index ecf51bb..6476c02 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp @@ -23,7 +23,7 @@ #include <GLES/glext.h> void GLEScmContext::init() { - android::Mutex::Autolock mutex(s_lock); + emugl::Mutex::AutoLock mutex(s_lock); if(!m_initialized) { s_glDispatch.dispatchFuncs(GLES_1_1); GLEScontext::init(); diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h index 1785877..fbb7023 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h +++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h @@ -23,7 +23,6 @@ #include <map> #include <vector> #include <string> -#include <utils/threads.h> typedef std::map<GLfloat,std::vector<int> > PointSizeIndices; diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp index 3ae271f..dd74750 100644 --- a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp @@ -582,7 +582,7 @@ GL_API void GL_APIENTRY glDrawElements( GLenum mode, GLsizei count, GLenum type 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<unsigned char *>(ctx->getBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)); - indices = buf+reinterpret_cast<uintptr_t>(elementsIndices); + indices = buf + SafeUIntFromPointer(elementsIndices); } ctx->setupArraysPointers(tmpArrs,0,count,type,indices,false); @@ -699,8 +699,6 @@ GL_API void GL_APIENTRY glGetBooleanv( GLenum pname, GLboolean *params) { return; } - GLint i; - switch(pname) { case GL_FRAMEBUFFER_BINDING_OES: @@ -745,7 +743,6 @@ GL_API void GL_APIENTRY glGetBufferParameteriv( GLenum target, GLenum pname, GL GET_CTX() SET_ERROR_IF(!(GLEScmValidate::bufferTarget(target) && GLEScmValidate::bufferParam(pname)),GL_INVALID_ENUM); SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); - bool ret = true; switch(pname) { case GL_BUFFER_SIZE: ctx->getBufferSize(target,params); @@ -787,7 +784,6 @@ GL_API void GL_APIENTRY glGetFixedv( GLenum pname, GLfixed *params) { size_t nParams = glParamSize(pname); GLfloat fParams[16]; - GLint i; switch(pname) { @@ -994,9 +990,9 @@ GL_API void GL_APIENTRY glGetPointerv( GLenum pname, void **params) { if(p) { if(p->isVBO()) { - *params = (void*)(p->getBufferOffset()); + *params = SafePointerFromUInt(p->getBufferOffset()); }else{ - *params = const_cast<void *>( p->getArrayData()); + *params = const_cast<void *>(p->getArrayData()); } } else { ctx->setGLerror(GL_INVALID_ENUM); @@ -1652,7 +1648,7 @@ GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOE { GET_CTX(); SET_ERROR_IF(!GLEScmValidate::textureTargetLimited(target),GL_INVALID_ENUM); - unsigned int imagehndl = ToTargetCompatibleHandle((uintptr_t)image); + unsigned int imagehndl = SafeUIntFromPointer(image); EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); if (img) { // Create the texture object in the underlying EGL implementation, @@ -1688,7 +1684,7 @@ GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GL { GET_CTX(); SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM); - unsigned int imagehndl = ToTargetCompatibleHandle((uintptr_t)image); + 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); @@ -2231,13 +2227,15 @@ void glDrawTexOES (T x, T y, T z, T width, T height) { int numClipPlanes; - GLint viewport[4]; + GLint viewport[4] = {}; z = (z>1 ? 1 : (z<0 ? 0 : z)); - T vertices[4*3] = {x , y, z, - x , y+height, z, - x+width, y+height, z, - x+width, y, z}; + T vertices[4*3] = { + x , y, z, + x , static_cast<T>(y+height), z, + static_cast<T>(x+width), static_cast<T>(y+height), z, + static_cast<T>(x+width), y, z + }; GLfloat texels[ctx->getMaxTexUnits()][4*2]; memset((void*)texels, 0, ctx->getMaxTexUnits()*4*2*sizeof(GLfloat)); diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/Android.mk b/emulator/opengl/host/libs/Translator/GLES_V2/Android.mk index f4845f7..438334a 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/Android.mk +++ b/emulator/opengl/host/libs/Translator/GLES_V2/Android.mk @@ -18,10 +18,12 @@ $(call emugl-end-module) ### GLES_V2 host implementation, 64-bit ############################## -$(call emugl-begin-host-shared-library,lib64GLES_V2_translator) -$(call emugl-import, lib64GLcommon) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64GLES_V2_translator) + $(call emugl-import, lib64GLcommon) -LOCAL_LDLIBS += -m64 -LOCAL_SRC_FILES := $(host_common_SRC_FILES) + LOCAL_LDLIBS += -m64 + LOCAL_SRC_FILES := $(host_common_SRC_FILES) -$(call emugl-end-module) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp index 1457cec..f8f674b 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp @@ -15,11 +15,10 @@ */ #include "GLESv2Context.h" - - +#include <string.h> void GLESv2Context::init() { - android::Mutex::Autolock mutex(s_lock); + emugl::Mutex::AutoLock mutex(s_lock); if(!m_initialized) { s_glDispatch.dispatchFuncs(GLES_2_0); GLEScontext::init(); diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h index 75af864..7e71177 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h +++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h @@ -20,7 +20,6 @@ #include <GLcommon/GLDispatch.h> #include <GLcommon/GLEScontext.h> #include <GLcommon/objectNameManager.h> -#include <utils/threads.h> diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp index 7ae9427..fe64f6f 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp @@ -593,7 +593,7 @@ GL_APICALL void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum t 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<unsigned char *>(ctx->getBindedBuffer(GL_ELEMENT_ARRAY_BUFFER)); - indices = buf+reinterpret_cast<uintptr_t>(elementsIndices); + indices = buf + SafeUIntFromPointer(elementsIndices); } GLESConversionArrays tmpArrs; @@ -867,7 +867,6 @@ GL_APICALL void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GET_CTX(); SET_ERROR_IF(!(GLESv2Validate::bufferTarget(target) && GLESv2Validate::bufferParam(pname)),GL_INVALID_ENUM); SET_ERROR_IF(!ctx->isBindedBuffer(target),GL_INVALID_OPERATION); - bool ret = true; switch(pname) { case GL_BUFFER_SIZE: ctx->getBufferSize(target,params); @@ -941,11 +940,19 @@ GL_APICALL void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* 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)) { - return; + if (destroyCtx) + deleteGLESContext(ctx); + return; } bool es2 = ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY; @@ -1031,6 +1038,8 @@ GL_APICALL void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params){ default: ctx->dispatcher().glGetIntegerv(pname,params); } + if (destroyCtx) + deleteGLESContext(ctx); } GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params){ @@ -2006,7 +2015,7 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglIma { GET_CTX(); SET_ERROR_IF(!GLESv2Validate::textureTargetLimited(target),GL_INVALID_ENUM); - unsigned int imagehndl = ToTargetCompatibleHandle((uintptr_t)image); + unsigned int imagehndl = SafeUIntFromPointer(image); EglImage *img = s_eglIface->eglAttachEGLImage(imagehndl); if (img) { // Create the texture object in the underlying EGL implementation, @@ -2042,7 +2051,7 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target { GET_CTX(); SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM); - unsigned int imagehndl = ToTargetCompatibleHandle((uintptr_t)image); + 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); diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp index 53d1314..3f00428 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include "GLESv2Validate.h" +#include <string.h> bool GLESv2Validate::blendEquationMode(GLenum mode){ return mode == GL_FUNC_ADD || diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp index a80326d..940538a 100644 --- a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp +++ b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp @@ -15,6 +15,7 @@ */ #include "ShaderParser.h" +#include <stdlib.h> #include <string.h> ShaderParser::ShaderParser():ObjectData(SHADER_DATA), @@ -223,8 +224,7 @@ void ShaderParser::parseOmitPrecision(){ SEMICOLON } statementState = PRECISION; const char *precision = NULL; - const char *delimiter = NULL; - + enum { PARSE_NONE, PARSE_IN_C_COMMENT, diff --git a/emulator/opengl/host/libs/Translator/GLcommon/Android.mk b/emulator/opengl/host/libs/Translator/GLcommon/Android.mk index 1236566..b215329 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/Android.mk +++ b/emulator/opengl/host/libs/Translator/GLcommon/Android.mk @@ -41,21 +41,23 @@ 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, libcutils libutils liblog) +$(call emugl-export,STATIC_LIBRARIES, libemugl_common) $(call emugl-end-module) ### EGL host implementation, 64-bit ################ - -$(call emugl-begin-host-static-library,lib64GLcommon) - -$(call emugl-import,lib64OpenglOsUtils) -translator_path := $(LOCAL_PATH)/.. -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, lib64cutils lib64utils lib64log) - -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64GLcommon) + + $(call emugl-import,lib64OpenglOsUtils) + translator_path := $(LOCAL_PATH)/.. + LOCAL_SRC_FILES := $(host_common_SRC_FILES) + LOCAL_CFLAGS += -fPIC + $(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, lib64emugl_common) + + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp index abed760..7b217fd 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp @@ -45,29 +45,30 @@ static GL_FUNC_PTR getGLFuncAddress(const char *funcName) { return ret; } -#define LOAD_GL_FUNC(name) { void * funcAddrs = NULL; \ - if(name == NULL){ \ - funcAddrs = (void *)getGLFuncAddress(#name); \ - if(funcAddrs){ \ - *(void**)(&name) = funcAddrs; \ - } else { \ - fprintf(stderr,"could not load func %s\n",#name); \ - *(void**)(&name) = (void *)dummy_##name; \ - } \ - } \ - } +#define LOAD_GL_FUNC(name) do { \ + if (!name) { \ + void* funcAddress = (void *)getGLFuncAddress(#name); \ + if (funcAddress) { \ + name = (__typeof__(name))(funcAddress); \ + } else { \ + fprintf(stderr, "Could not load func %s\n", #name); \ + name = (__typeof__(name))(dummy_##name); \ + } \ + } \ + } while (0) -#define LOAD_GLEXT_FUNC(name) { void * funcAddrs = NULL; \ - if(name == NULL){ \ - funcAddrs = (void *)getGLFuncAddress(#name); \ - if(funcAddrs) \ - *(void**)(&name) = funcAddrs; \ - } \ - } +#define LOAD_GLEXT_FUNC(name) do { \ + if (!name) { \ + void* funcAddress = (void *)getGLFuncAddress(#name); \ + if (funcAddress) { \ + name = (__typeof__(name))(funcAddress); \ + } \ + } \ + } while (0) /* initializing static GLDispatch members*/ -android::Mutex GLDispatch::s_lock; +emugl::Mutex GLDispatch::s_lock; void (GLAPIENTRY *GLDispatch::glActiveTexture)(GLenum) = NULL; void (GLAPIENTRY *GLDispatch::glBindBuffer)(GLenum,GLuint) = NULL; void (GLAPIENTRY *GLDispatch::glBindTexture)(GLenum, GLuint) = NULL; @@ -298,7 +299,7 @@ GLDispatch::GLDispatch():m_isLoaded(false){}; void GLDispatch::dispatchFuncs(GLESVersion version){ - android::Mutex::Autolock mutex(s_lock); + emugl::Mutex::AutoLock mutex(s_lock); if(m_isLoaded) return; diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp index 387eb2d..ba3edbe 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp @@ -23,6 +23,7 @@ #include <GLcommon/TextureUtils.h> #include <GLcommon/FramebufferData.h> #include <strings.h> +#include <string.h> //decleration static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize); @@ -84,7 +85,7 @@ void GLESConversionArrays::operator++(){ } GLDispatch GLEScontext::s_glDispatch; -android::Mutex GLEScontext::s_lock; +emugl::Mutex GLEScontext::s_lock; std::string* GLEScontext::s_glExtensions= NULL; std::string GLEScontext::s_glVendor; std::string GLEScontext::s_glRenderer; @@ -191,7 +192,7 @@ GLEScontext::~GLEScontext() { const GLvoid* GLEScontext::setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) { GLuint bufferName = m_arrayBuffer; if(bufferName) { - unsigned int offset = ToTargetCompatibleHandle((uintptr_t)data); + unsigned int offset = SafeUIntFromPointer(data); GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr()); m_map[arrType]->setBuffer(size,type,stride,vbo,bufferName,offset,normalize); return static_cast<const unsigned char*>(vbo->getData()) + offset; @@ -329,10 +330,8 @@ void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsiz RangeList ranges; RangeList conversions; GLushort* indices = NULL; - GLenum type = p->getType(); int attribSize = p->getSize(); int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize; - unsigned int size = p->getStride()?p->getStride()*count:attribSize*count*sizeof(GLfixed); char* data = (char*)p->getBufferData() + (first*stride); if(p->bufferNeedConversion()) { @@ -388,7 +387,6 @@ void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,G RangeList ranges; RangeList conversions; GLushort* conversionIndices = NULL; - GLenum type = p->getType(); int attribSize = p->getSize(); int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize; char* data = static_cast<char*>(p->getBufferData()); @@ -679,6 +677,10 @@ bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params) case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: *params = GL_RGBA; break; + + case GL_MAX_TEXTURE_SIZE: + *params = getMaxTexSize(); + break; default: return false; } diff --git a/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp b/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp index cfea855..3612211 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp @@ -18,12 +18,11 @@ #include <GLcommon/GLEScontext.h> -NameSpace::NameSpace(NamedObjectType p_type, GlobalNameSpace *globalNameSpace) : +NameSpace::NameSpace(NamedObjectType p_type, + GlobalNameSpace *globalNameSpace) : m_nextName(0), m_type(p_type), - m_globalNameSpace(globalNameSpace) -{ -} + m_globalNameSpace(globalNameSpace) {} NameSpace::~NameSpace() { @@ -35,14 +34,16 @@ NameSpace::~NameSpace() } ObjectLocalName -NameSpace::genName(ObjectLocalName p_localName, bool genGlobal, bool genLocal) +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() ); + } while(localName == 0 || + m_localToGlobalMap.find(localName) != + m_localToGlobalMap.end() ); } if (genGlobal) { @@ -114,15 +115,9 @@ NameSpace::replaceGlobalName(ObjectLocalName p_localName, unsigned int p_globalN } -GlobalNameSpace::GlobalNameSpace() -{ - mutex_init(&m_lock); -} +GlobalNameSpace::GlobalNameSpace() : m_lock() {} -GlobalNameSpace::~GlobalNameSpace() -{ - mutex_destroy(&m_lock); -} +GlobalNameSpace::~GlobalNameSpace() {} unsigned int GlobalNameSpace::genName(NamedObjectType p_type) @@ -130,7 +125,7 @@ GlobalNameSpace::genName(NamedObjectType p_type) if ( p_type >= NUM_OBJECT_TYPES ) return 0; unsigned int name = 0; - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); switch (p_type) { case VERTEXBUFFER: GLEScontext::dispatcher().glGenBuffers(1,&name); @@ -148,7 +143,6 @@ GlobalNameSpace::genName(NamedObjectType p_type) default: name = 0; } - mutex_unlock(&m_lock); return name; } @@ -160,11 +154,8 @@ GlobalNameSpace::deleteName(NamedObjectType p_type, unsigned int p_name) typedef std::pair<NamedObjectType, ObjectLocalName> ObjectIDPair; typedef std::map<ObjectIDPair, ObjectDataPtr> ObjectDataMap; -ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) -{ - mutex_init(&m_lock); - - for (int i=0; i<NUM_OBJECT_TYPES; i++) { +ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) : m_lock() { + for (int i=0; i < NUM_OBJECT_TYPES; i++) { m_nameSpace[i] = new NameSpace((NamedObjectType)i, globalNameSpace); } @@ -173,27 +164,24 @@ ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) ShareGroup::~ShareGroup() { - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); for (int t = 0; t < NUM_OBJECT_TYPES; t++) { delete m_nameSpace[t]; } - ObjectDataMap *map = (ObjectDataMap *)m_objectsData; - if (map) delete map; - - mutex_unlock(&m_lock); - mutex_destroy(&m_lock); + delete (ObjectDataMap *)m_objectsData; } ObjectLocalName -ShareGroup::genName(NamedObjectType p_type, ObjectLocalName p_localName, bool genLocal) +ShareGroup::genName(NamedObjectType p_type, + ObjectLocalName p_localName, + bool genLocal) { if (p_type >= NUM_OBJECT_TYPES) return 0; - mutex_lock(&m_lock); - ObjectLocalName localName = m_nameSpace[p_type]->genName(p_localName,true,genLocal); - mutex_unlock(&m_lock); - + emugl::Mutex::AutoLock _lock(m_lock); + ObjectLocalName localName = + m_nameSpace[p_type]->genName(p_localName, true, genLocal); return localName; } @@ -202,35 +190,28 @@ ShareGroup::genGlobalName(NamedObjectType p_type) { if (p_type >= NUM_OBJECT_TYPES) return 0; - mutex_lock(&m_lock); - unsigned int name = m_nameSpace[p_type]->genGlobalName(); - mutex_unlock(&m_lock); - - return name; + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->genGlobalName(); } unsigned int -ShareGroup::getGlobalName(NamedObjectType p_type, ObjectLocalName p_localName) +ShareGroup::getGlobalName(NamedObjectType p_type, + ObjectLocalName p_localName) { if (p_type >= NUM_OBJECT_TYPES) return 0; - mutex_lock(&m_lock); - unsigned int globalName = m_nameSpace[p_type]->getGlobalName(p_localName); - mutex_unlock(&m_lock); - - return globalName; + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->getGlobalName(p_localName); } ObjectLocalName -ShareGroup::getLocalName(NamedObjectType p_type, unsigned int p_globalName) +ShareGroup::getLocalName(NamedObjectType p_type, + unsigned int p_globalName) { if (p_type >= NUM_OBJECT_TYPES) return 0; - mutex_lock(&m_lock); - ObjectLocalName localName = m_nameSpace[p_type]->getLocalName(p_globalName); - mutex_unlock(&m_lock); - - return localName; + emugl::Mutex::AutoLock _lock(m_lock); + return m_nameSpace[p_type]->getLocalName(p_globalName); } void @@ -238,13 +219,12 @@ ShareGroup::deleteName(NamedObjectType p_type, ObjectLocalName p_localName) { if (p_type >= NUM_OBJECT_TYPES) return; - mutex_lock(&m_lock); + 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) ); } - mutex_unlock(&m_lock); } bool @@ -252,29 +232,29 @@ ShareGroup::isObject(NamedObjectType p_type, ObjectLocalName p_localName) { if (p_type >= NUM_OBJECT_TYPES) return 0; - mutex_lock(&m_lock); - bool exist = m_nameSpace[p_type]->isObject(p_localName); - mutex_unlock(&m_lock); - - return exist; + 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) +ShareGroup::replaceGlobalName(NamedObjectType p_type, + ObjectLocalName p_localName, + unsigned int p_globalName) { if (p_type >= NUM_OBJECT_TYPES) return; - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); m_nameSpace[p_type]->replaceGlobalName(p_localName, p_globalName); - mutex_unlock(&m_lock); } void -ShareGroup::setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, ObjectDataPtr data) +ShareGroup::setObjectData(NamedObjectType p_type, + ObjectLocalName p_localName, + ObjectDataPtr data) { if (p_type >= NUM_OBJECT_TYPES) return; - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ObjectDataMap *map = (ObjectDataMap *)m_objectsData; if (!map) { @@ -284,45 +264,36 @@ ShareGroup::setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, O ObjectIDPair id( p_type, p_localName ); map->insert( std::pair<ObjectIDPair, ObjectDataPtr>(id, data) ); - - mutex_unlock(&m_lock); } ObjectDataPtr -ShareGroup::getObjectData(NamedObjectType p_type, ObjectLocalName p_localName) +ShareGroup::getObjectData(NamedObjectType p_type, + ObjectLocalName p_localName) { ObjectDataPtr ret; if (p_type >= NUM_OBJECT_TYPES) return ret; - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ObjectDataMap *map = (ObjectDataMap *)m_objectsData; if (map) { - ObjectDataMap::iterator i = map->find( ObjectIDPair(p_type, p_localName) ); + ObjectDataMap::iterator i = + map->find( ObjectIDPair(p_type, p_localName) ); if (i != map->end()) ret = (*i).second; } - - mutex_unlock(&m_lock); - return ret; } ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) : - m_globalNameSpace(globalNameSpace) -{ - mutex_init(&m_lock); -} + m_lock(), m_globalNameSpace(globalNameSpace) {} -ObjectNameManager::~ObjectNameManager() -{ - mutex_destroy(&m_lock); -} +ObjectNameManager::~ObjectNameManager() {} ShareGroupPtr ObjectNameManager::createShareGroup(void *p_groupName) { - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ShareGroupPtr shareGroupReturn; @@ -334,19 +305,19 @@ ObjectNameManager::createShareGroup(void *p_groupName) // // Group does not exist, create new group // - shareGroupReturn = ShareGroupPtr( new ShareGroup(m_globalNameSpace) ); - m_groups.insert( std::pair<void *, ShareGroupPtr>(p_groupName, shareGroupReturn) ); + shareGroupReturn = ShareGroupPtr(new ShareGroup(m_globalNameSpace)); + m_groups.insert( + std::pair<void*, ShareGroupPtr>( + p_groupName, shareGroupReturn)); } - mutex_unlock(&m_lock); - return shareGroupReturn; } ShareGroupPtr ObjectNameManager::getShareGroup(void *p_groupName) { - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ShareGroupPtr shareGroupReturn(NULL); @@ -354,58 +325,45 @@ ObjectNameManager::getShareGroup(void *p_groupName) if (s != m_groups.end()) { shareGroupReturn = (*s).second; } - mutex_unlock(&m_lock); return shareGroupReturn; } ShareGroupPtr -ObjectNameManager::attachShareGroup(void *p_groupName, void *p_existingGroupName) +ObjectNameManager::attachShareGroup(void *p_groupName, + void *p_existingGroupName) { - mutex_lock(&m_lock); - - ShareGroupPtr shareGroupReturn; + emugl::Mutex::AutoLock _lock(m_lock); ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) ); if (s == m_groups.end()) { // ShareGroup did not found !!! - mutex_unlock(&m_lock); return ShareGroupPtr(NULL); } - shareGroupReturn = (*s).second; - - if (m_groups.find(p_groupName) == m_groups.end()) - { - m_groups.insert( std::pair<void *, ShareGroupPtr>(p_groupName, shareGroupReturn) ); + ShareGroupPtr shareGroupReturn((*s).second); + if (m_groups.find(p_groupName) == m_groups.end()) { + m_groups.insert( + std::pair<void*, ShareGroupPtr>( + p_groupName, shareGroupReturn)); } - - mutex_unlock(&m_lock); - return shareGroupReturn; } void ObjectNameManager::deleteShareGroup(void *p_groupName) { - mutex_lock(&m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ShareGroupsMap::iterator s( m_groups.find(p_groupName) ); if (s != m_groups.end()) { m_groups.erase(s); } - - mutex_unlock(&m_lock); } void *ObjectNameManager::getGlobalContext() { - void *ret = NULL; - - mutex_lock(&m_lock); - if (m_groups.size() > 0) ret = (*m_groups.begin()).first; - mutex_unlock(&m_lock); - - return ret; + emugl::Mutex::AutoLock _lock(m_lock); + return (m_groups.size() > 0) ? (*m_groups.begin()).first : NULL; } diff --git a/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h b/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h new file mode 100644 index 0000000..0d38905 --- /dev/null +++ b/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h @@ -0,0 +1,106 @@ +// 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 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/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h index de7d563..18a989c 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h @@ -18,7 +18,7 @@ #include <GLES/gl.h> #include <GLES2/gl2.h> -#include <utils/threads.h> +#include "emugl/common/mutex.h" #include "gldefs.h" #include "GLutils.h" @@ -260,8 +260,8 @@ public: static void (GL_APIENTRY *glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); private: - bool m_isLoaded; - static android::Mutex s_lock; + bool m_isLoaded; + static emugl::Mutex s_lock; }; #endif diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h index 3353ec1..38429d1 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h @@ -43,5 +43,5 @@ private: bool m_wasBound; }; -typedef SmartPtr<GLESbuffer> GLESbufferPtr; +typedef emugl::SmartPtr<GLESbuffer> GLESbufferPtr; #endif diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h index 20509fc..5aed0ad 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h @@ -20,7 +20,7 @@ #include "GLDispatch.h" #include "GLESpointer.h" #include "objectNameManager.h" -#include <utils/threads.h> +#include "emugl/common/mutex.h" #include <string> typedef std::map<GLenum,GLESpointer*> ArraysMap; @@ -187,7 +187,7 @@ protected: void initCapsLocked(const GLubyte * extensionString); virtual void initExtensionString() =0; - static android::Mutex s_lock; + static emugl::Mutex s_lock; static GLDispatch s_glDispatch; bool m_initialized; unsigned int m_activeTexture; diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/GLutils.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLutils.h index 2aed646..974b9be 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLutils.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLutils.h @@ -16,36 +16,37 @@ #ifndef GL_UTILS_H #define GL_UTILS_H -#include <inttypes.h> #include <assert.h> +#include <inttypes.h> -typedef enum{ - GLES_1_1 = 1, - GLES_2_0 = 2, - MAX_GLES_VERSION //Must be last - }GLESVersion; +typedef enum { + GLES_1_1 = 1, + GLES_2_0 = 2, + MAX_GLES_VERSION //Must be last +} GLESVersion; template <class T> void swap(T& x,T& y) { T temp; - temp=x; - x=y; - y=temp; + temp = x; + x = y; + y = temp; } bool isPowerOf2(int num); -inline -unsigned int ToTargetCompatibleHandle(uintptr_t hostHandle) -{ - // The host and target handles can have different sizes (e.g. 32-bit - // target handle for ARM, and 64-bit host handle on x86_64). - // This function checks that the input host handle value can be - // converted into a target handle one without losing any bits. - // - unsigned int targetHandle = (unsigned int)hostHandle; - assert(sizeof(targetHandle) == sizeof(hostHandle) || targetHandle == hostHandle); - return targetHandle; +// <EGL/egl.h> 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) { + // 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)); + return (unsigned int)(uintptr_t)(ptr); } #endif diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/SmartPtr.h b/emulator/opengl/host/libs/Translator/include/GLcommon/SmartPtr.h deleted file mode 100644 index 8ac93fb..0000000 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/SmartPtr.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -* 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 __SMART_PTR_H -#define __SMART_PTR_H - -#include <cutils/threads.h> -#include <cutils/atomic.h> - -template <class T, bool threadSafe = false> -class SmartPtr -{ -public: - explicit SmartPtr(T* ptr = (T*)NULL) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - m_ptr = ptr; - if (ptr) - m_pRefCount = new int32_t(1); - else - m_pRefCount = NULL; - } - - SmartPtr<T,threadSafe>(const SmartPtr<T,false>& rhs) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - } - - SmartPtr<T,threadSafe>(SmartPtr<T,true>& rhs) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - if (rhs.m_lock) mutex_lock(rhs.m_lock); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (rhs.m_lock) mutex_unlock(rhs.m_lock); - } - - ~SmartPtr() { - if (m_lock) mutex_lock(m_lock); - release(); - if (m_lock) - { - mutex_unlock(m_lock); - mutex_destroy(m_lock); - delete m_lock; - } - } - - T* Ptr() const { - return m_ptr; - } - - const T* constPtr() const - { - return m_ptr; - } - - T* operator->() const { - return m_ptr; - } - - T& operator*() const { - return *m_ptr; - } - - // This gives STL lists something to compare. - bool operator <(const SmartPtr<T>& t1) const { - return m_ptr < t1.m_ptr; - } - - SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs) - { - if (m_ptr == rhs.m_ptr) - return *this; - - if (m_lock) mutex_lock(m_lock); - release(); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (m_lock) mutex_unlock(m_lock); - - return *this; - } - - SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs) - { - if (m_ptr == rhs.m_ptr) - return *this; - - if (m_lock) mutex_lock(m_lock); - release(); - if (rhs.m_lock) mutex_lock(rhs.m_lock); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (rhs.m_lock) mutex_unlock(rhs.m_lock); - if (m_lock) mutex_unlock(m_lock); - - return *this; - } - -private: - int32_t *m_pRefCount; - mutex_t *m_lock; - T* m_ptr; - - // Increment the reference count on this pointer by 1. - int use() { - if (!m_pRefCount) return 0; - return android_atomic_inc(m_pRefCount) + 1; - } - - // Decrement the reference count on the pointer by 1. - // If the reference count goes to (or below) 0, the pointer is deleted. - int release() { - if (!m_pRefCount) return 0; - - int iVal = android_atomic_dec(m_pRefCount); - if (iVal > 1) - return iVal - 1; - - delete m_pRefCount; - m_pRefCount = NULL; - - if (m_ptr) { - delete m_ptr; - m_ptr = NULL; - } - return 0; - } - -}; - -#endif // of __SMART_PTR_H diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h b/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h index 3c5e15a..e0d1bfb 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h @@ -74,8 +74,8 @@ struct EglImage unsigned int border; }; -typedef SmartPtr<EglImage> ImagePtr; -typedef std::map< unsigned int, ImagePtr> ImagesHndlMap; +typedef emugl::SmartPtr<EglImage> ImagePtr; +typedef std::map< unsigned int, ImagePtr> ImagesHndlMap; class GLEScontext; diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h b/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h index 605fd29..4d4d038 100644 --- a/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h +++ b/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h @@ -16,9 +16,9 @@ #ifndef _OBJECT_NAME_MANAGER_H #define _OBJECT_NAME_MANAGER_H -#include <cutils/threads.h> #include <map> -#include "SmartPtr.h" +#include "emugl/common/mutex.h" +#include "emugl/common/smart_ptr.h" enum NamedObjectType { VERTEXBUFFER = 0, @@ -47,7 +47,7 @@ public: private: ObjectDataType m_dataType; }; -typedef SmartPtr<ObjectData> ObjectDataPtr; +typedef emugl::SmartPtr<ObjectData> ObjectDataPtr; typedef unsigned long long ObjectLocalName; typedef std::map<ObjectLocalName, unsigned int> NamesMap; @@ -129,7 +129,7 @@ public: void deleteName(NamedObjectType p_type, unsigned int p_name); private: - mutex_t m_lock; + emugl::Mutex m_lock; }; // @@ -143,7 +143,7 @@ private: class ShareGroup { friend class ObjectNameManager; - friend class SmartPtr<ShareGroup>; // to allow destructing when ShareGroupPtr refcount reaches zero + friend class emugl::SmartPtr<ShareGroup>; // to allow destructing when ShareGroupPtr refcount reaches zero public: @@ -204,12 +204,12 @@ private: ~ShareGroup(); private: - mutex_t m_lock; + emugl::Mutex m_lock; NameSpace *m_nameSpace[NUM_OBJECT_TYPES]; void *m_objectsData; }; -typedef SmartPtr<ShareGroup> ShareGroupPtr; +typedef emugl::SmartPtr<ShareGroup> ShareGroupPtr; typedef std::multimap<void *, ShareGroupPtr> ShareGroupsMap; // @@ -262,7 +262,7 @@ public: private: ShareGroupsMap m_groups; - mutex_t m_lock; + emugl::Mutex m_lock; GlobalNameSpace *m_globalNameSpace; }; diff --git a/emulator/opengl/host/libs/Translator/include/KHR/khrplatform.h b/emulator/opengl/host/libs/Translator/include/KHR/khrplatform.h new file mode 100644 index 0000000..c9e6f17 --- /dev/null +++ b/emulator/opengl/host/libs/Translator/include/KHR/khrplatform.h @@ -0,0 +1,282 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by sending them to the public Khronos Bugzilla + * (http://khronos.org/bugzilla) by filing a bug against product + * "Khronos (general)" component "Registry". + * + * A predefined template which fills in some of the bug fields can be + * reached using http://tinyurl.com/khrplatform-h-bugreport, but you + * must create a Bugzilla login first. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include <KHR/khrplatform.h> + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using <stdint.h> + */ +#include <stdint.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using <inttypes.h> + */ +#include <inttypes.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include <stdint.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/emulator/opengl/host/libs/libOpenglRender/Android.mk b/emulator/opengl/host/libs/libOpenglRender/Android.mk index 1d923b4..787ae83 100644 --- a/emulator/opengl/host/libs/libOpenglRender/Android.mk +++ b/emulator/opengl/host/libs/libOpenglRender/Android.mk @@ -54,7 +54,7 @@ $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) # use Translator's egl/gles headers LOCAL_C_INCLUDES += $(EMUGL_PATH)/host/libs/Translator/include -LOCAL_STATIC_LIBRARIES += libutils liblog +LOCAL_STATIC_LIBRARIES += libemugl_common $(call emugl-export,CFLAGS,$(host_common_CFLAGS)) @@ -62,22 +62,24 @@ $(call emugl-end-module) ### host libOpenglRender, 64-bit ######################################### -$(call emugl-begin-host-shared-library,lib64OpenglRender) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64OpenglRender) -$(call emugl-import,lib64GLESv1_dec lib64GLESv2_dec lib64_renderControl_dec lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-import,lib64GLESv1_dec lib64GLESv2_dec lib64_renderControl_dec lib64OpenglCodecCommon lib64OpenglOsUtils) -#LOCAL_LDFLAGS += -m64 # adding -m64 here doesn't work, because it somehow appear BEFORE -m32 in command-line. -LOCAL_LDLIBS += $(host_common_LDLIBS) -m64 # Put -m64 it in LOCAL_LDLIBS instead. + #LOCAL_LDFLAGS += -m64 # adding -m64 here doesn't work, because it somehow appear BEFORE -m32 in command-line. + LOCAL_LDLIBS += $(host_common_LDLIBS) -m64 # Put -m64 it in LOCAL_LDLIBS instead. -LOCAL_SRC_FILES := $(host_common_SRC_FILES) -$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include) -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) + LOCAL_SRC_FILES := $(host_common_SRC_FILES) + $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include) + $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) -# use Translator's egl/gles headers -LOCAL_C_INCLUDES += $(EMUGL_PATH)/host/libs/Translator/include + # use Translator's egl/gles headers + LOCAL_C_INCLUDES += $(EMUGL_PATH)/host/libs/Translator/include -LOCAL_STATIC_LIBRARIES += lib64utils lib64log + LOCAL_STATIC_LIBRARIES += lib64emugl_common -$(call emugl-export,CFLAGS,$(host_common_CFLAGS) -m64) + $(call emugl-export,CFLAGS,$(host_common_CFLAGS) -m64) -$(call emugl-end-module) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index 46c5acf..e612294 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -18,6 +18,7 @@ #include "EGLDispatch.h" #include "GLDispatch.h" #include "ThreadInfo.h" +#include "GLcommon/GLutils.h" #ifdef WITH_GLES2 #include "GL2Dispatch.h" #endif @@ -92,17 +93,19 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height, cb->m_internalFormat = texInternalFormat; if (fb->getCaps().has_eglimage_texture_2d) { - cb->m_eglImage = s_egl.eglCreateImageKHR(fb->getDisplay(), - s_egl.eglGetCurrentContext(), - EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer)cb->m_tex, - NULL); - - cb->m_blitEGLImage = s_egl.eglCreateImageKHR(fb->getDisplay(), - s_egl.eglGetCurrentContext(), - EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer)cb->m_blitTex, - NULL); + cb->m_eglImage = s_egl.eglCreateImageKHR( + fb->getDisplay(), + s_egl.eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, + (EGLClientBuffer)SafePointerFromUInt(cb->m_tex), + NULL); + + cb->m_blitEGLImage = s_egl.eglCreateImageKHR( + fb->getDisplay(), + s_egl.eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, + (EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), + NULL); } fb->unbind_locked(); @@ -201,7 +204,7 @@ bool ColorBuffer::blitFromCurrentReadBuffer() // save current viewport and match it to the current // colorbuffer size // - GLint vport[4]; + GLint vport[4] = {}; s_gl.glGetIntegerv(GL_VIEWPORT, vport); s_gl.glViewport(0, 0, m_width, m_height); @@ -295,6 +298,7 @@ bool ColorBuffer::bind_fbo() GL_TEXTURE_2D, m_tex, 0); GLenum status = s_gl.glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status != GL_FRAMEBUFFER_COMPLETE_OES) { + ERR("ColorBuffer::bind_fbo: FBO not complete: %#x\n", status); s_gl.glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); s_gl.glDeleteFramebuffersOES(1, &m_fbo); m_fbo = 0; diff --git a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h index 883162b..9a919c3 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h +++ b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h @@ -19,7 +19,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <GLES/gl.h> -#include <SmartPtr.h> +#include "emugl/common/smart_ptr.h" class ColorBuffer { @@ -55,6 +55,6 @@ private: GLenum m_internalFormat; }; -typedef SmartPtr<ColorBuffer> ColorBufferPtr; +typedef emugl::SmartPtr<ColorBuffer> ColorBufferPtr; #endif diff --git a/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp b/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp index ca7351e..08c71e8 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp @@ -67,7 +67,6 @@ InitConfigStatus FBConfig::initConfigList(FrameBuffer *fb) return ret; } - const FrameBufferCaps &caps = fb->getCaps(); EGLDisplay dpy = fb->getDisplay(); if (dpy == EGL_NO_DISPLAY) { diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index cfadf12..e7a7960 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -393,7 +393,7 @@ FrameBuffer::~FrameBuffer() void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); m_onPost = onPost; m_onPostContext = onPostContext; if (m_onPost && !m_fbImage) { @@ -490,7 +490,7 @@ HandleType FrameBuffer::genHandle() HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, GLenum p_internalFormat) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); HandleType ret = 0; ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) ); @@ -505,7 +505,7 @@ HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share, bool p_isGL2) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); HandleType ret = 0; RenderContextPtr share(NULL); @@ -527,7 +527,7 @@ HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share, HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_height) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); HandleType ret = 0; WindowSurfacePtr win( WindowSurface::create(p_config, p_width, p_height) ); @@ -541,32 +541,35 @@ HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_hei void FrameBuffer::DestroyRenderContext(HandleType p_context) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); m_contexts.erase(p_context); } void FrameBuffer::DestroyWindowSurface(HandleType p_surface) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); m_windows.erase(p_surface); } -void FrameBuffer::openColorBuffer(HandleType p_colorbuffer) +int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); if (c == m_colorbuffers.end()) { // bad colorbuffer handle - return; + ERR("FB: openColorBuffer cb handle %#x not found\n", p_colorbuffer); + return -1; } (*c).second.refcount++; + return 0; } void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); if (c == m_colorbuffers.end()) { + ERR("FB: closeColorBuffer cb handle %#x not found\n", p_colorbuffer); // bad colorbuffer handle return; } @@ -577,10 +580,11 @@ void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); WindowSurfaceMap::iterator w( m_windows.find(p_surface) ); if (w == m_windows.end()) { + ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n", p_surface); // bad surface handle return false; } @@ -591,16 +595,18 @@ bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); WindowSurfaceMap::iterator w( m_windows.find(p_surface) ); if (w == m_windows.end()) { // bad surface handle + ERR("%s: bad window surface handle %#x\n", __FUNCTION__, p_surface); return false; } ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { + ERR("%s: bad color buffer handle %#x\n", __FUNCTION__, p_colorbuffer); // bad colorbuffer handle return false; } @@ -614,7 +620,7 @@ bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { @@ -629,7 +635,7 @@ bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { @@ -642,7 +648,7 @@ bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { @@ -657,7 +663,7 @@ bool FrameBuffer::bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface) { - android::Mutex::Autolock mutex(m_lock); + emugl::Mutex::AutoLock mutex(m_lock); WindowSurfacePtr draw(NULL), read(NULL); RenderContextPtr ctx(NULL); diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h index de0b71c..f8683b2 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h @@ -20,7 +20,8 @@ #include "ColorBuffer.h" #include "RenderContext.h" #include "WindowSurface.h" -#include <utils/threads.h> +#include "emugl/common/mutex.h" + #include <map> #include <EGL/egl.h> #include <stdint.h> @@ -72,7 +73,7 @@ public: HandleType createColorBuffer(int p_width, int p_height, GLenum p_internalFormat); void DestroyRenderContext(HandleType p_context); void DestroyWindowSurface(HandleType p_surface); - void openColorBuffer(HandleType p_colorbuffer); + int openColorBuffer(HandleType p_colorbuffer); void closeColorBuffer(HandleType p_colorbuffer); bool bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface); @@ -111,7 +112,7 @@ private: int m_y; int m_width; int m_height; - android::Mutex m_lock; + emugl::Mutex m_lock; FBNativeWindowType m_nativeWindow; FrameBufferCaps m_caps; EGLDisplay m_eglDisplay; diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderContext.h b/emulator/opengl/host/libs/libOpenglRender/RenderContext.h index 9cbb5fc..80ac43f 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderContext.h +++ b/emulator/opengl/host/libs/libOpenglRender/RenderContext.h @@ -16,12 +16,12 @@ #ifndef _LIBRENDER_RENDERCONTEXT_H #define _LIBRENDER_RENDERCONTEXT_H -#include "SmartPtr.h" +#include "emugl/common/smart_ptr.h" #include <EGL/egl.h> #include "GLDecoderContextData.h" class RenderContext; -typedef SmartPtr<RenderContext> RenderContextPtr; +typedef emugl::SmartPtr<RenderContext> RenderContextPtr; class RenderContext { diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp index 6a15138..83ba9c5 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp @@ -215,13 +215,20 @@ static uint32_t rcCreateColorBuffer(uint32_t width, return fb->createColorBuffer(width, height, internalFormat); } -static void rcOpenColorBuffer(uint32_t colorbuffer) +static int rcOpenColorBuffer2(uint32_t colorbuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { - return; + return -1; } - fb->openColorBuffer( colorbuffer ); + return fb->openColorBuffer( colorbuffer ); +} + +// Deprecated, kept for compatibility with old system images only. +// Use rcOpenColorBuffer2 instead. +static void rcOpenColorBuffer(uint32_t colorbuffer) +{ + (void) rcOpenColorBuffer2(colorbuffer); } static void rcCloseColorBuffer(uint32_t colorbuffer) @@ -359,4 +366,5 @@ void initRenderControlContext(renderControl_decoder_context_t *dec) dec->set_rcColorBufferCacheFlush(rcColorBufferCacheFlush); dec->set_rcReadColorBuffer(rcReadColorBuffer); dec->set_rcUpdateColorBuffer(rcUpdateColorBuffer); + dec->set_rcOpenColorBuffer2(rcOpenColorBuffer2); } diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp index 1b2c0fe..9ae2a43 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp @@ -94,7 +94,7 @@ int RenderThread::Main() stats_totalBytes += readBuf.validData(); long long dt = GetCurrentTimeMS() - stats_t0; if (dt > 1000) { - float dts = (float)dt / 1000.0f; + //float dts = (float)dt / 1000.0f; //printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f)); stats_totalBytes = 0; stats_t0 = GetCurrentTimeMS(); diff --git a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp index 566ca40..5337009 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp @@ -15,17 +15,28 @@ */ #include "ThreadInfo.h" -#include <cutils/threads.h> +#include "emugl/common/lazy_instance.h" +#include "emugl/common/thread_store.h" -static thread_store_t s_tls = THREAD_STORE_INITIALIZER; +namespace { + +class ThreadInfoStore : public ::emugl::ThreadStore { +public: + ThreadInfoStore() : ::emugl::ThreadStore(NULL) {} +}; + +} // namespace + +static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT; RenderThreadInfo::RenderThreadInfo() { - thread_store_set(&s_tls, this, NULL); + s_tls->set(this); } RenderThreadInfo::~RenderThreadInfo() { + s_tls->set(NULL); } RenderThreadInfo* RenderThreadInfo::get() { - return (RenderThreadInfo*)thread_store_get(&s_tls); + return static_cast<RenderThreadInfo*>(s_tls->get()); } diff --git a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp index 9c32ff8..bdda01a 100644 --- a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp @@ -58,9 +58,6 @@ WindowSurface *WindowSurface::create(int p_config, int p_width, int p_height) } win->m_fbconf = fbconf; - FrameBuffer *fb = FrameBuffer::getFB(); - const FrameBufferCaps &caps = fb->getCaps(); - // // Create a pbuffer to be used as the egl surface // for that window. @@ -209,8 +206,6 @@ bool WindowSurface::resizePbuffer(unsigned int p_width, unsigned int p_height) m_eglSurface = NULL; } - const FrameBufferCaps &caps = fb->getCaps(); - // // Create pbuffer surface. // diff --git a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h index e9f1f7d..fe35a94 100644 --- a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h +++ b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h @@ -19,7 +19,7 @@ #include "ColorBuffer.h" #include "RenderContext.h" #include "FBConfig.h" -#include "SmartPtr.h" +#include "emugl/common/smart_ptr.h" #include "FixedBuffer.h" #include <EGL/egl.h> #include <GLES/gl.h> @@ -66,6 +66,6 @@ private: const FBConfig *m_fbconf; }; -typedef SmartPtr<WindowSurface> WindowSurfacePtr; +typedef emugl::SmartPtr<WindowSurface> WindowSurfacePtr; #endif diff --git a/emulator/opengl/host/libs/renderControl_dec/Android.mk b/emulator/opengl/host/libs/renderControl_dec/Android.mk index 1063532..4a97a93 100644 --- a/emulator/opengl/host/libs/renderControl_dec/Android.mk +++ b/emulator/opengl/host/libs/renderControl_dec/Android.mk @@ -10,10 +10,12 @@ $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) $(call emugl-end-module) ### host library, 64-bit #################################### -$(call emugl-begin-host-static-library,lib64_renderControl_dec) -$(call emugl-import,lib64OpenglCodecCommon) -$(call emugl-gen-decoder,$(LOCAL_PATH),renderControl) -# For renderControl_types.h -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) -$(call emugl-export,CFLAGS,-m64) -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64_renderControl_dec) + $(call emugl-import,lib64OpenglCodecCommon) + $(call emugl-gen-decoder,$(LOCAL_PATH),renderControl) + # For renderControl_types.h + $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) + $(call emugl-export,CFLAGS,-m64) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/libs/renderControl_dec/renderControl.in b/emulator/opengl/host/libs/renderControl_dec/renderControl.in index 8281fd9..55539f9 100644 --- a/emulator/opengl/host/libs/renderControl_dec/renderControl.in +++ b/emulator/opengl/host/libs/renderControl_dec/renderControl.in @@ -23,3 +23,4 @@ GL_ENTRY(void, rcBindRenderbuffer, uint32_t colorBuffer) GL_ENTRY(EGLint, rcColorBufferCacheFlush, uint32_t colorbuffer, EGLint postCount,int forRead) GL_ENTRY(void, rcReadColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels) GL_ENTRY(int, rcUpdateColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels) +GL_ENTRY(int, rcOpenColorBuffer2, uint32_t colorbuffer) diff --git a/emulator/opengl/host/renderer/main.cpp b/emulator/opengl/host/renderer/main.cpp index d2e3f72..2c3f8e2 100644 --- a/emulator/opengl/host/renderer/main.cpp +++ b/emulator/opengl/host/renderer/main.cpp @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) int winY = 0; int winWidth = 320; int winHeight = 480; - FBNativeWindowType windowId = NULL; + FBNativeWindowType windowId = 0; int iWindowId = 0; // diff --git a/emulator/opengl/host/tools/emugen/Android.mk b/emulator/opengl/host/tools/emugen/Android.mk index ad9ab06..e2f3939 100644 --- a/emulator/opengl/host/tools/emugen/Android.mk +++ b/emulator/opengl/host/tools/emugen/Android.mk @@ -1,15 +1,35 @@ -ifneq ($(HOST_OS),windows) +# Determine if the emugen build needs to be builts from +# sources. +EMUGL_BUILD_EMUGEN := +ifeq (true,$(BUILD_STANDALONE_EMULATOR)) + # The emulator's standalone build system can build host Linux + # binaries even when it targets Windows by setting + # LOCAL_HOST_BUILD to true, so rebuild from sources. + EMUGL_BUILD_EMUGEN := true +else + ifneq ($(HOST_OS),windows) + # The platform build can only build emugen when targetting + # the same host sytem. + EMUGL_BUILD_EMUGEN := true + endif +endif LOCAL_PATH:=$(call my-dir) +ifeq (true,$(EMUGL_BUILD_EMUGEN)) + $(call emugl-begin-host-executable,emugen) - LOCAL_SRC_FILES := \ - ApiGen.cpp \ - EntryPoint.cpp \ - main.cpp \ - strUtils.cpp \ - TypeFactory.cpp +LOCAL_SRC_FILES := \ + ApiGen.cpp \ + EntryPoint.cpp \ + main.cpp \ + strUtils.cpp \ + TypeFactory.cpp \ + +ifeq (true,$(BUILD_STANDALONE_EMULATOR)) +LOCAL_HOST_BUILD := true +endif $(call emugl-end-module) @@ -17,7 +37,7 @@ $(call emugl-end-module) # protocol encoders/ decoders. This variable is used by other emugl modules. EMUGL_EMUGEN := $(LOCAL_BUILT_MODULE) -else # windows build +else # windows platform build # on windows use the build host emugen executable # (that will be the linux exeutable when using mingw build) diff --git a/emulator/opengl/host/tools/emugen/ApiGen.cpp b/emulator/opengl/host/tools/emugen/ApiGen.cpp index 6964862..2e4c8d1 100644 --- a/emulator/opengl/host/tools/emugen/ApiGen.cpp +++ b/emulator/opengl/host/tools/emugen/ApiGen.cpp @@ -420,8 +420,8 @@ static void writeVarEncodingExpression(Var& var, FILE* fp) if (!var.isVoid()) { fprintf(fp, "\t\tmemcpy(ptr, &%s, %u); ptr += %u;\n", varname, - (uint) var.type()->bytes(), - (uint) var.type()->bytes()); + (unsigned) var.type()->bytes(), + (unsigned) var.type()->bytes()); } } } @@ -645,7 +645,7 @@ int ApiGen::genEncoderImpl(const std::string &filename) fprintf(fp, "\t return NULL;\n"); } else if (e->retval().type()->name() != "void") { fprintf(fp, "\n\t%s retval;\n", e->retval().type()->name().c_str()); - fprintf(fp, "\tstream->readback(&retval, %u);\n",(uint) e->retval().type()->bytes()); + fprintf(fp, "\tstream->readback(&retval, %u);\n",(unsigned) e->retval().type()->bytes()); fprintf(fp, "\treturn retval;\n"); } fprintf(fp, "}\n\n"); @@ -776,12 +776,10 @@ int ApiGen::genDecoderImpl(const std::string &filename) \tchar lastCall[256] = {0}; \n\ #endif \n\ \twhile ((len - pos >= 8) && !unknownOpcode) { \n\ -\t\tvoid *params[%u]; \n\ \t\tint opcode = *(int *)ptr; \n\ \t\tunsigned int packetLen = *(int *)(ptr + 4);\n\ \t\tif (len - pos < packetLen) return pos; \n\ -\t\tswitch(opcode) {\n", - (uint) m_maxEntryPointsParams); +\t\tswitch(opcode) {\n"); for (size_t f = 0; f < n; f++) { enum Pass_t { PASS_TmpBuffAlloc = 0, PASS_MemAlloc, PASS_DebugPrint, PASS_FunctionCall, PASS_Epilog, PASS_LAST }; @@ -823,7 +821,8 @@ int ApiGen::genDecoderImpl(const std::string &filename) } } else if (pass == PASS_DebugPrint) { fprintf(fp, "#ifdef DEBUG_PRINTOUT\n"); - fprintf(fp, "\t\t\tfprintf(stderr,\"%s: %s(%s)\\n\"", m_basename.c_str(), e->name().c_str(), printString.c_str()); + fprintf(fp, "\t\t\tfprintf(stderr,\"%s(%%p): %s(%s)\\n\", stream", + m_basename.c_str(), e->name().c_str(), printString.c_str()); if (e->vars().size() > 0 && !e->vars()[0].isVoid()) fprintf(fp, ","); } @@ -845,9 +844,9 @@ int ApiGen::genDecoderImpl(const std::string &filename) if (v->pointerDir() == Var::POINTER_IN || v->pointerDir() == Var::POINTER_INOUT) { if (pass == PASS_MemAlloc && v->pointerDir() == Var::POINTER_INOUT) { fprintf(fp, "\t\t\tsize_t tmpPtr%uSize = (size_t)*(unsigned int *)(ptr + %s);\n", - (uint) j, varoffset.c_str()); + (unsigned) j, varoffset.c_str()); fprintf(fp, "unsigned char *tmpPtr%u = (ptr + %s + 4);\n", - (uint) j, varoffset.c_str()); + (unsigned) j, varoffset.c_str()); } if (pass == PASS_FunctionCall) { if (v->nullAllowed()) { @@ -866,30 +865,33 @@ int ApiGen::genDecoderImpl(const std::string &filename) } else { // out pointer; if (pass == PASS_TmpBuffAlloc) { fprintf(fp, "\t\t\tsize_t tmpPtr%uSize = (size_t)*(unsigned int *)(ptr + %s);\n", - (uint) j, varoffset.c_str()); + (unsigned) j, varoffset.c_str()); if (!totalTmpBuffExist) { - fprintf(fp, "\t\t\tsize_t totalTmpSize = tmpPtr%uSize;\n", (uint)j); + fprintf(fp, "\t\t\tsize_t totalTmpSize = tmpPtr%uSize;\n", (unsigned)j); } else { - fprintf(fp, "\t\t\ttotalTmpSize += tmpPtr%uSize;\n", (uint)j); + fprintf(fp, "\t\t\ttotalTmpSize += tmpPtr%uSize;\n", (unsigned)j); } tmpBufOffset[j] = totalTmpBuffOffset; char tmpPtrName[16]; - sprintf(tmpPtrName," + tmpPtr%uSize", (uint)j); + sprintf(tmpPtrName," + tmpPtr%uSize", (unsigned)j); totalTmpBuffOffset += std::string(tmpPtrName); totalTmpBuffExist = true; } else if (pass == PASS_MemAlloc) { fprintf(fp, "\t\t\tunsigned char *tmpPtr%u = &tmpBuf[%s];\n", - (uint)j, tmpBufOffset[j].c_str()); + (unsigned)j, tmpBufOffset[j].c_str()); + fprintf(fp, "\t\t\tmemset(tmpPtr%u, 0, %s);\n", + (unsigned)j, + toString(v->type()->bytes()).c_str()); } else if (pass == PASS_FunctionCall) { if (v->nullAllowed()) { fprintf(fp, "tmpPtr%uSize == 0 ? NULL : (%s)(tmpPtr%u)", - (uint) j, v->type()->name().c_str(), (uint) j); + (unsigned) j, v->type()->name().c_str(), (unsigned) j); } else { - fprintf(fp, "(%s)(tmpPtr%u)", v->type()->name().c_str(), (uint) j); + fprintf(fp, "(%s)(tmpPtr%u)", v->type()->name().c_str(), (unsigned) j); } } else if (pass == PASS_DebugPrint) { fprintf(fp, "(%s)(tmpPtr%u), *(unsigned int *)(ptr + %s)", - v->type()->name().c_str(), (uint) j, + v->type()->name().c_str(), (unsigned) j, varoffset.c_str()); } varoffset += " + 4"; @@ -939,7 +941,7 @@ int ApiGen::genDecoderImpl(const std::string &filename) fprintf(fp, "\t\t} //switch\n"); if (strstr(m_basename.c_str(), "gl")) { fprintf(fp, "#ifdef CHECK_GL_ERROR\n"); - fprintf(fp, "\tint err = this->glGetError();\n"); + fprintf(fp, "\tint err = lastCall[0] ? this->glGetError() : GL_NO_ERROR;\n"); fprintf(fp, "\tif (err) fprintf(stderr, \"%s Error: 0x%%X in %%s\\n\", err, lastCall);\n", m_basename.c_str()); fprintf(fp, "#endif\n"); } @@ -1036,7 +1038,7 @@ int ApiGen::setGlobalAttribute(const std::string & line, size_t lc) if (token == "base_opcode") { std::string str = getNextToken(line, pos, &last, WHITESPACE); if (str.size() == 0) { - fprintf(stderr, "line %u: missing value for base_opcode\n", (uint) lc); + fprintf(stderr, "line %u: missing value for base_opcode\n", (unsigned) lc); } else { setBaseOpcode(atoi(str.c_str())); } diff --git a/emulator/opengl/host/tools/emugen/ApiGen.h b/emulator/opengl/host/tools/emugen/ApiGen.h index 1627ef6..8ba18af 100644 --- a/emulator/opengl/host/tools/emugen/ApiGen.h +++ b/emulator/opengl/host/tools/emugen/ApiGen.h @@ -54,6 +54,8 @@ public: case WRAPPER_SIDE: retval = "wrapper"; break; + default: + retval = "unknown"; } return retval; } diff --git a/emulator/opengl/host/tools/emugen/getopt.c b/emulator/opengl/host/tools/emugen/getopt.c new file mode 100644 index 0000000..3523538 --- /dev/null +++ b/emulator/opengl/host/tools/emugen/getopt.c @@ -0,0 +1,76 @@ +#include "getopt.h" + +#include <stdio.h> +#include <string.h> + +#define _getprogname() nargv[0] + +int opterr = 1; +int optind = 1; +int optopt = 0; +char* optarg; + +int getopt(int argc, char* const argv[], const char* ostr) { + static const char kEmpty[] = ""; + static const char* place = kEmpty; + if (!*place) { + if (optind >= argc) + return -1; + + const char* arg = argv[optind]; + if (arg[0] != '-') { + // Not an option. + return -1; + } + if (arg[1] == '-' && !arg[2]) { + // '--' -> end of options. + return -1; + } + if (!arg[1]) { + // Single '-', If the program wants it, treat it as an option. + // Otherwise, it's the end of options. + if (!strchr(ostr, '-')) { + return -1; + } + optopt = '-'; + place = arg + 1; + } else { + optopt = arg[1]; + place = arg + 2; + } + }; + + char* oindex = strchr(ostr, optopt); + if (!oindex) { + // Unsupported option. + (void)fprintf(stderr, "%s: illegal option -- %c\n", argv[0]); + return '?'; + } + if (oindex[1] != ':') { + // No argument needed. + optarg = NULL; + if (!*place) + optind++; + return optopt; + } + + // This option needs an argument. Either after the option character, + // or the argument that follows. + if (*place) { + optarg = (char *)place; + } else if (argc > ++optind) { + optarg = (char *)argv[optind]; + } else if (oindex[2] == ':') { + // Optional argument is missing. + place = kEmpty; + optarg = NULL; + return optopt; + } else { + // Missing argument. + place = kEmpty; + (void)fprintf(stderr, "%s: option requires an argument --%c\n", + argv[0], optopt); + return ':'; + } + return optopt; +} diff --git a/emulator/opengl/host/tools/emugen/getopt.h b/emulator/opengl/host/tools/emugen/getopt.h new file mode 100644 index 0000000..cc04850 --- /dev/null +++ b/emulator/opengl/host/tools/emugen/getopt.h @@ -0,0 +1,18 @@ +#ifndef GETOPT_H +#define GETOPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern int optind; +extern char* optarg; +extern int optopt; + +int getopt(int argc, char* const argv[], const char* ostr); + +#ifdef __cplusplus +} +#endif + +#endif // GETOPT_H diff --git a/emulator/opengl/host/tools/emugen/main.cpp b/emulator/opengl/host/tools/emugen/main.cpp index 96377f2..c0c24e9 100644 --- a/emulator/opengl/host/tools/emugen/main.cpp +++ b/emulator/opengl/host/tools/emugen/main.cpp @@ -20,6 +20,7 @@ #include "strUtils.h" #include "ApiGen.h" #include "TypeFactory.h" +#include "getopt.h" const std::string SPEC_EXTENSION = std::string(".in"); const std::string ATTRIB_EXTENSION = std::string(".attrib"); diff --git a/emulator/opengl/sdl.mk b/emulator/opengl/sdl.mk new file mode 100644 index 0000000..a85ed58 --- /dev/null +++ b/emulator/opengl/sdl.mk @@ -0,0 +1,25 @@ +# This contains common definitions used to define a host module to +# link SDL with the EmuGL test programs. + +ifeq ($(BUILD_STANDALONE_EMULATOR),true) + +# When using the emulator standalone build, inherit the values from the +# Makefile that included us. +EMUGL_SDL_CFLAGS := $(SDL_CFLAGS) +EMUGL_SDL_LDLIBS := $(SDL_LDLIBS) +EMUGL_SDL_STATIC_LIBRARIES := emulator_libSDL emulator_libSDLmain + +else # BUILD_STANDALONE_EMULATOR != true + +# Otherwise, use the prebuilt libraries that come with the platform. + +EMUGL_SDL_CONFIG ?= prebuilts/tools/$(HOST_PREBUILT_TAG)/sdl/bin/sdl-config +EMUGL_SDL_CFLAGS := $(shell $(EMUGL_SDL_CONFIG) --cflags) +EMUGL_SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(EMUGL_SDL_CONFIG) --static-libs)) +EMUGL_SDL_STATIC_LIBRARIES := libSDL libSDLmain + +ifeq ($(HOST_OS),windows) +EMUGL_SDL_LDLIBS += -lws2_32 +endif + +endif # BUILD_STANDALONE_EMULATOR != true diff --git a/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/emulator/opengl/shared/OpenglCodecCommon/Android.mk index 5deb1f7..83090d8 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/Android.mk +++ b/emulator/opengl/shared/OpenglCodecCommon/Android.mk @@ -24,19 +24,21 @@ endif $(call emugl-begin-host-static-library,libOpenglCodecCommon) LOCAL_SRC_FILES := $(host_commonSources) - -$(call emugl-export,STATIC_LIBRARIES,libcutils) -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) +$(call emugl-import, libemugl_common) +$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH)) +$(call emugl-export,LDLIBS,-lstdc++) $(call emugl-end-module) ### OpenglCodecCommon host, 64-bit ######################################### -$(call emugl-begin-host-static-library,lib64OpenglCodecCommon) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64OpenglCodecCommon) -LOCAL_SRC_FILES := $(host_commonSources) - -$(call emugl-export,STATIC_LIBRARIES,lib64cutils) -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) -$(call emugl-export,CFLAGS,-m64) -$(call emugl-end-module) + LOCAL_SRC_FILES := $(host_commonSources) + $(call emugl-import, lib64emugl_common) + $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH)) + $(call emugl-export,CFLAGS,-m64 -fPIC) + $(call emugl-export,LDLIBS,-lstdc++) + $(call emugl-end-module) +endif diff --git a/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h b/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h index 6f41fd7..4cad61f 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h +++ b/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h @@ -16,22 +16,12 @@ #ifndef _ERROR_LOG_H_ #define _ERROR_LOG_H_ -#if (HAVE_ANDROID_OS == 1) -# include <cutils/log.h> -# define ERR(...) ALOGE(__VA_ARGS__) -# ifdef EMUGL_DEBUG -# define DBG(...) ALOGD(__VA_ARGS__) -# else -# define DBG(...) ((void)0) -# endif +#include <stdio.h> +#define ERR(...) fprintf(stderr, __VA_ARGS__) +#ifdef EMUGL_DEBUG +# define DBG(...) fprintf(stderr, __VA_ARGS__) #else -# include <stdio.h> -# define ERR(...) fprintf(stderr, __VA_ARGS__) -# ifdef EMUGL_DEBUG -# define DBG(...) fprintf(stderr, __VA_ARGS__) -# else -# define DBG(...) ((void)0) -# endif +# define DBG(...) ((void)0) #endif -#endif +#endif // _ERROR_LOG_H_ diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp index 9795490..b02131c 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp @@ -19,7 +19,6 @@ #include <stdlib.h> #include <string.h> #include "glUtils.h" -#include <cutils/log.h> #ifndef MAX #define MAX(a, b) ((a) < (b) ? (b) : (a)) diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLDecoderContextData.h b/emulator/opengl/shared/OpenglCodecCommon/GLDecoderContextData.h index 23785ae..d5b5189 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/GLDecoderContextData.h +++ b/emulator/opengl/shared/OpenglCodecCommon/GLDecoderContextData.h @@ -53,12 +53,12 @@ public: void storePointerData(unsigned int loc, void *data, size_t len) { - assert(loc < m_nLocations); + assert(loc < (unsigned)m_nLocations); m_pointerData[loc].alloc(len); memcpy(m_pointerData[loc].ptr(), data, len); } void *pointerData(unsigned int loc) { - assert(loc < m_nLocations); + assert(loc < (unsigned)m_nLocations); return m_pointerData[loc].ptr(); } private: diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp index c7da37a..59f7b97 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp @@ -16,23 +16,22 @@ #include "GLSharedGroup.h" -/**** KeyedVector utilities ****/ - -template <typename T> -static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) { - for (size_t i = 0; i < v.size(); i++) - delete v.valueAt(i); - v.clear(); -} +#include <string.h> /**** BufferData ****/ BufferData::BufferData() : m_size(0) {}; + BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size) { - void * buffer = NULL; - if (size>0) buffer = m_fixedBuffer.alloc(size); - if (data) memcpy(buffer, data, size); + void* buffer = NULL; + + if (size > 0) { + buffer = m_fixedBuffer.alloc(size); + if (data) { + memcpy(buffer, data, size); + } + } } /**** ProgramData ****/ @@ -204,9 +203,7 @@ bool ProgramData::attachShader(GLuint shader) return false; } } - // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt() - // due to the default parameters. This is the desired insertAt() overload. - m_shaders.insertAt(shader, m_shaders.size(), 1); + m_shaders.append(shader); return true; } @@ -215,7 +212,7 @@ bool ProgramData::detachShader(GLuint shader) size_t n = m_shaders.size(); for (size_t i = 0; i < n; i++) { if (m_shaders[i] == shader) { - m_shaders.removeAt(i); + m_shaders.remove(i); return true; } } @@ -225,49 +222,32 @@ bool ProgramData::detachShader(GLuint shader) /***** GLSharedGroup ****/ GLSharedGroup::GLSharedGroup() : - m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)), - m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)), - m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL)) -{ -} + m_buffers(), m_programs(), m_shaders() {} -GLSharedGroup::~GLSharedGroup() -{ - m_buffers.clear(); - m_programs.clear(); - clearObjectMap(m_buffers); - clearObjectMap(m_programs); - clearObjectMap(m_shaders); -} +GLSharedGroup::~GLSharedGroup() {} BufferData * GLSharedGroup::getBufferData(GLuint bufferId) { - android::AutoMutex _lock(m_lock); - return m_buffers.valueFor(bufferId); + emugl::Mutex::AutoLock _lock(m_lock); + return m_buffers.get(bufferId); } void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data) { - android::AutoMutex _lock(m_lock); - m_buffers.add(bufferId, new BufferData(size, data)); + emugl::Mutex::AutoLock _lock(m_lock); + m_buffers.set(bufferId, new BufferData(size, data)); } void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data) { - android::AutoMutex _lock(m_lock); - ssize_t idx = m_buffers.indexOfKey(bufferId); - if (idx >= 0) { - delete m_buffers.valueAt(idx); - m_buffers.editValueAt(idx) = new BufferData(size, data); - } else { - m_buffers.add(bufferId, new BufferData(size, data)); - } + emugl::Mutex::AutoLock _lock(m_lock); + m_buffers.set(bufferId, new BufferData(size, data)); } GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data) { - android::AutoMutex _lock(m_lock); - BufferData * buf = m_buffers.valueFor(bufferId); + emugl::Mutex::AutoLock _lock(m_lock); + BufferData * buf = m_buffers.get(bufferId); if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE; //it's safe to update now @@ -277,215 +257,197 @@ GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsi void GLSharedGroup::deleteBufferData(GLuint bufferId) { - android::AutoMutex _lock(m_lock); - ssize_t idx = m_buffers.indexOfKey(bufferId); - if (idx >= 0) { - delete m_buffers.valueAt(idx); - m_buffers.removeItemsAt(idx); - } + emugl::Mutex::AutoLock _lock(m_lock); + (void) m_buffers.remove(bufferId); } void GLSharedGroup::addProgramData(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - { - m_programs.removeItem(program); - delete pData; - } - - m_programs.add(program,new ProgramData()); + emugl::Mutex::AutoLock _lock(m_lock); + m_programs.set(program, new ProgramData()); } void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes) { - android::AutoMutex _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - { + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData *pData = m_programs.get(program); + if (pData) { pData->initProgramData(numIndexes); } } bool GLSharedGroup::isProgramInitialized(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) - { - return pData->isInitialized(); - } - return false; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return pData && pData->isInitialized(); } void GLSharedGroup::deleteProgramData(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - delete pData; - m_programs.removeItem(program); + emugl::Mutex::AutoLock _lock(m_lock); + m_programs.remove(program); } void GLSharedGroup::attachShader(GLuint program, GLuint shader) { - android::AutoMutex _lock(m_lock); - ProgramData* programData = m_programs.valueFor(program); - ssize_t idx = m_shaders.indexOfKey(shader); - if (programData && idx >= 0) { - if (programData->attachShader(shader)) { - refShaderDataLocked(idx); - } + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* programData = m_programs.get(program); + if (programData && programData->attachShader(shader)) { + refShaderDataLocked(shader); } } void GLSharedGroup::detachShader(GLuint program, GLuint shader) { - android::AutoMutex _lock(m_lock); - ProgramData* programData = m_programs.valueFor(program); - ssize_t idx = m_shaders.indexOfKey(shader); - if (programData && idx >= 0) { - if (programData->detachShader(shader)) { - unrefShaderDataLocked(idx); - } + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* programData = m_programs.get(program); + if (programData && programData->detachShader(shader)) { + unrefShaderDataLocked(shader); } } -void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name) +void GLSharedGroup::setProgramIndexInfo(GLuint program, + GLuint index, + GLint base, + GLint size, + GLenum type, + const char* name) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) - { - pData->setIndexInfo(index,base,size,type); - - if (type == GL_SAMPLER_2D) { - size_t n = pData->getNumShaders(); - for (size_t i = 0; i < n; i++) { - GLuint shaderId = pData->getShader(i); - ShaderData* shader = m_shaders.valueFor(shaderId); - if (!shader) continue; - ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin(); - ShaderData::StringList::iterator nameEnd = shader->samplerExternalNames.end(); - while (nameIter != nameEnd) { - if (*nameIter == name) { - pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL); - break; - } - ++nameIter; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + if (!pData) { + return; + } + pData->setIndexInfo(index,base,size,type); + + if (type == GL_SAMPLER_2D) { + size_t n = pData->getNumShaders(); + for (size_t i = 0; i < n; i++) { + GLuint shaderId = pData->getShader(i); + ShaderData* shader = m_shaders.get(shaderId); + if (!shader) continue; +#if 0 // TODO(digit): Understand why samplerExternalNames is always empty? + ShaderData::StringList::iterator nameIter = + shader->samplerExternalNames.begin(); + ShaderData::StringList::iterator nameEnd = + shader->samplerExternalNames.end(); + while (nameIter != nameEnd) { + if (*nameIter == name) { + pData->setIndexFlags( + index, + ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL); + break; } + ++nameIter; } +#endif } } } + GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - GLenum type=0; - if (pData) - { - type = pData->getTypeForLocation(location); - } - return type; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return pData ? pData->getTypeForLocation(location) : 0; } bool GLSharedGroup::isProgram(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - return (pData!=NULL); + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return (pData != NULL); } void GLSharedGroup::setupLocationShiftWAR(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); if (pData) pData->setupLocationShiftWAR(); } -GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex) +GLint GLSharedGroup::locationWARHostToApp(GLuint program, + GLint hostLoc, + GLint arrIndex) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex); - else return hostLoc; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return pData ? pData->locationWARHostToApp(hostLoc, arrIndex) : hostLoc; } GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->locationWARAppToHost(appLoc); - else return appLoc; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return pData ? pData->locationWARAppToHost(appLoc) : appLoc; } bool GLSharedGroup::needUniformLocationWAR(GLuint program) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->needUniformLocationWAR(); - return false; + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); + return pData ? pData->needUniformLocationWAR() : false; } -GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const +GLint GLSharedGroup::getNextSamplerUniform(GLuint program, + GLint index, + GLint* val, + GLenum* target) const { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); return pData ? pData->getNextSamplerUniform(index, val, target) : -1; } -bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target) +bool GLSharedGroup::setSamplerUniform(GLuint program, + GLint appLoc, + GLint val, + GLenum* target) { - android::AutoMutex _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + emugl::Mutex::AutoLock _lock(m_lock); + ProgramData* pData = m_programs.get(program); return pData ? pData->setSamplerUniform(appLoc, val, target) : false; } bool GLSharedGroup::addShaderData(GLuint shader) { - android::AutoMutex _lock(m_lock); + emugl::Mutex::AutoLock _lock(m_lock); ShaderData* data = new ShaderData; - if (data) { - if (m_shaders.add(shader, data) < 0) { - delete data; - data = NULL; - } - data->refcount = 1; - } - return data != NULL; + data->refcount = 1; + m_shaders.set(shader, data); + return true; } ShaderData* GLSharedGroup::getShaderData(GLuint shader) { - android::AutoMutex _lock(m_lock); - return m_shaders.valueFor(shader); + emugl::Mutex::AutoLock _lock(m_lock); + ShaderData* data = m_shaders.get(shader); + if (data) { + data->refcount++; + } + return data; } void GLSharedGroup::unrefShaderData(GLuint shader) { - android::AutoMutex _lock(m_lock); - ssize_t idx = m_shaders.indexOfKey(shader); - if (idx >= 0) { - unrefShaderDataLocked(idx); - } + emugl::Mutex::AutoLock _lock(m_lock); + unrefShaderDataLocked(shader); } -void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx) +void GLSharedGroup::refShaderDataLocked(GLuint shader) { - assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size()); - ShaderData* data = m_shaders.valueAt(shaderIdx); - data->refcount++; + ShaderData* data = m_shaders.get(shader); + if (data) { + data->refcount++; + } } -void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx) +void GLSharedGroup::unrefShaderDataLocked(GLuint shader) { - assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size()); - ShaderData* data = m_shaders.valueAt(shaderIdx); - if (--data->refcount == 0) { - delete data; - m_shaders.removeItemsAt(shaderIdx); + ShaderData* data = m_shaders.get(shader); + if (data && --data->refcount == 0) { + m_shaders.remove(shader); } } diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h index 61b8f00..f111f99 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h +++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h @@ -16,6 +16,11 @@ #ifndef _GL_SHARED_GROUP_H_ #define _GL_SHARED_GROUP_H_ +#include "emugl/common/id_to_object_map.h" +#include "emugl/common/mutex.h" +#include "emugl/common/pod_vector.h" +#include "emugl/common/smart_ptr.h" + #define GL_API #ifndef ANDROID #define GL_APIENTRY @@ -30,18 +35,13 @@ #include <stdio.h> #include <stdlib.h> #include "ErrorLog.h" -#include <utils/KeyedVector.h> -#include <utils/List.h> -#include <utils/String8.h> -#include <utils/threads.h> #include "FixedBuffer.h" -#include "SmartPtr.h" struct BufferData { BufferData(); BufferData(GLsizeiptr size, void * data); GLsizeiptr m_size; - FixedBuffer m_fixedBuffer; + FixedBuffer m_fixedBuffer; }; class ProgramData { @@ -61,7 +61,7 @@ private: bool m_initialized; bool m_locShiftWAR; - android::Vector<GLuint> m_shaders; + emugl::PodVector<GLuint> m_shaders; public: enum { @@ -92,20 +92,22 @@ public: }; struct ShaderData { +#if 0 // TODO(digit): Undertand why this is never used? typedef android::List<android::String8> StringList; StringList samplerExternalNames; +#endif int refcount; }; class GLSharedGroup { private: - android::DefaultKeyedVector<GLuint, BufferData*> m_buffers; - android::DefaultKeyedVector<GLuint, ProgramData*> m_programs; - android::DefaultKeyedVector<GLuint, ShaderData*> m_shaders; - mutable android::Mutex m_lock; + emugl::IdToObjectMap<BufferData> m_buffers; + emugl::IdToObjectMap<ProgramData> m_programs; + emugl::IdToObjectMap<ShaderData> m_shaders; + mutable emugl::Mutex m_lock; - void refShaderDataLocked(ssize_t shaderIdx); - void unrefShaderDataLocked(ssize_t shaderIdx); + void refShaderDataLocked(GLuint shader); + void unrefShaderDataLocked(GLuint shader); public: GLSharedGroup(); @@ -138,6 +140,6 @@ public: void unrefShaderData(GLuint shader); }; -typedef SmartPtr<GLSharedGroup> GLSharedGroupPtr; +typedef emugl::SmartPtr<GLSharedGroup> GLSharedGroupPtr; #endif //_GL_SHARED_GROUP_H_ diff --git a/emulator/opengl/shared/OpenglCodecCommon/SmartPtr.h b/emulator/opengl/shared/OpenglCodecCommon/SmartPtr.h deleted file mode 100644 index 4bdfbe4..0000000 --- a/emulator/opengl/shared/OpenglCodecCommon/SmartPtr.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -* 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 __SMART_PTR_H -#define __SMART_PTR_H - -#include <cutils/threads.h> -#include <cutils/atomic.h> - -template <class T, bool threadSafe = false> -class SmartPtr -{ -public: - explicit SmartPtr(T* ptr = (T*)NULL) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - m_ptr = ptr; - if (ptr) - m_pRefCount = new int32_t(1); - else - m_pRefCount = NULL; - } - - SmartPtr<T,threadSafe>(const SmartPtr<T,false>& rhs) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - } - - SmartPtr<T,threadSafe>(SmartPtr<T,true>& rhs) { - if (threadSafe) { - m_lock = new mutex_t; - mutex_init(m_lock); - } - else m_lock = NULL; - - if (rhs.m_lock) mutex_lock(rhs.m_lock); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (rhs.m_lock) mutex_unlock(rhs.m_lock); - } - - ~SmartPtr() { - if (m_lock) mutex_lock(m_lock); - release(); - if (m_lock) - { - mutex_unlock(m_lock); - mutex_destroy(m_lock); - delete m_lock; - } - } - - T* Ptr() const { - return m_ptr; - } - - const T* constPtr() const - { - return m_ptr; - } - - T* operator->() const { - return m_ptr; - } - - T& operator*() const { - return *m_ptr; - } - - operator void*() const { - return (void *)m_ptr; - } - - // This gives STL lists something to compare. - bool operator <(const SmartPtr<T>& t1) const { - return m_ptr < t1.m_ptr; - } - - SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs) - { - if (m_ptr == rhs.m_ptr) - return *this; - - if (m_lock) mutex_lock(m_lock); - release(); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (m_lock) mutex_unlock(m_lock); - - return *this; - } - - SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs) - { - if (m_ptr == rhs.m_ptr) - return *this; - - if (m_lock) mutex_lock(m_lock); - release(); - if (rhs.m_lock) mutex_lock(rhs.m_lock); - m_pRefCount = rhs.m_pRefCount; - m_ptr = rhs.m_ptr; - use(); - if (rhs.m_lock) mutex_unlock(rhs.m_lock); - if (m_lock) mutex_unlock(m_lock); - - return *this; - } - -private: - int32_t *m_pRefCount; - mutex_t *m_lock; - T* m_ptr; - - // Increment the reference count on this pointer by 1. - int use() { - if (!m_pRefCount) return 0; - return android_atomic_inc(m_pRefCount) + 1; - } - - // Decrement the reference count on the pointer by 1. - // If the reference count goes to (or below) 0, the pointer is deleted. - int release() { - if (!m_pRefCount) return 0; - - int iVal = android_atomic_dec(m_pRefCount); - if (iVal > 1) - return iVal - 1; - - delete m_pRefCount; - m_pRefCount = NULL; - - if (m_ptr) { - delete m_ptr; - m_ptr = NULL; - } - return 0; - } - -}; - -#endif // of __SMART_PTR_H diff --git a/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp index f7a2314..726d359 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ #include "SocketStream.h" -#include <cutils/sockets.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -53,6 +52,7 @@ SocketStream::~SocketStream() #else ::close(m_sock); #endif + m_sock = -1; } if (m_buf != NULL) { free(m_buf); @@ -112,7 +112,6 @@ int SocketStream::writeFully(const void* buffer, size_t size) const unsigned char *SocketStream::readFully(void *buf, size_t len) { - const unsigned char* ret = NULL; if (!valid()) return NULL; if (!buf) { return NULL; // do not allow NULL buf in that implementation @@ -140,7 +139,7 @@ const unsigned char *SocketStream::read( void *buf, size_t *inout_len) int n; do { - n = recv(buf, *inout_len); + n = this->recv(buf, *inout_len); } while( n < 0 && errno == EINTR ); if (n > 0) { diff --git a/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp index 8a6e56e..ba355ab 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ #include "TcpStream.h" -#include <cutils/sockets.h> +#include "emugl/common/sockets.h" + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -30,77 +31,48 @@ #define LISTEN_BACKLOG 4 -TcpStream::TcpStream(size_t bufSize) : - SocketStream(bufSize) -{ -} +TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {} TcpStream::TcpStream(int sock, size_t bufSize) : - SocketStream(sock, bufSize) -{ + SocketStream(sock, bufSize) { // disable Nagle algorithm to improve bandwidth of small // packets which are quite common in our implementation. -#ifdef _WIN32 - DWORD flag; -#else - int flag; -#endif - flag = 1; - setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag) ); + emugl::socketTcpDisableNagle(sock); } -int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) -{ - m_sock = socket_loopback_server(0, SOCK_STREAM); +int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) { + m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM); if (!valid()) return int(ERR_INVALID_SOCKET); - /* get the actual port number assigned by the system */ - struct sockaddr_in addr; - socklen_t addrLen = sizeof(addr); - memset(&addr, 0, sizeof(addr)); - if (getsockname(m_sock, (struct sockaddr*)&addr, &addrLen) < 0) { - close(m_sock); + int port = emugl::socketGetPort(m_sock); + if (port < 0) { + ::close(m_sock); return int(ERR_INVALID_SOCKET); } - snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", ntohs(addr.sin_port)); + + snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", port); addrstr[MAX_ADDRSTR_LEN-1] = '\0'; return 0; } -SocketStream * TcpStream::accept() -{ - int clientSock = -1; - - while (true) { - struct sockaddr_in addr; - socklen_t len = sizeof(addr); - clientSock = ::accept(m_sock, (sockaddr *)&addr, &len); - - if (clientSock < 0 && errno == EINTR) { - continue; - } - break; - } +SocketStream * TcpStream::accept() { + int clientSock = emugl::socketAccept(m_sock); + if (clientSock < 0) + return NULL; - TcpStream *clientStream = NULL; - - if (clientSock >= 0) { - clientStream = new TcpStream(clientSock, m_bufsize); - } - return clientStream; + return new TcpStream(clientSock, m_bufsize); } -int TcpStream::connect(const char* addr) -{ +int TcpStream::connect(const char* addr) { int port = atoi(addr); - return connect("127.0.0.1",port); + m_sock = emugl::socketTcpLoopbackClient(port, SOCK_STREAM); + return valid() ? 0 : -1; } int TcpStream::connect(const char* hostname, unsigned short port) { - m_sock = socket_network_client(hostname, port, SOCK_STREAM); - if (!valid()) return -1; - return 0; + m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM); + return valid() ? 0 : -1; } diff --git a/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp index b2eef6d..7b2f67d 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp @@ -14,7 +14,9 @@ * limitations under the License. */ #include "UnixStream.h" -#include <cutils/sockets.h> + +#include "emugl/common/sockets.h" + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -92,7 +94,7 @@ int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN]) return -1; } - m_sock = socket_local_server(addrstr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); + m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM); if (!valid()) return int(ERR_INVALID_SOCKET); return 0; @@ -123,7 +125,7 @@ SocketStream * UnixStream::accept() int UnixStream::connect(const char* addr) { - m_sock = socket_local_client(addr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); + m_sock = emugl::socketLocalClient(addr, SOCK_STREAM); if (!valid()) return -1; return 0; diff --git a/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp index 76907a0..dcfb0c0 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp @@ -193,8 +193,6 @@ int Win32PipeStream::commitBuffer(size_t size) const unsigned char *Win32PipeStream::readFully(void *buf, size_t len) { - const unsigned char* ret = NULL; - if (m_pipe == INVALID_HANDLE_VALUE) return NULL; diff --git a/emulator/opengl/shared/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk index 8a6c18b..f9673fc 100644 --- a/emulator/opengl/shared/OpenglOsUtils/Android.mk +++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk @@ -10,6 +10,7 @@ LOCAL_PATH := $(call my-dir) host_common_SRC_FILES := osDynLibrary.cpp host_common_LDLIBS := +host_common_INCLUDES := $(LOCAL_PATH) ifeq ($(HOST_OS),windows) host_common_SRC_FILES += \ @@ -29,15 +30,19 @@ endif ### 32-bit host library #### $(call emugl-begin-host-static-library,libOpenglOsUtils) - $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) + $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES)) LOCAL_SRC_FILES = $(host_common_SRC_FILES) $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) + $(call emugl-import,libemugl_common) $(call emugl-end-module) ### 64-bit host library #### -$(call emugl-begin-host-static-library,lib64OpenglOsUtils) - $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) - LOCAL_SRC_FILES = $(host_common_SRC_FILES) - $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) - $(call emugl-export,CFLAGS,-m64) -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64OpenglOsUtils) + $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES)) + LOCAL_SRC_FILES = $(host_common_SRC_FILES) + $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) + $(call emugl-import,lib64emugl_common) + $(call emugl-export,CFLAGS,-m64 -fPIC) + $(call emugl-end-module) +endif diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp index d8879eb..ef2bebc 100644 --- a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp +++ b/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp @@ -15,6 +15,10 @@ */ #include "osThread.h" +#include "emugl/common/thread_store.h" + +#include <stdint.h> + namespace osUtils { Thread::Thread() : @@ -55,9 +59,8 @@ Thread::wait(int *exitStatus) return false; } - long long int ret=(long long int)retval; if (exitStatus) { - *exitStatus = (int)ret; + *exitStatus = (int)(uintptr_t)retval; } return true; } @@ -87,7 +90,8 @@ Thread::thread_main(void *p_arg) self->m_exitStatus = ret; pthread_mutex_unlock(&self->m_lock); - return (void*)ret; + ::emugl::ThreadStore::OnThreadExit(); + return (void*)(uintptr_t)ret; } } // of namespace osUtils diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp index 2d563f8..1a30b97 100644 --- a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp +++ b/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp @@ -15,6 +15,8 @@ */ #include "osThread.h" +#include "emugl/common/thread_store.h" + namespace osUtils { Thread::Thread() : @@ -95,6 +97,7 @@ Thread::thread_main(void *p_arg) Thread *self = (Thread *)p_arg; int ret = self->Main(); self->m_isRunning = false; + ::emugl::ThreadStore::OnThreadExit(); return ret; } diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk new file mode 100644 index 0000000..58dd6da --- /dev/null +++ b/emulator/opengl/shared/emugl/common/Android.mk @@ -0,0 +1,54 @@ +# This build script corresponds to a library containing many definitions +# common to both the guest and the host. They relate to +# +LOCAL_PATH := $(call my-dir) + +### emugl_common host library ########################################### + +commonSources := \ + id_to_object_map.cpp \ + lazy_instance.cpp \ + pod_vector.cpp \ + smart_ptr.cpp \ + sockets.cpp \ + thread_store.cpp \ + +host_commonSources := $(commonSources) + +$(call emugl-begin-host-static-library,libemugl_common) +LOCAL_SRC_FILES := $(host_commonSources) +$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) +$(call emugl-export,LDLIBS,-lstdc++) +$(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-static-library,lib64emugl_common) + LOCAL_SRC_FILES := $(host_commonSources) + $(call emugl-export,CFLAGS,-m64 -fPIC) + $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) + $(call emugl-export,LDLIBS,-lstdc++) + $(call emugl-end-module) +endif + + +### emugl_common_unittests ############################################## + +host_commonSources := \ + id_to_object_map_unittest.cpp \ + lazy_instance_unittest.cpp \ + pod_vector_unittest.cpp \ + mutex_unittest.cpp \ + smart_ptr_unittest.cpp \ + thread_store_unittest.cpp \ + +$(call emugl-begin-host-executable,emugl_common_host_unittests) +LOCAL_SRC_FILES := $(host_commonSources) +$(call emugl-import,libemugl_common libemugl_gtest) +$(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-executable,emugl64_common_host_unittests) + LOCAL_SRC_FILES := $(host_commonSources) + $(call emugl-import,lib64emugl_common lib64emugl_gtest) + $(call emugl-end-module) +endif diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map.cpp new file mode 100644 index 0000000..597c9eb --- /dev/null +++ b/emulator/opengl/shared/emugl/common/id_to_object_map.cpp @@ -0,0 +1,236 @@ +// Copyright (C) 2014 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 "emugl/common/id_to_object_map.h" + +#include <stdlib.h> + +namespace emugl { + +namespace { + +typedef IdToObjectMapBase::KeyType KeyType; + +enum { + kMinShift = 3, + kMaxShift = 31, + kMinCapacity = (1 << kMinShift), + kLoadScale = 1024, + kMinLoad = kLoadScale/4, // 25% minimum load. + kMaxLoad = kLoadScale*3/4, // 75% maximum load. + + kInvalidKey = IdToObjectMapBase::kMaxId + 1U, + kTombstone = IdToObjectMapBase::kMaxId + 2U, +}; + +// Return a number that indicates if the current |capacity| is appropriate +// to hold |size| items in our map. +// -1 -> the capacity is too small and needs to be increased. +// 0 -> the capacity is ok. +// +1 -> the capacity is too large and needs to be decreased. +int capacityCompare(size_t shift, size_t size) { + size_t capacity = 1U << shift; + // Essentially, one can rewrite: + // load < minLoad + // as: + // size / capacity < minLoad + // capacity * minLoad > size + if (capacity * kMinLoad > size * kLoadScale) + return +1; + + // Similarly, one can rewrite: + // load > maxLoad + // as: + // size / capacity > maxLoad + // capacity * maxLoad < size + if (capacity * kMaxLoad < size * kLoadScale) + return -1; + + return 0; +} + +size_t probeKeys(const KeyType* keys, size_t shift, KeyType key) { + static const int kPrimes[] = { + 1, /* For 1 << 0 */ + 2, + 3, + 7, + 13, + 31, + 61, + 127, + 251, + 509, + 1021, + 2039, + 4093, + 8191, + 16381, + 32749, + 65521, /* For 1 << 16 */ + 131071, + 262139, + 524287, + 1048573, + 2097143, + 4194301, + 8388593, + 16777213, + 33554393, + 67108859, + 134217689, + 268435399, + 536870909, + 1073741789, + 2147483647 /* For 1 << 31 */ + }; + + size_t slot = key % kPrimes[shift]; + size_t step = 0; + for (;;) { + KeyType k = keys[slot]; + if (k == kInvalidKey || k == kTombstone || k == key) + return slot; + + step += 1; + slot = (slot + step) & (1U << shift); + } +} + +} // namespace + +IdToObjectMapBase::IdToObjectMapBase() : + mCount(0), mShift(kMinShift) { + size_t capacity = 1U << mShift; + mKeys = static_cast<KeyType*>(::calloc(sizeof(mKeys[0]), capacity)); + mValues = static_cast<void**>(::calloc(sizeof(mValues[0]), capacity)); + for (size_t n = 0; n < capacity; ++n) { + mKeys[n] = kInvalidKey; + } +} + +IdToObjectMapBase::~IdToObjectMapBase() { + mShift = 0; + mCount = 0; + ::free(mKeys); + ::free(mValues); +} + +bool IdToObjectMapBase::contains(KeyType key) const { + size_t slot = probeKeys(mKeys, mShift, key); + switch (mKeys[slot]) { + case kInvalidKey: + case kTombstone: + return false; + default: + ; + } + return true; +} + +bool IdToObjectMapBase::find(KeyType key, void** value) const { + size_t slot = probeKeys(mKeys, mShift, key); + if (!isValidKey(mKeys[slot])) { + *value = NULL; + return false; + } + *value = mValues[slot]; + return true; +} + +void* IdToObjectMapBase::set(KeyType key, void* value) { + if (!value) + return remove(key); + + size_t slot = probeKeys(mKeys, mShift, key); + void* result; + if (isValidKey(mKeys[slot])) { + result = mValues[slot]; + mValues[slot] = value; + } else { + mKeys[slot] = key; + mValues[slot] = value; + result = NULL; + mCount++; + resize(mCount); + } + return result; +} + +void* IdToObjectMapBase::remove(KeyType key) { + size_t slot = probeKeys(mKeys, mShift, key); + if (!isValidKey(mKeys[slot])) + return NULL; + + void* result = mValues[slot]; + mValues[slot] = NULL; + mKeys[slot] = kTombstone; + mCount--; + return result; +} + +void IdToObjectMapBase::resize(size_t newSize) { + int ret = capacityCompare(mShift, newSize); + if (!ret) + return; + + size_t oldCapacity = 1U << mShift; + size_t newShift = mShift; + + if (ret < 0) { + // Capacity is too small and must be increased. + do { + if (newShift == kMaxShift) + break; + ++newShift; + } while (capacityCompare(newShift, newSize) < 0); + } else { + // Capacity is too large and must be decreased. + do { + if (newShift == kMinShift) + break; + newShift--; + } while (capacityCompare(newShift, newSize) > 0); + } + if (newShift == mShift) + return; + + // Allocate new arrays. + size_t newCapacity = 1U << newShift; + KeyType* newKeys = static_cast<KeyType*>( + ::calloc(sizeof(newKeys[0]), newCapacity)); + void** newValues = static_cast<void**>( + ::calloc(sizeof(newValues[0]), newCapacity)); + for (size_t n = 0; n < newCapacity; ++n) + newKeys[n] = kInvalidKey; + + // Copy old entries into new arrays. + for (size_t n = 0; n < oldCapacity; ++n) { + KeyType key = mKeys[n]; + if (isValidKey(key)) { + size_t newSlot = probeKeys(newKeys, newShift, key); + newKeys[newSlot] = key; + newValues[newSlot] = mValues[n]; + } + } + + // Swap arrays, and get rid of old ones. + ::free(mKeys); + ::free(mValues); + mKeys = newKeys; + mValues = newValues; + mShift = newShift; +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.h b/emulator/opengl/shared/emugl/common/id_to_object_map.h new file mode 100644 index 0000000..e3d0a81 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/id_to_object_map.h @@ -0,0 +1,176 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_ID_TO_OBJECT_MAP_H +#define EMUGL_COMMON_ID_TO_OBJECT_MAP_H + +#include <stddef.h> + +namespace emugl { + +// Base implementation class for IdToObjectMap template. +// Used to reduce template-instanciated code generation. +class IdToObjectMapBase { +public: + // The type of keys in this map. + typedef unsigned KeyType; + + // Values higher than kMaxId cannot be used as map keys. + enum { + kMaxId = 0xfffffffdU, + }; + + static inline bool isValidKey(KeyType key) { + return key <= kMaxId; + } + +protected: + IdToObjectMapBase(); + + ~IdToObjectMapBase(); + + void clear(); + + // Return size + inline size_t size() const { return mCount; } + + inline size_t capacity() const { return 1U << mShift; } + + // Return true iff the map contains a given key. + bool contains(KeyType key) const; + + // Find a value associated with a given |key| in the map. + // On success, return true and sets |*value| to the value/pointer, + // which is _still_ owned by the map. + // On failure, return false and sets |*value| to NULL. + bool find(KeyType key, void** value) const; + + // Associate a value with a given |key| in the map. + // Return the old value for the key, if any. Caller is responsible + // for freeing it. + void* set(KeyType key, void* value); + + // Remove the value associated with a given |key|. + // Return the old value, if any. Caller is responsible for + // freeing it. + void* remove(KeyType key); + + size_t mCount; + size_t mShift; + KeyType* mKeys; + void** mValues; + +private: + // Resize the map if needed to ensure it can hold at least |newSize| + // entries. + void resize(size_t newSize); +}; + +// A templated data container that acts as a dictionary mapping unsigned +// integer keys to heap-allocated objects of type T. The dictionary +// owns the objects associated with its keys, and automatically destroys +// them when it is destroyed, or during replacement or removal. +template <class T> +class IdToObjectMap : public IdToObjectMapBase { +public: + // Initialize an empty instance. + IdToObjectMap() : IdToObjectMapBase() {} + + // Destroy this instance. + ~IdToObjectMap() { + clear(); + } + + // Return the number of items in this map. + inline size_t size() const { return IdToObjectMapBase::size(); } + + // Return true iff the map is empty. + inline bool empty() const { return !IdToObjectMapBase::size(); } + + // Remove all items from the map. + void clear(); + + // Returns true iff the dictionary contains a value for |key|. + inline bool contains(KeyType key) const { + return IdToObjectMapBase::contains(key); + } + + // Find the value corresponding to |key| in this map. + // On success, return true, and sets |*value| to point to the + // value (still owned by the instance). On failure, return false. + inline bool find(KeyType key, T** value) const { + return IdToObjectMapBase::find(key, reinterpret_cast<void**>(value)); + } + + // Return the value associated with a given |key|, or NULL if it is + // not in the map. Result is still owned by the map. + inline T* get(KeyType key) const { + T* result = NULL; + this->find(key, &result); + return result; + } + + // Associate |value| with a given |key|. Returns true if a previous + // value was replaced, and false if this is the first time a value + // was associated with the given key. IMPORTANT: This transfers + // ownership of |value| to the map instance. In case of replacement, + // the old value is automatically destroyed. Using NULL as the value + // is equivalent to calling remove(). + bool set(KeyType key, T* value); + + // Remove any value associated with |key|. + // Return true iff a value was associated with the key and destroyed + // by this function, false if there was no value associated with the + // key (or if it was NULL). + bool remove(KeyType key); +}; + +template <class T> +void IdToObjectMap<T>::clear() { + size_t n = capacity(); + while (n > 0) { + --n; + if (!isValidKey(mKeys[n])) + continue; + + delete static_cast<T*>(mValues[n]); + mValues[n] = NULL; + mKeys[n] = kMaxId + 1U; + } + mCount = 0; +} + +template <class T> +bool IdToObjectMap<T>::set(KeyType key, T* value) { + T* oldValue = static_cast<T*>(IdToObjectMapBase::set(key, value)); + if (!oldValue) { + return false; + } + delete oldValue; + return true; +} + +template <class T> +bool IdToObjectMap<T>::remove(KeyType key) { + T* oldValue = static_cast<T*>(IdToObjectMapBase::remove(key)); + if (!oldValue) + return false; + delete oldValue; + return true; +} + +} // namespace emugl + + +#endif // EMUGL_COMMON_ID_TO_OBJECT_MAP_H diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp new file mode 100644 index 0000000..50740be --- /dev/null +++ b/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp @@ -0,0 +1,116 @@ +// Copyright (C) 2014 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 "emugl/common/id_to_object_map.h" + +#include <gtest/gtest.h> + +namespace emugl { + +namespace { + +typedef IdToObjectMapBase::KeyType KeyType; + +class Foo { +public: + Foo() : mVal(0) {} + Foo(int val) : mVal(val) {} + ~Foo() {} + int val() const { return mVal; } + void setVal(int val) { mVal = val; } +private: + int mVal; +}; + +} // namespace + +TEST(IdToObjectMap, Empty) { + IdToObjectMap<Foo> map; + EXPECT_TRUE(map.empty()); + EXPECT_EQ(0U, map.size()); +} + +TEST(IdToObjectMap, SetIntegerRange) { + IdToObjectMap<Foo> map; + KeyType kMax = 10000; + + // Add all items in the map. + for (KeyType n = 0; n < kMax; ++n) { + EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; + } + + // Check final size. + EXPECT_EQ(static_cast<size_t>(kMax), map.size()); + + // Find all items in the map. + for (KeyType n = 0; n < kMax; ++n) { + EXPECT_TRUE(map.contains(n)) << "For key " << n; + Foo* foo = NULL; + EXPECT_TRUE(map.find(n, &foo)) << "For key " << n; + if (foo) { + EXPECT_EQ(static_cast<int>(n), foo->val()) << "For key " << n; + } + } +} + +TEST(IdToObjectMap, RemoveAll) { + IdToObjectMap<Foo> map; + KeyType kMax = 10000; + + // Add all items in the map. + for (KeyType n = 0; n < kMax; ++n) { + EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; + } + + EXPECT_EQ(static_cast<size_t>(kMax), map.size()); + + for (KeyType n = 0; n < kMax; ++n) { + EXPECT_TRUE(map.remove(n)) << "For key " << n; + } + EXPECT_EQ(0U, map.size()); +} + +TEST(IdToObjectMap, RemoveOdd) { + IdToObjectMap<Foo> map; + KeyType kMax = 10000; + + // Add all items in the map. + for (KeyType n = 0; n < kMax; ++n) { + EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n; + } + + EXPECT_EQ(static_cast<size_t>(kMax), map.size()); + + for (KeyType n = 0; n < kMax; ++n) { + if (n & 1) { + EXPECT_TRUE(map.remove(n)) << "For key " << n; + } + } + EXPECT_EQ(static_cast<size_t>(kMax / 2), map.size()); + + for (KeyType n = 0; n < kMax; ++n) { + if (n & 1) { + EXPECT_FALSE(map.contains(n)) << "For key " << n; + } else { + EXPECT_TRUE(map.contains(n)) << "For key " << n; + Foo* foo = NULL; + EXPECT_TRUE(map.find(n, &foo)) << "For key " << n; + if (foo) { + EXPECT_EQ(static_cast<int>(n), foo->val()); + } + } + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/lazy_instance.cpp b/emulator/opengl/shared/emugl/common/lazy_instance.cpp new file mode 100644 index 0000000..ee715fa --- /dev/null +++ b/emulator/opengl/shared/emugl/common/lazy_instance.cpp @@ -0,0 +1,101 @@ +// Copyright (C) 2014 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 "emugl/common/lazy_instance.h" + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#else +# include <sched.h> +#endif + +namespace emugl { +namespace internal { + +typedef LazyInstanceState::AtomicType AtomicType; + +#if defined(__GNUC__) +static inline void compilerBarrier() { + __asm__ __volatile__ ("" : : : "memory"); +} +#else +#error "Your compiler is not supported" +#endif + +#if defined(__i386__) || defined(__x86_64__) +# define acquireBarrier() compilerBarrier() +# define releaseBarrier() compilerBarrier() +#else +# error "Your CPU is not supported" +#endif + +static inline AtomicType loadAcquire(AtomicType volatile* ptr) { + AtomicType ret = *ptr; + acquireBarrier(); + return ret; +} + +static inline void storeRelease(AtomicType volatile* ptr, AtomicType value) { + releaseBarrier(); + *ptr = value; +} + +static int atomicCompareAndSwap(AtomicType volatile* ptr, + int expected, + int value) { +#ifdef _WIN32 + return InterlockedCompareExchange(ptr, value, expected); +#elif defined(__GNUC__) + return __sync_val_compare_and_swap(ptr, expected, value); +#else +#error "Your compiler is not supported" +#endif +} + +static void yieldThread() { +#ifdef _WIN32 + ::Sleep(0); +#else + sched_yield(); +#endif +} + +bool LazyInstanceState::inInitState() { + return loadAcquire(&mState) == STATE_INIT; +} + +bool LazyInstanceState::needConstruction() { + AtomicType state = loadAcquire(&mState); + if (mState == STATE_DONE) + return false; + + state = atomicCompareAndSwap(&mState, STATE_INIT, STATE_CONSTRUCTING); + if (state == STATE_INIT) + return true; + + do { + yieldThread(); + state = loadAcquire(&mState); + } while (state != STATE_DONE); + + return false; +} + +void LazyInstanceState::doneConstructing() { + storeRelease(&mState, STATE_DONE); +} + +} // namespace internal +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/lazy_instance.h b/emulator/opengl/shared/emugl/common/lazy_instance.h new file mode 100644 index 0000000..6641c93 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/lazy_instance.h @@ -0,0 +1,156 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_LAZY_INSTANCE_H +#define EMUGL_COMMON_LAZY_INSTANCE_H + +#include <new> + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#endif + +namespace emugl { +namespace internal { + +// A LazyInstance is a helper template that can be used to perform +// thread-safe lazy initialization of static C++ objects without forcing +// the generation of C++ static constructors in the final executable. +// +// In a nutshell, you can replace a statement like: +// +// static Foo gFoo; +// +// With: +// +// static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT; +// +// In the first case, a hidden static C++ constructor is embedded in the +// final executable, and executed at *load* *time* to call the Foo::Foo +// constructor on the gFoo object. +// +// On the second case, gFoo will only be initialized lazily, i.e. the first +// time any code actually tries to access the variable. +// +// Note that access is slightly different, i.e.: +// +// gFoo.get() returns a reference to the lazy-initialized object. +// gFoo.ptr() returns a pointer to it. +// gFoo->Something() is equivalent to doing gFoo.ptr()->Something(). +// +// 'gFoo' is stored in the .bss section and this doesn't use heap allocation. +// This class can only be used to perform lazy initialization through the +// class' default constructor. For more specialized cases, you will have +// to create a derived class, e.g.: +// +// class FoorWithDefaultParams : public Foo { +// public: +// FooWithDefaultParams() : Foo(<default-parameters>) {} +// }; +// +// LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT; +// +// The implementation of LazyInstance relies on atomic operations and +// POD-struct class definitions, i.e. one that doesn't have any constructor, +// destructor, virtual members, or private ones, and that can be +// zero-initialized at link time. +// +// You can also use LazyInstance<> instances as static local variables, +// e.g.: +// +// Foo* getFooSingleton() { +// static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT; +// return sFoo.ptr(); +// } +// +// This is useful on Windows which doesn't support thread-safe lazy +// initialization of static C++ local variables, or when the code is +// compiled with -fno-threadsafe-statics. +// +// This class is heavily inspired by Chromium's implementation of the +// same-named class (see $CHROMIUM/src/base/lazy_instance.h). + +// Atomic state variable type. Used to ensure to synchronize concurrent +// initialization and access without incurring the full cost of a mutex +// lock/unlock. +struct LazyInstanceState { + enum { + STATE_INIT = 0, + STATE_CONSTRUCTING = 1, + STATE_DONE = 2, + }; + + bool inInitState(); + bool needConstruction(); + void doneConstructing(); + +#ifdef _WIN32 + typedef LONG volatile AtomicType; +#else + typedef int volatile AtomicType; +#endif + + volatile AtomicType mState; +}; + +#define LAZY_INSTANCE_STATE_INIT \ + { ::emugl::internal::LazyInstanceState::STATE_INIT } + +} // namespace internal + +// LazyInstance template definition, see comment above for usage +// instructions. It is crucial to make this a POD-struct compatible +// type [1]. +// +// [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures +// +template <class T> +struct LazyInstance { + bool hasInstance() const { return !mState.inInitState(); } + + T& get() const { return *ptr(); } + + T* ptr() const; + + const T* operator->() const { return ptr(); } + + T* operator->() { return ptr(); } + + T& operator*() { return get(); } + + // Really private, do not use. + union { + mutable internal::LazyInstanceState mState; + double mPadding; + }; + mutable char mStorage[sizeof(T)]; +}; + +// Initialization value, must resolve to all-0 to ensure the object +// instance is actually placed in the .bss +#define LAZY_INSTANCE_INIT { { LAZY_INSTANCE_STATE_INIT }, { 0 } } + +template <class T> +T* LazyInstance<T>::ptr() const { + if (mState.needConstruction()) { + new (mStorage) T(); + mState.doneConstructing(); + } + return reinterpret_cast<T*>(mStorage); +} + +} // namespace emugl + +#endif // EMUGL_COMMON_LAZY_INSTANCE_H diff --git a/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp b/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp new file mode 100644 index 0000000..824845f --- /dev/null +++ b/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2014 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 "emugl/common/lazy_instance.h" + +#include "emugl/common/mutex.h" +#include "emugl/common/testing/test_thread.h" + +#include <gtest/gtest.h> + +namespace emugl { + +namespace { + +class Foo { +public: + Foo() : mValue(42) {} + int get() const { return mValue; } + void set(int value) { mValue = value; } + ~Foo() { mValue = 13; } +private: + int mValue; +}; + +class StaticCounter { +public: + StaticCounter() { + Mutex::AutoLock lock(mMutex); + mCounter++; + } + + int getValue() const { + Mutex::AutoLock lock(mMutex); + return mCounter; + } + +private: + static Mutex mMutex; + static int mCounter; +}; + +// NOTE: This introduces a static C++ constructor for this object file, +// but that's ok because a LazyInstance<Mutex> should not be used to +// test the behaviour of LazyInstance :-) +Mutex StaticCounter::mMutex; +int StaticCounter::mCounter = 0; + +} // namespace + +TEST(LazyInstance, HasInstance) { + LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT; + EXPECT_FALSE(foo_instance.hasInstance()); + EXPECT_FALSE(foo_instance.hasInstance()); + foo_instance.ptr(); + EXPECT_TRUE(foo_instance.hasInstance()); +} + +TEST(LazyInstance, Simple) { + LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT; + Foo* foo1 = foo_instance.ptr(); + EXPECT_TRUE(foo1); + EXPECT_EQ(42, foo_instance->get()); + foo1->set(10); + EXPECT_EQ(10, foo_instance->get()); + EXPECT_EQ(foo1, foo_instance.ptr()); +} + +// For the following test, launch 1000 threads that each try to get +// the instance pointer of a lazy instance. Then verify that they're all +// the same value. +// +// The lazy instance has a special constructor that will increment a +// global counter. This allows us to ensure that it is only called once. +// + +namespace { + +// The following is the shared structure between all threads. +struct MultiState { + MultiState(LazyInstance<StaticCounter>* staticCounter) : + mMutex(), mStaticCounter(staticCounter), mCount(0) {} + + enum { + kMaxThreads = 1000, + }; + + Mutex mMutex; + LazyInstance<StaticCounter>* mStaticCounter; + size_t mCount; + void* mValues[kMaxThreads]; + TestThread* mThreads[kMaxThreads]; +}; + +// The thread function for the test below. +static void* threadFunc(void* param) { + MultiState* state = static_cast<MultiState*>(param); + Mutex::AutoLock lock(state->mMutex); + if (state->mCount < MultiState::kMaxThreads) { + state->mValues[state->mCount++] = state->mStaticCounter->ptr(); + } + return NULL; +} + +} // namespace + +TEST(LazyInstance, MultipleThreads) { + LazyInstance<StaticCounter> counter_instance = LAZY_INSTANCE_INIT; + MultiState state(&counter_instance); + const size_t kNumThreads = MultiState::kMaxThreads; + + // Create all threads. + for (size_t n = 0; n < kNumThreads; ++n) { + state.mThreads[n] = new TestThread(threadFunc, &state); + } + + // Wait for their completion. + for (size_t n = 0; n < kNumThreads; ++n) { + state.mThreads[n]->join(); + } + + // Now check that the constructor was only called once. + EXPECT_EQ(1, counter_instance->getValue()); + + // Now compare all the store values, they should be the same. + StaticCounter* expectedValue = counter_instance.ptr(); + for (size_t n = 0; n < kNumThreads; ++n) { + EXPECT_EQ(expectedValue, state.mValues[n]) << "For thread " << n; + } + + for (size_t n = 0; n < kNumThreads; ++n) { + delete state.mThreads[n]; + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/mutex.h b/emulator/opengl/shared/emugl/common/mutex.h new file mode 100644 index 0000000..c6cdcf2 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/mutex.h @@ -0,0 +1,92 @@ +// Copyright (C) 2014 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 EMUGL_MUTEX_H +#define EMUGL_MUTEX_H + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#else +# include <pthread.h> +#endif + +namespace emugl { + +// Simple wrapper class for mutexes. +class Mutex { +public: + // Constructor. + Mutex() { +#ifdef _WIN32 + ::InitializeCriticalSection(&mLock); +#else + ::pthread_mutex_init(&mLock, NULL); +#endif + } + + // Destructor. + ~Mutex() { +#ifdef _WIN32 + ::DeleteCriticalSection(&mLock); +#else + ::pthread_mutex_destroy(&mLock); +#endif + } + + // Acquire the mutex. + void lock() { +#ifdef _WIN32 + ::EnterCriticalSection(&mLock); +#else + ::pthread_mutex_lock(&mLock); +#endif + } + + // Release the mutex. + void unlock() { +#ifdef _WIN32 + ::LeaveCriticalSection(&mLock); +#else + ::pthread_mutex_unlock(&mLock); +#endif + } + + // Helper class to lock / unlock a mutex automatically on scope + // entry and exit. + class AutoLock { + public: + AutoLock(Mutex& mutex) : mMutex(&mutex) { + mMutex->lock(); + } + + ~AutoLock() { + mMutex->unlock(); + } + private: + Mutex* mMutex; + }; + +private: +#ifdef _WIN32 + CRITICAL_SECTION mLock; +#else + pthread_mutex_t mLock; +#endif + +}; + +} // namespace emugl + +#endif // EMUGL_MUTEX_H diff --git a/emulator/opengl/shared/emugl/common/mutex_unittest.cpp b/emulator/opengl/shared/emugl/common/mutex_unittest.cpp new file mode 100644 index 0000000..e952d75 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/mutex_unittest.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2014 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 "emugl/common/mutex.h" + +#include "emugl/common/testing/test_thread.h" + +#include <gtest/gtest.h> + +namespace emugl { + +// Check that construction and destruction doesn't crash. +TEST(Mutex, ConstructionDestruction) { + Mutex lock; +} + +// Check that a simple lock + unlock works. +TEST(Mutex, LockUnlock) { + Mutex lock; + lock.lock(); + lock.unlock(); +} + +// Check that AutoLock compiles and doesn't crash. +TEST(Mutex, AutoLock) { + Mutex mutex; + Mutex::AutoLock lock(mutex); +} + +// Wrapper class for threads. Does not use emugl::Thread intentionally. +// Common data type used by the following tests below. +struct ThreadParams { + ThreadParams() : mutex(), counter(0) {} + + Mutex mutex; + int counter; +}; + +// This thread function uses Mutex::lock/unlock to synchronize a counter +// increment operation. +static void* threadFunction(void* param) { + ThreadParams* p = static_cast<ThreadParams*>(param); + + p->mutex.lock(); + p->counter++; + p->mutex.unlock(); + return NULL; +} + +TEST(Mutex, Synchronization) { + const size_t kNumThreads = 2000; + TestThread* threads[kNumThreads]; + ThreadParams p; + + // Create and launch all threads. + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n] = new TestThread(threadFunction, &p); + } + + // Wait until their completion. + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n]->join(); + delete threads[n]; + } + + EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); +} + +// This thread function uses a Mutex::AutoLock to protect the counter. +static void* threadAutoLockFunction(void* param) { + ThreadParams* p = static_cast<ThreadParams*>(param); + + Mutex::AutoLock lock(p->mutex); + p->counter++; + return NULL; +} + +TEST(Mutex, AutoLockSynchronization) { + const size_t kNumThreads = 2000; + TestThread* threads[kNumThreads]; + ThreadParams p; + + // Create and launch all threads. + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n] = new TestThread(threadAutoLockFunction, &p); + } + + // Wait until their completion. + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n]->join(); + delete threads[n]; + } + + EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp new file mode 100644 index 0000000..c8ec3a6 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector.cpp @@ -0,0 +1,150 @@ +// Copyright (C) 2014 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 "emugl/common/pod_vector.h" + +#include <stdlib.h> +#include <string.h> + +#define USE_MALLOC_USABLE_SIZE 0 + +namespace emugl { + +static inline void swapPointers(char** p1, char** p2) { + char* tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +PodVectorBase::PodVectorBase(const PodVectorBase& other) { + initFrom(other.begin(), other.byteSize()); +} + +PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) { + initFrom(other.begin(), other.byteSize()); + return *this; +} + +PodVectorBase::~PodVectorBase() { + if (mBegin) { + // Sanity. + ::memset(mBegin, 0xee, byteSize()); + ::free(mBegin); + mBegin = NULL; + mEnd = NULL; + mLimit = NULL; + } +} + +void PodVectorBase::initFrom(const void* from, size_t fromLen) { + if (!fromLen || !from) { + mBegin = NULL; + mEnd = NULL; + mLimit = NULL; + } else { + mBegin = static_cast<char*>(::malloc(fromLen)); + mEnd = mLimit = mBegin + fromLen; + ::memcpy(mBegin, from, fromLen); + } +} + +void PodVectorBase::assignFrom(const PodVectorBase& other) { + resize(other.byteSize(), 1U); + ::memmove(begin(), other.begin(), byteSize()); +} + +void PodVectorBase::resize(size_t newSize, size_t itemSize) { + const size_t kMaxSize = maxItemCapacity(itemSize); + size_t oldCapacity = itemCapacity(itemSize); + const size_t kMinCapacity = 256 / itemSize; + + if (newSize < oldCapacity) { + // Only shrink if the new size is really small. + if (newSize < oldCapacity / 2 && oldCapacity > kMinCapacity) { + reserve(newSize, itemSize); + } + } else if (newSize > oldCapacity) { + size_t newCapacity = oldCapacity; + while (newCapacity < newSize) { + size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8; + if (newCapacity2 < newCapacity || newCapacity > kMaxSize) { + newCapacity = kMaxSize; + } else { + newCapacity = newCapacity2; + } + } + reserve(newCapacity, itemSize); + } + mEnd = mBegin + newSize * itemSize; +} + +void PodVectorBase::reserve(size_t newSize, size_t itemSize) { + if (newSize == 0) { + ::free(mBegin); + mBegin = NULL; + mEnd = NULL; + mLimit = NULL; + return; + } + + size_t oldByteSize = byteSize(); + size_t newByteCapacity = newSize * itemSize; + char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity)); + mBegin = newBegin; + mEnd = newBegin + oldByteSize; +#if USE_MALLOC_USABLE_SIZE + size_t usableSize = malloc_usable_size(mBegin); + if (usableSize > newByteCapacity) { + newByteCapacity = usableSize - (usableSize % itemSize); + } +#endif + mLimit = newBegin + newByteCapacity; + // Sanity. + if (newByteCapacity > oldByteSize) { + ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize); + } +} + +void PodVectorBase::removeAt(size_t itemPos, size_t itemSize) { + size_t count = itemCount(itemSize); + if (itemPos < count) { + size_t pos = itemPos * itemSize; + ::memmove(mBegin + pos, + mBegin + pos + itemSize, + byteSize() - pos - itemSize); + resize(count - 1U, itemSize); + } +} + +void* PodVectorBase::insertAt(size_t itemPos, size_t itemSize) { + size_t count = this->itemCount(itemSize); + resize(count + 1, itemSize); + size_t pos = itemPos * itemSize; + if (itemPos < count) { + ::memmove(mBegin + pos + itemSize, + mBegin + pos, + count * itemSize - pos); + // Sanity to avoid copying pointers and other bad stuff. + ::memset(mBegin + pos, 0, itemSize); + } + return mBegin + pos; +} + +void PodVectorBase::swapAll(PodVectorBase* other) { + swapPointers(&mBegin, &other->mBegin); + swapPointers(&mEnd, &other->mEnd); + swapPointers(&mLimit, &other->mLimit); +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/pod_vector.h b/emulator/opengl/shared/emugl/common/pod_vector.h new file mode 100644 index 0000000..c4e184b --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector.h @@ -0,0 +1,265 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_POD_VECTOR_H +#define EMUGL_COMMON_POD_VECTOR_H + + +#include <stddef.h> + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS 1 +#endif +#include <stdint.h> + +#ifndef SIZE_MAX +#error "You must define __STDC_LIMIT_MACROS before including <stddint.h>" +#endif + +namespace emugl { + +// A PodVector is a templated vector-like type that is used to store +// POD-struct compatible items only. This allows the implementation to +// use ::memmove() to move items, and also malloc_usable_size() to +// determine the best capacity. +// +// std::vector<> is capable of doing this in theory, using horrible +// templating tricks that make error messages very difficult to +// understand. +// +// Note that a PodVector can be used to store items that contain pointers, +// as long as these do not point to items in the same container. +// +// The PodVector provides methods that also follow the std::vector<> +// conventions, i.e. push_back() is an alias for append(). +// + +// NOTE: This is a re-implementation of +// external/qemu/android/base/containers/PodVector.h for emugl. + +// PodVectorBase is a base, non-templated, implementation class that all +// PodVector instances derive from. This is used to reduce template +// specialization. Do not use directly, i..e it's an implementation detail. +class PodVectorBase { +protected: + PodVectorBase() : mBegin(NULL), mEnd(NULL), mLimit(NULL) {} + explicit PodVectorBase(const PodVectorBase& other); + PodVectorBase& operator=(const PodVectorBase& other); + ~PodVectorBase(); + + bool empty() const { return mEnd == mBegin; } + + size_t byteSize() const { return mEnd - mBegin; } + + size_t byteCapacity() const { return mLimit - mBegin; } + + void* begin() { return mBegin; } + const void* begin() const { return mBegin; } + void* end() { return mEnd; } + const void* end() const { return mEnd; } + + void* itemAt(size_t pos, size_t itemSize) { + return mBegin + pos * itemSize; + } + + const void* itemAt(size_t pos, size_t itemSize) const { + return mBegin + pos * itemSize; + } + + void assignFrom(const PodVectorBase& other); + + inline size_t itemCount(size_t itemSize) const { + return byteSize() / itemSize; + } + + inline size_t itemCapacity(size_t itemSize) const { + return byteCapacity() / itemSize; + } + + inline size_t maxItemCapacity(size_t itemSize) const { + return SIZE_MAX / itemSize; + } + + void resize(size_t newSize, size_t itemSize); + void reserve(size_t newSize, size_t itemSize); + + void removeAt(size_t index, size_t itemSize); + void* insertAt(size_t index, size_t itemSize); + void swapAll(PodVectorBase* other); + + char* mBegin; + char* mEnd; + char* mLimit; + +private: + void initFrom(const void* from, size_t fromLen); +}; + + +// A PodVector<T> holds a vector (dynamically resizable array) or items +// that must be POD-struct compatible (i.e. they cannot have constructors, +// destructors, or virtual members). This allows the implementation to be +// small, fast and efficient, memory-wise. +// +// If you want to implement a vector of C++ objects, consider using +// std::vector<> instead, but keep in mind that this implies a non-trivial +// cost when appending, inserting, removing items in the collection. +// +template <typename T> +class PodVector : public PodVectorBase { +public: + // Default constructor for an empty PodVector<T> + PodVector() : PodVectorBase() {} + + // Copy constructor. This copies all items from |other| into + // the new instance with ::memmove(). + PodVector(const PodVector& other) : PodVectorBase(other) {} + + // Assignment operator. + PodVector& operator=(const PodVector& other) { + this->assignFrom(other); + return *this; + } + + // Destructor, this simply releases the internal storage block that + // holds all the items, but doesn't touch them otherwise. + ~PodVector() {} + + // Return true iff the PodVector<T> instance is empty, i.e. does not + // have any items. + bool empty() const { return PodVectorBase::empty(); } + + // Return the number of items in the current PodVector<T> instance. + size_t size() const { return PodVectorBase::itemCount(sizeof(T)); } + + // Return the current capacity in the current PodVector<T> instance. + // Do not use directly, except if you know what you're doing. Try to + // use resize() or reserve() instead. + size_t capacity() const { + return PodVectorBase::itemCapacity(sizeof(T)); + } + + // Return the maximum capacity of any PodVector<T> instance. + static inline size_t maxCapacity() { return SIZE_MAX / sizeof(T); } + + // Resize the vector to ensure it can hold |newSize| + // items. This may or may not call reserve() under the hood. + // It's a fatal error to try to resize above maxCapacity(). + void resize(size_t newSize) { + PodVectorBase::resize(newSize, sizeof(T)); + } + + // Resize the vector's storage array to ensure that it can hold at + // least |newSize| items. It's a fatal error to try to resize above + // maxCapacity(). + void reserve(size_t newSize) { + PodVectorBase::reserve(newSize, sizeof(T)); + } + + // Return a pointer to the first item in the vector. This is only + // valid until the next call to any function that changes the size + // or capacity of the vector. Can be NULL if the vector is empty. + T* begin() { + return reinterpret_cast<T*>(PodVectorBase::begin()); + } + + // Return a constant pointer to the first item in the vector. This is + // only valid until the next call to any function that changes the + // size of capacity of the vector. + const T* begin() const { + return reinterpret_cast<T*>(PodVectorBase::begin()); + } + + // Return a pointer past the last item in the vector. I.e. if the + // result is not NULL, then |result - 1| points to the last item. + // Can be NULL if the vector is empty. + T* end() { + return reinterpret_cast<T*>(PodVectorBase::end()); + } + + // Return a constant pointer past the last item in the vector. I.e. if + // the result is not NULL, then |result - 1| points to the last item. + // Can be NULL if the vector is empty. + const T* end() const { + return reinterpret_cast<T*>(PodVectorBase::end()); + } + + // Returns a reference to the item a position |index| in the vector. + // It may be a fatal error to access an out-of-bounds position. + T& operator[](size_t index) { + return *reinterpret_cast<T*>( + PodVectorBase::itemAt(index, sizeof(T))); + } + + const T& operator[](size_t index) const { + return *reinterpret_cast<const T*>( + PodVectorBase::itemAt(index, sizeof(T))); + } + + // Increase the vector's size by 1, then move all items past a given + // position to the right. Return the position of the insertion point + // to let the caller copy the content it desires there. It's preferrable + // to use insert() directly, which will do the item copy for you. + T* emplace(size_t index) { + return reinterpret_cast<T*>( + PodVectorBase::insertAt(index, sizeof(T))); + } + + // Insert an item at a given position. |index| is the insertion position + // which must be between 0 and size() included, or a fatal error may + // occur. |item| is a reference to an item to copy into the array, + // byte-by-byte. + void insert(size_t index, const T& item) { + *(this->emplace(index)) = item; + } + + // Prepend an item at the start of a vector. This moves all vector items + // to the right, and is thus costly. |item| is a reference to an item + // to copy to the start of the vector. + void prepend(const T& item) { + *(this->emplace(0U)) = item; + } + + // Append an item at the end of a vector. Specialized version of insert() + // which always uses size() as the insertion position. + void append(const T& item) { + *(this->emplace(this->size())) = item; + } + + // Remove the item at a given position. |index| is the position of the + // item to delete. It must be between 0 and size(), included, or + // a fatal error may occur. Deleting the item at position size() + // doesn't do anything. + void remove(size_t index) { + PodVectorBase::removeAt(index, sizeof(T)); + } + + void swap(PodVector* other) { + PodVectorBase::swapAll(other); + } + + // Compatibility methods for std::vector<> + void push_back(const T& item) { append(item); } + void pop() { remove(0U); } + + typedef T* iterator; + typedef const T* const_iterator; +}; + +} // namespace emugl + +#endif // EMUGL_COMMON_POD_VECTOR_H diff --git a/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp new file mode 100644 index 0000000..9ce509a --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp @@ -0,0 +1,127 @@ +// Copyright (C) 2014 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 "emugl/common/pod_vector.h" + +#include <gtest/gtest.h> + +namespace emugl { + +static int hashIndex(size_t n) { + return static_cast<int>(((n >> 14) * 13773) + (n * 51)); +} + +TEST(PodVector, Empty) { + PodVector<int> v; + EXPECT_TRUE(v.empty()); + EXPECT_EQ(0U, v.size()); +} + +TEST(PodVector, AppendOneItem) { + PodVector<int> v; + v.append(10234); + EXPECT_FALSE(v.empty()); + EXPECT_EQ(1U, v.size()); + EXPECT_EQ(10234, v[0]); +} + +TEST(PodVector, AppendLotsOfItems) { + PodVector<int> v; + const size_t kMaxCount = 10000; + for (size_t n = 0; n < kMaxCount; ++n) { + v.append(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v.size()); + for (size_t n = 0; n < kMaxCount; ++n) { + EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; + } +} + +TEST(PodVector, RemoveFrontItems) { + PodVector<int> v; + const size_t kMaxCount = 100; + for (size_t n = 0; n < kMaxCount; ++n) { + v.append(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v.size()); + for (size_t n = 0; n < kMaxCount; ++n) { + EXPECT_EQ(hashIndex(n), v[0]) << "At index " << n; + v.remove(0U); + EXPECT_EQ(kMaxCount - n - 1U, v.size()) << "At index " << n; + } +} + +TEST(PodVector, PrependItems) { + PodVector<int> v; + const size_t kMaxCount = 100; + for (size_t n = 0; n < kMaxCount; ++n) { + v.prepend(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v.size()); + for (size_t n = 0; n < kMaxCount; ++n) { + EXPECT_EQ(hashIndex(kMaxCount - n - 1), v[n]) << "At index " << n; + } +} + +TEST(PodVector, ResizeExpands) { + PodVector<int> v; + const size_t kMaxCount = 100; + const size_t kMaxCount2 = 10000; + for (size_t n = 0; n < kMaxCount; ++n) { + v.append(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v.size()); + v.resize(kMaxCount2); + EXPECT_EQ(kMaxCount2, v.size()); + for (size_t n = 0; n < kMaxCount; ++n) { + EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; + } +} + +TEST(PodVector, ResizeTruncates) { + PodVector<int> v; + const size_t kMaxCount = 10000; + const size_t kMaxCount2 = 10; + for (size_t n = 0; n < kMaxCount; ++n) { + v.append(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v.size()); + v.resize(kMaxCount2); + EXPECT_EQ(kMaxCount2, v.size()); + for (size_t n = 0; n < kMaxCount2; ++n) { + EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n; + } +} + + +TEST(PodVector, AssignmentOperator) { + PodVector<int> v1; + const size_t kMaxCount = 10000; + for (size_t n = 0; n < kMaxCount; ++n) { + v1.append(hashIndex(n)); + } + EXPECT_EQ(kMaxCount, v1.size()); + + PodVector<int> v2; + v2 = v1; + + v1.reserve(0); + + EXPECT_EQ(kMaxCount, v2.size()); + for (size_t n = 0; n < kMaxCount; ++n) { + EXPECT_EQ(hashIndex(n), v2[n]) << "At index " << n; + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h new file mode 100644 index 0000000..3d263e9 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h @@ -0,0 +1,27 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_SCOPED_POINTER_VECTOR_H +#define EMUGL_COMMON_SCOPED_POINTER_VECTOR_H + +namespace emugl { + +template <class T> +class ScopedPointerVector { + ScopedPointerVector +}; + +} // namespace emugl + +#endif // EMUGL_COMMON_SCOPED_POINTER_VECTOR_H diff --git a/emulator/opengl/shared/emugl/common/smart_ptr.cpp b/emulator/opengl/shared/emugl/common/smart_ptr.cpp new file mode 100644 index 0000000..703487d --- /dev/null +++ b/emulator/opengl/shared/emugl/common/smart_ptr.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2014 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 "emugl/common/smart_ptr.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +namespace emugl { + +// Thread-safe atomic reference-counting type. +class RefCount { +public: + RefCount() : mCount(1) {} + ~RefCount() {} + + // Technically not thread-safe, use only for testing. + int count() const { return (int)mCount; } + + void increment() { +#ifdef _WIN32 + InterlockedIncrement(&mCount); +#else + __sync_fetch_and_add(&mCount, 1); +#endif + } + + bool decrement() { +#ifdef _WIN32 + return InterlockedDecrement(&mCount) == 0; +#else + return __sync_add_and_fetch(&mCount, -1) == 0; +#endif + } + +private: +#ifdef _WIN32 + LONG mCount; +#else + int mCount; +#endif +}; + + +// SmartPtrBase implementation. + +SmartPtrBase::SmartPtrBase(void* ptr) : mPtr(ptr), mRefCount(NULL) { + if (mPtr) + mRefCount = new RefCount(); +} + + +SmartPtrBase::SmartPtrBase(const SmartPtrBase& other) + : mPtr(other.mPtr), mRefCount(other.mRefCount) { + if (mRefCount) + mRefCount->increment(); +} + + +int SmartPtrBase::getRefCount() const { + return mRefCount ? mRefCount->count() : 0; +} + + +void SmartPtrBase::addRef() { + if (mRefCount) + mRefCount->increment(); +} + + +void* SmartPtrBase::copyFrom(const SmartPtrBase& other) { + void* old_ptr = release(); + + mPtr = other.mPtr; + mRefCount = other.mRefCount; + if (mRefCount) + mRefCount->increment(); + + return old_ptr; +} + + +void* SmartPtrBase::release() { + void* old_ptr = mPtr; + RefCount* old_refcount = mRefCount; + + if (old_refcount) { + mPtr = NULL; + mRefCount = NULL; + + if (old_refcount->decrement()) { + delete old_refcount; + return old_ptr; + } + } + + return NULL; +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/smart_ptr.h b/emulator/opengl/shared/emugl/common/smart_ptr.h new file mode 100644 index 0000000..73efdd6 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/smart_ptr.h @@ -0,0 +1,150 @@ +// Copyright (C) 2014 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 EMUGL_SMART_PTR_H +#define EMUGL_SMART_PTR_H + +#include <stddef.h> + +namespace emugl { + +// Hidden atomic ref-counting implementation. +class RefCount; + +// Base class for all templated SmartPtr<> instances. Reduces +// template expansion and code. Consider this to be an implementation +// detail of SmartPtr<>, so don't rely on anything here. +class SmartPtrBase { +public: + // Defrault constructor. + SmartPtrBase() : mPtr(NULL), mRefCount(NULL) {} + + // Normal constructor. This takes ownership of |ptr|, though only + // template instances are capable of destroying the object. + explicit SmartPtrBase(void* ptr); + + // Copy-constructor, this increments the reference count. + SmartPtrBase(const SmartPtrBase& other); + + // Assignment operator, also increments the reference count. + SmartPtrBase& operator=(const SmartPtrBase& other); + + // Nothing happens in this destructor, the real work must be performed + // in subclasses. + ~SmartPtrBase() {} + + + // Used to enable 'if (smart_ptr) { ... }' properly. + operator void*() const { + return mPtr; + } + + // Return internal reference count value, only use for unit testing. + int getRefCount() const; + +protected: + // Used internally to increment the reference count. + void addRef(); + + // Copy the |other| into this instance, returns the old pointer value + // if it needs to be destroyed by the caller, or NULL otherwise. + void* copyFrom(const SmartPtrBase& other); + + // Used internally to decrement the reference count, if it reaches 0, + // returns the pointer to be destroyed, NULL otherwise. + void* release(); + + void* mPtr; + RefCount* mRefCount; +}; + + +// The real template class to be used for smart pointers. +// Typical uses: +// +// SmartPtr<Foo> ptr(new Foo()); // takes ownership. +// SmartPtr<Foo> ptr2; // empty pointer. +// ptr2 = ptr; // copies pointer + increment reference count. +// Foo* obj = ptr.Ptr(); // access pointed object. +// ptr->DoStuff(); // operate directly on pointed object. +// (*ptr)->DoStuff(); // same here. +// +// On scope exit, the internal reference count is decremented and the +// object is deleted automatically when it reaches 0, indicating that +// there are no more owners. +// +// IMPORTANT: You need to be sure that only one 'chain' of smart pointers +// own a given object. I.e. the following is incorrect: +// +// Foo* foo = new Foo(); // create new instance. +// SmartPtr<Foo> ptr(foo); // |ptr| takes ownership of |foo|. +// SmartPtr<Foo> ptr2(foo); // |ptr2| takes also ownership of |foo|. +// +// The problem is that |ptr| and |ptr2| don't know anything about each +// other, and will not share the same reference count. Once a smart pointer +// owns an object, only use other smart pointers that are copy-constructed +// or assigned with the initial one to keep everything consistent. +template <class T> +class SmartPtr : public emugl::SmartPtrBase { +public: + // Default constructor. The instance holds a NULL pointer. + SmartPtr() : SmartPtrBase() {} + + // Regular constructor, takes ownership of |ptr|. + explicit SmartPtr(T* ptr) : SmartPtrBase(ptr) {} + + // Copy-constructor, |this| and |other| will share the same internal + // reference count, which is incremented by 1. + SmartPtr(const SmartPtr& other) + : SmartPtrBase(reinterpret_cast<const SmartPtrBase&>(other)) {} + + // Assignment operator, same semantics as copy-constructor. + SmartPtr& operator=(const SmartPtr& other) { + void* old_ptr = copyFrom(static_cast<const SmartPtrBase&>(other)); + if (old_ptr) + delete reinterpret_cast<T*>(old_ptr); + return *this; + } + + // Destructor, decrements reference count and destroys the object + // if it reaches 0 (indicating this was the last owning smart pointer). + ~SmartPtr() { + void* ptr = release(); + if (ptr) + delete reinterpret_cast<T*>(ptr); + } + + // Return owned object instance, or NULL. + T* Ptr() const { + return reinterpret_cast<T*>(mPtr); + } + + // Return owned object instance, or NULL + const T* constPtr() const { + return reinterpret_cast<const T*>(mPtr); + } + + // Operate directly on owned object. + T* operator->() const { + return Ptr(); + } + + // Return reference to owned object. + T& operator*() const { + return *Ptr(); + } +}; + +} // namespace emugl + +#endif // EMUGL_SMART_PTR_H diff --git a/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp b/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp new file mode 100644 index 0000000..db9e5f2 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/smart_ptr_unittest.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2014 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 "emugl/common/smart_ptr.h" + +#include <gtest/gtest.h> + +namespace emugl { + +// This Test sub-class is used to track allocations and deallocations of +// the MyTestClass instances that are created through newInstance(). +// See below for typical usage. +class SmartPtrTest : public testing::Test { +public: + SmartPtrTest() : mNewCount(0), mDeleteCount(0), mDoCount(0) {} + + ~SmartPtrTest() { + mNewCount = 0; + mDoCount = 0; + mDeleteCount = 0; + } + + class MyClass; + + MyClass* newInstance() { + return new MyClass(this); + } + + class MyClass { + public: + MyClass(SmartPtrTest* test) : mTest(test) { + mTest->mNewCount++; + } + + void doStuff() { + mTest->mDoCount++; + } + + ~MyClass() { + mTest->mDeleteCount++; + } + private: + SmartPtrTest* mTest; + }; + + int mNewCount; + int mDeleteCount; + int mDoCount; +}; + + +TEST_F(SmartPtrTest, Empty) { + SmartPtr<MyClass> ptr; + EXPECT_FALSE(ptr.Ptr()); + + EXPECT_EQ(0, mNewCount); + EXPECT_EQ(0, mDeleteCount); + EXPECT_EQ(0, mDoCount); +} + + +TEST_F(SmartPtrTest, SingleRef) { + MyClass* obj = newInstance(); + EXPECT_EQ(1, mNewCount); + + { + SmartPtr<MyClass> ptr(obj); + EXPECT_EQ(obj, ptr.Ptr()); + + EXPECT_EQ(1, mNewCount); + EXPECT_EQ(0, mDeleteCount); + EXPECT_EQ(0, mDoCount); + } + // Check that the object was deleted. + EXPECT_EQ(1, mDeleteCount); +} + + +TEST_F(SmartPtrTest, CopyConstructor) { + MyClass* obj = newInstance(); + EXPECT_EQ(1, mNewCount); + + { + SmartPtr<MyClass> ptr1(obj); + { + SmartPtr<MyClass> ptr2(ptr1); + EXPECT_EQ(2, ptr1.getRefCount()); + EXPECT_EQ(2, ptr2.getRefCount()); + EXPECT_EQ(1, mNewCount); + EXPECT_EQ(0, mDeleteCount); + EXPECT_EQ(0, mDoCount); + } + EXPECT_EQ(1, mNewCount); + EXPECT_EQ(0, mDeleteCount); + EXPECT_EQ(0, mDoCount); + } + EXPECT_EQ(1, mNewCount); + EXPECT_EQ(1, mDeleteCount); + EXPECT_EQ(0, mDoCount); +} + + +TEST_F(SmartPtrTest, AssignmentOperator) { + SmartPtr<MyClass> ptr1(newInstance()); + SmartPtr<MyClass> ptr2(newInstance()); + EXPECT_EQ(2, mNewCount); + EXPECT_EQ(0, mDeleteCount); + EXPECT_EQ(0, mDoCount); + + ptr2 = ptr1; + EXPECT_EQ(2, mNewCount); + EXPECT_EQ(1, mDeleteCount); + + EXPECT_EQ(ptr1.Ptr(), ptr2.Ptr()); + EXPECT_EQ(2, ptr1.getRefCount()); + EXPECT_EQ(2, ptr2.getRefCount()); +} + + +TEST_F(SmartPtrTest, ArrowOperator) { + SmartPtr<MyClass> ptr(newInstance()); + ptr->doStuff(); + EXPECT_EQ(1, mDoCount); + + (*ptr).doStuff(); + EXPECT_EQ(2, mDoCount); +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/sockets.cpp b/emulator/opengl/shared/emugl/common/sockets.cpp new file mode 100644 index 0000000..2a13d72 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/sockets.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2014 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 "emugl/common/sockets.h" + +#include <errno.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/un.h> +#include <sys/stat.h> +#endif + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +namespace emugl { + +namespace { + +static void socketSetReuseAddress(int s) { +#ifdef _WIN32 + // The default behaviour on Windows is equivalent to SO_REUSEADDR + // so we don't need to set this option. Moreover, one should never + // set this option with WinSock because it's badly implemented and + // generates a huge security issue. See: + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx +#else + int val = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); +#endif +} + +// Helper union to store a socket address. +struct SockAddr { + socklen_t len; + union { + sockaddr generic; + sockaddr_in inet; +#ifndef _WIN32 + sockaddr_un local; +#endif + }; + + int getFamily() const { return generic.sa_family; } + + void initEmpty() { + ::memset(this, 0, sizeof(*this)); + this->len = static_cast<socklen_t>(sizeof(*this)); + } + + int initFromInet(uint32_t ip_address, int port) { + if (port < 0 || port >= 65536) + return -EINVAL; + + ::memset(this, 0, sizeof(*this)); + this->inet.sin_family = AF_INET; + this->inet.sin_port = htons(port); + this->inet.sin_addr.s_addr = htonl(ip_address); + this->len = sizeof(this->inet); + return 0; + } + + int initFromLocalhost(int port) { + return initFromInet(0x7f000001, port); + } + +#ifndef _WIN32 + // Initialize the SockAddr from a Unix path. Returns 0 on success, + // or -errno code on failure. + int initFromUnixPath(const char* path) { + if (!path || !path[0]) + return -EINVAL; + + size_t pathLen = ::strlen(path); + if (pathLen >= sizeof(local.sun_path)) + return -E2BIG; + + ::memset(this, 0, sizeof(*this)); + this->local.sun_family = AF_LOCAL; + ::memcpy(this->local.sun_path, path, pathLen + 1U); + this->len = pathLen + offsetof(sockaddr_un, sun_path); + return 0; + } +#endif +}; + +int socketBindInternal(const SockAddr* addr, int socketType) { + int s = ::socket(addr->getFamily(), socketType, 0); + if (s < 0) + return -errno; + + // Bind to the socket. + if (::bind(s, &addr->generic, addr->len) < 0 || + ::listen(s, 5) < 0) { + int ret = -errno; + ::close(s); + return ret; + } + + socketSetReuseAddress(s); + return s; +} + +int socketConnectInternal(const SockAddr* addr, int socketType) { + int s = ::socket(addr->getFamily(), socketType, 0); + if (s < 0) + return -errno; + + int ret; + do { + ret = ::connect(s, &addr->generic, addr->len); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + ret = -errno; + ::close(s); + return ret; + } + + return s; +} + +} // namespace + +void socketTcpDisableNagle(int s) { + // disable Nagle algorithm to improve bandwidth of small + // packets which are quite common in our implementation. +#ifdef _WIN32 + DWORD flag; +#else + int flag; +#endif + flag = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, + (const char*)&flag, sizeof(flag)); +} + +int socketGetPort(int s) { + SockAddr addr; + addr.initEmpty(); + if (getsockname(s, &addr.generic, &addr.len) < 0) { + return -errno; + } + switch (addr.generic.sa_family) { + case AF_INET: + return ntohs(addr.inet.sin_port); + default: + ; + } + return -EINVAL; +} + +#ifndef _WIN32 +int socketLocalServer(const char* path, int socketType) { + SockAddr addr; + int ret = addr.initFromUnixPath(path); + if (ret < 0) { + return ret; + } + return socketBindInternal(&addr, socketType); +} + +int socketLocalClient(const char* path, int socketType) { + SockAddr addr; + int ret = addr.initFromUnixPath(path); + if (ret < 0) { + return ret; + } + return socketConnectInternal(&addr, socketType); +} +#endif // !_WIN32 + +int socketTcpLoopbackServer(int port, int socketType) { + SockAddr addr; + int ret = addr.initFromLocalhost(port); + if (ret < 0) { + return ret; + } + return socketBindInternal(&addr, socketType); +} + +int socketTcpLoopbackClient(int port, int socketType) { + SockAddr addr; + int ret = addr.initFromLocalhost(port); + if (ret < 0) { + return ret; + } + return socketConnectInternal(&addr, socketType); +} + +int socketTcpClient(const char* hostname, int port, int socketType) { + // TODO(digit): Implement this. + return -ENOSYS; +} + +int socketAccept(int serverSocket) { + int ret; + do { + ret = ::accept(serverSocket, NULL, NULL); + } while (ret < 0 && errno == EINTR); + return ret; +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/sockets.h b/emulator/opengl/shared/emugl/common/sockets.h new file mode 100644 index 0000000..11e7ac7 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/sockets.h @@ -0,0 +1,57 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_SOCKETS_H +#define EMUGL_COMMON_SOCKETS_H + +// A set of helper functions used to deal with sockets in a portable way. + +namespace emugl { + +// Disable Nagle's algorithm for socket descriptor |s|. This assumes +// that |s| is a TCP socket descriptor. +void socketTcpDisableNagle(int s); + +// Return the port associated with a given IP or IPv6 socket, +// or -errno code on failure. +int socketGetPort(int s); + +// Bind to a local/Unix path, and return its socket descriptor on success, +// or -errno code on failure. +int socketLocalServer(const char* path, int socketType); + +// Connect to a Unix local path, and return a new socket descriptor +// on success, or -errno code on failure. +int socketLocalClient(const char* path, int socketType); + +// Bind to a localhost TCP socket, and return its socket descriptor on +// success, or -errno code on failure. +int socketTcpLoopbackServer(int port, int socketType); + +// Connect to a localhost TCP port, and return a new socket descriptor on +// success, or -errno code on failure. +int socketTcpLoopbackClient(int port, int socketType); + +// Connect to a TCP host, and return a new socket descriptor on +// success, or -errno code on failure. +int socketTcpClient(const char* hostname, int port, int socketType); + +// Accept a new connection. |serverSocket| must be a bound server socket +// descriptor. Returns new socket descriptor on success, or -errno code +// on failure. +int socketAccept(int serverSocket); + +} // namespace emugl + +#endif // EMUGL_COMMON_SOCKETS_H diff --git a/emulator/opengl/shared/emugl/common/testing/test_thread.h b/emulator/opengl/shared/emugl/common/testing/test_thread.h new file mode 100644 index 0000000..2d758b3 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/testing/test_thread.h @@ -0,0 +1,78 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_TESTING_TEST_THREAD_H +#define EMUGL_COMMON_TESTING_TEST_THREAD_H + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#else +# include <pthread.h> +#endif + +namespace emugl { + +// Very basic platform thread wrapper that only uses a tiny stack. +// This shall only be used during unit testing, and allows test code +// to not depend on the implementation of emugl::Thread. +class TestThread { +public: + // Main thread function type. + typedef void* (ThreadFunction)(void* param); + + // Constructor actually launches a new platform thread. + TestThread(ThreadFunction* func, void* funcParam) { +#ifdef _WIN32 + mThread = CreateThread(NULL, + 16384, + (DWORD WINAPI (*)(void*))func, + funcParam, + NULL, + NULL); +#else + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 16384); + pthread_create(&mThread, &attr, func, funcParam); + pthread_attr_destroy(&attr); +#endif + } + + ~TestThread() { +#ifdef _WIN32 + CloseHandle(mThread); +#endif + } + + void join() { +#ifdef _WIN32 + WaitForSingleObject(mThread, INFINITE); +#else + void* ret = NULL; + pthread_join(mThread, &ret); +#endif + } + +private: +#ifdef _WIN32 + HANDLE mThread; +#else + pthread_t mThread; +#endif +}; + +} // namespace emugl + +#endif // EMUGL_COMMON_TESTING_TEST_THREAD_H diff --git a/emulator/opengl/shared/emugl/common/thread_store.cpp b/emulator/opengl/shared/emugl/common/thread_store.cpp new file mode 100644 index 0000000..ea64c6f --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_store.cpp @@ -0,0 +1,242 @@ +// Copyright (C) 2014 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 "emugl/common/thread_store.h" + +#ifdef _WIN32 +#include "emugl/common/lazy_instance.h" +#endif + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// Set to 1 to print debug messages. +#define DEBUG_THREAD_STORE 0 + +#if DEBUG_THREAD_STORE +# define D(...) do { printf("%s:%d: ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); fflush(stdout); } while (0) +#else +# define D(...) ((void)0) +#endif + +namespace emugl { + +#ifdef _WIN32 + +namespace { + +// The ThreadStore implementation on Windows is very tricky, because +// TlsAlloc() doesn't allow one to provide a destructor function. As +// such threads are expected to destroy all TLS values explicitely. +// +// To solve this issue, this source file provides a static method called +// ThreadStore::OnThreadExit() that must be called when a thread exits, +// which will cleanup all values for the current thread. +// +// But this forces us to track thread-specific values ourselves. + +// Maximum amount of thread-specific slots supported by this implementation. +enum { + kMaxTlsSlots = 64 +}; + +// TlsSlotArray is a thread-specific array of values. Instances will +// be stored in a Win32 TLS value controlled by a single master TLS +// key. +// +typedef void* TlsSlotArray[kMaxTlsSlots]; + +// Global state shared by all threads +class GlobalState { +public: + GlobalState() { + D("Entering\n"); + mMasterTls = TlsAlloc(); + D("Master TLS = %d\n", (int)mMasterTls); + InitializeCriticalSection(&mSection); + mLastIndex = 0; + ::memset(mDestructors, 0, sizeof(mDestructors)); + D("Exiting\n"); + } + + // Register a new TLS key, or return -1 on error (too many keys). + // |destroy| is the destructor function for the key. + int registerKey(ThreadStore::Destructor* destroy) { + D("Entering destroy=%p\n", destroy); + int ret = -1; + EnterCriticalSection(&mSection); + if (mLastIndex < kMaxTlsSlots) { + ret = mLastIndex++; + mDestructors[ret] = destroy; + } + LeaveCriticalSection(&mSection); + D("Exiting newKey=%d\n", ret); + return ret; + } + + void unregisterKey(int key) { + D("key=%d\n", key); + if (key < 0 || key >= kMaxTlsSlots) { + D("Invalid key\n"); + return; + } + + // Note: keys are not reusable, but remove the destructor to avoid + // crashes in leaveCurrentThread() when it points to a function that + // is going to be unloaded from the process' address space. + EnterCriticalSection(&mSection); + mDestructors[key] = NULL; + LeaveCriticalSection(&mSection); + D("Exiting\n"); + } + + // Get the current thread-local value for a given |key|. + void* getValue(int key) const { + D("Entering key=%d\n", key); + if (key < 0 || key >= kMaxTlsSlots) { + D("Invalid key, result=NULL\n"); + return NULL; + } + + TlsSlotArray* array = getArray(); + void* ret = (*array)[key]; + D("Exiting keyValue=%p\n", ret); + return ret; + } + + // Set the current thread-local |value| for a given |key|. + void setValue(int key, void* value) { + D("Entering key=%d\n",key); + if (key < 0 || key >= kMaxTlsSlots) { + D("Invalid key, returning\n"); + return; + } + + TlsSlotArray* array = getArray(); + (*array)[key] = value; + D("Exiting\n"); + } + + // Call this when a thread exits to destroy all its thread-local values. + void leaveCurrentThread() { + D("Entering\n"); + TlsSlotArray* array = + reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls)); + if (!array) { + D("Exiting, no thread-local data in this thread\n"); + return; + } + + for (size_t n = 0; n < kMaxTlsSlots; ++n) { + void* value = array[n]; + if (value) { + (*array)[n] = NULL; + // NOTE: In theory, a destructor could reset the slot to + // a new value, and we would have to loop in this function + // in interesting ways. In practice, ignore the issue. + EnterCriticalSection(&mSection); + ThreadStore::Destructor* destroy = mDestructors[n]; + LeaveCriticalSection(&mSection); + if (destroy) { + D("Calling destructor %p for key=%d, with value=%p\n", + destroy, (int)n, value); + (*destroy)(value); + } + } + } + TlsSetValue(mMasterTls, NULL); + ::free(array); + D("Exiting\n"); + } + +private: + // Return the thread-local array of TLS slots for the current thread. + // Cannot return NULL. + TlsSlotArray* getArray() const { + D("Entering\n"); + TlsSlotArray* array = + reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls)); + if (!array) { + array = reinterpret_cast<TlsSlotArray*>( + ::calloc(sizeof(*array), 1)); + TlsSetValue(mMasterTls, array); + D("Allocated new array at %p\n", array); + } else { + D("Retrieved array at %p\n", array); + } + return array; + } + + DWORD mMasterTls; + CRITICAL_SECTION mSection; + int mLastIndex; + ThreadStore::Destructor* mDestructors[kMaxTlsSlots]; +}; + +LazyInstance<GlobalState> gGlobalState = LAZY_INSTANCE_INIT; + +} // namespace + +ThreadStore::ThreadStore(Destructor* destroy) { + D("Entering this=%p destroy=%p\n", this, destroy); + mKey = gGlobalState->registerKey(destroy); + D("Exiting this=%p key=%d\n", this, mKey); +} + +ThreadStore::~ThreadStore() { + D("Entering this=%p\n", this); + GlobalState* state = gGlobalState.ptr(); + state->unregisterKey(mKey); + D("Exiting this=%p\n", this); +} + +void* ThreadStore::get() const { + D("Entering this=%p\n", this); + void* ret = gGlobalState->getValue(mKey); + D("Exiting this=%p value=%p\n", this, ret); + return ret; +} + +void ThreadStore::set(void* value) { + D("Entering this=%p value=%p\n", this, value); + gGlobalState->setValue(mKey, value); + D("Exiting this=%p\n", this); +} + +// static +void ThreadStore::OnThreadExit() { + gGlobalState->leaveCurrentThread(); +} + +#else // !_WIN32 + +ThreadStore::ThreadStore(Destructor* destroy) { + int ret = pthread_key_create(&mKey, destroy); + if (ret != 0) { + fprintf(stderr, + "Could not create thread store key: %s\n", + strerror(ret)); + exit(1); + } +} + +ThreadStore::~ThreadStore() { + pthread_key_delete(mKey); +} + +#endif // !_WIN32 + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_store.h b/emulator/opengl/shared/emugl/common/thread_store.h new file mode 100644 index 0000000..5fd08bd --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_store.h @@ -0,0 +1,110 @@ +// Copyright (C) 2014 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 EMUGL_COMMON_THREAD_STORE_H +#define EMUGL_COMMON_THREAD_STORE_H + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#else +# include <pthread.h> +#endif + +namespace emugl { + +// A class to model storage of thread-specific values, that can be +// destroyed on thread exit. +// +// Note that on Windows, a thread must call OnThreadExit() explicitly +// here to ensure that the values are probably discarded. This is an +// unfortunate requirement of the Win32 API, which doesn't support +// destructors at all. +// +// There are various hacks on the web to try to achieve this automatically +// (e.g. [1]) but they rely on using the Microsoft build tools, +// which doesn't work for us. +// +// Note another important issue with ThreadStore instances: if you create +// one instance in a shared library, you need to make sure that it is +// always destroyed before the library is unloaded. Otherwise, future +// thread exit will likely crash, due to calling a destructor function +// that is no longer in the process' address space. +// +// Finally, destroying an instance does _not_ free the corresponding values, +// because doing so properly requires coordinating all participating threads, +// which is impossible to achieve in the most general case. Thus, consider +// that thread-local values are always leaked on library unload, or on +// program exit. +// +// [1] http://stackoverflow.com/questions/14538159/about-tls-callback-in-windows + +class ThreadStore { +public: + // Type of a function used to destroy a thread-specific value that + // was previously assigned by calling set(). + typedef void (Destructor)(void* value); + + // Initialize instance so that is hold keys that must be destroyed + // on thread exit by calling |destroy|. + explicit ThreadStore(Destructor* destroy); + + // NOTE: Destructor don't free the thread-local values, but are required + // to avoid crashes (see note above). + ~ThreadStore(); + + // Retrieve current thread-specific value from store. +#ifdef _WIN32 + void* get() const; +#else + inline void* get() const { + return pthread_getspecific(mKey); + } +#endif + + // Set the new thread-specific value. +#ifdef _WIN32 + void set(void* value); +#else + inline void set(void* value) { + pthread_setspecific(mKey, value); + } +#endif + +#ifdef _WIN32 + // Each thread should call this function on exit to ensure that + // all corresponding TLS values are properly freed. + static void OnThreadExit(); +#else + // Nothing to do on Posix. + static inline void OnThreadExit() {} +#endif + +private: + // Ensure you can't create an empty ThreadStore instance, or simply + // copy it in any way. + ThreadStore(); + ThreadStore(const ThreadStore&); + ThreadStore& operator=(const ThreadStore&); + +#ifdef _WIN32 + int mKey; +#else + pthread_key_t mKey; +#endif +}; + +} // namespace emugl + +#endif // EMUGL_COMMON_THREAD_STORE_H diff --git a/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp b/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp new file mode 100644 index 0000000..6b5dddb --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2014 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 "emugl/common/thread_store.h" + +#include "emugl/common/mutex.h" +#include "emugl/common/testing/test_thread.h" + +#include <gtest/gtest.h> + +namespace emugl { + +namespace { + +// Helper class used to count instance creation and destruction. +class StaticCounter { +public: + enum { + kMaxInstances = 1000, + }; + + StaticCounter() { + Mutex::AutoLock lock(mMutex); + if (mCreationCount < kMaxInstances) + mInstances[mCreationCount] = this; + mCreationCount++; + } + + ~StaticCounter() { + Mutex::AutoLock lock(mMutex); + mDestructionCount++; + } + + static void reset() { + Mutex::AutoLock lock(mMutex); + mCreationCount = 0; + mDestructionCount = 0; + } + + static size_t getCreationCount() { + Mutex::AutoLock lock(mMutex); + return mCreationCount; + } + + static size_t getDestructionCount() { + Mutex::AutoLock lock(mMutex); + return mDestructionCount; + } + + static void freeAll() { + for (size_t n = 0; n < kMaxInstances; ++n) + delete mInstances[n]; + } + +private: + static Mutex mMutex; + static size_t mCreationCount; + static size_t mDestructionCount; + static StaticCounter* mInstances[kMaxInstances]; +}; + +Mutex StaticCounter::mMutex; +size_t StaticCounter::mCreationCount = 0; +size_t StaticCounter::mDestructionCount = 0; +StaticCounter* StaticCounter::mInstances[kMaxInstances]; + +} // namespace + +// Just check that we can create a new ThreadStore with an empty +// destructor, and use it in the current thread. +TEST(ThreadStore, MainThreadWithoutDestructor) { + ThreadStore store(NULL); + static int x = 42; + store.set(&x); + EXPECT_EQ(&x, store.get()); +} + +// The following test checks that exiting a thread correctly deletes +// any thread-local value stored in it. +static void simplyDestroy(void* value) { + delete (StaticCounter*) value; +} + +static void* simpleThreadFunc(void* param) { + ThreadStore* store = static_cast<ThreadStore*>(param); + store->set(new StaticCounter()); + ThreadStore::OnThreadExit(); + return NULL; +} + +TEST(ThreadStore, ThreadsWithDestructor) { + ThreadStore store(simplyDestroy); + const size_t kNumThreads = 1000; + TestThread* threads[kNumThreads]; + StaticCounter::reset(); + + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n] = new TestThread(&simpleThreadFunc, &store); + } + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n]->join(); + } + + EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount()); + EXPECT_EQ(kNumThreads, StaticCounter::getDestructionCount()); + + for (size_t n = 0; n < kNumThreads; ++n) { + delete threads[n]; + } +} + +TEST(ThreadStore, ThreadsWithoutDestructor) { + ThreadStore store(NULL); + const size_t kNumThreads = 1000; + TestThread* threads[kNumThreads]; + StaticCounter::reset(); + + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n] = new TestThread(&simpleThreadFunc, &store); + } + for (size_t n = 0; n < kNumThreads; ++n) { + threads[n]->join(); + } + + EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount()); + EXPECT_EQ(0U, StaticCounter::getDestructionCount()); + + StaticCounter::freeAll(); + + for (size_t n = 0; n < kNumThreads; ++n) { + delete threads[n]; + } +} + +} // namespace emugl diff --git a/emulator/opengl/tests/emulator_test_renderer/Android.mk b/emulator/opengl/tests/emulator_test_renderer/Android.mk index 9c4cfdd..d585513 100644 --- a/emulator/opengl/tests/emulator_test_renderer/Android.mk +++ b/emulator/opengl/tests/emulator_test_renderer/Android.mk @@ -5,17 +5,8 @@ $(call emugl-import,libOpenglRender event_injector) LOCAL_SRC_FILES := main.cpp -PREBUILT := $(HOST_PREBUILT_TAG) -LOCAL_SDL_CONFIG ?= prebuilts/tools/$(PREBUILT)/sdl/bin/sdl-config -LOCAL_SDL_CFLAGS := $(shell $(LOCAL_SDL_CONFIG) --cflags) -LOCAL_SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(LOCAL_SDL_CONFIG) --static-libs)) - -LOCAL_CFLAGS += $(LOCAL_SDL_CFLAGS) -g -O0 -LOCAL_LDLIBS += $(LOCAL_SDL_LDLIBS) - -ifeq ($(HOST_OS),windows) -LOCAL_LDLIBS += -lws2_32 -endif +LOCAL_CFLAGS += $(EMUGL_SDL_CFLAGS) -g -O0 +LOCAL_LDLIBS += $(EMUGL_SDL_LDLIBS) LOCAL_STATIC_LIBRARIES += libSDL libSDLmain diff --git a/emulator/opengl/tests/event_injector/sockets.c b/emulator/opengl/tests/event_injector/sockets.c index a2cc334..33df32b 100644 --- a/emulator/opengl/tests/event_injector/sockets.c +++ b/emulator/opengl/tests/event_injector/sockets.c @@ -24,10 +24,6 @@ #include <stdlib.h> #include <string.h> #include <limits.h> -//#include "android/utils/path.h" -//#include "android/utils/debug.h" -//#include "android/utils/misc.h" -//#include "android/utils/system.h" #define D(...) ((void)0) diff --git a/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk b/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk index a66207e..1f25a33 100644 --- a/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk +++ b/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk @@ -3,28 +3,23 @@ LOCAL_PATH:= $(call my-dir) $(call emugl-begin-host-executable,triangleCM) $(call emugl-import,libEGL_translator libGLES_CM_translator) -PREBUILT := $(HOST_PREBUILT_TAG) -LOCAL_SDL_CONFIG ?= prebuilts/tools/$(PREBUILT)/sdl/bin/sdl-config -LOCAL_SDL_CFLAGS := $(shell $(LOCAL_SDL_CONFIG) --cflags) -LOCAL_SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(LOCAL_SDL_CONFIG) --static-libs)) - ifeq ($(HOST_OS),darwin) # SDK 10.6+ deprecates __dyld_func_lookup required by dlcompat_init_func # in SDL_dlcompat.o this module depends. Instruct linker to resolved it at runtime. OSX_VERSION_MAJOR := $(shell echo $(mac_sdk_version) | cut -d . -f 2) OSX_VERSION_MAJOR_GREATER_THAN_OR_EQUAL_TO_6 := $(shell [ $(OSX_VERSION_MAJOR) -ge 6 ] && echo true) ifeq ($(OSX_VERSION_MAJOR_GREATER_THAN_OR_EQUAL_TO_6),true) - LOCAL_SDL_LDLIBS += -Wl,-undefined,dynamic_lookup + LOCAL_LDLIBS += -Wl,-undefined,dynamic_lookup endif endif LOCAL_SRC_FILES:= \ triangleCM.cpp -LOCAL_CFLAGS += $(LOCAL_SDL_CFLAGS) -g -O0 -LOCAL_LDLIBS += $(LOCAL_SDL_LDLIBS) +LOCAL_CFLAGS += $(EMUGL_SDL_CFLAGS) -g -O0 +LOCAL_LDLIBS += $(EMUGL_SDL_LDLIBS) -lstdc++ -LOCAL_STATIC_LIBRARIES += libSDL libSDLmain +LOCAL_STATIC_LIBRARIES += $(EMUGL_SDL_STATIC_LIBRARIES) ifeq ($(HOST_OS),darwin) $(call emugl-import,libMac_view) diff --git a/emulator/opengl/tests/translator_tests/GLES_CM/triangleCM.cpp b/emulator/opengl/tests/translator_tests/GLES_CM/triangleCM.cpp index 7547cd0..0e86166 100644 --- a/emulator/opengl/tests/translator_tests/GLES_CM/triangleCM.cpp +++ b/emulator/opengl/tests/translator_tests/GLES_CM/triangleCM.cpp @@ -148,13 +148,10 @@ int main(int argc, char **argv) bool useCopy = false; bool useSubCopy = false; - int c; - extern char *optarg; - #ifdef _WIN32 HWND windowId = NULL; #elif __linux__ - Window windowId = NULL; + Window windowId = 0; #elif __APPLE__ void* windowId = NULL; #endif @@ -282,17 +279,17 @@ int main(int argc, char **argv) #define MIN_T 0 GLbyte byteVertices[] = { -1,-1,0, // Position - 255,0,0,255, // Color + (GLbyte)255,0,0,(GLbyte)255, // Color MIN_T, MIN_T, // texture 12, //point size 1,-1,0, - 0,255,0,255, + 0,(GLbyte)255,0,(GLbyte)255, MAX_T,MIN_T, 47, 0,1,0, - 0,0,255,255, + 0,0,(GLbyte)255,(GLbyte)255, MID_T, MAX_T, 14 }; diff --git a/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk index e72da96..10b3b0c 100644 --- a/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk +++ b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk @@ -3,18 +3,13 @@ LOCAL_PATH:= $(call my-dir) $(call emugl-begin-host-executable,triangleV2) $(call emugl-import,libEGL_translator libGLES_V2_translator) -PREBUILT := $(HOST_PREBUILT_TAG) -LOCAL_SDL_CONFIG ?= prebuilts/tools/$(PREBUILT)/sdl/bin/sdl-config -LOCAL_SDL_CFLAGS := $(shell $(LOCAL_SDL_CONFIG) --cflags) -LOCAL_SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(LOCAL_SDL_CONFIG) --static-libs)) - LOCAL_SRC_FILES:= \ triangleV2.cpp -LOCAL_CFLAGS += $(LOCAL_SDL_CFLAGS) -g -O0 -LOCAL_LDLIBS += $(LOCAL_SDL_LDLIBS) +LOCAL_CFLAGS += $(EMUGL_SDL_CFLAGS) -g -O0 +LOCAL_LDLIBS += $(EMUGL_SDL_LDLIBS) -lstdc++ -LOCAL_STATIC_LIBRARIES += libSDL libSDLmain +LOCAL_STATIC_LIBRARIES += $(EMUGL_SDL_STATIC_LIBRARIES) ifeq ($(HOST_OS),darwin) # SDK 10.6+ deprecates __dyld_func_lookup required by dlcompat_init_func @@ -28,4 +23,3 @@ ifeq ($(HOST_OS),darwin) endif $(call emugl-end-module) - diff --git a/emulator/opengl/tests/translator_tests/GLES_V2/triangleV2.cpp b/emulator/opengl/tests/translator_tests/GLES_V2/triangleV2.cpp index 59535c5..3a8ff0f 100644 --- a/emulator/opengl/tests/translator_tests/GLES_V2/triangleV2.cpp +++ b/emulator/opengl/tests/translator_tests/GLES_V2/triangleV2.cpp @@ -313,20 +313,6 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n int main(int argc, char **argv) #endif { - GLuint ui32Vbo = 0; // Vertex buffer object handle - GLuint ui32IndexVbo; - GLuint ui32Texture; - - int nframes = 100; - bool immidateMode = false; - bool useIndices = false; - bool useTexture = true; - bool useCompTexture = false; - bool useFixed = true; - bool usePoints = false; - bool useCopy = false; - bool useSubCopy = false; - #ifdef _WIN32 int argc; char **argv = parseCmdLine(lpCmdLine, &argc); @@ -372,7 +358,7 @@ int main(int argc, char **argv) #ifdef _WIN32 HWND windowId = NULL; #elif __linux__ - Window windowId = NULL; + Window windowId = 0; #elif __APPLE__ void* windowId = NULL; #endif diff --git a/emulator/opengl/tests/ut_renderer/Android.mk b/emulator/opengl/tests/ut_renderer/Android.mk index fe8e7ac..91608b2 100644 --- a/emulator/opengl/tests/ut_renderer/Android.mk +++ b/emulator/opengl/tests/ut_renderer/Android.mk @@ -3,7 +3,7 @@ LOCAL_PATH:=$(call my-dir) ifeq ($(HOST_OS), linux) $(call emugl-begin-host-executable,ut_renderer) -$(call emugl-import,libut_rendercontrol_dec libGLESv1_dec libGLESv2_dec libEGL_host_wrapper) +$(call emugl-import,libut_rendercontrol_dec libGLESv1_dec libGLESv2_dec libEGL_host_wrapper libOpenglRender) LOCAL_SRC_FILES := ut_renderer.cpp \ RenderingThread.cpp \ diff --git a/emulator/opengl/tests/ut_renderer/Renderer.cpp b/emulator/opengl/tests/ut_renderer/Renderer.cpp index 22afadb..1102014 100644 --- a/emulator/opengl/tests/ut_renderer/Renderer.cpp +++ b/emulator/opengl/tests/ut_renderer/Renderer.cpp @@ -56,7 +56,7 @@ Renderer::Renderer() int Renderer::createSurface(RenderingThread *thread, const ClientHandle & handle) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); assert(m_surfaces.find(handle) == m_surfaces.end()); if (handle.handle == 0) { @@ -75,7 +75,7 @@ int Renderer::createSurface(RenderingThread *thread, const ClientHandle & handle int Renderer::destroySurface(RenderingThread *thread, const ClientHandle &handle) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); SurfaceMap::iterator i = m_surfaces.find(handle); if (i == m_surfaces.end()) { @@ -90,7 +90,7 @@ int Renderer::destroySurface(RenderingThread *thread, const ClientHandle &handle int Renderer::createContext(RenderingThread *thread, const ClientHandle &handle, ClientHandle shareCtx, int version) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); assert(m_ctxs.find(handle) == m_ctxs.end()); RendererContext *shared = NULL; @@ -115,7 +115,7 @@ int Renderer::createContext(RenderingThread *thread, const ClientHandle &handle, int Renderer::destroyContext(RenderingThread *thread, const ClientHandle &handle) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); ContextMap::iterator i = m_ctxs.find(handle); if (i == m_ctxs.end()) { @@ -133,7 +133,7 @@ int Renderer::makeCurrent(RenderingThread *thread, const ClientHandle &readSurface, const ClientHandle & ctx) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); RendererContext *currentContext = thread->currentContext(); @@ -172,7 +172,7 @@ int Renderer::makeCurrent(RenderingThread *thread, int Renderer::swapBuffers(RenderingThread *thread, const ClientHandle &surface) { - android::Mutex::Autolock(this->m_mutex); + emugl::Mutex::AutoLock(this->m_mutex); SurfaceMap::iterator s = m_surfaces.find(surface); if (s == m_surfaces.end()) { diff --git a/emulator/opengl/tests/ut_renderer/Renderer.h b/emulator/opengl/tests/ut_renderer/Renderer.h index cdf10b6..81f4077 100644 --- a/emulator/opengl/tests/ut_renderer/Renderer.h +++ b/emulator/opengl/tests/ut_renderer/Renderer.h @@ -19,7 +19,7 @@ #include "RendererSurface.h" #include "RendererContext.h" #include "NativeWindowing.h" -#include <utils/threads.h> +#include "emugl/common/mutex.h" class RenderingThread; @@ -57,6 +57,6 @@ private: NativeWindowing *m_nw; EGLDisplay m_dpy; - android::Mutex m_mutex; // single global mutex for the renderer class; + emugl::Mutex m_mutex; // single global mutex for the renderer class; }; #endif |