diff options
| author | David 'Digit' Turner <digit@google.com> | 2014-03-11 19:58:51 +0000 |
|---|---|---|
| committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-03-11 19:58:51 +0000 |
| commit | 84b68033f6b92a3c35ac1d3ab7f8278c54744cff (patch) | |
| tree | ba6e795703570bd83fbfcdf92216359452ebb358 /emulator/opengl | |
| parent | 81431aae3aaf95209a606511b3a81f6aa06ffe9f (diff) | |
| parent | 56b89bc863d1a5da6234f05923f63b5466e1ce3f (diff) | |
| download | sdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.zip sdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.tar.gz sdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.tar.bz2 | |
Merge changes I205392bd,I84a058bb,I22c67f11,Id18319e8,I9836ed96, ... into idea133
* changes:
emulator/opengl: Allow standalone build.
emulator/opengl: Remove libcutils/libutils/liblog
emulator/opengl: Remove <utils/List.h> + <utils/String8.h>
emulator/opengl: Remove android::KeyedVector usage.
emulator/opengl: Remove android::Vector<> usage.
emulator/opengl: Remove <cutils/sockets.h>
Diffstat (limited to 'emulator/opengl')
40 files changed, 1945 insertions, 376 deletions
diff --git a/emulator/opengl/Android.mk b/emulator/opengl/Android.mk index 0f5b856..6cab042 100644 --- a/emulator/opengl/Android.mk +++ b/emulator/opengl/Android.mk @@ -24,6 +24,12 @@ 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 # See the definition of emugl-begin-module in common.mk diff --git a/emulator/opengl/common.mk b/emulator/opengl/common.mk index be5eaf5..d411899 100644 --- a/emulator/opengl/common.mk +++ b/emulator/opengl/common.mk @@ -28,6 +28,20 @@ emugl-begin-host-executable = $(call emugl-begin-module,$1,HOST_EXECUTABLE,HOST) _emugl_modules := _emugl_HOST_modules := +ifeq ($(BUILD_STANDALONE_EMULATOR),true) +define EMUGL_LOCAL_EXTRAS +LOCAL_CC := $$(call my-host-tool,CC) +LOCAL_CXX := $$(call my-host-tool,CXX) +LOCAL_LD := $$(call my-host-tool,LD) +LOCAL_AR := $$(call my-host-tool,AR) +LOCAL_CFLAGS := $$(call my-host-tool,CFLAGS) $$(LOCAL_CFLAGS) +LOCAL_LDFLAGS := $$(call my-host-tool,LDFLAGS) $$(LOCAL_LDFLAGS) +LOCAL_LDLIBS := $$(LOCAL_LDLIBS) $$(call my-host-tool,LDLIBS) +endef +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 +49,16 @@ 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)) \ $(call _emugl-init-module,$1,$2,$3) # 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))\ @@ -118,7 +134,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 +164,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/googletest.mk b/emulator/opengl/googletest.mk index 9719138..a49789a 100644 --- a/emulator/opengl/googletest.mk +++ b/emulator/opengl/googletest.mk @@ -5,26 +5,39 @@ # 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). -LOCAL_PATH := external/gtest -$(call emugl-begin-host-static-library,libemugl_gtest) -LOCAL_SRC_FILES := \ - src/gtest-all.cc \ - src/gtest_main.cc -LOCAL_CFLAGS += -O0 -LOCAL_CPP_EXTENSION := .cc -$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include) -$(call emugl-export,LDLIBS,-lpthread) -$(call emugl-end-module) +ifeq (true,$(BUILD_STANDALONE_EMULATOR)) +LOCAL_PATH := $(EMULATOR_GTEST_SOURCES_DIR) +else +LOCAL_PATH := $(EMUGL_PATH)/../../../external/gtest +endif -$(call emugl-begin-host-static-library,lib64emugl_gtest) -LOCAL_SRC_FILES := \ +common_SRC_FILES := \ src/gtest-all.cc \ src/gtest_main.cc -LOCAL_CFLAGS += -O0 -LOCAL_C_INCLUDES += $(LOCAL_PATH)/include + +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,CFLAGS,-m64) -$(call emugl-export,LDLIBS,-lpthread -m64) +$(call emugl-export,LDLIBS,$(common_LDLIBS)) $(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host-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..811a2bb 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-host-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/GLESv2_dec/Android.mk b/emulator/opengl/host/libs/GLESv2_dec/Android.mk index 7a034ec..03692ee 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-host-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/Translator/EGL/Android.mk b/emulator/opengl/host/libs/Translator/EGL/Android.mk index f1a6d3a..40f165a 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-host-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/GLES_CM/Android.mk b/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk index 9aa74a7..b126902 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-host-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_V2/Android.mk b/emulator/opengl/host/libs/Translator/GLES_V2/Android.mk index f4845f7..9175ab5 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-host-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/GLcommon/Android.mk b/emulator/opengl/host/libs/Translator/GLcommon/Android.mk index 2c16878..375da8b 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, libemugl_common libutils libcutils 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, lib64emugl_common lib64utils lib64cutils lib64log) - -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host-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/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/libOpenglRender/Android.mk b/emulator/opengl/host/libs/libOpenglRender/Android.mk index 8b8ba79..3cfbef0 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 += libemugl_common libutils libcutils 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-host-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 += lib64emugl_common lib64utils lib64cutils 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/renderControl_dec/Android.mk b/emulator/opengl/host/libs/renderControl_dec/Android.mk index 1063532..3bc5c3e 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-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) +endif
\ No newline at end of file diff --git a/emulator/opengl/host/tools/emugen/Android.mk b/emulator/opengl/host/tools/emugen/Android.mk index ad9ab06..ae1b3ac 100644 --- a/emulator/opengl/host/tools/emugen/Android.mk +++ b/emulator/opengl/host/tools/emugen/Android.mk @@ -1,15 +1,15 @@ -ifneq ($(HOST_OS),windows) - LOCAL_PATH:=$(call my-dir) $(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 \ + +LOCAL_HOST_BUILD := true $(call emugl-end-module) @@ -17,10 +17,3 @@ $(call emugl-end-module) # protocol encoders/ decoders. This variable is used by other emugl modules. EMUGL_EMUGEN := $(LOCAL_BUILT_MODULE) -else # windows build - -# on windows use the build host emugen executable -# (that will be the linux exeutable when using mingw build) -EMUGL_EMUGEN := $(BUILD_OUT_EXECUTABLES)/emugen - -endif diff --git a/emulator/opengl/host/tools/emugen/ApiGen.cpp b/emulator/opengl/host/tools/emugen/ApiGen.cpp index 6964862..2c331b9 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"); @@ -781,7 +781,7 @@ int ApiGen::genDecoderImpl(const std::string &filename) \t\tunsigned int packetLen = *(int *)(ptr + 4);\n\ \t\tif (len - pos < packetLen) return pos; \n\ \t\tswitch(opcode) {\n", - (uint) m_maxEntryPointsParams); + (unsigned) m_maxEntryPointsParams); for (size_t f = 0; f < n; f++) { enum Pass_t { PASS_TmpBuffAlloc = 0, PASS_MemAlloc, PASS_DebugPrint, PASS_FunctionCall, PASS_Epilog, PASS_LAST }; @@ -845,9 +845,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 +866,30 @@ 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()); } 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"; @@ -1036,7 +1036,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/getopt.c b/emulator/opengl/host/tools/emugen/getopt.c new file mode 100644 index 0000000..0ac02d8 --- /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; +const 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 = place; + } else if (argc > ++optind) { + optarg = 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..5ad039c --- /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 const 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..d9778ae 100644 --- a/emulator/opengl/host/tools/emugen/main.cpp +++ b/emulator/opengl/host/tools/emugen/main.cpp @@ -21,6 +21,10 @@ #include "ApiGen.h" #include "TypeFactory.h" +#ifdef _WIN32 +#include "getopt.h" +#endif + const std::string SPEC_EXTENSION = std::string(".in"); const std::string ATTRIB_EXTENSION = std::string(".attrib"); const std::string TYPES_EXTENTION = std::string(".types"); diff --git a/emulator/opengl/sdl.mk b/emulator/opengl/sdl.mk index 658e2d4..a85ed58 100644 --- a/emulator/opengl/sdl.mk +++ b/emulator/opengl/sdl.mk @@ -7,6 +7,7 @@ ifeq ($(BUILD_STANDALONE_EMULATOR),true) # 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 @@ -15,6 +16,7 @@ else # BUILD_STANDALONE_EMULATOR != true 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 diff --git a/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/emulator/opengl/shared/OpenglCodecCommon/Android.mk index 5deb1f7..b6a7e07 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-host-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 43577d4..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_ -#ifdef __ANDROID__ -# 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/GLSharedGroup.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp index a054562..db7f418 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) { emugl::Mutex::AutoLock _lock(m_lock); - return m_buffers.valueFor(bufferId); + return m_buffers.get(bufferId); } void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data) { emugl::Mutex::AutoLock _lock(m_lock); - m_buffers.add(bufferId, new BufferData(size, data)); + m_buffers.set(bufferId, new BufferData(size, data)); } void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data) { emugl::Mutex::AutoLock _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)); - } + m_buffers.set(bufferId, new BufferData(size, data)); } GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data) { emugl::Mutex::AutoLock _lock(m_lock); - BufferData * buf = m_buffers.valueFor(bufferId); + 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 @@ -278,32 +258,20 @@ GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsi void GLSharedGroup::deleteBufferData(GLuint bufferId) { emugl::Mutex::AutoLock _lock(m_lock); - ssize_t idx = m_buffers.indexOfKey(bufferId); - if (idx >= 0) { - delete m_buffers.valueAt(idx); - m_buffers.removeItemsAt(idx); - } + ssize_t idx = m_buffers.remove(bufferId); } void GLSharedGroup::addProgramData(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - { - m_programs.removeItem(program); - delete pData; - } - - m_programs.add(program,new ProgramData()); + m_programs.set(program, new ProgramData()); } void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - { + ProgramData *pData = m_programs.get(program); + if (pData) { pData->initProgramData(numIndexes); } } @@ -311,136 +279,135 @@ void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes) bool GLSharedGroup::isProgramInitialized(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) - { - return pData->isInitialized(); - } - return false; + ProgramData* pData = m_programs.get(program); + return pData && pData->isInitialized(); } void GLSharedGroup::deleteProgramData(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData *pData = m_programs.valueFor(program); - if (pData) - delete pData; - m_programs.removeItem(program); + m_programs.remove(program); } void GLSharedGroup::attachShader(GLuint program, GLuint shader) { emugl::Mutex::AutoLock _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); - } + ProgramData* programData = m_programs.get(program); + if (programData && programData->attachShader(shader)) { + refShaderDataLocked(shader); } } void GLSharedGroup::detachShader(GLuint program, GLuint shader) { emugl::Mutex::AutoLock _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); - } + 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) { emugl::Mutex::AutoLock _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; + 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) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - GLenum type=0; - if (pData) - { - type = pData->getTypeForLocation(location); - } - return type; + ProgramData* pData = m_programs.get(program); + return pData ? pData->getTypeForLocation(location) : 0; } bool GLSharedGroup::isProgram(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - return (pData!=NULL); + ProgramData* pData = m_programs.get(program); + return (pData != NULL); } void GLSharedGroup::setupLocationShiftWAR(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + 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) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex); - else return hostLoc; + ProgramData* pData = m_programs.get(program); + return pData ? pData->locationWARHostToApp(hostLoc, arrIndex) : hostLoc; } GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->locationWARAppToHost(appLoc); - else return appLoc; + ProgramData* pData = m_programs.get(program); + return pData ? pData->locationWARAppToHost(appLoc) : appLoc; } bool GLSharedGroup::needUniformLocationWAR(GLuint program) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); - if (pData) return pData->needUniformLocationWAR(); - return false; + 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 { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + 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) { emugl::Mutex::AutoLock _lock(m_lock); - ProgramData* pData = m_programs.valueFor(program); + ProgramData* pData = m_programs.get(program); return pData ? pData->setSamplerUniform(appLoc, val, target) : false; } @@ -448,44 +415,39 @@ bool GLSharedGroup::addShaderData(GLuint shader) { 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) { emugl::Mutex::AutoLock _lock(m_lock); - return m_shaders.valueFor(shader); + ShaderData* data = m_shaders.get(shader); + if (data) { + data->refcount++; + } + return data; } void GLSharedGroup::unrefShaderData(GLuint shader) { emugl::Mutex::AutoLock _lock(m_lock); - ssize_t idx = m_shaders.indexOfKey(shader); - if (idx >= 0) { - unrefShaderDataLocked(idx); - } + 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 02278a2..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 "FixedBuffer.h" -#include "emugl/common/mutex.h" -#include "emugl/common/smart_ptr.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; + 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(); diff --git a/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp index f7a2314..3ef4c6f 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); @@ -140,7 +140,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/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk index d8807d0..566fd10 100644 --- a/emulator/opengl/shared/OpenglOsUtils/Android.mk +++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk @@ -37,10 +37,11 @@ $(call emugl-begin-host-static-library,libOpenglOsUtils) $(call emugl-end-module) ### 64-bit host library #### -$(call emugl-begin-host-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-export,CFLAGS,-m64) - $(call emugl-import,lib64emugl_common) -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host-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-export,CFLAGS,-m64 -fPIC) + $(call emugl-end-module) +endif
\ No newline at end of file diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk index f1c20b5..fd7761e 100644 --- a/emulator/opengl/shared/emugl/common/Android.mk +++ b/emulator/opengl/shared/emugl/common/Android.mk @@ -6,26 +6,37 @@ 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) -$(call emugl-begin-host-static-library,lib64emugl_common) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-export,CFLAGS,-m64) -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host-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 \ @@ -35,7 +46,9 @@ LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-import,libemugl_common libemugl_gtest) $(call emugl-end-module) -$(call emugl-begin-host-executable,emugl64_common_host_unittests) -LOCAL_SRC_FILES := $(host_commonSources) -$(call emugl-import,lib64emugl_common lib64emugl_gtest) -$(call emugl-end-module) +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host-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/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp new file mode 100644 index 0000000..3fe8f15 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector.cpp @@ -0,0 +1,151 @@ +// 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) { + const size_t kMaxSize = maxItemCapacity(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..22a8a1d --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector.h @@ -0,0 +1,267 @@ +// 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) { + const size_t kMaxCapacity = SIZE_MAX / itemSize; + return mBegin + pos * itemSize; + } + + const void* itemAt(size_t pos, size_t itemSize) const { + const size_t kMaxCapacity = SIZE_MAX / itemSize; + 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/sockets.cpp b/emulator/opengl/shared/emugl/common/sockets.cpp new file mode 100644 index 0000000..feb6d38 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/sockets.cpp @@ -0,0 +1,221 @@ +// 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 <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/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 d14d369..1f25a33 100644 --- a/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk +++ b/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk @@ -9,7 +9,7 @@ ifeq ($(HOST_OS),darwin) 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 @@ -17,9 +17,9 @@ LOCAL_SRC_FILES:= \ triangleCM.cpp LOCAL_CFLAGS += $(EMUGL_SDL_CFLAGS) -g -O0 -LOCAL_LDLIBS += $(EMUGL_SDL_LDLIBS) +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_V2/Android.mk b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk index 98f85a3..10b3b0c 100644 --- a/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk +++ b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk @@ -7,9 +7,9 @@ LOCAL_SRC_FILES:= \ triangleV2.cpp LOCAL_CFLAGS += $(EMUGL_SDL_CFLAGS) -g -O0 -LOCAL_LDLIBS += $(EMUGL_SDL_LDLIBS) +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 @@ -23,4 +23,3 @@ ifeq ($(HOST_OS),darwin) endif $(call emugl-end-module) - 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 \ |
