diff --git a/tools/emulator/opengl/Android.mk b/tools/emulator/opengl/Android.mk index a67facb3f..2c1cb6448 100644 --- a/tools/emulator/opengl/Android.mk +++ b/tools/emulator/opengl/Android.mk @@ -9,15 +9,6 @@ # ifeq (true,$(BUILD_EMULATOR_OPENGL)) -# By default, always build the gralloc.goldfish support library to ensure -# that SurfaceFlinger always uses our GLES emulation libraries. If you -# don't want this, explicitely set BUILD_EMULATOR_OPENGL_DRIVER to 'false' -# in your environment or your BoardConfig.mk. For the record, this should -# only be done for debugging specific applications and requires remoting -# the GL window from the emulator UI to be usable. -# -BUILD_EMULATOR_OPENGL_DRIVER ?= true - # Top-level for all modules EMUGL_PATH := $(call my-dir) @@ -75,13 +66,8 @@ include $(EMUGL_PATH)/system/OpenglSystemCommon/Android.mk include $(EMUGL_PATH)/system/GLESv1/Android.mk include $(EMUGL_PATH)/system/GLESv2/Android.mk -ifeq (false,$(BUILD_EMULATOR_OPENGL_DRIVER)) - include $(EMUGL_PATH)/tests/ut_rendercontrol_enc/Android.mk - include $(EMUGL_PATH)/tests/gles_android_wrapper/Android.mk -else - include $(EMUGL_PATH)/system/gralloc/Android.mk - include $(EMUGL_PATH)/system/egl/Android.mk -endif +include $(EMUGL_PATH)/system/gralloc/Android.mk +include $(EMUGL_PATH)/system/egl/Android.mk # Host static libraries include $(EMUGL_PATH)/host/libs/GLESv1_dec/Android.mk @@ -99,12 +85,7 @@ include $(EMUGL_PATH)/host/libs/libOpenglRender/Android.mk # Host executables include $(EMUGL_PATH)/host/renderer/Android.mk -# Host unit-test for the renderer. this one uses its own small -# EGL host wrapper. -include $(EMUGL_PATH)/tests/event_injector/Android.mk -include $(EMUGL_PATH)/tests/EGL_host_wrapper/Android.mk -include $(EMUGL_PATH)/tests/emulator_test_renderer/Android.mk -include $(EMUGL_PATH)/tests/ut_renderer/Android.mk +# Host unit-test for the renderer. include $(EMUGL_PATH)/tests/translator_tests/MacCommon/Android.mk include $(EMUGL_PATH)/tests/translator_tests/GLES_CM/Android.mk diff --git a/tools/emulator/opengl/host/include/libOpenglRender/render_api.h b/tools/emulator/opengl/host/include/libOpenglRender/render_api.h index 97a229245..bb331920a 100644 --- a/tools/emulator/opengl/host/include/libOpenglRender/render_api.h +++ b/tools/emulator/opengl/host/include/libOpenglRender/render_api.h @@ -32,6 +32,16 @@ extern "C" { // bool initLibrary(void); +// list of constants to be passed to setStreamMode, which determines +// which +#define STREAM_MODE_DEFAULT 0 +#define STREAM_MODE_TCP 1 +#define STREAM_MODE_UNIX 2 +#define STREAM_MODE_PIPE 3 + +// Change the stream mode. This must be called before initOpenGLRenderer +int setStreamMode(int mode); + // // initOpenGLRenderer - initialize the OpenGL renderer process. // portNum is the tcp port number the renderer is listening to. diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp index 31f59c194..78f305c77 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp @@ -15,6 +15,11 @@ */ #include "RenderServer.h" #include "TcpStream.h" +#ifdef _WIN32 +#include "Win32PipeStream.h" +#else +#include "UnixStream.h" +#endif #include "RenderThread.h" #include "FrameBuffer.h" #include @@ -27,6 +32,8 @@ RenderServer::RenderServer() : { } +extern "C" int gRendererStreamMode; + RenderServer *RenderServer::create(int port) { RenderServer *server = new RenderServer(); @@ -34,7 +41,16 @@ RenderServer *RenderServer::create(int port) return NULL; } - server->m_listenSock = new TcpStream(); + if (gRendererStreamMode == STREAM_MODE_TCP) { + server->m_listenSock = new TcpStream(); + } else { +#ifdef _WIN32 + server->m_listenSock = new Win32PipeStream(); +#else + server->m_listenSock = new UnixStream(); +#endif + } + if (server->m_listenSock->listen(port) < 0) { ERR("RenderServer::create failed to listen on port %d\n", port); delete server; @@ -49,7 +65,7 @@ int RenderServer::Main() RenderThreadsSet threads; while(1) { - TcpStream *stream = m_listenSock->accept(); + SocketStream *stream = m_listenSock->accept(); if (!stream) { fprintf(stderr,"Error accepting connection, aborting\n"); break; diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.h b/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.h index 1de40530c..98e989063 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderServer.h @@ -16,7 +16,7 @@ #ifndef _LIB_OPENGL_RENDER_RENDER_SERVER_H #define _LIB_OPENGL_RENDER_RENDER_SERVER_H -#include "TcpStream.h" +#include "SocketStream.h" #include "osThread.h" class RenderServer : public osUtils::Thread @@ -31,7 +31,7 @@ private: RenderServer(); private: - TcpStream *m_listenSock; + SocketStream *m_listenSock; bool m_exiting; }; diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp index eeaa631e9..8a5f46422 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp @@ -20,6 +20,13 @@ #include "osProcess.h" #include "TimeUtils.h" +#include "TcpStream.h" +#ifdef _WIN32 +#include "Win32PipeStream.h" +#else +#include "UnixStream.h" +#endif + #include "EGLDispatch.h" #include "GLDispatch.h" #include "GL2Dispatch.h" @@ -270,15 +277,33 @@ void repaintOpenGLDisplay() } } + +/* NOTE: For now, always use TCP mode by default, until the emulator + * has been updated to support Unix and Win32 pipes + */ +#define DEFAULT_STREAM_MODE STREAM_MODE_TCP + +int gRendererStreamMode = DEFAULT_STREAM_MODE; + IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) { - TcpStream *stream = new TcpStream(p_stream_buffer_size); + SocketStream* stream = NULL; + + if (gRendererStreamMode == STREAM_MODE_TCP) { + stream = new TcpStream(p_stream_buffer_size); + } else { +#ifdef _WIN32 + stream = new Win32PipeStream(p_stream_buffer_size); +#else /* !_WIN32 */ + stream = new UnixStream(p_stream_buffer_size); +#endif + } + if (!stream) { ERR("createRenderThread failed to create stream\n"); return NULL; } - - if (stream->connect("localhost", s_renderPort) < 0) { + if (stream->connect(s_renderPort) < 0) { ERR("createRenderThread failed to connect\n"); delete stream; return NULL; @@ -287,10 +312,36 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) // // send clientFlags to the renderer // - unsigned int *pClientFlags = + unsigned int *pClientFlags = (unsigned int *)stream->allocBuffer(sizeof(unsigned int)); *pClientFlags = clientFlags; stream->commitBuffer(sizeof(unsigned int)); return stream; } + +int +setStreamMode(int mode) +{ + switch (mode) { + case STREAM_MODE_DEFAULT: + mode = DEFAULT_STREAM_MODE; + break; + + case STREAM_MODE_TCP: + break; + +#ifndef _WIN32 + case STREAM_MODE_UNIX: + break; +#else /* _WIN32 */ + case STREAM_MODE_PIPE: + break; +#endif /* _WIN32 */ + default: + // Invalid stream mode + return -1; + } + gRendererStreamMode = mode; + return 0; +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk index fa1b248ed..2f7da7976 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk @@ -3,16 +3,19 @@ # LOCAL_PATH := $(call my-dir) -### CodecCommon guest ############################################## -$(call emugl-begin-static-library,libOpenglCodecCommon) - -LOCAL_SRC_FILES := \ +commonSources := \ GLClientState.cpp \ GLSharedGroup.cpp \ glUtils.cpp \ + SocketStream.cpp \ TcpStream.cpp \ TimeUtils.cpp +### CodecCommon guest ############################################## +$(call emugl-begin-static-library,libOpenglCodecCommon) + +LOCAL_SRC_FILES := $(commonSources) + LOCAL_CFLAGS += -DLOG_TAG=\"eglCodecCommon\" $(call emugl-export,SHARED_LIBRARIES,libcutils libutils) @@ -22,11 +25,13 @@ $(call emugl-end-module) ### OpenglCodecCommon host ############################################## $(call emugl-begin-host-static-library,libOpenglCodecCommon) -LOCAL_SRC_FILES := \ - GLClientState.cpp \ - glUtils.cpp \ - TcpStream.cpp \ - TimeUtils.cpp +LOCAL_SRC_FILES := $(commonSources) + +ifeq ($(HOST_OS),windows) + LOCAL_SRC_FILES += Win32PipeStream.cpp +else + LOCAL_SRC_FILES += UnixStream.cpp +endif $(call emugl-export,STATIC_LIBRARIES,libcutils) $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp new file mode 100644 index 000000000..244cfbb20 --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.cpp @@ -0,0 +1,163 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "SocketStream.h" +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#else +#include +#endif + +SocketStream::SocketStream(size_t bufSize) : + IOStream(bufSize), + m_sock(-1), + m_bufsize(bufSize), + m_buf(NULL) +{ +} + +SocketStream::SocketStream(int sock, size_t bufSize) : + IOStream(bufSize), + m_sock(sock), + m_bufsize(bufSize), + m_buf(NULL) +{ +} + +SocketStream::~SocketStream() +{ + if (m_sock >= 0) { +#ifdef _WIN32 + closesocket(m_sock); +#else + ::close(m_sock); +#endif + } + if (m_buf != NULL) { + free(m_buf); + m_buf = NULL; + } +} + + +void *SocketStream::allocBuffer(size_t minSize) +{ + size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); + if (!m_buf) { + m_buf = (unsigned char *)malloc(allocSize); + } + else if (m_bufsize < allocSize) { + unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); + if (p != NULL) { + m_buf = p; + m_bufsize = allocSize; + } else { + ERR("%s: realloc (%d) failed\n", __FUNCTION__, allocSize); + free(m_buf); + m_buf = NULL; + m_bufsize = 0; + } + } + + return m_buf; +}; + +int SocketStream::commitBuffer(size_t size) +{ + if (!valid()) return -1; + + size_t res = size; + int retval = 0; + + while (res > 0) { + ssize_t stat = ::send(m_sock, (const char *)(m_buf) + (size - res), res, 0); + if (stat < 0) { + if (errno != EINTR) { + retval = stat; + ERR("%s: failed: %s\n", __FUNCTION__, strerror(errno)); + break; + } + } else { + res -= stat; + } + } + return retval; +} + +const unsigned char *SocketStream::readFully(void *buf, size_t len) +{ + const unsigned char* ret = NULL; + if (!valid()) return NULL; + if (!buf) { + return NULL; // do not allow NULL buf in that implementation + } + size_t res = len; + while (res > 0) { + ssize_t stat = ::recv(m_sock, (char *)(buf) + len - res, res, 0); + if (stat > 0) { + res -= stat; + continue; + } + if (stat == 0 || errno != EINTR) { // client shutdown or error + return NULL; + } + } + return (const unsigned char *)buf; +} + +const unsigned char *SocketStream::read( void *buf, size_t *inout_len) +{ + if (!valid()) return NULL; + if (!buf) { + return NULL; // do not allow NULL buf in that implementation + } + + int n; + do { + n = recv(buf, *inout_len); + } while( n < 0 && errno == EINTR ); + + if (n > 0) { + *inout_len = n; + return (const unsigned char *)buf; + } + + return NULL; +} + +int SocketStream::recv(void *buf, size_t len) +{ + if (!valid()) return int(ERR_INVALID_SOCKET); + int res = 0; + while(true) { + res = ::recv(m_sock, (char *)buf, len, 0); + if (res < 0) { + if (errno == EINTR) { + continue; + } + } + break; + } + return res; +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.h b/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.h new file mode 100644 index 000000000..c54dea702 --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/SocketStream.h @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef __SOCKET_STREAM_H +#define __SOCKET_STREAM_H + +#include +#include "IOStream.h" + +class SocketStream : public IOStream { +public: + typedef enum { ERR_INVALID_SOCKET = -1000 } SocketStreamError; + + explicit SocketStream(size_t bufsize = 10000); + virtual ~SocketStream(); + + virtual int listen(unsigned short port) = 0; + virtual SocketStream *accept() = 0; + virtual int connect(unsigned short port) = 0; + + virtual void *allocBuffer(size_t minSize); + virtual int commitBuffer(size_t size); + virtual const unsigned char *readFully(void *buf, size_t len); + virtual const unsigned char *read(void *buf, size_t *inout_len); + + bool valid() { return m_sock >= 0; } + virtual int recv(void *buf, size_t len); + +protected: + int m_sock; + size_t m_bufsize; + unsigned char *m_buf; + + SocketStream(int sock, size_t bufSize); + int writeFully(const void *buf, size_t len); +}; + +#endif /* __SOCKET_STREAM_H */ diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp index c057ff991..4da2cec3a 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.cpp @@ -29,18 +29,12 @@ #endif TcpStream::TcpStream(size_t bufSize) : - IOStream(bufSize), - m_sock(-1), - m_bufsize(bufSize), - m_buf(NULL) + SocketStream(bufSize) { } TcpStream::TcpStream(int sock, size_t bufSize) : - IOStream(bufSize), - m_sock(sock), - m_bufsize(bufSize), - m_buf(NULL) + SocketStream(sock, bufSize) { // disable Nagle algorithm to improve bandwidth of small // packets which are quite common in our implementation. @@ -53,34 +47,15 @@ TcpStream::TcpStream(int sock, size_t bufSize) : setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag) ); } -TcpStream::~TcpStream() +int TcpStream::listen(unsigned short port) { - if (m_sock >= 0) { -#ifdef _WIN32 - closesocket(m_sock); -#else - ::close(m_sock); -#endif - } - if (m_buf != NULL) { - free(m_buf); - } -} - - -int TcpStream::listen(unsigned short port, bool localhost_only) -{ - if (localhost_only) { - m_sock = socket_loopback_server(port, SOCK_STREAM); - } else { - m_sock = socket_inaddr_any_server(port, SOCK_STREAM); - } + m_sock = socket_loopback_server(port, SOCK_STREAM); if (!valid()) return int(ERR_INVALID_SOCKET); return 0; } -TcpStream * TcpStream::accept() +SocketStream * TcpStream::accept() { int clientSock = -1; @@ -103,120 +78,14 @@ TcpStream * TcpStream::accept() return clientStream; } +int TcpStream::connect(unsigned short port) +{ + return connect("127.0.0.1",port); +} -int TcpStream::connect(const char *hostname, unsigned short port) +int TcpStream::connect(const char* hostname, unsigned short port) { m_sock = socket_network_client(hostname, port, SOCK_STREAM); if (!valid()) return -1; return 0; } - -void *TcpStream::allocBuffer(size_t minSize) -{ - size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); - if (!m_buf) { - m_buf = (unsigned char *)malloc(allocSize); - } - else if (m_bufsize < allocSize) { - unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); - if (p != NULL) { - m_buf = p; - m_bufsize = allocSize; - } else { - ERR("realloc (%d) failed\n", allocSize); - free(m_buf); - m_buf = NULL; - m_bufsize = 0; - } - } - - return m_buf; -}; - -int TcpStream::commitBuffer(size_t size) -{ - return writeFully(m_buf, size); -} - -int TcpStream::writeFully(const void *buf, size_t len) -{ - if (!valid()) return -1; - - size_t res = len; - int retval = 0; - - while (res > 0) { - ssize_t stat = ::send(m_sock, (const char *)(buf) + (len - res), res, 0); - if (stat < 0) { - if (errno != EINTR) { - retval = stat; - ERR("TcpStream::writeFully failed: %s\n", strerror(errno)); - break; - } - } else { - res -= stat; - } - } - return retval; -} - -const unsigned char *TcpStream::readFully(void *buf, size_t len) -{ - if (!valid()) return NULL; - if (!buf) { - return NULL; // do not allow NULL buf in that implementation - } - size_t res = len; - while (res > 0) { - ssize_t stat = ::recv(m_sock, (char *)(buf) + len - res, res, 0); - if (stat == 0) { - // client shutdown; - return NULL; - } else if (stat < 0) { - if (errno == EINTR) { - continue; - } else { - return NULL; - } - } else { - res -= stat; - } - } - return (const unsigned char *)buf; -} - -const unsigned char *TcpStream::read( void *buf, size_t *inout_len) -{ - if (!valid()) return NULL; - if (!buf) { - return NULL; // do not allow NULL buf in that implementation - } - - int n; - do { - n = recv(buf, *inout_len); - } while( n < 0 && errno == EINTR ); - - if (n > 0) { - *inout_len = n; - return (const unsigned char *)buf; - } - - return NULL; -} - -int TcpStream::recv(void *buf, size_t len) -{ - if (!valid()) return int(ERR_INVALID_SOCKET); - int res = 0; - while(true) { - res = ::recv(m_sock, (char *)buf, len, 0); - if (res < 0) { - if (errno == EINTR) { - continue; - } - } - break; - } - return res; -} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.h b/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.h index 75218434b..811a87157 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.h +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/TcpStream.h @@ -16,35 +16,16 @@ #ifndef __TCP_STREAM_H #define __TCP_STREAM_H -#include -#include "IOStream.h" +#include "SocketStream.h" - -class TcpStream : public IOStream { +class TcpStream : public SocketStream { public: - typedef enum { ERR_INVALID_SOCKET = -1000 } TcpStreamError; - explicit TcpStream(size_t bufsize = 10000); - ~TcpStream(); - int listen(unsigned short port, bool localhost_only = true); - TcpStream *accept(); - int connect(const char *hostname, unsigned short port); - - virtual void *allocBuffer(size_t minSize); - virtual int commitBuffer(size_t size); - virtual const unsigned char *readFully( void *buf, size_t len); - virtual const unsigned char *read( void *buf, size_t *inout_len); - - bool valid() { return m_sock >= 0; } - int recv(void *buf, size_t len); - + virtual int listen(unsigned short port); + virtual SocketStream *accept(); + virtual int connect(unsigned short port); + int connect(const char* hostname, unsigned short port); private: - int writeFully(const void *buf, size_t len); - -private: - int m_sock; - size_t m_bufsize; - unsigned char *m_buf; TcpStream(int sock, size_t bufSize); }; diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp new file mode 100644 index 000000000..8e463a370 --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.cpp @@ -0,0 +1,137 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "UnixStream.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Not all systems define PATH_MAX, those who don't generally don't + * have a limit on the maximum path size, so use a value that is + * large enough for our very limited needs. + */ +#ifndef PATH_MAX +#define PATH_MAX 128 +#endif + +UnixStream::UnixStream(size_t bufSize) : + SocketStream(bufSize) +{ +} + +UnixStream::UnixStream(int sock, size_t bufSize) : + SocketStream(sock, bufSize) +{ +} + +/* Initialize a sockaddr_un with the appropriate values corresponding + * to a given 'virtual port'. Returns 0 on success, -1 on error. + */ +static int +make_unix_path(char *path, size_t pathlen, int port_number) +{ + char tmp[PATH_MAX]; // temp directory + int ret = 0; + + // First, create user-specific temp directory if needed + const char* user = getenv("USER"); + if (user != NULL) { + struct stat st; + snprintf(tmp, sizeof(tmp), "/tmp/android-%s", user); + do { + ret = ::lstat(tmp, &st); + } while (ret < 0 && errno == EINTR); + + if (ret < 0 && errno == ENOENT) { + do { + ret = ::mkdir(tmp, 0766); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + ERR("Could not create temp directory: %s", tmp); + user = NULL; // will fall-back to /tmp + } + } + else if (ret < 0) { + user = NULL; // will fallback to /tmp + } + } + + if (user == NULL) { // fallback to /tmp in case of error + snprintf(tmp, sizeof(tmp), "/tmp"); + } + + // Now, initialize it properly + snprintf(path, pathlen, "%s/qemu-gles-%d", tmp, port_number); + return 0; +} + + +int UnixStream::listen(unsigned short port) +{ + char path[PATH_MAX]; + + if (make_unix_path(path, sizeof(path), port) < 0) { + return -1; + } + + m_sock = socket_local_server(path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); + if (!valid()) return int(ERR_INVALID_SOCKET); + + return 0; +} + +SocketStream * UnixStream::accept() +{ + int clientSock = -1; + + while (true) { + struct sockaddr_un addr; + socklen_t len = sizeof(addr); + clientSock = ::accept(m_sock, (sockaddr *)&addr, &len); + + if (clientSock < 0 && errno == EINTR) { + continue; + } + break; + } + + UnixStream *clientStream = NULL; + + if (clientSock >= 0) { + clientStream = new UnixStream(clientSock, m_bufsize); + } + return clientStream; +} + +int UnixStream::connect(unsigned short port) +{ + char path[PATH_MAX]; + + if (make_unix_path(path, sizeof(path), port) < 0) + return -1; + + m_sock = socket_local_client(path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); + if (!valid()) return -1; + + return 0; +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.h b/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.h new file mode 100644 index 000000000..c184b19fe --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/UnixStream.h @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef __UNIX_STREAM_H +#define __UNIX_STREAM_H + +#include "SocketStream.h" + +class UnixStream : public SocketStream { +public: + explicit UnixStream(size_t bufsize = 10000); + virtual int listen(unsigned short port); + virtual SocketStream *accept(); + virtual int connect(unsigned short port); +private: + UnixStream(int sock, size_t bufSize); +}; + +#endif diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp new file mode 100644 index 000000000..e1a0b9b7d --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.cpp @@ -0,0 +1,239 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "Win32PipeStream.h" + +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#error ONLY BUILD THIS SOURCE FILE FOR WINDOWS! +#endif + +/* The official documentation states that the name of a given named + * pipe cannot be more than 256 characters long. + */ +#define NAMED_PIPE_MAX 256 + +Win32PipeStream::Win32PipeStream(size_t bufSize) : + SocketStream(bufSize), + m_pipe(INVALID_HANDLE_VALUE) +{ +} + +Win32PipeStream::Win32PipeStream(HANDLE pipe, size_t bufSize) : + SocketStream(-1, bufSize), + m_pipe(pipe) +{ +} + +Win32PipeStream::~Win32PipeStream() +{ + if (m_pipe != INVALID_HANDLE_VALUE) { + CloseHandle(m_pipe); + m_pipe = INVALID_HANDLE_VALUE; + } +} + +/* Initialize the pipe name corresponding to a given port + */ +static void +make_pipe_name(char *path, size_t pathlen, int port_number) +{ + snprintf(path, pathlen, "\\\\.\\pipe\\qemu-gles-%d", port_number); +} + + +/* Technical note: Named pipes work differently from BSD Sockets. + * One does not create/bind a pipe, and collect a new handle each + * time a client connects with accept(). + * + * Instead, the server creates a new pipe instance each time it wants + * to get a new client connection, then calls ConnectNamedPipe() to + * wait for a connection. + * + * So listen() is a no-op, and accept() really creates the pipe handle. + * + * Also, connect() must create a pipe handle with CreateFile() and + * wait for a server instance with WaitNamedPipe() + */ +int Win32PipeStream::listen(unsigned short port) +{ + // just save the port number for accept() + m_port = port; + return 0; +} + +SocketStream * Win32PipeStream::accept() +{ + char path[NAMED_PIPE_MAX+1]; + SocketStream* clientStream; + HANDLE pipe; + + make_pipe_name(path, sizeof(path), m_port); + + pipe = ::CreateNamedPipe( + path, // pipe name + PIPE_ACCESS_DUPLEX, // read-write access + PIPE_TYPE_BYTE | // byte-oriented writes + PIPE_READMODE_BYTE | // byte-oriented reads + PIPE_WAIT, // blocking operations + PIPE_UNLIMITED_INSTANCES, // no limit on clients + 4096, // input buffer size + 4096, // output buffer size + 0, // client time-out + NULL); // default security attributes + + if (pipe == INVALID_HANDLE_VALUE) { + ERR("%s: CreateNamedPipe failed %d\n", __FUNCTION__, (int)GetLastError()); + return NULL; + } + + // Stupid Win32 API design: If a client is already connected, then + // ConnectNamedPipe will return 0, and GetLastError() will return + // ERROR_PIPE_CONNECTED. This is not an error! It just means that the + // function didn't have to wait. + // + if (::ConnectNamedPipe(pipe, NULL) == 0 && GetLastError() != ERROR_PIPE_CONNECTED) { + ERR("%s: ConnectNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); + CloseHandle(pipe); + return NULL; + } + + clientStream = new Win32PipeStream(pipe, m_bufsize); + return clientStream; +} + +int Win32PipeStream::connect(unsigned short port) +{ + char path[NAMED_PIPE_MAX+1]; + HANDLE pipe; + int tries = 10; + + make_pipe_name(path, sizeof(path), port); + + /* We're going to loop in order to wait for the pipe server to + * be setup properly. + */ + for (; tries > 0; tries--) { + pipe = ::CreateFile( + path, // pipe name + GENERIC_READ | GENERIC_WRITE, // read & write + 0, // no sharing + NULL, // default security attrs + OPEN_EXISTING, // open existing pipe + 0, // default attributes + NULL); // no template file + + /* If we have a valid pipe handle, break from the loop */ + if (pipe != INVALID_HANDLE_VALUE) { + break; + } + + /* We can get here if the pipe is busy, i.e. if the server hasn't + * create a new pipe instance to service our request. In which case + * GetLastError() will return ERROR_PIPE_BUSY. + * + * If so, then use WaitNamedPipe() to wait for a decent time + * to try again. + */ + if (GetLastError() != ERROR_PIPE_BUSY) { + /* Not ERROR_PIPE_BUSY */ + ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError()); + errno = EINVAL; + return -1; + } + + /* Wait for 5 seconds */ + if ( !WaitNamedPipe(path, 5000) ) { + ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); + errno = EINVAL; + return -1; + } + } + + m_pipe = pipe; + return 0; +} + +/* Special buffer methods, since we can't use socket functions here */ + +int Win32PipeStream::commitBuffer(size_t size) +{ + if (m_pipe == INVALID_HANDLE_VALUE) + return -1; + + size_t res = size; + int retval = 0; + + while (res > 0) { + DWORD written; + if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) { + retval = -1; + ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError()); + break; + } + res -= written; + } + return retval; +} + +const unsigned char *Win32PipeStream::readFully(void *buf, size_t len) +{ + const unsigned char* ret = NULL; + + if (m_pipe == INVALID_HANDLE_VALUE) + return NULL; + + if (!buf) { + return NULL; // do not allow NULL buf in that implementation + } + + size_t res = len; + while (res > 0) { + DWORD readcount = 0; + if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) { + errno = (int)GetLastError(); + return NULL; + } + res -= readcount; + } + return (const unsigned char *)buf; +} + +const unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len) +{ + size_t len = *inout_len; + DWORD readcount; + + if (m_pipe == INVALID_HANDLE_VALUE) + return NULL; + + if (!buf) { + return NULL; // do not allow NULL buf in that implementation + } + + if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) { + errno = (int)GetLastError(); + return NULL; + } + + *inout_len = (size_t)readcount; + return (const unsigned char *)buf; +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.h b/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.h new file mode 100644 index 000000000..41145453d --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/Win32PipeStream.h @@ -0,0 +1,41 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef __WIN32_PIPE_STREAM_H +#define __WIN32_PIPE_STREAM_H + +#include "SocketStream.h" +#include + +class Win32PipeStream : public SocketStream { +public: + explicit Win32PipeStream(size_t bufsize = 10000); + virtual ~Win32PipeStream(); + virtual int listen(unsigned short port); + virtual SocketStream *accept(); + virtual int connect(unsigned short port); + + virtual int commitBuffer(size_t size); + virtual const unsigned char *readFully(void *buf, size_t len); + virtual const unsigned char *read(void *buf, size_t *inout_len); + +private: + Win32PipeStream(HANDLE pipe, size_t bufSize); + HANDLE m_pipe; + int m_port; +}; + + +#endif diff --git a/tools/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp b/tools/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp index 0cddb644a..66611eee6 100644 --- a/tools/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp +++ b/tools/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp @@ -27,6 +27,7 @@ Thread::Thread() : Thread::~Thread() { + pthread_mutex_destroy(&m_lock); } bool diff --git a/tools/emulator/opengl/system/OpenglSystemCommon/HostConnection.cpp b/tools/emulator/opengl/system/OpenglSystemCommon/HostConnection.cpp index c967b4f58..29273416c 100644 --- a/tools/emulator/opengl/system/OpenglSystemCommon/HostConnection.cpp +++ b/tools/emulator/opengl/system/OpenglSystemCommon/HostConnection.cpp @@ -60,22 +60,6 @@ HostConnection *HostConnection::get() return NULL; } -#if 0 - TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE); - if (stream) { - if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) { - LOGE("Failed to connect to host (TcpStream)!!!\n"); - delete stream; - stream = NULL; - } - else { - con->m_stream = stream; - LOGE("Established TCP connection with HOST\n"); - } - } - if (!stream) -#endif - if (useQemuPipe) { QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE); if (!stream) { @@ -108,11 +92,11 @@ HostConnection *HostConnection::get() } // send zero 'clientFlags' to the host. - unsigned int *pClientFlags = + unsigned int *pClientFlags = (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int)); *pClientFlags = 0; con->m_stream->commitBuffer(sizeof(unsigned int)); - + LOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid()); tinfo->hostConn = con; } diff --git a/tools/emulator/opengl/system/egl/egl.cfg b/tools/emulator/opengl/system/egl/egl.cfg index 9d3f2dc38..951a2e8d6 100644 --- a/tools/emulator/opengl/system/egl/egl.cfg +++ b/tools/emulator/opengl/system/egl/egl.cfg @@ -1 +1,2 @@ -0 0 emulation +0 1 emulation +0 0 android diff --git a/tools/emulator/opengl/system/gralloc/gralloc.cpp b/tools/emulator/opengl/system/gralloc/gralloc.cpp index 258b0db85..9c3df9744 100644 --- a/tools/emulator/opengl/system/gralloc/gralloc.cpp +++ b/tools/emulator/opengl/system/gralloc/gralloc.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "gralloc_cb.h" +#include #include #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define # include @@ -25,6 +25,7 @@ #include #include #include +#include "gralloc_cb.h" #include "HostConnection.h" #include "glUtils.h" #include