Merge "ADT: fix spurious SDK refresh when opening layout editor." into idea133
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
index 5a09758..28b1689 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
@@ -289,10 +289,15 @@
@Override
public String getNamespace() {
if (mNamespace == null) {
- ManifestData manifestData = AndroidManifestHelper.parseForData(mProject);
- if (manifestData != null) {
- String javaPackage = manifestData.getPackage();
- mNamespace = String.format(AdtConstants.NS_CUSTOM_RESOURCES, javaPackage);
+ boolean token = RenderSecurityManager.enterSafeRegion(mCredential);
+ try {
+ ManifestData manifestData = AndroidManifestHelper.parseForData(mProject);
+ if (manifestData != null) {
+ String javaPackage = manifestData.getPackage();
+ mNamespace = String.format(AdtConstants.NS_CUSTOM_RESOURCES, javaPackage);
+ }
+ } finally {
+ RenderSecurityManager.exitSafeRegion(token);
}
}
@@ -440,23 +445,33 @@
@Override
public ILayoutPullParser getParser(String layoutName) {
- // Try to compute the ResourceValue for this layout since layoutlib
- // must be an older version which doesn't pass the value:
- if (mResourceResolver != null) {
- ResourceValue value = mResourceResolver.getProjectResource(ResourceType.LAYOUT,
- layoutName);
- if (value != null) {
- return getParser(value);
+ boolean token = RenderSecurityManager.enterSafeRegion(mCredential);
+ try {
+ // Try to compute the ResourceValue for this layout since layoutlib
+ // must be an older version which doesn't pass the value:
+ if (mResourceResolver != null) {
+ ResourceValue value = mResourceResolver.getProjectResource(ResourceType.LAYOUT,
+ layoutName);
+ if (value != null) {
+ return getParser(value);
+ }
}
- }
- return getParser(layoutName, null);
+ return getParser(layoutName, null);
+ } finally {
+ RenderSecurityManager.exitSafeRegion(token);
+ }
}
@Override
public ILayoutPullParser getParser(ResourceValue layoutResource) {
- return getParser(layoutResource.getName(),
- new File(layoutResource.getValue()));
+ boolean token = RenderSecurityManager.enterSafeRegion(mCredential);
+ try {
+ return getParser(layoutResource.getName(),
+ new File(layoutResource.getValue()));
+ } finally {
+ RenderSecurityManager.exitSafeRegion(token);
+ }
}
private ILayoutPullParser getParser(String layoutName, File xml) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
index 1f90779..fd8125e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
@@ -33,10 +33,10 @@
import com.android.sdklib.IAndroidTarget;
import com.android.tools.lint.checks.BuiltinIssueRegistry;
import com.android.tools.lint.client.api.Configuration;
-import com.android.tools.lint.client.api.IDomParser;
-import com.android.tools.lint.client.api.IJavaParser;
import com.android.tools.lint.client.api.IssueRegistry;
+import com.android.tools.lint.client.api.JavaParser;
import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.XmlParser;
import com.android.tools.lint.detector.api.ClassContext;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.DefaultPosition;
@@ -105,7 +105,6 @@
import java.util.Map;
import java.util.WeakHashMap;
-import lombok.ast.TypeReference;
import lombok.ast.ecj.EcjTreeConverter;
import lombok.ast.grammar.ParseProblem;
import lombok.ast.grammar.Source;
@@ -114,7 +113,7 @@
* Eclipse implementation for running lint on workspace files and projects.
*/
@SuppressWarnings("restriction") // DOM model
-public class EclipseLintClient extends LintClient implements IDomParser {
+public class EclipseLintClient extends LintClient {
static final String MARKER_CHECKID_PROPERTY = "checkid"; //$NON-NLS-1$
private static final String MODEL_PROPERTY = "model"; //$NON-NLS-1$
private final List<? extends IResource> mResources;
@@ -206,12 +205,98 @@
}
@Override
- public IDomParser getDomParser() {
- return this;
+ public XmlParser getXmlParser() {
+ return new XmlParser() {
+ @Override
+ public Document parseXml(@NonNull XmlContext context) {
+ // Map File to IFile
+ IFile file = AdtUtils.fileToIFile(context.file);
+ if (file == null || !file.exists()) {
+ String path = context.file.getPath();
+ AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path);
+ return null;
+ }
+
+ IStructuredModel model = null;
+ try {
+ IModelManager modelManager = StructuredModelManager.getModelManager();
+ if (modelManager == null) {
+ // This can happen if incremental lint is running right as Eclipse is
+ // shutting down
+ return null;
+ }
+ model = modelManager.getModelForRead(file);
+ if (model instanceof IDOMModel) {
+ context.setProperty(MODEL_PROPERTY, model);
+ IDOMModel domModel = (IDOMModel) model;
+ return domModel.getDocument();
+ }
+ } catch (IOException e) {
+ AdtPlugin.log(e, "Cannot read XML file");
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+
+ return null;
+ }
+
+ @Override
+ public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node) {
+ IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
+ return new LazyLocation(context.file, model.getStructuredDocument(),
+ (IndexedRegion) node);
+ }
+
+ @Override
+ public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node,
+ int start, int end) {
+ IndexedRegion region = (IndexedRegion) node;
+ int nodeStart = region.getStartOffset();
+
+ IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
+ // Get line number
+ LazyLocation location = new LazyLocation(context.file,
+ model.getStructuredDocument(), region);
+ int line = location.getStart().getLine();
+
+ Position startPos = new DefaultPosition(line, -1, nodeStart + start);
+ Position endPos = new DefaultPosition(line, -1, nodeStart + end);
+ return Location.create(context.file, startPos, endPos);
+ }
+
+ @Override
+ public int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node) {
+ IndexedRegion region = (IndexedRegion) node;
+ return region.getStartOffset();
+ }
+
+ @Override
+ public int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node) {
+ IndexedRegion region = (IndexedRegion) node;
+ return region.getEndOffset();
+ }
+
+ @Override
+ public @NonNull Handle createLocationHandle(final @NonNull XmlContext context,
+ final @NonNull Node node) {
+ IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
+ return new LazyLocation(context.file, model.getStructuredDocument(),
+ (IndexedRegion) node);
+ }
+
+ @Override
+ public void dispose(@NonNull XmlContext context, @NonNull Document document) {
+ IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
+ assert model != null : context.file;
+ if (model != null) {
+ model.releaseFromRead();
+ }
+ }
+ };
}
@Override
- public IJavaParser getJavaParser() {
+ public JavaParser getJavaParser(@Nullable Project project) {
if (mJavaParser == null) {
mJavaParser = new EclipseJavaParser();
}
@@ -219,40 +304,6 @@
return mJavaParser;
}
- // ----- Implements IDomParser -----
-
- @Override
- public Document parseXml(@NonNull XmlContext context) {
- // Map File to IFile
- IFile file = AdtUtils.fileToIFile(context.file);
- if (file == null || !file.exists()) {
- String path = context.file.getPath();
- AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path);
- return null;
- }
-
- IStructuredModel model = null;
- try {
- IModelManager modelManager = StructuredModelManager.getModelManager();
- if (modelManager == null) {
- // This can happen if incremental lint is running right as Eclipse is shutting down
- return null;
- }
- model = modelManager.getModelForRead(file);
- if (model instanceof IDOMModel) {
- context.setProperty(MODEL_PROPERTY, model);
- IDOMModel domModel = (IDOMModel) model;
- return domModel.getDocument();
- }
- } catch (IOException e) {
- AdtPlugin.log(e, "Cannot read XML file");
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
-
- return null;
- }
-
// Cache for {@link getProject}
private IProject mLastEclipseProject;
private Project mLastLintProject;
@@ -735,48 +786,6 @@
}
}
- @Override
- public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node) {
- IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
- return new LazyLocation(context.file, model.getStructuredDocument(), (IndexedRegion) node);
- }
-
- @Override
- public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node,
- int start, int end) {
- IndexedRegion region = (IndexedRegion) node;
- int nodeStart = region.getStartOffset();
-
- IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
- // Get line number
- LazyLocation location = new LazyLocation(context.file, model.getStructuredDocument(),
- region);
- int line = location.getStart().getLine();
-
- Position startPos = new DefaultPosition(line, -1, nodeStart + start);
- Position endPos = new DefaultPosition(line, -1, nodeStart + end);
- return Location.create(context.file, startPos, endPos);
- }
-
- @Override
- public int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node) {
- IndexedRegion region = (IndexedRegion) node;
- return region.getStartOffset();
- }
-
- @Override
- public int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node) {
- IndexedRegion region = (IndexedRegion) node;
- return region.getEndOffset();
- }
-
- @Override
- public @NonNull Handle createLocationHandle(final @NonNull XmlContext context,
- final @NonNull Node node) {
- IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
- return new LazyLocation(context.file, model.getStructuredDocument(), (IndexedRegion) node);
- }
-
private Map<Project, ClassPathInfo> mProjectInfo;
@Override
@@ -902,15 +911,6 @@
}
@Override
- public void dispose(@NonNull XmlContext context, @NonNull Document document) {
- IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY);
- assert model != null : context.file;
- if (model != null) {
- model.releaseFromRead();
- }
- }
-
- @Override
@NonNull
public IAndroidTarget[] getTargets() {
return Sdk.getCurrent().getTargets();
@@ -1102,7 +1102,7 @@
}
}
- private static class EclipseJavaParser implements IJavaParser {
+ private static class EclipseJavaParser extends JavaParser {
private static final boolean USE_ECLIPSE_PARSER = true;
private final Parser mParser;
@@ -1129,6 +1129,11 @@
}
@Override
+ public void prepareJavaParse(@NonNull List<JavaContext> contexts) {
+ // TODO: Use batch compiler from lint-cli.jar
+ }
+
+ @Override
public lombok.ast.Node parseJava(@NonNull JavaContext context) {
if (USE_ECLIPSE_PARSER) {
// Use Eclipse's compiler
@@ -1230,14 +1235,15 @@
@Override
@Nullable
- public lombok.ast.Node resolve(@NonNull JavaContext context,
+ public ResolvedNode resolve(@NonNull JavaContext context,
@NonNull lombok.ast.Node node) {
return null;
}
@Override
@Nullable
- public TypeReference getType(@NonNull JavaContext context, @NonNull lombok.ast.Node node) {
+ public TypeDescriptor getType(@NonNull JavaContext context,
+ @NonNull lombok.ast.Node node) {
return null;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfigurationTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfigurationTest.java
index 088ece7..7fd042e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfigurationTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfigurationTest.java
@@ -21,9 +21,9 @@
import com.android.tools.lint.checks.DuplicateIdDetector;
import com.android.tools.lint.checks.UnusedResourceDetector;
import com.android.tools.lint.client.api.Configuration;
-import com.android.tools.lint.client.api.IDomParser;
-import com.android.tools.lint.client.api.IJavaParser;
+import com.android.tools.lint.client.api.JavaParser;
import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.XmlParser;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
@@ -200,7 +200,7 @@
}
@Override
- public IDomParser getDomParser() {
+ public XmlParser getXmlParser() {
return null;
}
@@ -210,7 +210,7 @@
}
@Override
- public IJavaParser getJavaParser() {
+ public JavaParser getJavaParser(@Nullable Project project) {
return null;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandlerTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandlerTest.java
index 9a66985..1e04a29 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandlerTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandlerTest.java
@@ -40,10 +40,10 @@
import com.android.tools.lint.checks.SecurityDetector;
import com.android.tools.lint.client.api.Configuration;
import com.android.tools.lint.client.api.DefaultConfiguration;
-import com.android.tools.lint.client.api.IDomParser;
-import com.android.tools.lint.client.api.IJavaParser;
+import com.android.tools.lint.client.api.JavaParser;
import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.client.api.LintDriver;
+import com.android.tools.lint.client.api.XmlParser;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Issue;
@@ -831,15 +831,13 @@
@Override
@Nullable
- public IJavaParser getJavaParser() {
- return new EclipseLintClient(null, null, null, false).getJavaParser();
+ public JavaParser getJavaParser(@Nullable Project project) {
+ return new EclipseLintClient(null, null, null, false).getJavaParser(project);
}
@Override
- @Nullable
- public IDomParser getDomParser() {
- //return new LintCliXmlParser();
- return new EclipseLintClient(null, null, null, false).getDomParser();
+ public XmlParser getXmlParser() {
+ return new EclipseLintClient(null, null, null, false).getXmlParser();
}
});
File projectDir = AdtUtils.getAbsolutePath(project).toFile();
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 @@
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_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 @@
$(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 @@
# $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 @@
$(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
+
+ifeq (true,$(BUILD_STANDALONE_EMULATOR))
+LOCAL_PATH := $(EMULATOR_GTEST_SOURCES_DIR)
+else
+LOCAL_PATH := $(EMUGL_PATH)/../../../external/gtest
+endif
+
+common_SRC_FILES := \
+ src/gtest-all.cc \
+ src/gtest_main.cc
+
+common_CFLAGS := -O0
+
+ifneq (windows,$(HOST_OS))
+ common_LDLIBS += -lpthread
+endif
$(call emugl-begin-host-static-library,libemugl_gtest)
-LOCAL_SRC_FILES := \
- src/gtest-all.cc \
- src/gtest_main.cc
-LOCAL_CFLAGS += -O0
+LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_CFLAGS += $(common_CFLAGS)
LOCAL_CPP_EXTENSION := .cc
$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include)
-$(call emugl-export,LDLIBS,-lpthread)
+$(call emugl-export,LDLIBS,$(common_LDLIBS))
$(call emugl-end-module)
-$(call emugl-begin-host-static-library,lib64emugl_gtest)
-LOCAL_SRC_FILES := \
- src/gtest-all.cc \
- src/gtest_main.cc
-LOCAL_CFLAGS += -O0
-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,-lpthread -m64)
-$(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 @@
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 @@
$(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 @@
$(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)
+ LOCAL_LDLIBS += $(host_common_LDLIBS) -m64
+ LOCAL_SRC_FILES := $(host_common_SRC_FILES)
-$(call emugl-end-module)
-
+ $(call emugl-end-module)
+endif
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
index 3516986..24b9a0d 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
@@ -16,7 +16,6 @@
#include "EglDisplay.h"
#include "EglOsApi.h"
#include <GLcommon/GLutils.h>
-#include <utils/threads.h>
EglDisplay::EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault) :
m_dpy(dpy),
@@ -31,7 +30,7 @@
};
EglDisplay::~EglDisplay() {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
//
// Destroy the global context if one was created.
@@ -59,7 +58,7 @@
EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;}
void EglDisplay::initialize(int renderableType) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
m_initialized = true;
initConfigurations(renderableType);
m_configInitialized = true;
@@ -68,7 +67,7 @@
bool EglDisplay::isInitialize() { return m_initialized;}
void EglDisplay::terminate(){
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
m_contexts.clear();
m_surfaces.clear();
m_initialized = false;
@@ -128,7 +127,7 @@
}
EglConfig* EglDisplay::getConfig(EGLConfig conf) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
if(static_cast<EGLConfig>(*it) == conf) {
@@ -140,7 +139,7 @@
}
SurfacePtr EglDisplay::getSurface(EGLSurface surface) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* surface is "key" in map<unsigned int, SurfacePtr>. */
unsigned int hndl = SafeUIntFromPointer(surface);
SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
@@ -150,7 +149,7 @@
}
ContextPtr EglDisplay::getContext(EGLContext ctx) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* ctx is "key" in map<unsigned int, ContextPtr>. */
unsigned int hndl = SafeUIntFromPointer(ctx);
ContextsHndlMap::iterator it = m_contexts.find(hndl);
@@ -160,7 +159,7 @@
}
bool EglDisplay::removeSurface(EGLSurface s) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* s is "key" in map<unsigned int, SurfacePtr>. */
unsigned int hndl = SafeUIntFromPointer(s);
SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
@@ -172,7 +171,7 @@
}
bool EglDisplay::removeSurface(SurfacePtr s) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
SurfacesHndlMap::iterator it;
for(it = m_surfaces.begin(); it!= m_surfaces.end();it++)
@@ -189,7 +188,7 @@
}
bool EglDisplay::removeContext(EGLContext ctx) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* ctx is "key" in map<unsigned int, ContextPtr>. */
unsigned int hndl = SafeUIntFromPointer(ctx);
ContextsHndlMap::iterator it = m_contexts.find(hndl);
@@ -201,7 +200,7 @@
}
bool EglDisplay::removeContext(ContextPtr ctx) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ContextsHndlMap::iterator it;
for(it = m_contexts.begin(); it != m_contexts.end();it++) {
@@ -217,7 +216,7 @@
}
EglConfig* EglDisplay::getConfig(EGLint id) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
if((*it)->id() == id) {
@@ -229,7 +228,7 @@
}
int EglDisplay::getConfigs(EGLConfig* configs,int config_size) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
int i = 0;
for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && i < config_size ;i++,it++) {
configs[i] = static_cast<EGLConfig>(*it);
@@ -238,7 +237,7 @@
}
int EglDisplay::chooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
return doChooseConfigs(dummy, configs, config_size);
}
@@ -258,7 +257,7 @@
}
EGLSurface EglDisplay::addSurface(SurfacePtr s ) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
unsigned int hndl = s.Ptr()->getHndl();
EGLSurface ret =reinterpret_cast<EGLSurface> (hndl);
@@ -271,7 +270,7 @@
}
EGLContext EglDisplay::addContext(ContextPtr ctx ) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
unsigned int hndl = ctx.Ptr()->getHndl();
EGLContext ret = reinterpret_cast<EGLContext> (hndl);
@@ -285,7 +284,7 @@
EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
do { ++m_nextEglImageId; } while(m_nextEglImageId == 0);
img->imageId = m_nextEglImageId;
m_eglImages[m_nextEglImageId] = img;
@@ -293,7 +292,7 @@
}
ImagePtr EglDisplay::getImage(EGLImageKHR img) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* img is "key" in map<unsigned int, ImagePtr>. */
unsigned int hndl = SafeUIntFromPointer(img);
ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
@@ -301,7 +300,7 @@
}
bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
/* img is "key" in map<unsigned int, ImagePtr>. */
unsigned int hndl = SafeUIntFromPointer(img);
ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
@@ -314,7 +313,7 @@
}
EGLNativeContextType EglDisplay::getGlobalSharedContext(){
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
#ifndef _WIN32
// find an existing OpenGL context to share with, if exist
EGLNativeContextType ret =
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
index 889a84f..47a2598 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
+++ b/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
@@ -20,7 +20,7 @@
#include <map>
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
#include "emugl/common/smart_ptr.h"
#include "EglConfig.h"
@@ -82,7 +82,7 @@
SurfacesHndlMap m_surfaces;
GlobalNameSpace m_globalNameSpace;
ObjectNameManager *m_manager[MAX_GLES_VERSION];
- android::Mutex m_lock;
+ emugl::Mutex m_lock;
ImagesHndlMap m_eglImages;
unsigned int m_nextEglImageId;
EGLNativeContextType m_globalSharedContext;
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp
index 8e5b462..95b696e 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.cpp
@@ -51,7 +51,7 @@
EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy,EGLNativeInternalDisplayType idpy) {
//search if it is not already exists
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) {
if((*it).second == dpy) return (*it).first;
}
@@ -68,7 +68,7 @@
}
bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) {
if(static_cast<EGLDisplay>((*it).first) == dpy) {
delete (*it).first;
@@ -80,7 +80,7 @@
}
EglDisplay* EglGlobalInfo::getDisplay(EGLNativeDisplayType dpy) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
for(DisplaysMap::iterator it = m_displays.begin(); it != m_displays.end() ;it++) {
if((*it).second == dpy) return (*it).first;
}
@@ -88,7 +88,7 @@
}
EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
DisplaysMap::iterator it = m_displays.find(static_cast<EglDisplay*>(dpy));
return (it != m_displays.end() ? (*it).first : NULL);
}
@@ -99,7 +99,7 @@
void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
if (!m_gles_extFuncs_inited[ver]) {
ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1);
m_gles_extFuncs_inited[ver] = true;
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h
index ec07ffe..f56b79e 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h
+++ b/emulator/opengl/host/libs/Translator/EGL/EglGlobalInfo.h
@@ -16,14 +16,15 @@
#ifndef EGL_GLOBAL_INFO
#define EGL_GLOBAL_INFO
-#include <list>
-#include <EGL/egl.h>
-#include <utils/threads.h>
-#include <GLcommon/TranslatorIfaces.h>
#include "EglDisplay.h"
#include "EglConfig.h"
#include "EglContext.h"
+#include <GLcommon/TranslatorIfaces.h>
+#include "emugl/common/mutex.h"
+#include <list>
+#include <EGL/egl.h>
+
typedef std::map<EglDisplay*,EGLNativeDisplayType>DisplaysMap;
@@ -58,7 +59,7 @@
EGLNativeInternalDisplayType m_default;
GLESiface* m_gles_ifaces[MAX_GLES_VERSION];
bool m_gles_extFuncs_inited[MAX_GLES_VERSION];
- android::Mutex m_lock;
+ emugl::Mutex m_lock;
};
#endif
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
index 1d5c494..e31dea5 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
@@ -50,11 +50,11 @@
#define tls_thread EglThreadInfo::get()
EglGlobalInfo* g_eglInfo = NULL;
-android::Mutex s_eglLock;
+emugl::Mutex s_eglLock;
void initGlobalInfo()
{
- android::Mutex::Autolock mutex(s_eglLock);
+ emugl::Mutex::AutoLock mutex(s_eglLock);
if (!g_eglInfo) {
g_eglInfo = EglGlobalInfo::getInstance();
}
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp
index 1b403f2..6481774 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglThreadInfo.cpp
@@ -16,26 +16,33 @@
#include "EglThreadInfo.h"
#include "EglOsApi.h"
-EglThreadInfo::EglThreadInfo():m_err(EGL_SUCCESS),m_api(EGL_OPENGL_ES_API) {}
+#include "emugl/common/lazy_instance.h"
+#include "emugl/common/thread_store.h"
-#include <cutils/threads.h>
+namespace {
-static thread_store_t s_tls = THREAD_STORE_INITIALIZER;
-
-static void tlsDestruct(void *ptr)
-{
- if (ptr) {
- EglThreadInfo *ti = (EglThreadInfo *)ptr;
- delete ti;
+class EglThreadInfoStore : public emugl::ThreadStore {
+public:
+ EglThreadInfoStore() : emugl::ThreadStore(&destructor) {}
+private:
+ static void destructor(void* value) {
+ delete static_cast<EglThreadInfo*>(value);
}
-}
+};
+
+} // namespace
+
+EglThreadInfo::EglThreadInfo() :
+ m_err(EGL_SUCCESS), m_api(EGL_OPENGL_ES_API) {}
+
+static emugl::LazyInstance<EglThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
EglThreadInfo* EglThreadInfo::get(void)
{
- EglThreadInfo *ti = (EglThreadInfo *)thread_store_get(&s_tls);
+ EglThreadInfo *ti = static_cast<EglThreadInfo*>(s_tls->get());
if (!ti) {
ti = new EglThreadInfo();
- thread_store_set(&s_tls, ti, tlsDestruct);
+ s_tls->set(ti);
}
return ti;
}
diff --git a/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp b/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp
index a8c624e..41cf8c4 100644
--- a/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/EglX11Api.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
#include "EglOsApi.h"
+#include "emugl/common/mutex.h"
+
#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
-#include <utils/threads.h>
class ErrorHandler{
@@ -29,7 +30,7 @@
private:
static int s_lastErrorCode;
int (*m_oldErrorHandler) (Display *, XErrorEvent *);
-static android::Mutex s_lock;
+static emugl::Mutex s_lock;
static int errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event);
};
@@ -50,17 +51,17 @@
};
int ErrorHandler::s_lastErrorCode = 0;
-android::Mutex ErrorHandler::s_lock;
+emugl::Mutex ErrorHandler::s_lock;
ErrorHandler::ErrorHandler(EGLNativeDisplayType dpy){
- android::Mutex::Autolock mutex(s_lock);
+ emugl::Mutex::AutoLock mutex(s_lock);
XSync(dpy,False);
s_lastErrorCode = 0;
m_oldErrorHandler = XSetErrorHandler(errorHandlerProc);
}
ErrorHandler::~ErrorHandler(){
- android::Mutex::Autolock mutex(s_lock);
+ emugl::Mutex::AutoLock mutex(s_lock);
XSetErrorHandler(m_oldErrorHandler);
s_lastErrorCode = 0;
}
diff --git a/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp b/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp
index 4f5d75f..1571b3a 100644
--- a/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp
+++ b/emulator/opengl/host/libs/Translator/EGL/ThreadInfo.cpp
@@ -14,16 +14,47 @@
* limitations under the License.
*/
-#include <stdio.h>
#include "ThreadInfo.h"
-//#define TRACE_THREADINFO
-#ifdef TRACE_THREADINFO
+#include "emugl/common/lazy_instance.h"
+#include "emugl/common/thread_store.h"
+
+#include <stdio.h>
+
+// Set TRACE_THREADINFO to 1 to debug creation/destruction of ThreadInfo
+// instances.
+#define TRACE_THREADINFO 0
+
+#if TRACE_THREADINFO
#define LOG_THREADINFO(x...) fprintf(stderr, x)
#else
#define LOG_THREADINFO(x...)
#endif
+namespace {
+
+class ThreadInfoStore : public ::emugl::ThreadStore {
+public:
+ ThreadInfoStore() : ::emugl::ThreadStore(&destructor) {}
+
+ size_t getInstanceCount() const { return mNumInstances; }
+
+private:
+ static void destructor(void* value) {
+ LOG_THREADINFO("%s: EFL %p (%d instances)\n", __FUNCTION__,
+ value, mNumInstances);
+ delete static_cast<ThreadInfo*>(value);
+ mNumInstances--;
+ }
+
+ static size_t mNumInstances;
+};
+
+size_t ThreadInfoStore::mNumInstances = 0;
+
+} // namespace
+
+
void ThreadInfo::updateInfo(ContextPtr eglCtx,
EglDisplay* dpy,
GLEScontext* glesCtx,
@@ -37,27 +68,16 @@
objManager = manager;
}
-#include <cutils/threads.h>
-static thread_store_t s_tls = THREAD_STORE_INITIALIZER;
-static int active_instance = 0;
-static void tlsDestruct(void *ptr)
-{
- active_instance--;
- LOG_THREADINFO("tlsDestruct EGL %lx %d\n", (long)ptr, active_instance);
- if (ptr) {
- ThreadInfo *ti = (ThreadInfo *)ptr;
- delete ti;
- }
-}
+static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
ThreadInfo *getThreadInfo()
{
- ThreadInfo *ti = (ThreadInfo *)thread_store_get(&s_tls);
+ ThreadInfo *ti = static_cast<ThreadInfo*>(s_tls->get());
if (!ti) {
ti = new ThreadInfo();
- thread_store_set(&s_tls, ti, tlsDestruct);
- active_instance++;
- LOG_THREADINFO("getThreadInfo EGL %lx %d\n", (long)ti, active_instance);
+ s_tls->set(ti);
+ LOG_THREADINFO("%s: EGL %p (%d instances)\n", __FUNCTION__,
+ ti, (int)ThreadInfoStore::getInstanceCount());
}
return ti;
}
diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk b/emulator/opengl/host/libs/Translator/GLES_CM/Android.mk
index 9aa74a7..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 @@
### 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_CM/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp
index af5c0d8..66adefb 100644
--- a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.cpp
@@ -51,7 +51,7 @@
void GLDispatch::dispatchFuncs() {
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
if(m_isLoaded)
return;
LOAD_GL_FUNC(glActiveTexture);
diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h
index 9dc320f..ae8c9f8 100644
--- a/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h
+++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLDispatch.h
@@ -17,7 +17,7 @@
#define GLDISPATCHH
#include <GLES/gl.h>
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
#define GLAPIENTRY GL_APIENTRY
@@ -151,8 +151,8 @@
void (GLAPIENTRY *glVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void (GLAPIENTRY *glViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
private:
- bool m_isLoaded;
- android::Mutex m_lock;
+ bool m_isLoaded;
+ emugl::Mutex m_lock;
};
#endif
diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp
index ecf51bb..6476c02 100644
--- a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp
@@ -23,7 +23,7 @@
#include <GLES/glext.h>
void GLEScmContext::init() {
- android::Mutex::Autolock mutex(s_lock);
+ emugl::Mutex::AutoLock mutex(s_lock);
if(!m_initialized) {
s_glDispatch.dispatchFuncs(GLES_1_1);
GLEScontext::init();
diff --git a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h
index 1785877..fbb7023 100644
--- a/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h
+++ b/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.h
@@ -23,7 +23,6 @@
#include <map>
#include <vector>
#include <string>
-#include <utils/threads.h>
typedef std::map<GLfloat,std::vector<int> > PointSizeIndices;
diff --git a/emulator/opengl/host/libs/Translator/GLES_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 @@
### 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/GLES_V2/GLESv2Context.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp
index 1457cec..f8f674b 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp
@@ -15,11 +15,10 @@
*/
#include "GLESv2Context.h"
-
-
+#include <string.h>
void GLESv2Context::init() {
- android::Mutex::Autolock mutex(s_lock);
+ emugl::Mutex::AutoLock mutex(s_lock);
if(!m_initialized) {
s_glDispatch.dispatchFuncs(GLES_2_0);
GLEScontext::init();
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h
index 75af864..7e71177 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.h
@@ -20,7 +20,6 @@
#include <GLcommon/GLDispatch.h>
#include <GLcommon/GLEScontext.h>
#include <GLcommon/objectNameManager.h>
-#include <utils/threads.h>
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp
index 53d1314..3f00428 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Validate.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "GLESv2Validate.h"
+#include <string.h>
bool GLESv2Validate::blendEquationMode(GLenum mode){
return mode == GL_FUNC_ADD ||
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
index a80326d..311a9ed 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
@@ -15,6 +15,7 @@
*/
#include "ShaderParser.h"
+#include <stdlib.h>
#include <string.h>
ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
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 @@
$(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 ################
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host-static-library,lib64GLcommon)
-$(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-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)
+ $(call emugl-end-module)
+endif
\ No newline at end of file
diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
index abed760..54aa200 100644
--- a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
+++ b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp
@@ -67,7 +67,7 @@
/* initializing static GLDispatch members*/
-android::Mutex GLDispatch::s_lock;
+emugl::Mutex GLDispatch::s_lock;
void (GLAPIENTRY *GLDispatch::glActiveTexture)(GLenum) = NULL;
void (GLAPIENTRY *GLDispatch::glBindBuffer)(GLenum,GLuint) = NULL;
void (GLAPIENTRY *GLDispatch::glBindTexture)(GLenum, GLuint) = NULL;
@@ -298,7 +298,7 @@
void GLDispatch::dispatchFuncs(GLESVersion version){
- android::Mutex::Autolock mutex(s_lock);
+ emugl::Mutex::AutoLock mutex(s_lock);
if(m_isLoaded)
return;
diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp
index 6572719..46f039c 100644
--- a/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp
+++ b/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp
@@ -23,6 +23,7 @@
#include <GLcommon/TextureUtils.h>
#include <GLcommon/FramebufferData.h>
#include <strings.h>
+#include <string.h>
//decleration
static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
@@ -84,7 +85,7 @@
}
GLDispatch GLEScontext::s_glDispatch;
-android::Mutex GLEScontext::s_lock;
+emugl::Mutex GLEScontext::s_lock;
std::string* GLEScontext::s_glExtensions= NULL;
std::string GLEScontext::s_glVendor;
std::string GLEScontext::s_glRenderer;
diff --git a/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp b/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp
index cfea855..3612211 100644
--- a/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp
+++ b/emulator/opengl/host/libs/Translator/GLcommon/objectNameManager.cpp
@@ -18,12 +18,11 @@
#include <GLcommon/GLEScontext.h>
-NameSpace::NameSpace(NamedObjectType p_type, GlobalNameSpace *globalNameSpace) :
+NameSpace::NameSpace(NamedObjectType p_type,
+ GlobalNameSpace *globalNameSpace) :
m_nextName(0),
m_type(p_type),
- m_globalNameSpace(globalNameSpace)
-{
-}
+ m_globalNameSpace(globalNameSpace) {}
NameSpace::~NameSpace()
{
@@ -35,14 +34,16 @@
}
ObjectLocalName
-NameSpace::genName(ObjectLocalName p_localName, bool genGlobal, bool genLocal)
+NameSpace::genName(ObjectLocalName p_localName,
+ bool genGlobal, bool genLocal)
{
-
ObjectLocalName localName = p_localName;
if (genLocal) {
do {
localName = ++m_nextName;
- } while( localName == 0 || m_localToGlobalMap.find(localName) != m_localToGlobalMap.end() );
+ } while(localName == 0 ||
+ m_localToGlobalMap.find(localName) !=
+ m_localToGlobalMap.end() );
}
if (genGlobal) {
@@ -114,15 +115,9 @@
}
-GlobalNameSpace::GlobalNameSpace()
-{
- mutex_init(&m_lock);
-}
+GlobalNameSpace::GlobalNameSpace() : m_lock() {}
-GlobalNameSpace::~GlobalNameSpace()
-{
- mutex_destroy(&m_lock);
-}
+GlobalNameSpace::~GlobalNameSpace() {}
unsigned int
GlobalNameSpace::genName(NamedObjectType p_type)
@@ -130,7 +125,7 @@
if ( p_type >= NUM_OBJECT_TYPES ) return 0;
unsigned int name = 0;
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
switch (p_type) {
case VERTEXBUFFER:
GLEScontext::dispatcher().glGenBuffers(1,&name);
@@ -148,7 +143,6 @@
default:
name = 0;
}
- mutex_unlock(&m_lock);
return name;
}
@@ -160,11 +154,8 @@
typedef std::pair<NamedObjectType, ObjectLocalName> ObjectIDPair;
typedef std::map<ObjectIDPair, ObjectDataPtr> ObjectDataMap;
-ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace)
-{
- mutex_init(&m_lock);
-
- for (int i=0; i<NUM_OBJECT_TYPES; i++) {
+ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) : m_lock() {
+ for (int i=0; i < NUM_OBJECT_TYPES; i++) {
m_nameSpace[i] = new NameSpace((NamedObjectType)i, globalNameSpace);
}
@@ -173,27 +164,24 @@
ShareGroup::~ShareGroup()
{
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
for (int t = 0; t < NUM_OBJECT_TYPES; t++) {
delete m_nameSpace[t];
}
- ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
- if (map) delete map;
-
- mutex_unlock(&m_lock);
- mutex_destroy(&m_lock);
+ delete (ObjectDataMap *)m_objectsData;
}
ObjectLocalName
-ShareGroup::genName(NamedObjectType p_type, ObjectLocalName p_localName, bool genLocal)
+ShareGroup::genName(NamedObjectType p_type,
+ ObjectLocalName p_localName,
+ bool genLocal)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
- mutex_lock(&m_lock);
- ObjectLocalName localName = m_nameSpace[p_type]->genName(p_localName,true,genLocal);
- mutex_unlock(&m_lock);
-
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ObjectLocalName localName =
+ m_nameSpace[p_type]->genName(p_localName, true, genLocal);
return localName;
}
@@ -202,35 +190,28 @@
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
- mutex_lock(&m_lock);
- unsigned int name = m_nameSpace[p_type]->genGlobalName();
- mutex_unlock(&m_lock);
-
- return name;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return m_nameSpace[p_type]->genGlobalName();
}
unsigned int
-ShareGroup::getGlobalName(NamedObjectType p_type, ObjectLocalName p_localName)
+ShareGroup::getGlobalName(NamedObjectType p_type,
+ ObjectLocalName p_localName)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
- mutex_lock(&m_lock);
- unsigned int globalName = m_nameSpace[p_type]->getGlobalName(p_localName);
- mutex_unlock(&m_lock);
-
- return globalName;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return m_nameSpace[p_type]->getGlobalName(p_localName);
}
ObjectLocalName
-ShareGroup::getLocalName(NamedObjectType p_type, unsigned int p_globalName)
+ShareGroup::getLocalName(NamedObjectType p_type,
+ unsigned int p_globalName)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
- mutex_lock(&m_lock);
- ObjectLocalName localName = m_nameSpace[p_type]->getLocalName(p_globalName);
- mutex_unlock(&m_lock);
-
- return localName;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return m_nameSpace[p_type]->getLocalName(p_globalName);
}
void
@@ -238,13 +219,12 @@
{
if (p_type >= NUM_OBJECT_TYPES) return;
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
m_nameSpace[p_type]->deleteName(p_localName);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (map) {
map->erase( ObjectIDPair(p_type, p_localName) );
}
- mutex_unlock(&m_lock);
}
bool
@@ -252,29 +232,29 @@
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
- mutex_lock(&m_lock);
- bool exist = m_nameSpace[p_type]->isObject(p_localName);
- mutex_unlock(&m_lock);
-
- return exist;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return m_nameSpace[p_type]->isObject(p_localName);
}
void
-ShareGroup::replaceGlobalName(NamedObjectType p_type, ObjectLocalName p_localName, unsigned int p_globalName)
+ShareGroup::replaceGlobalName(NamedObjectType p_type,
+ ObjectLocalName p_localName,
+ unsigned int p_globalName)
{
if (p_type >= NUM_OBJECT_TYPES) return;
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
m_nameSpace[p_type]->replaceGlobalName(p_localName, p_globalName);
- mutex_unlock(&m_lock);
}
void
-ShareGroup::setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, ObjectDataPtr data)
+ShareGroup::setObjectData(NamedObjectType p_type,
+ ObjectLocalName p_localName,
+ ObjectDataPtr data)
{
if (p_type >= NUM_OBJECT_TYPES) return;
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (!map) {
@@ -284,45 +264,36 @@
ObjectIDPair id( p_type, p_localName );
map->insert( std::pair<ObjectIDPair, ObjectDataPtr>(id, data) );
-
- mutex_unlock(&m_lock);
}
ObjectDataPtr
-ShareGroup::getObjectData(NamedObjectType p_type, ObjectLocalName p_localName)
+ShareGroup::getObjectData(NamedObjectType p_type,
+ ObjectLocalName p_localName)
{
ObjectDataPtr ret;
if (p_type >= NUM_OBJECT_TYPES) return ret;
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (map) {
- ObjectDataMap::iterator i = map->find( ObjectIDPair(p_type, p_localName) );
+ ObjectDataMap::iterator i =
+ map->find( ObjectIDPair(p_type, p_localName) );
if (i != map->end()) ret = (*i).second;
}
-
- mutex_unlock(&m_lock);
-
return ret;
}
ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) :
- m_globalNameSpace(globalNameSpace)
-{
- mutex_init(&m_lock);
-}
+ m_lock(), m_globalNameSpace(globalNameSpace) {}
-ObjectNameManager::~ObjectNameManager()
-{
- mutex_destroy(&m_lock);
-}
+ObjectNameManager::~ObjectNameManager() {}
ShareGroupPtr
ObjectNameManager::createShareGroup(void *p_groupName)
{
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupPtr shareGroupReturn;
@@ -334,19 +305,19 @@
//
// Group does not exist, create new group
//
- shareGroupReturn = ShareGroupPtr( new ShareGroup(m_globalNameSpace) );
- m_groups.insert( std::pair<void *, ShareGroupPtr>(p_groupName, shareGroupReturn) );
+ shareGroupReturn = ShareGroupPtr(new ShareGroup(m_globalNameSpace));
+ m_groups.insert(
+ std::pair<void*, ShareGroupPtr>(
+ p_groupName, shareGroupReturn));
}
- mutex_unlock(&m_lock);
-
return shareGroupReturn;
}
ShareGroupPtr
ObjectNameManager::getShareGroup(void *p_groupName)
{
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupPtr shareGroupReturn(NULL);
@@ -354,58 +325,45 @@
if (s != m_groups.end()) {
shareGroupReturn = (*s).second;
}
- mutex_unlock(&m_lock);
return shareGroupReturn;
}
ShareGroupPtr
-ObjectNameManager::attachShareGroup(void *p_groupName, void *p_existingGroupName)
+ObjectNameManager::attachShareGroup(void *p_groupName,
+ void *p_existingGroupName)
{
- mutex_lock(&m_lock);
-
- ShareGroupPtr shareGroupReturn;
+ emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) );
if (s == m_groups.end()) {
// ShareGroup did not found !!!
- mutex_unlock(&m_lock);
return ShareGroupPtr(NULL);
}
- shareGroupReturn = (*s).second;
-
- if (m_groups.find(p_groupName) == m_groups.end())
- {
- m_groups.insert( std::pair<void *, ShareGroupPtr>(p_groupName, shareGroupReturn) );
+ ShareGroupPtr shareGroupReturn((*s).second);
+ if (m_groups.find(p_groupName) == m_groups.end()) {
+ m_groups.insert(
+ std::pair<void*, ShareGroupPtr>(
+ p_groupName, shareGroupReturn));
}
-
- mutex_unlock(&m_lock);
-
return shareGroupReturn;
}
void
ObjectNameManager::deleteShareGroup(void *p_groupName)
{
- mutex_lock(&m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
if (s != m_groups.end()) {
m_groups.erase(s);
}
-
- mutex_unlock(&m_lock);
}
void *ObjectNameManager::getGlobalContext()
{
- void *ret = NULL;
-
- mutex_lock(&m_lock);
- if (m_groups.size() > 0) ret = (*m_groups.begin()).first;
- mutex_unlock(&m_lock);
-
- return ret;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return (m_groups.size() > 0) ? (*m_groups.begin()).first : NULL;
}
diff --git a/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h b/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h
new file mode 100644
index 0000000..0d38905
--- /dev/null
+++ b/emulator/opengl/host/libs/Translator/include/ETC1/etc1.h
@@ -0,0 +1,106 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __etc1_h__
+#define __etc1_h__
+
+#define ETC1_ENCODED_BLOCK_SIZE 8
+#define ETC1_DECODED_BLOCK_SIZE 48
+
+#ifndef ETC1_RGB8_OES
+#define ETC1_RGB8_OES 0x8D64
+#endif
+
+typedef unsigned char etc1_byte;
+typedef int etc1_bool;
+typedef unsigned int etc1_uint32;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Encode a block of pixels.
+//
+// pIn is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
+// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
+// value of pixel (x, y).
+//
+// validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
+// the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
+//
+// pOut is an ETC1 compressed version of the data.
+
+void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 validPixelMask, etc1_byte* pOut);
+
+// Decode a block of pixels.
+//
+// pIn is an ETC1 compressed version of the data.
+//
+// pOut is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
+// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
+// value of pixel (x, y).
+
+void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut);
+
+// Return the size of the encoded image data (does not include size of PKM header).
+
+etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height);
+
+// Encode an entire image.
+// pIn - pointer to the image data. Formatted such that
+// pixel (x,y) is at pIn + pixelSize * x + stride * y;
+// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
+// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
+// returns non-zero if there is an error.
+
+int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
+ etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut);
+
+// Decode an entire image.
+// pIn - pointer to encoded data.
+// pOut - pointer to the image data. Will be written such that
+// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
+// large enough to store entire image.
+// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
+// returns non-zero if there is an error.
+
+int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
+ etc1_uint32 width, etc1_uint32 height,
+ etc1_uint32 pixelSize, etc1_uint32 stride);
+
+// Size of a PKM header, in bytes.
+
+#define ETC_PKM_HEADER_SIZE 16
+
+// Format a PKM header
+
+void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height);
+
+// Check if a PKM header is correctly formatted.
+
+etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader);
+
+// Read the image width from a PKM header
+
+etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader);
+
+// Read the image height from a PKM header
+
+etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h
index de7d563..18a989c 100644
--- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h
+++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLDispatch.h
@@ -18,7 +18,7 @@
#include <GLES/gl.h>
#include <GLES2/gl2.h>
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
#include "gldefs.h"
#include "GLutils.h"
@@ -260,8 +260,8 @@
static void (GL_APIENTRY *glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
private:
- bool m_isLoaded;
- static android::Mutex s_lock;
+ bool m_isLoaded;
+ static emugl::Mutex s_lock;
};
#endif
diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h b/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h
index 20509fc..5aed0ad 100644
--- a/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h
+++ b/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h
@@ -20,7 +20,7 @@
#include "GLDispatch.h"
#include "GLESpointer.h"
#include "objectNameManager.h"
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
#include <string>
typedef std::map<GLenum,GLESpointer*> ArraysMap;
@@ -187,7 +187,7 @@
void initCapsLocked(const GLubyte * extensionString);
virtual void initExtensionString() =0;
- static android::Mutex s_lock;
+ static emugl::Mutex s_lock;
static GLDispatch s_glDispatch;
bool m_initialized;
unsigned int m_activeTexture;
diff --git a/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h b/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h
index 0a00644..4d4d038 100644
--- a/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h
+++ b/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h
@@ -16,8 +16,8 @@
#ifndef _OBJECT_NAME_MANAGER_H
#define _OBJECT_NAME_MANAGER_H
-#include <cutils/threads.h>
#include <map>
+#include "emugl/common/mutex.h"
#include "emugl/common/smart_ptr.h"
enum NamedObjectType {
@@ -129,7 +129,7 @@
void deleteName(NamedObjectType p_type, unsigned int p_name);
private:
- mutex_t m_lock;
+ emugl::Mutex m_lock;
};
//
@@ -204,7 +204,7 @@
~ShareGroup();
private:
- mutex_t m_lock;
+ emugl::Mutex m_lock;
NameSpace *m_nameSpace[NUM_OBJECT_TYPES];
void *m_objectsData;
};
@@ -262,7 +262,7 @@
private:
ShareGroupsMap m_groups;
- mutex_t m_lock;
+ emugl::Mutex m_lock;
GlobalNameSpace *m_globalNameSpace;
};
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 @@
# 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 @@
### 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/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
index cfadf12..238f2c9 100644
--- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
+++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
@@ -393,7 +393,7 @@
void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
m_onPost = onPost;
m_onPostContext = onPostContext;
if (m_onPost && !m_fbImage) {
@@ -490,7 +490,7 @@
HandleType FrameBuffer::createColorBuffer(int p_width, int p_height,
GLenum p_internalFormat)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0;
ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) );
@@ -505,7 +505,7 @@
HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share,
bool p_isGL2)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0;
RenderContextPtr share(NULL);
@@ -527,7 +527,7 @@
HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_height)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0;
WindowSurfacePtr win( WindowSurface::create(p_config, p_width, p_height) );
@@ -541,19 +541,19 @@
void FrameBuffer::DestroyRenderContext(HandleType p_context)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
m_contexts.erase(p_context);
}
void FrameBuffer::DestroyWindowSurface(HandleType p_surface)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
m_windows.erase(p_surface);
}
void FrameBuffer::openColorBuffer(HandleType p_colorbuffer)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) {
// bad colorbuffer handle
@@ -564,7 +564,7 @@
void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) {
// bad colorbuffer handle
@@ -577,7 +577,7 @@
bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfaceMap::iterator w( m_windows.find(p_surface) );
if (w == m_windows.end()) {
@@ -591,7 +591,7 @@
bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface,
HandleType p_colorbuffer)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfaceMap::iterator w( m_windows.find(p_surface) );
if (w == m_windows.end()) {
@@ -614,7 +614,7 @@
int x, int y, int width, int height,
GLenum format, GLenum type, void *pixels)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
if (c == m_colorbuffers.end()) {
@@ -629,7 +629,7 @@
bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
if (c == m_colorbuffers.end()) {
@@ -642,7 +642,7 @@
bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
if (c == m_colorbuffers.end()) {
@@ -657,7 +657,7 @@
HandleType p_drawSurface,
HandleType p_readSurface)
{
- android::Mutex::Autolock mutex(m_lock);
+ emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfacePtr draw(NULL), read(NULL);
RenderContextPtr ctx(NULL);
diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
index de0b71c..5b03624 100644
--- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
+++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
@@ -20,7 +20,8 @@
#include "ColorBuffer.h"
#include "RenderContext.h"
#include "WindowSurface.h"
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
+
#include <map>
#include <EGL/egl.h>
#include <stdint.h>
@@ -111,7 +112,7 @@
int m_y;
int m_width;
int m_height;
- android::Mutex m_lock;
+ emugl::Mutex m_lock;
FBNativeWindowType m_nativeWindow;
FrameBufferCaps m_caps;
EGLDisplay m_eglDisplay;
diff --git a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp
index 566ca40..5337009 100644
--- a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp
+++ b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp
@@ -15,17 +15,28 @@
*/
#include "ThreadInfo.h"
-#include <cutils/threads.h>
+#include "emugl/common/lazy_instance.h"
+#include "emugl/common/thread_store.h"
-static thread_store_t s_tls = THREAD_STORE_INITIALIZER;
+namespace {
+
+class ThreadInfoStore : public ::emugl::ThreadStore {
+public:
+ ThreadInfoStore() : ::emugl::ThreadStore(NULL) {}
+};
+
+} // namespace
+
+static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
RenderThreadInfo::RenderThreadInfo() {
- thread_store_set(&s_tls, this, NULL);
+ s_tls->set(this);
}
RenderThreadInfo::~RenderThreadInfo() {
+ s_tls->set(NULL);
}
RenderThreadInfo* RenderThreadInfo::get() {
- return (RenderThreadInfo*)thread_store_get(&s_tls);
+ return static_cast<RenderThreadInfo*>(s_tls->get());
}
diff --git a/emulator/opengl/host/libs/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-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..e2f3939 100644
--- a/emulator/opengl/host/tools/emugen/Android.mk
+++ b/emulator/opengl/host/tools/emugen/Android.mk
@@ -1,15 +1,35 @@
-ifneq ($(HOST_OS),windows)
+# Determine if the emugen build needs to be builts from
+# sources.
+EMUGL_BUILD_EMUGEN :=
+ifeq (true,$(BUILD_STANDALONE_EMULATOR))
+ # The emulator's standalone build system can build host Linux
+ # binaries even when it targets Windows by setting
+ # LOCAL_HOST_BUILD to true, so rebuild from sources.
+ EMUGL_BUILD_EMUGEN := true
+else
+ ifneq ($(HOST_OS),windows)
+ # The platform build can only build emugen when targetting
+ # the same host sytem.
+ EMUGL_BUILD_EMUGEN := true
+ endif
+endif
LOCAL_PATH:=$(call my-dir)
+ifeq (true,$(EMUGL_BUILD_EMUGEN))
+
$(call emugl-begin-host-executable,emugen)
- LOCAL_SRC_FILES := \
- ApiGen.cpp \
- EntryPoint.cpp \
- main.cpp \
- strUtils.cpp \
- TypeFactory.cpp
+LOCAL_SRC_FILES := \
+ ApiGen.cpp \
+ EntryPoint.cpp \
+ main.cpp \
+ strUtils.cpp \
+ TypeFactory.cpp \
+
+ifeq (true,$(BUILD_STANDALONE_EMULATOR))
+LOCAL_HOST_BUILD := true
+endif
$(call emugl-end-module)
@@ -17,7 +37,7 @@
# protocol encoders/ decoders. This variable is used by other emugl modules.
EMUGL_EMUGEN := $(LOCAL_BUILT_MODULE)
-else # windows build
+else # windows platform build
# on windows use the build host emugen executable
# (that will be the linux exeutable when using mingw build)
diff --git a/emulator/opengl/host/tools/emugen/ApiGen.cpp b/emulator/opengl/host/tools/emugen/ApiGen.cpp
index 6964862..2c331b9 100644
--- a/emulator/opengl/host/tools/emugen/ApiGen.cpp
+++ b/emulator/opengl/host/tools/emugen/ApiGen.cpp
@@ -420,8 +420,8 @@
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 @@
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 @@
\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 @@
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 @@
} 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 @@
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 @@
# 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 @@
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 @@
$(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)
+ 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)
-
+ $(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 c7da37a..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 @@
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 @@
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 @@
/***** GLSharedGroup ****/
GLSharedGroup::GLSharedGroup() :
- m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
- m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
- m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
-{
-}
+ m_buffers(), m_programs(), m_shaders() {}
-GLSharedGroup::~GLSharedGroup()
-{
- m_buffers.clear();
- m_programs.clear();
- clearObjectMap(m_buffers);
- clearObjectMap(m_programs);
- clearObjectMap(m_shaders);
-}
+GLSharedGroup::~GLSharedGroup() {}
BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
{
- android::AutoMutex _lock(m_lock);
- return m_buffers.valueFor(bufferId);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ return m_buffers.get(bufferId);
}
void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
{
- android::AutoMutex _lock(m_lock);
- m_buffers.add(bufferId, new BufferData(size, data));
+ emugl::Mutex::AutoLock _lock(m_lock);
+ m_buffers.set(bufferId, new BufferData(size, data));
}
void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
{
- android::AutoMutex _lock(m_lock);
- ssize_t idx = m_buffers.indexOfKey(bufferId);
- if (idx >= 0) {
- delete m_buffers.valueAt(idx);
- m_buffers.editValueAt(idx) = new BufferData(size, data);
- } else {
- m_buffers.add(bufferId, new BufferData(size, data));
- }
+ emugl::Mutex::AutoLock _lock(m_lock);
+ m_buffers.set(bufferId, new BufferData(size, data));
}
GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
{
- android::AutoMutex _lock(m_lock);
- BufferData * buf = m_buffers.valueFor(bufferId);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ BufferData * buf = m_buffers.get(bufferId);
if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
//it's safe to update now
@@ -277,215 +257,197 @@
void GLSharedGroup::deleteBufferData(GLuint bufferId)
{
- android::AutoMutex _lock(m_lock);
- ssize_t idx = m_buffers.indexOfKey(bufferId);
- if (idx >= 0) {
- delete m_buffers.valueAt(idx);
- m_buffers.removeItemsAt(idx);
- }
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ssize_t idx = m_buffers.remove(bufferId);
}
void GLSharedGroup::addProgramData(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- {
- m_programs.removeItem(program);
- delete pData;
- }
-
- m_programs.add(program,new ProgramData());
+ emugl::Mutex::AutoLock _lock(m_lock);
+ m_programs.set(program, new ProgramData());
}
void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
{
- android::AutoMutex _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- {
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData *pData = m_programs.get(program);
+ if (pData) {
pData->initProgramData(numIndexes);
}
}
bool GLSharedGroup::isProgramInitialized(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData)
- {
- return pData->isInitialized();
- }
- return false;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return pData && pData->isInitialized();
}
void GLSharedGroup::deleteProgramData(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- delete pData;
- m_programs.removeItem(program);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ m_programs.remove(program);
}
void GLSharedGroup::attachShader(GLuint program, GLuint shader)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* programData = m_programs.valueFor(program);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (programData && idx >= 0) {
- if (programData->attachShader(shader)) {
- refShaderDataLocked(idx);
- }
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* programData = m_programs.get(program);
+ if (programData && programData->attachShader(shader)) {
+ refShaderDataLocked(shader);
}
}
void GLSharedGroup::detachShader(GLuint program, GLuint shader)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* programData = m_programs.valueFor(program);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (programData && idx >= 0) {
- if (programData->detachShader(shader)) {
- unrefShaderDataLocked(idx);
- }
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* programData = m_programs.get(program);
+ if (programData && programData->detachShader(shader)) {
+ unrefShaderDataLocked(shader);
}
}
-void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
+void GLSharedGroup::setProgramIndexInfo(GLuint program,
+ GLuint index,
+ GLint base,
+ GLint size,
+ GLenum type,
+ const char* name)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData)
- {
- pData->setIndexInfo(index,base,size,type);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ if (!pData) {
+ return;
+ }
+ pData->setIndexInfo(index,base,size,type);
- if (type == GL_SAMPLER_2D) {
- size_t n = pData->getNumShaders();
- for (size_t i = 0; i < n; i++) {
- GLuint shaderId = pData->getShader(i);
- ShaderData* shader = m_shaders.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;
+ if (type == GL_SAMPLER_2D) {
+ size_t n = pData->getNumShaders();
+ for (size_t i = 0; i < n; i++) {
+ GLuint shaderId = pData->getShader(i);
+ ShaderData* shader = m_shaders.get(shaderId);
+ if (!shader) continue;
+#if 0 // TODO(digit): Understand why samplerExternalNames is always empty?
+ ShaderData::StringList::iterator nameIter =
+ shader->samplerExternalNames.begin();
+ ShaderData::StringList::iterator nameEnd =
+ shader->samplerExternalNames.end();
+ while (nameIter != nameEnd) {
+ if (*nameIter == name) {
+ pData->setIndexFlags(
+ index,
+ ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
+ break;
}
+ ++nameIter;
}
+#endif
}
}
}
+
GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- GLenum type=0;
- if (pData)
- {
- type = pData->getTypeForLocation(location);
- }
- return type;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->getTypeForLocation(location) : 0;
}
bool GLSharedGroup::isProgram(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- return (pData!=NULL);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return (pData != NULL);
}
void GLSharedGroup::setupLocationShiftWAR(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
if (pData) pData->setupLocationShiftWAR();
}
-GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
+GLint GLSharedGroup::locationWARHostToApp(GLuint program,
+ GLint hostLoc,
+ GLint arrIndex)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
- else return hostLoc;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->locationWARHostToApp(hostLoc, arrIndex) : hostLoc;
}
GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->locationWARAppToHost(appLoc);
- else return appLoc;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->locationWARAppToHost(appLoc) : appLoc;
}
bool GLSharedGroup::needUniformLocationWAR(GLuint program)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->needUniformLocationWAR();
- return false;
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->needUniformLocationWAR() : false;
}
-GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
+GLint GLSharedGroup::getNextSamplerUniform(GLuint program,
+ GLint index,
+ GLint* val,
+ GLenum* target) const
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
}
-bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
+bool GLSharedGroup::setSamplerUniform(GLuint program,
+ GLint appLoc,
+ GLint val,
+ GLenum* target)
{
- android::AutoMutex _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ProgramData* pData = m_programs.get(program);
return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
}
bool GLSharedGroup::addShaderData(GLuint shader)
{
- android::AutoMutex _lock(m_lock);
+ emugl::Mutex::AutoLock _lock(m_lock);
ShaderData* data = new ShaderData;
- if (data) {
- if (m_shaders.add(shader, data) < 0) {
- delete data;
- data = NULL;
- }
- data->refcount = 1;
- }
- return data != NULL;
+ data->refcount = 1;
+ m_shaders.set(shader, data);
+ return true;
}
ShaderData* GLSharedGroup::getShaderData(GLuint shader)
{
- android::AutoMutex _lock(m_lock);
- return m_shaders.valueFor(shader);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ ShaderData* data = m_shaders.get(shader);
+ if (data) {
+ data->refcount++;
+ }
+ return data;
}
void GLSharedGroup::unrefShaderData(GLuint shader)
{
- android::AutoMutex _lock(m_lock);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (idx >= 0) {
- unrefShaderDataLocked(idx);
+ emugl::Mutex::AutoLock _lock(m_lock);
+ unrefShaderDataLocked(shader);
+}
+
+void GLSharedGroup::refShaderDataLocked(GLuint shader)
+{
+ ShaderData* data = m_shaders.get(shader);
+ if (data) {
+ data->refcount++;
}
}
-void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
+void GLSharedGroup::unrefShaderDataLocked(GLuint shader)
{
- assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
- ShaderData* data = m_shaders.valueAt(shaderIdx);
- data->refcount++;
-}
-
-void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
-{
- 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 e7341dc..f111f99 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -16,6 +16,11 @@
#ifndef _GL_SHARED_GROUP_H_
#define _GL_SHARED_GROUP_H_
+#include "emugl/common/id_to_object_map.h"
+#include "emugl/common/mutex.h"
+#include "emugl/common/pod_vector.h"
+#include "emugl/common/smart_ptr.h"
+
#define GL_API
#ifndef ANDROID
#define GL_APIENTRY
@@ -30,18 +35,13 @@
#include <stdio.h>
#include <stdlib.h>
#include "ErrorLog.h"
-#include <utils/KeyedVector.h>
-#include <utils/List.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
#include "FixedBuffer.h"
-#include "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 @@
bool m_initialized;
bool m_locShiftWAR;
- android::Vector<GLuint> m_shaders;
+ emugl::PodVector<GLuint> m_shaders;
public:
enum {
@@ -92,20 +92,22 @@
};
struct ShaderData {
+#if 0 // TODO(digit): Undertand why this is never used?
typedef android::List<android::String8> StringList;
StringList samplerExternalNames;
+#endif
int refcount;
};
class GLSharedGroup {
private:
- android::DefaultKeyedVector<GLuint, BufferData*> m_buffers;
- android::DefaultKeyedVector<GLuint, ProgramData*> m_programs;
- android::DefaultKeyedVector<GLuint, ShaderData*> m_shaders;
- mutable android::Mutex m_lock;
+ emugl::IdToObjectMap<BufferData> m_buffers;
+ emugl::IdToObjectMap<ProgramData> m_programs;
+ emugl::IdToObjectMap<ShaderData> m_shaders;
+ mutable emugl::Mutex m_lock;
- void refShaderDataLocked(ssize_t shaderIdx);
- void unrefShaderDataLocked(ssize_t shaderIdx);
+ void refShaderDataLocked(GLuint shader);
+ void unrefShaderDataLocked(GLuint shader);
public:
GLSharedGroup();
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 @@
#else
::close(m_sock);
#endif
+ m_sock = -1;
}
if (m_buf != NULL) {
free(m_buf);
@@ -140,7 +140,7 @@
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;
+SocketStream * TcpStream::accept() {
+ int clientSock = emugl::socketAccept(m_sock);
+ if (clientSock < 0)
+ return NULL;
- 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;
- }
-
- 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 @@
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 @@
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 8a6c18b..a3dd3c2 100644
--- a/emulator/opengl/shared/OpenglOsUtils/Android.mk
+++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk
@@ -10,6 +10,7 @@
host_common_SRC_FILES := osDynLibrary.cpp
host_common_LDLIBS :=
+host_common_INCLUDES := $(LOCAL_PATH)
ifeq ($(HOST_OS),windows)
host_common_SRC_FILES += \
@@ -29,15 +30,19 @@
### 32-bit host library ####
$(call emugl-begin-host-static-library,libOpenglOsUtils)
- $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
+ $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES))
LOCAL_SRC_FILES = $(host_common_SRC_FILES)
$(call emugl-export,LDLIBS,$(host_common_LDLIBS))
+ $(call emugl-import,libemugl_common)
$(call emugl-end-module)
### 64-bit host library ####
-$(call emugl-begin-host-static-library,lib64OpenglOsUtils)
- $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
- LOCAL_SRC_FILES = $(host_common_SRC_FILES)
- $(call emugl-export,LDLIBS,$(host_common_LDLIBS))
- $(call emugl-export,CFLAGS,-m64)
-$(call emugl-end-module)
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-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-import,lib64emugl_common)
+ $(call emugl-export,CFLAGS,-m64 -fPIC)
+ $(call emugl-end-module)
+endif
diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp
index 8cd73a9..ef2bebc 100644
--- a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp
+++ b/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp
@@ -15,6 +15,8 @@
*/
#include "osThread.h"
+#include "emugl/common/thread_store.h"
+
#include <stdint.h>
namespace osUtils {
@@ -88,6 +90,7 @@
self->m_exitStatus = ret;
pthread_mutex_unlock(&self->m_lock);
+ ::emugl::ThreadStore::OnThreadExit();
return (void*)(uintptr_t)ret;
}
diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp
index 2d563f8..1a30b97 100644
--- a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp
+++ b/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp
@@ -15,6 +15,8 @@
*/
#include "osThread.h"
+#include "emugl/common/thread_store.h"
+
namespace osUtils {
Thread::Thread() :
@@ -95,6 +97,7 @@
Thread *self = (Thread *)p_arg;
int ret = self->Main();
self->m_isRunning = false;
+ ::emugl::ThreadStore::OnThreadExit();
return ret;
}
diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk
index 5c444fd..fd7761e 100644
--- a/emulator/opengl/shared/emugl/common/Android.mk
+++ b/emulator/opengl/shared/emugl/common/Android.mk
@@ -6,31 +6,49 @@
### 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 := \
- smart_ptr_unittest.cpp
+ id_to_object_map_unittest.cpp \
+ lazy_instance_unittest.cpp \
+ pod_vector_unittest.cpp \
+ mutex_unittest.cpp \
+ smart_ptr_unittest.cpp \
+ thread_store_unittest.cpp \
$(call emugl-begin-host-executable,emugl_common_host_unittests)
LOCAL_SRC_FILES := $(host_commonSources)
$(call emugl-import,libemugl_common libemugl_gtest)
$(call emugl-end-module)
-$(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/lazy_instance.cpp b/emulator/opengl/shared/emugl/common/lazy_instance.cpp
new file mode 100644
index 0000000..ee715fa
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/lazy_instance.cpp
@@ -0,0 +1,101 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/lazy_instance.h"
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#else
+# include <sched.h>
+#endif
+
+namespace emugl {
+namespace internal {
+
+typedef LazyInstanceState::AtomicType AtomicType;
+
+#if defined(__GNUC__)
+static inline void compilerBarrier() {
+ __asm__ __volatile__ ("" : : : "memory");
+}
+#else
+#error "Your compiler is not supported"
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+# define acquireBarrier() compilerBarrier()
+# define releaseBarrier() compilerBarrier()
+#else
+# error "Your CPU is not supported"
+#endif
+
+static inline AtomicType loadAcquire(AtomicType volatile* ptr) {
+ AtomicType ret = *ptr;
+ acquireBarrier();
+ return ret;
+}
+
+static inline void storeRelease(AtomicType volatile* ptr, AtomicType value) {
+ releaseBarrier();
+ *ptr = value;
+}
+
+static int atomicCompareAndSwap(AtomicType volatile* ptr,
+ int expected,
+ int value) {
+#ifdef _WIN32
+ return InterlockedCompareExchange(ptr, value, expected);
+#elif defined(__GNUC__)
+ return __sync_val_compare_and_swap(ptr, expected, value);
+#else
+#error "Your compiler is not supported"
+#endif
+}
+
+static void yieldThread() {
+#ifdef _WIN32
+ ::Sleep(0);
+#else
+ sched_yield();
+#endif
+}
+
+bool LazyInstanceState::inInitState() {
+ return loadAcquire(&mState) == STATE_INIT;
+}
+
+bool LazyInstanceState::needConstruction() {
+ AtomicType state = loadAcquire(&mState);
+ if (mState == STATE_DONE)
+ return false;
+
+ state = atomicCompareAndSwap(&mState, STATE_INIT, STATE_CONSTRUCTING);
+ if (state == STATE_INIT)
+ return true;
+
+ do {
+ yieldThread();
+ state = loadAcquire(&mState);
+ } while (state != STATE_DONE);
+
+ return false;
+}
+
+void LazyInstanceState::doneConstructing() {
+ storeRelease(&mState, STATE_DONE);
+}
+
+} // namespace internal
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/lazy_instance.h b/emulator/opengl/shared/emugl/common/lazy_instance.h
new file mode 100644
index 0000000..6641c93
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/lazy_instance.h
@@ -0,0 +1,156 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_LAZY_INSTANCE_H
+#define EMUGL_COMMON_LAZY_INSTANCE_H
+
+#include <new>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#endif
+
+namespace emugl {
+namespace internal {
+
+// A LazyInstance is a helper template that can be used to perform
+// thread-safe lazy initialization of static C++ objects without forcing
+// the generation of C++ static constructors in the final executable.
+//
+// In a nutshell, you can replace a statement like:
+//
+// static Foo gFoo;
+//
+// With:
+//
+// static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT;
+//
+// In the first case, a hidden static C++ constructor is embedded in the
+// final executable, and executed at *load* *time* to call the Foo::Foo
+// constructor on the gFoo object.
+//
+// On the second case, gFoo will only be initialized lazily, i.e. the first
+// time any code actually tries to access the variable.
+//
+// Note that access is slightly different, i.e.:
+//
+// gFoo.get() returns a reference to the lazy-initialized object.
+// gFoo.ptr() returns a pointer to it.
+// gFoo->Something() is equivalent to doing gFoo.ptr()->Something().
+//
+// 'gFoo' is stored in the .bss section and this doesn't use heap allocation.
+// This class can only be used to perform lazy initialization through the
+// class' default constructor. For more specialized cases, you will have
+// to create a derived class, e.g.:
+//
+// class FoorWithDefaultParams : public Foo {
+// public:
+// FooWithDefaultParams() : Foo(<default-parameters>) {}
+// };
+//
+// LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT;
+//
+// The implementation of LazyInstance relies on atomic operations and
+// POD-struct class definitions, i.e. one that doesn't have any constructor,
+// destructor, virtual members, or private ones, and that can be
+// zero-initialized at link time.
+//
+// You can also use LazyInstance<> instances as static local variables,
+// e.g.:
+//
+// Foo* getFooSingleton() {
+// static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT;
+// return sFoo.ptr();
+// }
+//
+// This is useful on Windows which doesn't support thread-safe lazy
+// initialization of static C++ local variables, or when the code is
+// compiled with -fno-threadsafe-statics.
+//
+// This class is heavily inspired by Chromium's implementation of the
+// same-named class (see $CHROMIUM/src/base/lazy_instance.h).
+
+// Atomic state variable type. Used to ensure to synchronize concurrent
+// initialization and access without incurring the full cost of a mutex
+// lock/unlock.
+struct LazyInstanceState {
+ enum {
+ STATE_INIT = 0,
+ STATE_CONSTRUCTING = 1,
+ STATE_DONE = 2,
+ };
+
+ bool inInitState();
+ bool needConstruction();
+ void doneConstructing();
+
+#ifdef _WIN32
+ typedef LONG volatile AtomicType;
+#else
+ typedef int volatile AtomicType;
+#endif
+
+ volatile AtomicType mState;
+};
+
+#define LAZY_INSTANCE_STATE_INIT \
+ { ::emugl::internal::LazyInstanceState::STATE_INIT }
+
+} // namespace internal
+
+// LazyInstance template definition, see comment above for usage
+// instructions. It is crucial to make this a POD-struct compatible
+// type [1].
+//
+// [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures
+//
+template <class T>
+struct LazyInstance {
+ bool hasInstance() const { return !mState.inInitState(); }
+
+ T& get() const { return *ptr(); }
+
+ T* ptr() const;
+
+ const T* operator->() const { return ptr(); }
+
+ T* operator->() { return ptr(); }
+
+ T& operator*() { return get(); }
+
+ // Really private, do not use.
+ union {
+ mutable internal::LazyInstanceState mState;
+ double mPadding;
+ };
+ mutable char mStorage[sizeof(T)];
+};
+
+// Initialization value, must resolve to all-0 to ensure the object
+// instance is actually placed in the .bss
+#define LAZY_INSTANCE_INIT { { LAZY_INSTANCE_STATE_INIT }, { 0 } }
+
+template <class T>
+T* LazyInstance<T>::ptr() const {
+ if (mState.needConstruction()) {
+ new (mStorage) T();
+ mState.doneConstructing();
+ }
+ return reinterpret_cast<T*>(mStorage);
+}
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_LAZY_INSTANCE_H
diff --git a/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp b/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp
new file mode 100644
index 0000000..824845f
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/lazy_instance_unittest.cpp
@@ -0,0 +1,146 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/lazy_instance.h"
+
+#include "emugl/common/mutex.h"
+#include "emugl/common/testing/test_thread.h"
+
+#include <gtest/gtest.h>
+
+namespace emugl {
+
+namespace {
+
+class Foo {
+public:
+ Foo() : mValue(42) {}
+ int get() const { return mValue; }
+ void set(int value) { mValue = value; }
+ ~Foo() { mValue = 13; }
+private:
+ int mValue;
+};
+
+class StaticCounter {
+public:
+ StaticCounter() {
+ Mutex::AutoLock lock(mMutex);
+ mCounter++;
+ }
+
+ int getValue() const {
+ Mutex::AutoLock lock(mMutex);
+ return mCounter;
+ }
+
+private:
+ static Mutex mMutex;
+ static int mCounter;
+};
+
+// NOTE: This introduces a static C++ constructor for this object file,
+// but that's ok because a LazyInstance<Mutex> should not be used to
+// test the behaviour of LazyInstance :-)
+Mutex StaticCounter::mMutex;
+int StaticCounter::mCounter = 0;
+
+} // namespace
+
+TEST(LazyInstance, HasInstance) {
+ LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT;
+ EXPECT_FALSE(foo_instance.hasInstance());
+ EXPECT_FALSE(foo_instance.hasInstance());
+ foo_instance.ptr();
+ EXPECT_TRUE(foo_instance.hasInstance());
+}
+
+TEST(LazyInstance, Simple) {
+ LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT;
+ Foo* foo1 = foo_instance.ptr();
+ EXPECT_TRUE(foo1);
+ EXPECT_EQ(42, foo_instance->get());
+ foo1->set(10);
+ EXPECT_EQ(10, foo_instance->get());
+ EXPECT_EQ(foo1, foo_instance.ptr());
+}
+
+// For the following test, launch 1000 threads that each try to get
+// the instance pointer of a lazy instance. Then verify that they're all
+// the same value.
+//
+// The lazy instance has a special constructor that will increment a
+// global counter. This allows us to ensure that it is only called once.
+//
+
+namespace {
+
+// The following is the shared structure between all threads.
+struct MultiState {
+ MultiState(LazyInstance<StaticCounter>* staticCounter) :
+ mMutex(), mStaticCounter(staticCounter), mCount(0) {}
+
+ enum {
+ kMaxThreads = 1000,
+ };
+
+ Mutex mMutex;
+ LazyInstance<StaticCounter>* mStaticCounter;
+ size_t mCount;
+ void* mValues[kMaxThreads];
+ TestThread* mThreads[kMaxThreads];
+};
+
+// The thread function for the test below.
+static void* threadFunc(void* param) {
+ MultiState* state = static_cast<MultiState*>(param);
+ Mutex::AutoLock lock(state->mMutex);
+ if (state->mCount < MultiState::kMaxThreads) {
+ state->mValues[state->mCount++] = state->mStaticCounter->ptr();
+ }
+ return NULL;
+}
+
+} // namespace
+
+TEST(LazyInstance, MultipleThreads) {
+ LazyInstance<StaticCounter> counter_instance = LAZY_INSTANCE_INIT;
+ MultiState state(&counter_instance);
+ const size_t kNumThreads = MultiState::kMaxThreads;
+
+ // Create all threads.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ state.mThreads[n] = new TestThread(threadFunc, &state);
+ }
+
+ // Wait for their completion.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ state.mThreads[n]->join();
+ }
+
+ // Now check that the constructor was only called once.
+ EXPECT_EQ(1, counter_instance->getValue());
+
+ // Now compare all the store values, they should be the same.
+ StaticCounter* expectedValue = counter_instance.ptr();
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ EXPECT_EQ(expectedValue, state.mValues[n]) << "For thread " << n;
+ }
+
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ delete state.mThreads[n];
+ }
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/mutex.h b/emulator/opengl/shared/emugl/common/mutex.h
new file mode 100644
index 0000000..c6cdcf2
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/mutex.h
@@ -0,0 +1,92 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_MUTEX_H
+#define EMUGL_MUTEX_H
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#else
+# include <pthread.h>
+#endif
+
+namespace emugl {
+
+// Simple wrapper class for mutexes.
+class Mutex {
+public:
+ // Constructor.
+ Mutex() {
+#ifdef _WIN32
+ ::InitializeCriticalSection(&mLock);
+#else
+ ::pthread_mutex_init(&mLock, NULL);
+#endif
+ }
+
+ // Destructor.
+ ~Mutex() {
+#ifdef _WIN32
+ ::DeleteCriticalSection(&mLock);
+#else
+ ::pthread_mutex_destroy(&mLock);
+#endif
+ }
+
+ // Acquire the mutex.
+ void lock() {
+#ifdef _WIN32
+ ::EnterCriticalSection(&mLock);
+#else
+ ::pthread_mutex_lock(&mLock);
+#endif
+ }
+
+ // Release the mutex.
+ void unlock() {
+#ifdef _WIN32
+ ::LeaveCriticalSection(&mLock);
+#else
+ ::pthread_mutex_unlock(&mLock);
+#endif
+ }
+
+ // Helper class to lock / unlock a mutex automatically on scope
+ // entry and exit.
+ class AutoLock {
+ public:
+ AutoLock(Mutex& mutex) : mMutex(&mutex) {
+ mMutex->lock();
+ }
+
+ ~AutoLock() {
+ mMutex->unlock();
+ }
+ private:
+ Mutex* mMutex;
+ };
+
+private:
+#ifdef _WIN32
+ CRITICAL_SECTION mLock;
+#else
+ pthread_mutex_t mLock;
+#endif
+
+};
+
+} // namespace emugl
+
+#endif // EMUGL_MUTEX_H
diff --git a/emulator/opengl/shared/emugl/common/mutex_unittest.cpp b/emulator/opengl/shared/emugl/common/mutex_unittest.cpp
new file mode 100644
index 0000000..e952d75
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/mutex_unittest.cpp
@@ -0,0 +1,108 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/mutex.h"
+
+#include "emugl/common/testing/test_thread.h"
+
+#include <gtest/gtest.h>
+
+namespace emugl {
+
+// Check that construction and destruction doesn't crash.
+TEST(Mutex, ConstructionDestruction) {
+ Mutex lock;
+}
+
+// Check that a simple lock + unlock works.
+TEST(Mutex, LockUnlock) {
+ Mutex lock;
+ lock.lock();
+ lock.unlock();
+}
+
+// Check that AutoLock compiles and doesn't crash.
+TEST(Mutex, AutoLock) {
+ Mutex mutex;
+ Mutex::AutoLock lock(mutex);
+}
+
+// Wrapper class for threads. Does not use emugl::Thread intentionally.
+// Common data type used by the following tests below.
+struct ThreadParams {
+ ThreadParams() : mutex(), counter(0) {}
+
+ Mutex mutex;
+ int counter;
+};
+
+// This thread function uses Mutex::lock/unlock to synchronize a counter
+// increment operation.
+static void* threadFunction(void* param) {
+ ThreadParams* p = static_cast<ThreadParams*>(param);
+
+ p->mutex.lock();
+ p->counter++;
+ p->mutex.unlock();
+ return NULL;
+}
+
+TEST(Mutex, Synchronization) {
+ const size_t kNumThreads = 2000;
+ TestThread* threads[kNumThreads];
+ ThreadParams p;
+
+ // Create and launch all threads.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n] = new TestThread(threadFunction, &p);
+ }
+
+ // Wait until their completion.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n]->join();
+ delete threads[n];
+ }
+
+ EXPECT_EQ(static_cast<int>(kNumThreads), p.counter);
+}
+
+// This thread function uses a Mutex::AutoLock to protect the counter.
+static void* threadAutoLockFunction(void* param) {
+ ThreadParams* p = static_cast<ThreadParams*>(param);
+
+ Mutex::AutoLock lock(p->mutex);
+ p->counter++;
+ return NULL;
+}
+
+TEST(Mutex, AutoLockSynchronization) {
+ const size_t kNumThreads = 2000;
+ TestThread* threads[kNumThreads];
+ ThreadParams p;
+
+ // Create and launch all threads.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n] = new TestThread(threadAutoLockFunction, &p);
+ }
+
+ // Wait until their completion.
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n]->join();
+ delete threads[n];
+ }
+
+ EXPECT_EQ(static_cast<int>(kNumThreads), p.counter);
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp
new file mode 100644
index 0000000..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/shared/emugl/common/testing/test_thread.h b/emulator/opengl/shared/emugl/common/testing/test_thread.h
new file mode 100644
index 0000000..2d758b3
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/testing/test_thread.h
@@ -0,0 +1,78 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_TESTING_TEST_THREAD_H
+#define EMUGL_COMMON_TESTING_TEST_THREAD_H
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#else
+# include <pthread.h>
+#endif
+
+namespace emugl {
+
+// Very basic platform thread wrapper that only uses a tiny stack.
+// This shall only be used during unit testing, and allows test code
+// to not depend on the implementation of emugl::Thread.
+class TestThread {
+public:
+ // Main thread function type.
+ typedef void* (ThreadFunction)(void* param);
+
+ // Constructor actually launches a new platform thread.
+ TestThread(ThreadFunction* func, void* funcParam) {
+#ifdef _WIN32
+ mThread = CreateThread(NULL,
+ 16384,
+ (DWORD WINAPI (*)(void*))func,
+ funcParam,
+ NULL,
+ NULL);
+#else
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 16384);
+ pthread_create(&mThread, &attr, func, funcParam);
+ pthread_attr_destroy(&attr);
+#endif
+ }
+
+ ~TestThread() {
+#ifdef _WIN32
+ CloseHandle(mThread);
+#endif
+ }
+
+ void join() {
+#ifdef _WIN32
+ WaitForSingleObject(mThread, INFINITE);
+#else
+ void* ret = NULL;
+ pthread_join(mThread, &ret);
+#endif
+ }
+
+private:
+#ifdef _WIN32
+ HANDLE mThread;
+#else
+ pthread_t mThread;
+#endif
+};
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_TESTING_TEST_THREAD_H
diff --git a/emulator/opengl/shared/emugl/common/thread_store.cpp b/emulator/opengl/shared/emugl/common/thread_store.cpp
new file mode 100644
index 0000000..ea64c6f
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/thread_store.cpp
@@ -0,0 +1,242 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/thread_store.h"
+
+#ifdef _WIN32
+#include "emugl/common/lazy_instance.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Set to 1 to print debug messages.
+#define DEBUG_THREAD_STORE 0
+
+#if DEBUG_THREAD_STORE
+# define D(...) do { printf("%s:%d: ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); fflush(stdout); } while (0)
+#else
+# define D(...) ((void)0)
+#endif
+
+namespace emugl {
+
+#ifdef _WIN32
+
+namespace {
+
+// The ThreadStore implementation on Windows is very tricky, because
+// TlsAlloc() doesn't allow one to provide a destructor function. As
+// such threads are expected to destroy all TLS values explicitely.
+//
+// To solve this issue, this source file provides a static method called
+// ThreadStore::OnThreadExit() that must be called when a thread exits,
+// which will cleanup all values for the current thread.
+//
+// But this forces us to track thread-specific values ourselves.
+
+// Maximum amount of thread-specific slots supported by this implementation.
+enum {
+ kMaxTlsSlots = 64
+};
+
+// TlsSlotArray is a thread-specific array of values. Instances will
+// be stored in a Win32 TLS value controlled by a single master TLS
+// key.
+//
+typedef void* TlsSlotArray[kMaxTlsSlots];
+
+// Global state shared by all threads
+class GlobalState {
+public:
+ GlobalState() {
+ D("Entering\n");
+ mMasterTls = TlsAlloc();
+ D("Master TLS = %d\n", (int)mMasterTls);
+ InitializeCriticalSection(&mSection);
+ mLastIndex = 0;
+ ::memset(mDestructors, 0, sizeof(mDestructors));
+ D("Exiting\n");
+ }
+
+ // Register a new TLS key, or return -1 on error (too many keys).
+ // |destroy| is the destructor function for the key.
+ int registerKey(ThreadStore::Destructor* destroy) {
+ D("Entering destroy=%p\n", destroy);
+ int ret = -1;
+ EnterCriticalSection(&mSection);
+ if (mLastIndex < kMaxTlsSlots) {
+ ret = mLastIndex++;
+ mDestructors[ret] = destroy;
+ }
+ LeaveCriticalSection(&mSection);
+ D("Exiting newKey=%d\n", ret);
+ return ret;
+ }
+
+ void unregisterKey(int key) {
+ D("key=%d\n", key);
+ if (key < 0 || key >= kMaxTlsSlots) {
+ D("Invalid key\n");
+ return;
+ }
+
+ // Note: keys are not reusable, but remove the destructor to avoid
+ // crashes in leaveCurrentThread() when it points to a function that
+ // is going to be unloaded from the process' address space.
+ EnterCriticalSection(&mSection);
+ mDestructors[key] = NULL;
+ LeaveCriticalSection(&mSection);
+ D("Exiting\n");
+ }
+
+ // Get the current thread-local value for a given |key|.
+ void* getValue(int key) const {
+ D("Entering key=%d\n", key);
+ if (key < 0 || key >= kMaxTlsSlots) {
+ D("Invalid key, result=NULL\n");
+ return NULL;
+ }
+
+ TlsSlotArray* array = getArray();
+ void* ret = (*array)[key];
+ D("Exiting keyValue=%p\n", ret);
+ return ret;
+ }
+
+ // Set the current thread-local |value| for a given |key|.
+ void setValue(int key, void* value) {
+ D("Entering key=%d\n",key);
+ if (key < 0 || key >= kMaxTlsSlots) {
+ D("Invalid key, returning\n");
+ return;
+ }
+
+ TlsSlotArray* array = getArray();
+ (*array)[key] = value;
+ D("Exiting\n");
+ }
+
+ // Call this when a thread exits to destroy all its thread-local values.
+ void leaveCurrentThread() {
+ D("Entering\n");
+ TlsSlotArray* array =
+ reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls));
+ if (!array) {
+ D("Exiting, no thread-local data in this thread\n");
+ return;
+ }
+
+ for (size_t n = 0; n < kMaxTlsSlots; ++n) {
+ void* value = array[n];
+ if (value) {
+ (*array)[n] = NULL;
+ // NOTE: In theory, a destructor could reset the slot to
+ // a new value, and we would have to loop in this function
+ // in interesting ways. In practice, ignore the issue.
+ EnterCriticalSection(&mSection);
+ ThreadStore::Destructor* destroy = mDestructors[n];
+ LeaveCriticalSection(&mSection);
+ if (destroy) {
+ D("Calling destructor %p for key=%d, with value=%p\n",
+ destroy, (int)n, value);
+ (*destroy)(value);
+ }
+ }
+ }
+ TlsSetValue(mMasterTls, NULL);
+ ::free(array);
+ D("Exiting\n");
+ }
+
+private:
+ // Return the thread-local array of TLS slots for the current thread.
+ // Cannot return NULL.
+ TlsSlotArray* getArray() const {
+ D("Entering\n");
+ TlsSlotArray* array =
+ reinterpret_cast<TlsSlotArray*>(TlsGetValue(mMasterTls));
+ if (!array) {
+ array = reinterpret_cast<TlsSlotArray*>(
+ ::calloc(sizeof(*array), 1));
+ TlsSetValue(mMasterTls, array);
+ D("Allocated new array at %p\n", array);
+ } else {
+ D("Retrieved array at %p\n", array);
+ }
+ return array;
+ }
+
+ DWORD mMasterTls;
+ CRITICAL_SECTION mSection;
+ int mLastIndex;
+ ThreadStore::Destructor* mDestructors[kMaxTlsSlots];
+};
+
+LazyInstance<GlobalState> gGlobalState = LAZY_INSTANCE_INIT;
+
+} // namespace
+
+ThreadStore::ThreadStore(Destructor* destroy) {
+ D("Entering this=%p destroy=%p\n", this, destroy);
+ mKey = gGlobalState->registerKey(destroy);
+ D("Exiting this=%p key=%d\n", this, mKey);
+}
+
+ThreadStore::~ThreadStore() {
+ D("Entering this=%p\n", this);
+ GlobalState* state = gGlobalState.ptr();
+ state->unregisterKey(mKey);
+ D("Exiting this=%p\n", this);
+}
+
+void* ThreadStore::get() const {
+ D("Entering this=%p\n", this);
+ void* ret = gGlobalState->getValue(mKey);
+ D("Exiting this=%p value=%p\n", this, ret);
+ return ret;
+}
+
+void ThreadStore::set(void* value) {
+ D("Entering this=%p value=%p\n", this, value);
+ gGlobalState->setValue(mKey, value);
+ D("Exiting this=%p\n", this);
+}
+
+// static
+void ThreadStore::OnThreadExit() {
+ gGlobalState->leaveCurrentThread();
+}
+
+#else // !_WIN32
+
+ThreadStore::ThreadStore(Destructor* destroy) {
+ int ret = pthread_key_create(&mKey, destroy);
+ if (ret != 0) {
+ fprintf(stderr,
+ "Could not create thread store key: %s\n",
+ strerror(ret));
+ exit(1);
+ }
+}
+
+ThreadStore::~ThreadStore() {
+ pthread_key_delete(mKey);
+}
+
+#endif // !_WIN32
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/thread_store.h b/emulator/opengl/shared/emugl/common/thread_store.h
new file mode 100644
index 0000000..5fd08bd
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/thread_store.h
@@ -0,0 +1,110 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_THREAD_STORE_H
+#define EMUGL_COMMON_THREAD_STORE_H
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#else
+# include <pthread.h>
+#endif
+
+namespace emugl {
+
+// A class to model storage of thread-specific values, that can be
+// destroyed on thread exit.
+//
+// Note that on Windows, a thread must call OnThreadExit() explicitly
+// here to ensure that the values are probably discarded. This is an
+// unfortunate requirement of the Win32 API, which doesn't support
+// destructors at all.
+//
+// There are various hacks on the web to try to achieve this automatically
+// (e.g. [1]) but they rely on using the Microsoft build tools,
+// which doesn't work for us.
+//
+// Note another important issue with ThreadStore instances: if you create
+// one instance in a shared library, you need to make sure that it is
+// always destroyed before the library is unloaded. Otherwise, future
+// thread exit will likely crash, due to calling a destructor function
+// that is no longer in the process' address space.
+//
+// Finally, destroying an instance does _not_ free the corresponding values,
+// because doing so properly requires coordinating all participating threads,
+// which is impossible to achieve in the most general case. Thus, consider
+// that thread-local values are always leaked on library unload, or on
+// program exit.
+//
+// [1] http://stackoverflow.com/questions/14538159/about-tls-callback-in-windows
+
+class ThreadStore {
+public:
+ // Type of a function used to destroy a thread-specific value that
+ // was previously assigned by calling set().
+ typedef void (Destructor)(void* value);
+
+ // Initialize instance so that is hold keys that must be destroyed
+ // on thread exit by calling |destroy|.
+ explicit ThreadStore(Destructor* destroy);
+
+ // NOTE: Destructor don't free the thread-local values, but are required
+ // to avoid crashes (see note above).
+ ~ThreadStore();
+
+ // Retrieve current thread-specific value from store.
+#ifdef _WIN32
+ void* get() const;
+#else
+ inline void* get() const {
+ return pthread_getspecific(mKey);
+ }
+#endif
+
+ // Set the new thread-specific value.
+#ifdef _WIN32
+ void set(void* value);
+#else
+ inline void set(void* value) {
+ pthread_setspecific(mKey, value);
+ }
+#endif
+
+#ifdef _WIN32
+ // Each thread should call this function on exit to ensure that
+ // all corresponding TLS values are properly freed.
+ static void OnThreadExit();
+#else
+ // Nothing to do on Posix.
+ static inline void OnThreadExit() {}
+#endif
+
+private:
+ // Ensure you can't create an empty ThreadStore instance, or simply
+ // copy it in any way.
+ ThreadStore();
+ ThreadStore(const ThreadStore&);
+ ThreadStore& operator=(const ThreadStore&);
+
+#ifdef _WIN32
+ int mKey;
+#else
+ pthread_key_t mKey;
+#endif
+};
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_THREAD_STORE_H
diff --git a/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp b/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp
new file mode 100644
index 0000000..6b5dddb
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/thread_store_unittest.cpp
@@ -0,0 +1,146 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/thread_store.h"
+
+#include "emugl/common/mutex.h"
+#include "emugl/common/testing/test_thread.h"
+
+#include <gtest/gtest.h>
+
+namespace emugl {
+
+namespace {
+
+// Helper class used to count instance creation and destruction.
+class StaticCounter {
+public:
+ enum {
+ kMaxInstances = 1000,
+ };
+
+ StaticCounter() {
+ Mutex::AutoLock lock(mMutex);
+ if (mCreationCount < kMaxInstances)
+ mInstances[mCreationCount] = this;
+ mCreationCount++;
+ }
+
+ ~StaticCounter() {
+ Mutex::AutoLock lock(mMutex);
+ mDestructionCount++;
+ }
+
+ static void reset() {
+ Mutex::AutoLock lock(mMutex);
+ mCreationCount = 0;
+ mDestructionCount = 0;
+ }
+
+ static size_t getCreationCount() {
+ Mutex::AutoLock lock(mMutex);
+ return mCreationCount;
+ }
+
+ static size_t getDestructionCount() {
+ Mutex::AutoLock lock(mMutex);
+ return mDestructionCount;
+ }
+
+ static void freeAll() {
+ for (size_t n = 0; n < kMaxInstances; ++n)
+ delete mInstances[n];
+ }
+
+private:
+ static Mutex mMutex;
+ static size_t mCreationCount;
+ static size_t mDestructionCount;
+ static StaticCounter* mInstances[kMaxInstances];
+};
+
+Mutex StaticCounter::mMutex;
+size_t StaticCounter::mCreationCount = 0;
+size_t StaticCounter::mDestructionCount = 0;
+StaticCounter* StaticCounter::mInstances[kMaxInstances];
+
+} // namespace
+
+// Just check that we can create a new ThreadStore with an empty
+// destructor, and use it in the current thread.
+TEST(ThreadStore, MainThreadWithoutDestructor) {
+ ThreadStore store(NULL);
+ static int x = 42;
+ store.set(&x);
+ EXPECT_EQ(&x, store.get());
+}
+
+// The following test checks that exiting a thread correctly deletes
+// any thread-local value stored in it.
+static void simplyDestroy(void* value) {
+ delete (StaticCounter*) value;
+}
+
+static void* simpleThreadFunc(void* param) {
+ ThreadStore* store = static_cast<ThreadStore*>(param);
+ store->set(new StaticCounter());
+ ThreadStore::OnThreadExit();
+ return NULL;
+}
+
+TEST(ThreadStore, ThreadsWithDestructor) {
+ ThreadStore store(simplyDestroy);
+ const size_t kNumThreads = 1000;
+ TestThread* threads[kNumThreads];
+ StaticCounter::reset();
+
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n] = new TestThread(&simpleThreadFunc, &store);
+ }
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n]->join();
+ }
+
+ EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount());
+ EXPECT_EQ(kNumThreads, StaticCounter::getDestructionCount());
+
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ delete threads[n];
+ }
+}
+
+TEST(ThreadStore, ThreadsWithoutDestructor) {
+ ThreadStore store(NULL);
+ const size_t kNumThreads = 1000;
+ TestThread* threads[kNumThreads];
+ StaticCounter::reset();
+
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n] = new TestThread(&simpleThreadFunc, &store);
+ }
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ threads[n]->join();
+ }
+
+ EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount());
+ EXPECT_EQ(0U, StaticCounter::getDestructionCount());
+
+ StaticCounter::freeAll();
+
+ for (size_t n = 0; n < kNumThreads; ++n) {
+ delete threads[n];
+ }
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/tests/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 @@
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 @@
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 @@
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 @@
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 @@
ifeq ($(HOST_OS), linux)
$(call emugl-begin-host-executable,ut_renderer)
-$(call emugl-import,libut_rendercontrol_dec libGLESv1_dec libGLESv2_dec libEGL_host_wrapper)
+$(call emugl-import,libut_rendercontrol_dec libGLESv1_dec libGLESv2_dec libEGL_host_wrapper libOpenglRender)
LOCAL_SRC_FILES := ut_renderer.cpp \
RenderingThread.cpp \
diff --git a/emulator/opengl/tests/ut_renderer/Renderer.cpp b/emulator/opengl/tests/ut_renderer/Renderer.cpp
index 22afadb..1102014 100644
--- a/emulator/opengl/tests/ut_renderer/Renderer.cpp
+++ b/emulator/opengl/tests/ut_renderer/Renderer.cpp
@@ -56,7 +56,7 @@
int Renderer::createSurface(RenderingThread *thread, const ClientHandle & handle)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
assert(m_surfaces.find(handle) == m_surfaces.end());
if (handle.handle == 0) {
@@ -75,7 +75,7 @@
int Renderer::destroySurface(RenderingThread *thread, const ClientHandle &handle)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
SurfaceMap::iterator i = m_surfaces.find(handle);
if (i == m_surfaces.end()) {
@@ -90,7 +90,7 @@
int Renderer::createContext(RenderingThread *thread, const ClientHandle &handle, ClientHandle shareCtx, int version)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
assert(m_ctxs.find(handle) == m_ctxs.end());
RendererContext *shared = NULL;
@@ -115,7 +115,7 @@
int Renderer::destroyContext(RenderingThread *thread, const ClientHandle &handle)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
ContextMap::iterator i = m_ctxs.find(handle);
if (i == m_ctxs.end()) {
@@ -133,7 +133,7 @@
const ClientHandle &readSurface,
const ClientHandle & ctx)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
RendererContext *currentContext = thread->currentContext();
@@ -172,7 +172,7 @@
int Renderer::swapBuffers(RenderingThread *thread,
const ClientHandle &surface)
{
- android::Mutex::Autolock(this->m_mutex);
+ emugl::Mutex::AutoLock(this->m_mutex);
SurfaceMap::iterator s = m_surfaces.find(surface);
if (s == m_surfaces.end()) {
diff --git a/emulator/opengl/tests/ut_renderer/Renderer.h b/emulator/opengl/tests/ut_renderer/Renderer.h
index cdf10b6..81f4077 100644
--- a/emulator/opengl/tests/ut_renderer/Renderer.h
+++ b/emulator/opengl/tests/ut_renderer/Renderer.h
@@ -19,7 +19,7 @@
#include "RendererSurface.h"
#include "RendererContext.h"
#include "NativeWindowing.h"
-#include <utils/threads.h>
+#include "emugl/common/mutex.h"
class RenderingThread;
@@ -57,6 +57,6 @@
NativeWindowing *m_nw;
EGLDisplay m_dpy;
- android::Mutex m_mutex; // single global mutex for the renderer class;
+ emugl::Mutex m_mutex; // single global mutex for the renderer class;
};
#endif