aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/shared
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2014-03-11 19:58:51 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-03-11 19:58:51 +0000
commit84b68033f6b92a3c35ac1d3ab7f8278c54744cff (patch)
treeba6e795703570bd83fbfcdf92216359452ebb358 /emulator/opengl/shared
parent81431aae3aaf95209a606511b3a81f6aa06ffe9f (diff)
parent56b89bc863d1a5da6234f05923f63b5466e1ce3f (diff)
downloadsdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.zip
sdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.tar.gz
sdk-84b68033f6b92a3c35ac1d3ab7f8278c54744cff.tar.bz2
Merge changes I205392bd,I84a058bb,I22c67f11,Id18319e8,I9836ed96, ... into idea133
* changes: emulator/opengl: Allow standalone build. emulator/opengl: Remove libcutils/libutils/liblog emulator/opengl: Remove <utils/List.h> + <utils/String8.h> emulator/opengl: Remove android::KeyedVector usage. emulator/opengl: Remove android::Vector<> usage. emulator/opengl: Remove <cutils/sockets.h>
Diffstat (limited to 'emulator/opengl/shared')
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/Android.mk22
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h22
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp248
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h26
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp4
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp72
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp8
-rw-r--r--emulator/opengl/shared/OpenglOsUtils/Android.mk15
-rw-r--r--emulator/opengl/shared/emugl/common/Android.mk29
-rw-r--r--emulator/opengl/shared/emugl/common/id_to_object_map.cpp236
-rw-r--r--emulator/opengl/shared/emugl/common/id_to_object_map.h176
-rw-r--r--emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp116
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector.cpp151
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector.h267
-rw-r--r--emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp127
-rw-r--r--emulator/opengl/shared/emugl/common/scoped_pointer_vector.h27
-rw-r--r--emulator/opengl/shared/emugl/common/sockets.cpp221
-rw-r--r--emulator/opengl/shared/emugl/common/sockets.h57
18 files changed, 1573 insertions, 251 deletions
diff --git a/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/emulator/opengl/shared/OpenglCodecCommon/Android.mk
index 5deb1f7..b6a7e07 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/Android.mk
+++ b/emulator/opengl/shared/OpenglCodecCommon/Android.mk
@@ -24,19 +24,21 @@ endif
$(call emugl-begin-host-static-library,libOpenglCodecCommon)
LOCAL_SRC_FILES := $(host_commonSources)
-
-$(call emugl-export,STATIC_LIBRARIES,libcutils)
-$(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
+$(call emugl-import, libemugl_common)
+$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH))
+$(call emugl-export,LDLIBS,-lstdc++)
$(call emugl-end-module)
### OpenglCodecCommon host, 64-bit #########################################
-$(call emugl-begin-host-static-library,lib64OpenglCodecCommon)
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host-static-library,lib64OpenglCodecCommon)
-LOCAL_SRC_FILES := $(host_commonSources)
-
-$(call emugl-export,STATIC_LIBRARIES,lib64cutils)
-$(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
-$(call emugl-export,CFLAGS,-m64)
-$(call emugl-end-module)
+ LOCAL_SRC_FILES := $(host_commonSources)
+ $(call emugl-import, lib64emugl_common)
+ $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH))
+ $(call emugl-export,CFLAGS,-m64 -fPIC)
+ $(call emugl-export,LDLIBS,-lstdc++)
+ $(call emugl-end-module)
+endif
diff --git a/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h b/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h
index 43577d4..4cad61f 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h
+++ b/emulator/opengl/shared/OpenglCodecCommon/ErrorLog.h
@@ -16,22 +16,12 @@
#ifndef _ERROR_LOG_H_
#define _ERROR_LOG_H_
-#ifdef __ANDROID__
-# include <cutils/log.h>
-# define ERR(...) ALOGE(__VA_ARGS__)
-# ifdef EMUGL_DEBUG
-# define DBG(...) ALOGD(__VA_ARGS__)
-# else
-# define DBG(...) ((void)0)
-# endif
+#include <stdio.h>
+#define ERR(...) fprintf(stderr, __VA_ARGS__)
+#ifdef EMUGL_DEBUG
+# define DBG(...) fprintf(stderr, __VA_ARGS__)
#else
-# include <stdio.h>
-# define ERR(...) fprintf(stderr, __VA_ARGS__)
-# ifdef EMUGL_DEBUG
-# define DBG(...) fprintf(stderr, __VA_ARGS__)
-# else
-# define DBG(...) ((void)0)
-# endif
+# define DBG(...) ((void)0)
#endif
-#endif
+#endif // _ERROR_LOG_H_
diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
index a054562..db7f418 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -16,23 +16,22 @@
#include "GLSharedGroup.h"
-/**** KeyedVector utilities ****/
-
-template <typename T>
-static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) {
- for (size_t i = 0; i < v.size(); i++)
- delete v.valueAt(i);
- v.clear();
-}
+#include <string.h>
/**** BufferData ****/
BufferData::BufferData() : m_size(0) {};
+
BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
{
- void * buffer = NULL;
- if (size>0) buffer = m_fixedBuffer.alloc(size);
- if (data) memcpy(buffer, data, size);
+ void* buffer = NULL;
+
+ if (size > 0) {
+ buffer = m_fixedBuffer.alloc(size);
+ if (data) {
+ memcpy(buffer, data, size);
+ }
+ }
}
/**** ProgramData ****/
@@ -204,9 +203,7 @@ bool ProgramData::attachShader(GLuint shader)
return false;
}
}
- // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
- // due to the default parameters. This is the desired insertAt() overload.
- m_shaders.insertAt(shader, m_shaders.size(), 1);
+ m_shaders.append(shader);
return true;
}
@@ -215,7 +212,7 @@ bool ProgramData::detachShader(GLuint shader)
size_t n = m_shaders.size();
for (size_t i = 0; i < n; i++) {
if (m_shaders[i] == shader) {
- m_shaders.removeAt(i);
+ m_shaders.remove(i);
return true;
}
}
@@ -225,49 +222,32 @@ bool ProgramData::detachShader(GLuint shader)
/***** GLSharedGroup ****/
GLSharedGroup::GLSharedGroup() :
- m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
- m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
- m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
-{
-}
+ m_buffers(), m_programs(), m_shaders() {}
-GLSharedGroup::~GLSharedGroup()
-{
- m_buffers.clear();
- m_programs.clear();
- clearObjectMap(m_buffers);
- clearObjectMap(m_programs);
- clearObjectMap(m_shaders);
-}
+GLSharedGroup::~GLSharedGroup() {}
BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
{
emugl::Mutex::AutoLock _lock(m_lock);
- return m_buffers.valueFor(bufferId);
+ return m_buffers.get(bufferId);
}
void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
{
emugl::Mutex::AutoLock _lock(m_lock);
- m_buffers.add(bufferId, new BufferData(size, data));
+ m_buffers.set(bufferId, new BufferData(size, data));
}
void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ssize_t idx = m_buffers.indexOfKey(bufferId);
- if (idx >= 0) {
- delete m_buffers.valueAt(idx);
- m_buffers.editValueAt(idx) = new BufferData(size, data);
- } else {
- m_buffers.add(bufferId, new BufferData(size, data));
- }
+ m_buffers.set(bufferId, new BufferData(size, data));
}
GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
{
emugl::Mutex::AutoLock _lock(m_lock);
- BufferData * buf = m_buffers.valueFor(bufferId);
+ BufferData * buf = m_buffers.get(bufferId);
if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
//it's safe to update now
@@ -278,32 +258,20 @@ GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsi
void GLSharedGroup::deleteBufferData(GLuint bufferId)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ssize_t idx = m_buffers.indexOfKey(bufferId);
- if (idx >= 0) {
- delete m_buffers.valueAt(idx);
- m_buffers.removeItemsAt(idx);
- }
+ ssize_t idx = m_buffers.remove(bufferId);
}
void GLSharedGroup::addProgramData(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- {
- m_programs.removeItem(program);
- delete pData;
- }
-
- m_programs.add(program,new ProgramData());
+ m_programs.set(program, new ProgramData());
}
void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- {
+ ProgramData *pData = m_programs.get(program);
+ if (pData) {
pData->initProgramData(numIndexes);
}
}
@@ -311,136 +279,135 @@ void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
bool GLSharedGroup::isProgramInitialized(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData)
- {
- return pData->isInitialized();
- }
- return false;
+ ProgramData* pData = m_programs.get(program);
+ return pData && pData->isInitialized();
}
void GLSharedGroup::deleteProgramData(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData *pData = m_programs.valueFor(program);
- if (pData)
- delete pData;
- m_programs.removeItem(program);
+ m_programs.remove(program);
}
void GLSharedGroup::attachShader(GLuint program, GLuint shader)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* programData = m_programs.valueFor(program);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (programData && idx >= 0) {
- if (programData->attachShader(shader)) {
- refShaderDataLocked(idx);
- }
+ ProgramData* programData = m_programs.get(program);
+ if (programData && programData->attachShader(shader)) {
+ refShaderDataLocked(shader);
}
}
void GLSharedGroup::detachShader(GLuint program, GLuint shader)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* programData = m_programs.valueFor(program);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (programData && idx >= 0) {
- if (programData->detachShader(shader)) {
- unrefShaderDataLocked(idx);
- }
+ ProgramData* programData = m_programs.get(program);
+ if (programData && programData->detachShader(shader)) {
+ unrefShaderDataLocked(shader);
}
}
-void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
+void GLSharedGroup::setProgramIndexInfo(GLuint program,
+ GLuint index,
+ GLint base,
+ GLint size,
+ GLenum type,
+ const char* name)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData)
- {
- pData->setIndexInfo(index,base,size,type);
-
- if (type == GL_SAMPLER_2D) {
- size_t n = pData->getNumShaders();
- for (size_t i = 0; i < n; i++) {
- GLuint shaderId = pData->getShader(i);
- ShaderData* shader = m_shaders.valueFor(shaderId);
- if (!shader) continue;
- ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
- ShaderData::StringList::iterator nameEnd = shader->samplerExternalNames.end();
- while (nameIter != nameEnd) {
- if (*nameIter == name) {
- pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
- break;
- }
- ++nameIter;
+ ProgramData* pData = m_programs.get(program);
+ if (!pData) {
+ return;
+ }
+ pData->setIndexInfo(index,base,size,type);
+
+ if (type == GL_SAMPLER_2D) {
+ size_t n = pData->getNumShaders();
+ for (size_t i = 0; i < n; i++) {
+ GLuint shaderId = pData->getShader(i);
+ ShaderData* shader = m_shaders.get(shaderId);
+ if (!shader) continue;
+#if 0 // TODO(digit): Understand why samplerExternalNames is always empty?
+ ShaderData::StringList::iterator nameIter =
+ shader->samplerExternalNames.begin();
+ ShaderData::StringList::iterator nameEnd =
+ shader->samplerExternalNames.end();
+ while (nameIter != nameEnd) {
+ if (*nameIter == name) {
+ pData->setIndexFlags(
+ index,
+ ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
+ break;
}
+ ++nameIter;
}
+#endif
}
}
}
+
GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- GLenum type=0;
- if (pData)
- {
- type = pData->getTypeForLocation(location);
- }
- return type;
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->getTypeForLocation(location) : 0;
}
bool GLSharedGroup::isProgram(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- return (pData!=NULL);
+ ProgramData* pData = m_programs.get(program);
+ return (pData != NULL);
}
void GLSharedGroup::setupLocationShiftWAR(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ ProgramData* pData = m_programs.get(program);
if (pData) pData->setupLocationShiftWAR();
}
-GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
+GLint GLSharedGroup::locationWARHostToApp(GLuint program,
+ GLint hostLoc,
+ GLint arrIndex)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
- else return hostLoc;
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->locationWARHostToApp(hostLoc, arrIndex) : hostLoc;
}
GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->locationWARAppToHost(appLoc);
- else return appLoc;
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->locationWARAppToHost(appLoc) : appLoc;
}
bool GLSharedGroup::needUniformLocationWAR(GLuint program)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
- if (pData) return pData->needUniformLocationWAR();
- return false;
+ ProgramData* pData = m_programs.get(program);
+ return pData ? pData->needUniformLocationWAR() : false;
}
-GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
+GLint GLSharedGroup::getNextSamplerUniform(GLuint program,
+ GLint index,
+ GLint* val,
+ GLenum* target) const
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ ProgramData* pData = m_programs.get(program);
return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
}
-bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
+bool GLSharedGroup::setSamplerUniform(GLuint program,
+ GLint appLoc,
+ GLint val,
+ GLenum* target)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ProgramData* pData = m_programs.valueFor(program);
+ ProgramData* pData = m_programs.get(program);
return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
}
@@ -448,44 +415,39 @@ bool GLSharedGroup::addShaderData(GLuint shader)
{
emugl::Mutex::AutoLock _lock(m_lock);
ShaderData* data = new ShaderData;
- if (data) {
- if (m_shaders.add(shader, data) < 0) {
- delete data;
- data = NULL;
- }
- data->refcount = 1;
- }
- return data != NULL;
+ data->refcount = 1;
+ m_shaders.set(shader, data);
+ return true;
}
ShaderData* GLSharedGroup::getShaderData(GLuint shader)
{
emugl::Mutex::AutoLock _lock(m_lock);
- return m_shaders.valueFor(shader);
+ ShaderData* data = m_shaders.get(shader);
+ if (data) {
+ data->refcount++;
+ }
+ return data;
}
void GLSharedGroup::unrefShaderData(GLuint shader)
{
emugl::Mutex::AutoLock _lock(m_lock);
- ssize_t idx = m_shaders.indexOfKey(shader);
- if (idx >= 0) {
- unrefShaderDataLocked(idx);
- }
+ unrefShaderDataLocked(shader);
}
-void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
+void GLSharedGroup::refShaderDataLocked(GLuint shader)
{
- assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
- ShaderData* data = m_shaders.valueAt(shaderIdx);
- data->refcount++;
+ ShaderData* data = m_shaders.get(shader);
+ if (data) {
+ data->refcount++;
+ }
}
-void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
+void GLSharedGroup::unrefShaderDataLocked(GLuint shader)
{
- assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
- ShaderData* data = m_shaders.valueAt(shaderIdx);
- if (--data->refcount == 0) {
- delete data;
- m_shaders.removeItemsAt(shaderIdx);
+ ShaderData* data = m_shaders.get(shader);
+ if (data && --data->refcount == 0) {
+ m_shaders.remove(shader);
}
}
diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
index 02278a2..f111f99 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -16,6 +16,11 @@
#ifndef _GL_SHARED_GROUP_H_
#define _GL_SHARED_GROUP_H_
+#include "emugl/common/id_to_object_map.h"
+#include "emugl/common/mutex.h"
+#include "emugl/common/pod_vector.h"
+#include "emugl/common/smart_ptr.h"
+
#define GL_API
#ifndef ANDROID
#define GL_APIENTRY
@@ -30,18 +35,13 @@
#include <stdio.h>
#include <stdlib.h>
#include "ErrorLog.h"
-#include <utils/KeyedVector.h>
-#include <utils/List.h>
-#include <utils/String8.h>
#include "FixedBuffer.h"
-#include "emugl/common/mutex.h"
-#include "emugl/common/smart_ptr.h"
struct BufferData {
BufferData();
BufferData(GLsizeiptr size, void * data);
GLsizeiptr m_size;
- FixedBuffer m_fixedBuffer;
+ FixedBuffer m_fixedBuffer;
};
class ProgramData {
@@ -61,7 +61,7 @@ private:
bool m_initialized;
bool m_locShiftWAR;
- android::Vector<GLuint> m_shaders;
+ emugl::PodVector<GLuint> m_shaders;
public:
enum {
@@ -92,20 +92,22 @@ public:
};
struct ShaderData {
+#if 0 // TODO(digit): Undertand why this is never used?
typedef android::List<android::String8> StringList;
StringList samplerExternalNames;
+#endif
int refcount;
};
class GLSharedGroup {
private:
- android::DefaultKeyedVector<GLuint, BufferData*> m_buffers;
- android::DefaultKeyedVector<GLuint, ProgramData*> m_programs;
- android::DefaultKeyedVector<GLuint, ShaderData*> m_shaders;
+ emugl::IdToObjectMap<BufferData> m_buffers;
+ emugl::IdToObjectMap<ProgramData> m_programs;
+ emugl::IdToObjectMap<ShaderData> m_shaders;
mutable emugl::Mutex m_lock;
- void refShaderDataLocked(ssize_t shaderIdx);
- void unrefShaderDataLocked(ssize_t shaderIdx);
+ void refShaderDataLocked(GLuint shader);
+ void unrefShaderDataLocked(GLuint shader);
public:
GLSharedGroup();
diff --git a/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp
index f7a2314..3ef4c6f 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp
+++ b/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
#include "SocketStream.h"
-#include <cutils/sockets.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -53,6 +52,7 @@ SocketStream::~SocketStream()
#else
::close(m_sock);
#endif
+ m_sock = -1;
}
if (m_buf != NULL) {
free(m_buf);
@@ -140,7 +140,7 @@ const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
int n;
do {
- n = recv(buf, *inout_len);
+ n = this->recv(buf, *inout_len);
} while( n < 0 && errno == EINTR );
if (n > 0) {
diff --git a/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp
index 8a6e56e..ba355ab 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp
+++ b/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
#include "TcpStream.h"
-#include <cutils/sockets.h>
+#include "emugl/common/sockets.h"
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -30,77 +31,48 @@
#define LISTEN_BACKLOG 4
-TcpStream::TcpStream(size_t bufSize) :
- SocketStream(bufSize)
-{
-}
+TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {}
TcpStream::TcpStream(int sock, size_t bufSize) :
- SocketStream(sock, bufSize)
-{
+ SocketStream(sock, bufSize) {
// disable Nagle algorithm to improve bandwidth of small
// packets which are quite common in our implementation.
-#ifdef _WIN32
- DWORD flag;
-#else
- int flag;
-#endif
- flag = 1;
- setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag) );
+ emugl::socketTcpDisableNagle(sock);
}
-int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN])
-{
- m_sock = socket_loopback_server(0, SOCK_STREAM);
+int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
+ m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM);
if (!valid())
return int(ERR_INVALID_SOCKET);
- /* get the actual port number assigned by the system */
- struct sockaddr_in addr;
- socklen_t addrLen = sizeof(addr);
- memset(&addr, 0, sizeof(addr));
- if (getsockname(m_sock, (struct sockaddr*)&addr, &addrLen) < 0) {
- close(m_sock);
+ int port = emugl::socketGetPort(m_sock);
+ if (port < 0) {
+ ::close(m_sock);
return int(ERR_INVALID_SOCKET);
}
- snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", ntohs(addr.sin_port));
+
+ snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", port);
addrstr[MAX_ADDRSTR_LEN-1] = '\0';
return 0;
}
-SocketStream * TcpStream::accept()
-{
- int clientSock = -1;
-
- while (true) {
- struct sockaddr_in addr;
- socklen_t len = sizeof(addr);
- clientSock = ::accept(m_sock, (sockaddr *)&addr, &len);
-
- if (clientSock < 0 && errno == EINTR) {
- continue;
- }
- break;
- }
+SocketStream * TcpStream::accept() {
+ int clientSock = emugl::socketAccept(m_sock);
+ if (clientSock < 0)
+ return NULL;
- TcpStream *clientStream = NULL;
-
- if (clientSock >= 0) {
- clientStream = new TcpStream(clientSock, m_bufsize);
- }
- return clientStream;
+ return new TcpStream(clientSock, m_bufsize);
}
-int TcpStream::connect(const char* addr)
-{
+int TcpStream::connect(const char* addr) {
int port = atoi(addr);
- return connect("127.0.0.1",port);
+ m_sock = emugl::socketTcpLoopbackClient(port, SOCK_STREAM);
+ return valid() ? 0 : -1;
}
int TcpStream::connect(const char* hostname, unsigned short port)
{
- m_sock = socket_network_client(hostname, port, SOCK_STREAM);
- if (!valid()) return -1;
- return 0;
+ m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM);
+ return valid() ? 0 : -1;
}
diff --git a/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp b/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp
index b2eef6d..7b2f67d 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp
+++ b/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
#include "UnixStream.h"
-#include <cutils/sockets.h>
+
+#include "emugl/common/sockets.h"
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -92,7 +94,7 @@ int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
return -1;
}
- m_sock = socket_local_server(addrstr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+ m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM);
if (!valid()) return int(ERR_INVALID_SOCKET);
return 0;
@@ -123,7 +125,7 @@ SocketStream * UnixStream::accept()
int UnixStream::connect(const char* addr)
{
- m_sock = socket_local_client(addr, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+ m_sock = emugl::socketLocalClient(addr, SOCK_STREAM);
if (!valid()) return -1;
return 0;
diff --git a/emulator/opengl/shared/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk
index d8807d0..566fd10 100644
--- a/emulator/opengl/shared/OpenglOsUtils/Android.mk
+++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk
@@ -37,10 +37,11 @@ $(call emugl-begin-host-static-library,libOpenglOsUtils)
$(call emugl-end-module)
### 64-bit host library ####
-$(call emugl-begin-host-static-library,lib64OpenglOsUtils)
- $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES))
- LOCAL_SRC_FILES = $(host_common_SRC_FILES)
- $(call emugl-export,LDLIBS,$(host_common_LDLIBS))
- $(call emugl-export,CFLAGS,-m64)
- $(call emugl-import,lib64emugl_common)
-$(call emugl-end-module)
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host-static-library,lib64OpenglOsUtils)
+ $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES))
+ LOCAL_SRC_FILES = $(host_common_SRC_FILES)
+ $(call emugl-export,LDLIBS,$(host_common_LDLIBS))
+ $(call emugl-export,CFLAGS,-m64 -fPIC)
+ $(call emugl-end-module)
+endif \ No newline at end of file
diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk
index f1c20b5..fd7761e 100644
--- a/emulator/opengl/shared/emugl/common/Android.mk
+++ b/emulator/opengl/shared/emugl/common/Android.mk
@@ -6,26 +6,37 @@ LOCAL_PATH := $(call my-dir)
### emugl_common host library ###########################################
commonSources := \
+ id_to_object_map.cpp \
lazy_instance.cpp \
+ pod_vector.cpp \
smart_ptr.cpp \
+ sockets.cpp \
thread_store.cpp \
host_commonSources := $(commonSources)
$(call emugl-begin-host-static-library,libemugl_common)
LOCAL_SRC_FILES := $(host_commonSources)
+$(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared)
+$(call emugl-export,LDLIBS,-lstdc++)
$(call emugl-end-module)
-$(call emugl-begin-host-static-library,lib64emugl_common)
-LOCAL_SRC_FILES := $(host_commonSources)
-$(call emugl-export,CFLAGS,-m64)
-$(call emugl-end-module)
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host-static-library,lib64emugl_common)
+ LOCAL_SRC_FILES := $(host_commonSources)
+ $(call emugl-export,CFLAGS,-m64 -fPIC)
+ $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared)
+ $(call emugl-export,LDLIBS,-lstdc++)
+ $(call emugl-end-module)
+endif
### emugl_common_unittests ##############################################
host_commonSources := \
+ id_to_object_map_unittest.cpp \
lazy_instance_unittest.cpp \
+ pod_vector_unittest.cpp \
mutex_unittest.cpp \
smart_ptr_unittest.cpp \
thread_store_unittest.cpp \
@@ -35,7 +46,9 @@ LOCAL_SRC_FILES := $(host_commonSources)
$(call emugl-import,libemugl_common libemugl_gtest)
$(call emugl-end-module)
-$(call emugl-begin-host-executable,emugl64_common_host_unittests)
-LOCAL_SRC_FILES := $(host_commonSources)
-$(call emugl-import,lib64emugl_common lib64emugl_gtest)
-$(call emugl-end-module)
+ifdef EMUGL_BUILD_64BITS
+ $(call emugl-begin-host-executable,emugl64_common_host_unittests)
+ LOCAL_SRC_FILES := $(host_commonSources)
+ $(call emugl-import,lib64emugl_common lib64emugl_gtest)
+ $(call emugl-end-module)
+endif
diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map.cpp
new file mode 100644
index 0000000..597c9eb
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/id_to_object_map.cpp
@@ -0,0 +1,236 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/id_to_object_map.h"
+
+#include <stdlib.h>
+
+namespace emugl {
+
+namespace {
+
+typedef IdToObjectMapBase::KeyType KeyType;
+
+enum {
+ kMinShift = 3,
+ kMaxShift = 31,
+ kMinCapacity = (1 << kMinShift),
+ kLoadScale = 1024,
+ kMinLoad = kLoadScale/4, // 25% minimum load.
+ kMaxLoad = kLoadScale*3/4, // 75% maximum load.
+
+ kInvalidKey = IdToObjectMapBase::kMaxId + 1U,
+ kTombstone = IdToObjectMapBase::kMaxId + 2U,
+};
+
+// Return a number that indicates if the current |capacity| is appropriate
+// to hold |size| items in our map.
+// -1 -> the capacity is too small and needs to be increased.
+// 0 -> the capacity is ok.
+// +1 -> the capacity is too large and needs to be decreased.
+int capacityCompare(size_t shift, size_t size) {
+ size_t capacity = 1U << shift;
+ // Essentially, one can rewrite:
+ // load < minLoad
+ // as:
+ // size / capacity < minLoad
+ // capacity * minLoad > size
+ if (capacity * kMinLoad > size * kLoadScale)
+ return +1;
+
+ // Similarly, one can rewrite:
+ // load > maxLoad
+ // as:
+ // size / capacity > maxLoad
+ // capacity * maxLoad < size
+ if (capacity * kMaxLoad < size * kLoadScale)
+ return -1;
+
+ return 0;
+}
+
+size_t probeKeys(const KeyType* keys, size_t shift, KeyType key) {
+ static const int kPrimes[] = {
+ 1, /* For 1 << 0 */
+ 2,
+ 3,
+ 7,
+ 13,
+ 31,
+ 61,
+ 127,
+ 251,
+ 509,
+ 1021,
+ 2039,
+ 4093,
+ 8191,
+ 16381,
+ 32749,
+ 65521, /* For 1 << 16 */
+ 131071,
+ 262139,
+ 524287,
+ 1048573,
+ 2097143,
+ 4194301,
+ 8388593,
+ 16777213,
+ 33554393,
+ 67108859,
+ 134217689,
+ 268435399,
+ 536870909,
+ 1073741789,
+ 2147483647 /* For 1 << 31 */
+ };
+
+ size_t slot = key % kPrimes[shift];
+ size_t step = 0;
+ for (;;) {
+ KeyType k = keys[slot];
+ if (k == kInvalidKey || k == kTombstone || k == key)
+ return slot;
+
+ step += 1;
+ slot = (slot + step) & (1U << shift);
+ }
+}
+
+} // namespace
+
+IdToObjectMapBase::IdToObjectMapBase() :
+ mCount(0), mShift(kMinShift) {
+ size_t capacity = 1U << mShift;
+ mKeys = static_cast<KeyType*>(::calloc(sizeof(mKeys[0]), capacity));
+ mValues = static_cast<void**>(::calloc(sizeof(mValues[0]), capacity));
+ for (size_t n = 0; n < capacity; ++n) {
+ mKeys[n] = kInvalidKey;
+ }
+}
+
+IdToObjectMapBase::~IdToObjectMapBase() {
+ mShift = 0;
+ mCount = 0;
+ ::free(mKeys);
+ ::free(mValues);
+}
+
+bool IdToObjectMapBase::contains(KeyType key) const {
+ size_t slot = probeKeys(mKeys, mShift, key);
+ switch (mKeys[slot]) {
+ case kInvalidKey:
+ case kTombstone:
+ return false;
+ default:
+ ;
+ }
+ return true;
+}
+
+bool IdToObjectMapBase::find(KeyType key, void** value) const {
+ size_t slot = probeKeys(mKeys, mShift, key);
+ if (!isValidKey(mKeys[slot])) {
+ *value = NULL;
+ return false;
+ }
+ *value = mValues[slot];
+ return true;
+}
+
+void* IdToObjectMapBase::set(KeyType key, void* value) {
+ if (!value)
+ return remove(key);
+
+ size_t slot = probeKeys(mKeys, mShift, key);
+ void* result;
+ if (isValidKey(mKeys[slot])) {
+ result = mValues[slot];
+ mValues[slot] = value;
+ } else {
+ mKeys[slot] = key;
+ mValues[slot] = value;
+ result = NULL;
+ mCount++;
+ resize(mCount);
+ }
+ return result;
+}
+
+void* IdToObjectMapBase::remove(KeyType key) {
+ size_t slot = probeKeys(mKeys, mShift, key);
+ if (!isValidKey(mKeys[slot]))
+ return NULL;
+
+ void* result = mValues[slot];
+ mValues[slot] = NULL;
+ mKeys[slot] = kTombstone;
+ mCount--;
+ return result;
+}
+
+void IdToObjectMapBase::resize(size_t newSize) {
+ int ret = capacityCompare(mShift, newSize);
+ if (!ret)
+ return;
+
+ size_t oldCapacity = 1U << mShift;
+ size_t newShift = mShift;
+
+ if (ret < 0) {
+ // Capacity is too small and must be increased.
+ do {
+ if (newShift == kMaxShift)
+ break;
+ ++newShift;
+ } while (capacityCompare(newShift, newSize) < 0);
+ } else {
+ // Capacity is too large and must be decreased.
+ do {
+ if (newShift == kMinShift)
+ break;
+ newShift--;
+ } while (capacityCompare(newShift, newSize) > 0);
+ }
+ if (newShift == mShift)
+ return;
+
+ // Allocate new arrays.
+ size_t newCapacity = 1U << newShift;
+ KeyType* newKeys = static_cast<KeyType*>(
+ ::calloc(sizeof(newKeys[0]), newCapacity));
+ void** newValues = static_cast<void**>(
+ ::calloc(sizeof(newValues[0]), newCapacity));
+ for (size_t n = 0; n < newCapacity; ++n)
+ newKeys[n] = kInvalidKey;
+
+ // Copy old entries into new arrays.
+ for (size_t n = 0; n < oldCapacity; ++n) {
+ KeyType key = mKeys[n];
+ if (isValidKey(key)) {
+ size_t newSlot = probeKeys(newKeys, newShift, key);
+ newKeys[newSlot] = key;
+ newValues[newSlot] = mValues[n];
+ }
+ }
+
+ // Swap arrays, and get rid of old ones.
+ ::free(mKeys);
+ ::free(mValues);
+ mKeys = newKeys;
+ mValues = newValues;
+ mShift = newShift;
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map.h b/emulator/opengl/shared/emugl/common/id_to_object_map.h
new file mode 100644
index 0000000..e3d0a81
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/id_to_object_map.h
@@ -0,0 +1,176 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_ID_TO_OBJECT_MAP_H
+#define EMUGL_COMMON_ID_TO_OBJECT_MAP_H
+
+#include <stddef.h>
+
+namespace emugl {
+
+// Base implementation class for IdToObjectMap template.
+// Used to reduce template-instanciated code generation.
+class IdToObjectMapBase {
+public:
+ // The type of keys in this map.
+ typedef unsigned KeyType;
+
+ // Values higher than kMaxId cannot be used as map keys.
+ enum {
+ kMaxId = 0xfffffffdU,
+ };
+
+ static inline bool isValidKey(KeyType key) {
+ return key <= kMaxId;
+ }
+
+protected:
+ IdToObjectMapBase();
+
+ ~IdToObjectMapBase();
+
+ void clear();
+
+ // Return size
+ inline size_t size() const { return mCount; }
+
+ inline size_t capacity() const { return 1U << mShift; }
+
+ // Return true iff the map contains a given key.
+ bool contains(KeyType key) const;
+
+ // Find a value associated with a given |key| in the map.
+ // On success, return true and sets |*value| to the value/pointer,
+ // which is _still_ owned by the map.
+ // On failure, return false and sets |*value| to NULL.
+ bool find(KeyType key, void** value) const;
+
+ // Associate a value with a given |key| in the map.
+ // Return the old value for the key, if any. Caller is responsible
+ // for freeing it.
+ void* set(KeyType key, void* value);
+
+ // Remove the value associated with a given |key|.
+ // Return the old value, if any. Caller is responsible for
+ // freeing it.
+ void* remove(KeyType key);
+
+ size_t mCount;
+ size_t mShift;
+ KeyType* mKeys;
+ void** mValues;
+
+private:
+ // Resize the map if needed to ensure it can hold at least |newSize|
+ // entries.
+ void resize(size_t newSize);
+};
+
+// A templated data container that acts as a dictionary mapping unsigned
+// integer keys to heap-allocated objects of type T. The dictionary
+// owns the objects associated with its keys, and automatically destroys
+// them when it is destroyed, or during replacement or removal.
+template <class T>
+class IdToObjectMap : public IdToObjectMapBase {
+public:
+ // Initialize an empty instance.
+ IdToObjectMap() : IdToObjectMapBase() {}
+
+ // Destroy this instance.
+ ~IdToObjectMap() {
+ clear();
+ }
+
+ // Return the number of items in this map.
+ inline size_t size() const { return IdToObjectMapBase::size(); }
+
+ // Return true iff the map is empty.
+ inline bool empty() const { return !IdToObjectMapBase::size(); }
+
+ // Remove all items from the map.
+ void clear();
+
+ // Returns true iff the dictionary contains a value for |key|.
+ inline bool contains(KeyType key) const {
+ return IdToObjectMapBase::contains(key);
+ }
+
+ // Find the value corresponding to |key| in this map.
+ // On success, return true, and sets |*value| to point to the
+ // value (still owned by the instance). On failure, return false.
+ inline bool find(KeyType key, T** value) const {
+ return IdToObjectMapBase::find(key, reinterpret_cast<void**>(value));
+ }
+
+ // Return the value associated with a given |key|, or NULL if it is
+ // not in the map. Result is still owned by the map.
+ inline T* get(KeyType key) const {
+ T* result = NULL;
+ this->find(key, &result);
+ return result;
+ }
+
+ // Associate |value| with a given |key|. Returns true if a previous
+ // value was replaced, and false if this is the first time a value
+ // was associated with the given key. IMPORTANT: This transfers
+ // ownership of |value| to the map instance. In case of replacement,
+ // the old value is automatically destroyed. Using NULL as the value
+ // is equivalent to calling remove().
+ bool set(KeyType key, T* value);
+
+ // Remove any value associated with |key|.
+ // Return true iff a value was associated with the key and destroyed
+ // by this function, false if there was no value associated with the
+ // key (or if it was NULL).
+ bool remove(KeyType key);
+};
+
+template <class T>
+void IdToObjectMap<T>::clear() {
+ size_t n = capacity();
+ while (n > 0) {
+ --n;
+ if (!isValidKey(mKeys[n]))
+ continue;
+
+ delete static_cast<T*>(mValues[n]);
+ mValues[n] = NULL;
+ mKeys[n] = kMaxId + 1U;
+ }
+ mCount = 0;
+}
+
+template <class T>
+bool IdToObjectMap<T>::set(KeyType key, T* value) {
+ T* oldValue = static_cast<T*>(IdToObjectMapBase::set(key, value));
+ if (!oldValue) {
+ return false;
+ }
+ delete oldValue;
+ return true;
+}
+
+template <class T>
+bool IdToObjectMap<T>::remove(KeyType key) {
+ T* oldValue = static_cast<T*>(IdToObjectMapBase::remove(key));
+ if (!oldValue)
+ return false;
+ delete oldValue;
+ return true;
+}
+
+} // namespace emugl
+
+
+#endif // EMUGL_COMMON_ID_TO_OBJECT_MAP_H
diff --git a/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp b/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp
new file mode 100644
index 0000000..50740be
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/id_to_object_map_unittest.cpp
@@ -0,0 +1,116 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/id_to_object_map.h"
+
+#include <gtest/gtest.h>
+
+namespace emugl {
+
+namespace {
+
+typedef IdToObjectMapBase::KeyType KeyType;
+
+class Foo {
+public:
+ Foo() : mVal(0) {}
+ Foo(int val) : mVal(val) {}
+ ~Foo() {}
+ int val() const { return mVal; }
+ void setVal(int val) { mVal = val; }
+private:
+ int mVal;
+};
+
+} // namespace
+
+TEST(IdToObjectMap, Empty) {
+ IdToObjectMap<Foo> map;
+ EXPECT_TRUE(map.empty());
+ EXPECT_EQ(0U, map.size());
+}
+
+TEST(IdToObjectMap, SetIntegerRange) {
+ IdToObjectMap<Foo> map;
+ KeyType kMax = 10000;
+
+ // Add all items in the map.
+ for (KeyType n = 0; n < kMax; ++n) {
+ EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n;
+ }
+
+ // Check final size.
+ EXPECT_EQ(static_cast<size_t>(kMax), map.size());
+
+ // Find all items in the map.
+ for (KeyType n = 0; n < kMax; ++n) {
+ EXPECT_TRUE(map.contains(n)) << "For key " << n;
+ Foo* foo = NULL;
+ EXPECT_TRUE(map.find(n, &foo)) << "For key " << n;
+ if (foo) {
+ EXPECT_EQ(static_cast<int>(n), foo->val()) << "For key " << n;
+ }
+ }
+}
+
+TEST(IdToObjectMap, RemoveAll) {
+ IdToObjectMap<Foo> map;
+ KeyType kMax = 10000;
+
+ // Add all items in the map.
+ for (KeyType n = 0; n < kMax; ++n) {
+ EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n;
+ }
+
+ EXPECT_EQ(static_cast<size_t>(kMax), map.size());
+
+ for (KeyType n = 0; n < kMax; ++n) {
+ EXPECT_TRUE(map.remove(n)) << "For key " << n;
+ }
+ EXPECT_EQ(0U, map.size());
+}
+
+TEST(IdToObjectMap, RemoveOdd) {
+ IdToObjectMap<Foo> map;
+ KeyType kMax = 10000;
+
+ // Add all items in the map.
+ for (KeyType n = 0; n < kMax; ++n) {
+ EXPECT_FALSE(map.set(n, new Foo(n))) << "For key " << n;
+ }
+
+ EXPECT_EQ(static_cast<size_t>(kMax), map.size());
+
+ for (KeyType n = 0; n < kMax; ++n) {
+ if (n & 1) {
+ EXPECT_TRUE(map.remove(n)) << "For key " << n;
+ }
+ }
+ EXPECT_EQ(static_cast<size_t>(kMax / 2), map.size());
+
+ for (KeyType n = 0; n < kMax; ++n) {
+ if (n & 1) {
+ EXPECT_FALSE(map.contains(n)) << "For key " << n;
+ } else {
+ EXPECT_TRUE(map.contains(n)) << "For key " << n;
+ Foo* foo = NULL;
+ EXPECT_TRUE(map.find(n, &foo)) << "For key " << n;
+ if (foo) {
+ EXPECT_EQ(static_cast<int>(n), foo->val());
+ }
+ }
+ }
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp
new file mode 100644
index 0000000..3fe8f15
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector.cpp
@@ -0,0 +1,151 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/pod_vector.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define USE_MALLOC_USABLE_SIZE 0
+
+namespace emugl {
+
+static inline void swapPointers(char** p1, char** p2) {
+ char* tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+}
+
+PodVectorBase::PodVectorBase(const PodVectorBase& other) {
+ initFrom(other.begin(), other.byteSize());
+}
+
+PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) {
+ initFrom(other.begin(), other.byteSize());
+ return *this;
+}
+
+PodVectorBase::~PodVectorBase() {
+ if (mBegin) {
+ // Sanity.
+ ::memset(mBegin, 0xee, byteSize());
+ ::free(mBegin);
+ mBegin = NULL;
+ mEnd = NULL;
+ mLimit = NULL;
+ }
+}
+
+void PodVectorBase::initFrom(const void* from, size_t fromLen) {
+ if (!fromLen || !from) {
+ mBegin = NULL;
+ mEnd = NULL;
+ mLimit = NULL;
+ } else {
+ mBegin = static_cast<char*>(::malloc(fromLen));
+ mEnd = mLimit = mBegin + fromLen;
+ ::memcpy(mBegin, from, fromLen);
+ }
+}
+
+void PodVectorBase::assignFrom(const PodVectorBase& other) {
+ resize(other.byteSize(), 1U);
+ ::memmove(begin(), other.begin(), byteSize());
+}
+
+void PodVectorBase::resize(size_t newSize, size_t itemSize) {
+ const size_t kMaxSize = maxItemCapacity(itemSize);
+ size_t oldCapacity = itemCapacity(itemSize);
+ const size_t kMinCapacity = 256 / itemSize;
+
+ if (newSize < oldCapacity) {
+ // Only shrink if the new size is really small.
+ if (newSize < oldCapacity / 2 && oldCapacity > kMinCapacity) {
+ reserve(newSize, itemSize);
+ }
+ } else if (newSize > oldCapacity) {
+ size_t newCapacity = oldCapacity;
+ while (newCapacity < newSize) {
+ size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8;
+ if (newCapacity2 < newCapacity || newCapacity > kMaxSize) {
+ newCapacity = kMaxSize;
+ } else {
+ newCapacity = newCapacity2;
+ }
+ }
+ reserve(newCapacity, itemSize);
+ }
+ mEnd = mBegin + newSize * itemSize;
+}
+
+void PodVectorBase::reserve(size_t newSize, size_t itemSize) {
+ const size_t kMaxSize = maxItemCapacity(itemSize);
+ if (newSize == 0) {
+ ::free(mBegin);
+ mBegin = NULL;
+ mEnd = NULL;
+ mLimit = NULL;
+ return;
+ }
+
+ size_t oldByteSize = byteSize();
+ size_t newByteCapacity = newSize * itemSize;
+ char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity));
+ mBegin = newBegin;
+ mEnd = newBegin + oldByteSize;
+#if USE_MALLOC_USABLE_SIZE
+ size_t usableSize = malloc_usable_size(mBegin);
+ if (usableSize > newByteCapacity) {
+ newByteCapacity = usableSize - (usableSize % itemSize);
+ }
+#endif
+ mLimit = newBegin + newByteCapacity;
+ // Sanity.
+ if (newByteCapacity > oldByteSize) {
+ ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize);
+ }
+}
+
+void PodVectorBase::removeAt(size_t itemPos, size_t itemSize) {
+ size_t count = itemCount(itemSize);
+ if (itemPos < count) {
+ size_t pos = itemPos * itemSize;
+ ::memmove(mBegin + pos,
+ mBegin + pos + itemSize,
+ byteSize() - pos - itemSize);
+ resize(count - 1U, itemSize);
+ }
+}
+
+void* PodVectorBase::insertAt(size_t itemPos, size_t itemSize) {
+ size_t count = this->itemCount(itemSize);
+ resize(count + 1, itemSize);
+ size_t pos = itemPos * itemSize;
+ if (itemPos < count) {
+ ::memmove(mBegin + pos + itemSize,
+ mBegin + pos,
+ count * itemSize - pos);
+ // Sanity to avoid copying pointers and other bad stuff.
+ ::memset(mBegin + pos, 0, itemSize);
+ }
+ return mBegin + pos;
+}
+
+void PodVectorBase::swapAll(PodVectorBase* other) {
+ swapPointers(&mBegin, &other->mBegin);
+ swapPointers(&mEnd, &other->mEnd);
+ swapPointers(&mLimit, &other->mLimit);
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/pod_vector.h b/emulator/opengl/shared/emugl/common/pod_vector.h
new file mode 100644
index 0000000..22a8a1d
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector.h
@@ -0,0 +1,267 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_POD_VECTOR_H
+#define EMUGL_COMMON_POD_VECTOR_H
+
+
+#include <stddef.h>
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS 1
+#endif
+#include <stdint.h>
+
+#ifndef SIZE_MAX
+#error "You must define __STDC_LIMIT_MACROS before including <stddint.h>"
+#endif
+
+namespace emugl {
+
+// A PodVector is a templated vector-like type that is used to store
+// POD-struct compatible items only. This allows the implementation to
+// use ::memmove() to move items, and also malloc_usable_size() to
+// determine the best capacity.
+//
+// std::vector<> is capable of doing this in theory, using horrible
+// templating tricks that make error messages very difficult to
+// understand.
+//
+// Note that a PodVector can be used to store items that contain pointers,
+// as long as these do not point to items in the same container.
+//
+// The PodVector provides methods that also follow the std::vector<>
+// conventions, i.e. push_back() is an alias for append().
+//
+
+// NOTE: This is a re-implementation of
+// external/qemu/android/base/containers/PodVector.h for emugl.
+
+// PodVectorBase is a base, non-templated, implementation class that all
+// PodVector instances derive from. This is used to reduce template
+// specialization. Do not use directly, i..e it's an implementation detail.
+class PodVectorBase {
+protected:
+ PodVectorBase() : mBegin(NULL), mEnd(NULL), mLimit(NULL) {}
+ explicit PodVectorBase(const PodVectorBase& other);
+ PodVectorBase& operator=(const PodVectorBase& other);
+ ~PodVectorBase();
+
+ bool empty() const { return mEnd == mBegin; }
+
+ size_t byteSize() const { return mEnd - mBegin; }
+
+ size_t byteCapacity() const { return mLimit - mBegin; }
+
+ void* begin() { return mBegin; }
+ const void* begin() const { return mBegin; }
+ void* end() { return mEnd; }
+ const void* end() const { return mEnd; }
+
+ void* itemAt(size_t pos, size_t itemSize) {
+ const size_t kMaxCapacity = SIZE_MAX / itemSize;
+ return mBegin + pos * itemSize;
+ }
+
+ const void* itemAt(size_t pos, size_t itemSize) const {
+ const size_t kMaxCapacity = SIZE_MAX / itemSize;
+ return mBegin + pos * itemSize;
+ }
+
+ void assignFrom(const PodVectorBase& other);
+
+ inline size_t itemCount(size_t itemSize) const {
+ return byteSize() / itemSize;
+ }
+
+ inline size_t itemCapacity(size_t itemSize) const {
+ return byteCapacity() / itemSize;
+ }
+
+ inline size_t maxItemCapacity(size_t itemSize) const {
+ return SIZE_MAX / itemSize;
+ }
+
+ void resize(size_t newSize, size_t itemSize);
+ void reserve(size_t newSize, size_t itemSize);
+
+ void removeAt(size_t index, size_t itemSize);
+ void* insertAt(size_t index, size_t itemSize);
+ void swapAll(PodVectorBase* other);
+
+ char* mBegin;
+ char* mEnd;
+ char* mLimit;
+
+private:
+ void initFrom(const void* from, size_t fromLen);
+};
+
+
+// A PodVector<T> holds a vector (dynamically resizable array) or items
+// that must be POD-struct compatible (i.e. they cannot have constructors,
+// destructors, or virtual members). This allows the implementation to be
+// small, fast and efficient, memory-wise.
+//
+// If you want to implement a vector of C++ objects, consider using
+// std::vector<> instead, but keep in mind that this implies a non-trivial
+// cost when appending, inserting, removing items in the collection.
+//
+template <typename T>
+class PodVector : public PodVectorBase {
+public:
+ // Default constructor for an empty PodVector<T>
+ PodVector() : PodVectorBase() {}
+
+ // Copy constructor. This copies all items from |other| into
+ // the new instance with ::memmove().
+ PodVector(const PodVector& other) : PodVectorBase(other) {}
+
+ // Assignment operator.
+ PodVector& operator=(const PodVector& other) {
+ this->assignFrom(other);
+ return *this;
+ }
+
+ // Destructor, this simply releases the internal storage block that
+ // holds all the items, but doesn't touch them otherwise.
+ ~PodVector() {}
+
+ // Return true iff the PodVector<T> instance is empty, i.e. does not
+ // have any items.
+ bool empty() const { return PodVectorBase::empty(); }
+
+ // Return the number of items in the current PodVector<T> instance.
+ size_t size() const { return PodVectorBase::itemCount(sizeof(T)); }
+
+ // Return the current capacity in the current PodVector<T> instance.
+ // Do not use directly, except if you know what you're doing. Try to
+ // use resize() or reserve() instead.
+ size_t capacity() const {
+ return PodVectorBase::itemCapacity(sizeof(T));
+ }
+
+ // Return the maximum capacity of any PodVector<T> instance.
+ static inline size_t maxCapacity() { return SIZE_MAX / sizeof(T); }
+
+ // Resize the vector to ensure it can hold |newSize|
+ // items. This may or may not call reserve() under the hood.
+ // It's a fatal error to try to resize above maxCapacity().
+ void resize(size_t newSize) {
+ PodVectorBase::resize(newSize, sizeof(T));
+ }
+
+ // Resize the vector's storage array to ensure that it can hold at
+ // least |newSize| items. It's a fatal error to try to resize above
+ // maxCapacity().
+ void reserve(size_t newSize) {
+ PodVectorBase::reserve(newSize, sizeof(T));
+ }
+
+ // Return a pointer to the first item in the vector. This is only
+ // valid until the next call to any function that changes the size
+ // or capacity of the vector. Can be NULL if the vector is empty.
+ T* begin() {
+ return reinterpret_cast<T*>(PodVectorBase::begin());
+ }
+
+ // Return a constant pointer to the first item in the vector. This is
+ // only valid until the next call to any function that changes the
+ // size of capacity of the vector.
+ const T* begin() const {
+ return reinterpret_cast<T*>(PodVectorBase::begin());
+ }
+
+ // Return a pointer past the last item in the vector. I.e. if the
+ // result is not NULL, then |result - 1| points to the last item.
+ // Can be NULL if the vector is empty.
+ T* end() {
+ return reinterpret_cast<T*>(PodVectorBase::end());
+ }
+
+ // Return a constant pointer past the last item in the vector. I.e. if
+ // the result is not NULL, then |result - 1| points to the last item.
+ // Can be NULL if the vector is empty.
+ const T* end() const {
+ return reinterpret_cast<T*>(PodVectorBase::end());
+ }
+
+ // Returns a reference to the item a position |index| in the vector.
+ // It may be a fatal error to access an out-of-bounds position.
+ T& operator[](size_t index) {
+ return *reinterpret_cast<T*>(
+ PodVectorBase::itemAt(index, sizeof(T)));
+ }
+
+ const T& operator[](size_t index) const {
+ return *reinterpret_cast<const T*>(
+ PodVectorBase::itemAt(index, sizeof(T)));
+ }
+
+ // Increase the vector's size by 1, then move all items past a given
+ // position to the right. Return the position of the insertion point
+ // to let the caller copy the content it desires there. It's preferrable
+ // to use insert() directly, which will do the item copy for you.
+ T* emplace(size_t index) {
+ return reinterpret_cast<T*>(
+ PodVectorBase::insertAt(index, sizeof(T)));
+ }
+
+ // Insert an item at a given position. |index| is the insertion position
+ // which must be between 0 and size() included, or a fatal error may
+ // occur. |item| is a reference to an item to copy into the array,
+ // byte-by-byte.
+ void insert(size_t index, const T& item) {
+ *(this->emplace(index)) = item;
+ }
+
+ // Prepend an item at the start of a vector. This moves all vector items
+ // to the right, and is thus costly. |item| is a reference to an item
+ // to copy to the start of the vector.
+ void prepend(const T& item) {
+ *(this->emplace(0U)) = item;
+ }
+
+ // Append an item at the end of a vector. Specialized version of insert()
+ // which always uses size() as the insertion position.
+ void append(const T& item) {
+ *(this->emplace(this->size())) = item;
+ }
+
+ // Remove the item at a given position. |index| is the position of the
+ // item to delete. It must be between 0 and size(), included, or
+ // a fatal error may occur. Deleting the item at position size()
+ // doesn't do anything.
+ void remove(size_t index) {
+ PodVectorBase::removeAt(index, sizeof(T));
+ }
+
+ void swap(PodVector* other) {
+ PodVectorBase::swapAll(other);
+ }
+
+ // Compatibility methods for std::vector<>
+ void push_back(const T& item) { append(item); }
+ void pop() { remove(0U); }
+
+ typedef T* iterator;
+ typedef const T* const_iterator;
+};
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_POD_VECTOR_H
diff --git a/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp
new file mode 100644
index 0000000..9ce509a
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/pod_vector_unittest.cpp
@@ -0,0 +1,127 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/pod_vector.h"
+
+#include <gtest/gtest.h>
+
+namespace emugl {
+
+static int hashIndex(size_t n) {
+ return static_cast<int>(((n >> 14) * 13773) + (n * 51));
+}
+
+TEST(PodVector, Empty) {
+ PodVector<int> v;
+ EXPECT_TRUE(v.empty());
+ EXPECT_EQ(0U, v.size());
+}
+
+TEST(PodVector, AppendOneItem) {
+ PodVector<int> v;
+ v.append(10234);
+ EXPECT_FALSE(v.empty());
+ EXPECT_EQ(1U, v.size());
+ EXPECT_EQ(10234, v[0]);
+}
+
+TEST(PodVector, AppendLotsOfItems) {
+ PodVector<int> v;
+ const size_t kMaxCount = 10000;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v.append(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v.size());
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n;
+ }
+}
+
+TEST(PodVector, RemoveFrontItems) {
+ PodVector<int> v;
+ const size_t kMaxCount = 100;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v.append(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v.size());
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ EXPECT_EQ(hashIndex(n), v[0]) << "At index " << n;
+ v.remove(0U);
+ EXPECT_EQ(kMaxCount - n - 1U, v.size()) << "At index " << n;
+ }
+}
+
+TEST(PodVector, PrependItems) {
+ PodVector<int> v;
+ const size_t kMaxCount = 100;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v.prepend(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v.size());
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ EXPECT_EQ(hashIndex(kMaxCount - n - 1), v[n]) << "At index " << n;
+ }
+}
+
+TEST(PodVector, ResizeExpands) {
+ PodVector<int> v;
+ const size_t kMaxCount = 100;
+ const size_t kMaxCount2 = 10000;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v.append(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v.size());
+ v.resize(kMaxCount2);
+ EXPECT_EQ(kMaxCount2, v.size());
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n;
+ }
+}
+
+TEST(PodVector, ResizeTruncates) {
+ PodVector<int> v;
+ const size_t kMaxCount = 10000;
+ const size_t kMaxCount2 = 10;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v.append(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v.size());
+ v.resize(kMaxCount2);
+ EXPECT_EQ(kMaxCount2, v.size());
+ for (size_t n = 0; n < kMaxCount2; ++n) {
+ EXPECT_EQ(hashIndex(n), v[n]) << "At index " << n;
+ }
+}
+
+
+TEST(PodVector, AssignmentOperator) {
+ PodVector<int> v1;
+ const size_t kMaxCount = 10000;
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ v1.append(hashIndex(n));
+ }
+ EXPECT_EQ(kMaxCount, v1.size());
+
+ PodVector<int> v2;
+ v2 = v1;
+
+ v1.reserve(0);
+
+ EXPECT_EQ(kMaxCount, v2.size());
+ for (size_t n = 0; n < kMaxCount; ++n) {
+ EXPECT_EQ(hashIndex(n), v2[n]) << "At index " << n;
+ }
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h
new file mode 100644
index 0000000..3d263e9
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/scoped_pointer_vector.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_SCOPED_POINTER_VECTOR_H
+#define EMUGL_COMMON_SCOPED_POINTER_VECTOR_H
+
+namespace emugl {
+
+template <class T>
+class ScopedPointerVector {
+ ScopedPointerVector
+};
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_SCOPED_POINTER_VECTOR_H
diff --git a/emulator/opengl/shared/emugl/common/sockets.cpp b/emulator/opengl/shared/emugl/common/sockets.cpp
new file mode 100644
index 0000000..feb6d38
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/sockets.cpp
@@ -0,0 +1,221 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "emugl/common/sockets.h"
+
+#include <errno.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace emugl {
+
+namespace {
+
+static void socketSetReuseAddress(int s) {
+#ifdef _WIN32
+ // The default behaviour on WIndows is equivalent to SO_REUSEADDR
+ // so we don't need to set this option. Moreover, one should never
+ // set this option with WinSock because it's badly implemented and
+ // generates a huge security issue. See:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx
+#else
+ int val = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+#endif
+}
+
+// Helper union to store a socket address.
+struct SockAddr {
+ socklen_t len;
+ union {
+ sockaddr generic;
+ sockaddr_in inet;
+#ifndef _WIN32
+ sockaddr_un local;
+#endif
+ };
+
+ int getFamily() const { return generic.sa_family; }
+
+ void initEmpty() {
+ ::memset(this, 0, sizeof(*this));
+ this->len = static_cast<socklen_t>(sizeof(*this));
+ }
+
+ int initFromInet(uint32_t ip_address, int port) {
+ if (port < 0 || port >= 65536)
+ return -EINVAL;
+
+ ::memset(this, 0, sizeof(*this));
+ this->inet.sin_family = AF_INET;
+ this->inet.sin_port = htons(port);
+ this->inet.sin_addr.s_addr = htonl(ip_address);
+ this->len = sizeof(this->inet);
+ return 0;
+ }
+
+ int initFromLocalhost(int port) {
+ return initFromInet(0x7f000001, port);
+ }
+
+#ifndef _WIN32
+ // Initialize the SockAddr from a Unix path. Returns 0 on success,
+ // or -errno code on failure.
+ int initFromUnixPath(const char* path) {
+ if (!path || !path[0])
+ return -EINVAL;
+
+ size_t pathLen = ::strlen(path);
+ if (pathLen >= sizeof(local.sun_path))
+ return -E2BIG;
+
+ ::memset(this, 0, sizeof(*this));
+ this->local.sun_family = AF_LOCAL;
+ ::memcpy(this->local.sun_path, path, pathLen + 1U);
+ this->len = pathLen + offsetof(sockaddr_un, sun_path);
+ return 0;
+ }
+#endif
+};
+
+int socketBindInternal(const SockAddr* addr, int socketType) {
+ int s = ::socket(addr->getFamily(), socketType, 0);
+ if (s < 0)
+ return -errno;
+
+ // Bind to the socket.
+ if (::bind(s, &addr->generic, addr->len) < 0 ||
+ ::listen(s, 5) < 0) {
+ int ret = -errno;
+ ::close(s);
+ return ret;
+ }
+
+ socketSetReuseAddress(s);
+ return s;
+}
+
+int socketConnectInternal(const SockAddr* addr, int socketType) {
+ int s = ::socket(addr->getFamily(), socketType, 0);
+ if (s < 0)
+ return -errno;
+
+ int ret;
+ do {
+ ret = ::connect(s, &addr->generic, addr->len);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0) {
+ ret = -errno;
+ ::close(s);
+ return ret;
+ }
+
+ return s;
+}
+
+} // namespace
+
+void socketTcpDisableNagle(int s) {
+ // disable Nagle algorithm to improve bandwidth of small
+ // packets which are quite common in our implementation.
+#ifdef _WIN32
+ DWORD flag;
+#else
+ int flag;
+#endif
+ flag = 1;
+ setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
+ (const char*)&flag, sizeof(flag));
+}
+
+int socketGetPort(int s) {
+ SockAddr addr;
+ addr.initEmpty();
+ if (getsockname(s, &addr.generic, &addr.len) < 0) {
+ return -errno;
+ }
+ switch (addr.generic.sa_family) {
+ case AF_INET:
+ return ntohs(addr.inet.sin_port);
+ default:
+ ;
+ }
+ return -EINVAL;
+}
+
+#ifndef _WIN32
+int socketLocalServer(const char* path, int socketType) {
+ SockAddr addr;
+ int ret = addr.initFromUnixPath(path);
+ if (ret < 0) {
+ return ret;
+ }
+ return socketBindInternal(&addr, socketType);
+}
+
+int socketLocalClient(const char* path, int socketType) {
+ SockAddr addr;
+ int ret = addr.initFromUnixPath(path);
+ if (ret < 0) {
+ return ret;
+ }
+ return socketConnectInternal(&addr, socketType);
+}
+#endif // !_WIN32
+
+int socketTcpLoopbackServer(int port, int socketType) {
+ SockAddr addr;
+ int ret = addr.initFromLocalhost(port);
+ if (ret < 0) {
+ return ret;
+ }
+ return socketBindInternal(&addr, socketType);
+}
+
+int socketTcpLoopbackClient(int port, int socketType) {
+ SockAddr addr;
+ int ret = addr.initFromLocalhost(port);
+ if (ret < 0) {
+ return ret;
+ }
+ return socketConnectInternal(&addr, socketType);
+}
+
+int socketTcpClient(const char* hostname, int port, int socketType) {
+ // TODO(digit): Implement this.
+ return -ENOSYS;
+}
+
+int socketAccept(int serverSocket) {
+ int ret;
+ do {
+ ret = ::accept(serverSocket, NULL, NULL);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+} // namespace emugl
diff --git a/emulator/opengl/shared/emugl/common/sockets.h b/emulator/opengl/shared/emugl/common/sockets.h
new file mode 100644
index 0000000..11e7ac7
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/sockets.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMUGL_COMMON_SOCKETS_H
+#define EMUGL_COMMON_SOCKETS_H
+
+// A set of helper functions used to deal with sockets in a portable way.
+
+namespace emugl {
+
+// Disable Nagle's algorithm for socket descriptor |s|. This assumes
+// that |s| is a TCP socket descriptor.
+void socketTcpDisableNagle(int s);
+
+// Return the port associated with a given IP or IPv6 socket,
+// or -errno code on failure.
+int socketGetPort(int s);
+
+// Bind to a local/Unix path, and return its socket descriptor on success,
+// or -errno code on failure.
+int socketLocalServer(const char* path, int socketType);
+
+// Connect to a Unix local path, and return a new socket descriptor
+// on success, or -errno code on failure.
+int socketLocalClient(const char* path, int socketType);
+
+// Bind to a localhost TCP socket, and return its socket descriptor on
+// success, or -errno code on failure.
+int socketTcpLoopbackServer(int port, int socketType);
+
+// Connect to a localhost TCP port, and return a new socket descriptor on
+// success, or -errno code on failure.
+int socketTcpLoopbackClient(int port, int socketType);
+
+// Connect to a TCP host, and return a new socket descriptor on
+// success, or -errno code on failure.
+int socketTcpClient(const char* hostname, int port, int socketType);
+
+// Accept a new connection. |serverSocket| must be a bound server socket
+// descriptor. Returns new socket descriptor on success, or -errno code
+// on failure.
+int socketAccept(int serverSocket);
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_SOCKETS_H