Merge "emulator: opengl: Use QEMU pipe."

This commit is contained in:
David 'Digit' Turner
2011-05-03 07:23:18 -07:00
committed by Android Code Review
10 changed files with 317 additions and 36 deletions

View File

@@ -134,7 +134,7 @@ int TcpStream::writeFully(const void *buf, size_t len)
if (stat < 0) {
if (errno != EINTR) {
retval = stat;
ERR("TcpStream::writeFully failed, errno = %d\n", errno);
ERR("TcpStream::writeFully failed: %s\n", strerror(errno));
break;
}
} else {
@@ -161,7 +161,7 @@ const unsigned char *TcpStream::readFully(void *buf, size_t len)
if (errno == EINTR) {
continue;
} else {
ERR("TcpStream::readFully failed, errno = %d 0x%x \n", errno,buf);
ERR("TcpStream::readFully failed (buf 0x%x): %s\n", buf, strerror(errno));
return NULL;
}
} else {

View File

@@ -428,7 +428,7 @@ void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum
count * glSizeof(type));
// XXX - OPTIMIZATION (see the other else branch) should be implemented
if(!has_indirect_arrays) {
LOGD("unoptimized drawelements !!!\n");
//LOGD("unoptimized drawelements !!!\n");
}
} else {
// we are all direct arrays and immidate mode index array -

View File

@@ -12,6 +12,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
LOCAL_SRC_FILES := \
HostConnection.cpp \
QemuPipeStream.cpp \
ThreadInfo.cpp
LOCAL_C_INCLUDES += \

View File

@@ -15,12 +15,16 @@
*/
#include "HostConnection.h"
#include "TcpStream.h"
#include "QemuPipeStream.h"
#include "ThreadInfo.h"
#include <cutils/log.h>
#define STREAM_BUFFER_SIZE 4*1024*1024
#define STREAM_PORT_NUM 4141
/* Set to 1 to use a QEMU pipe, or 0 for a TCP connection */
#define USE_QEMU_PIPE 1
HostConnection::HostConnection() :
m_stream(NULL),
m_glEnc(NULL),
@@ -37,36 +41,52 @@ HostConnection::~HostConnection()
HostConnection *HostConnection::get()
{
/* TODO: Make this configurable with a system property */
const int useQemuPipe = USE_QEMU_PIPE;
// Get thread info
EGLThreadInfo *tinfo = getEGLThreadInfo();
if (!tinfo) {
return NULL;
}
//
// create new host connection for that thread if needed
//
if (tinfo->hostConn == NULL) {
HostConnection *con = new HostConnection();
if (NULL == con) {
return NULL;
}
TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
if (!stream) {
LOGE("Failed to create TcpStream for host connection!!!\n");
delete con;
return NULL;
if (useQemuPipe) {
QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
if (!stream) {
LOGE("Failed to create QemuPipeStream for host connection!!!\n");
delete con;
return NULL;
}
if (stream->connect() < 0) {
LOGE("Failed to connect to host !!!\n");
delete con;
return NULL;
}
con->m_stream = stream;
}
else /* !useQemuPipe */
{
TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
if (!stream) {
LOGE("Failed to create TcpStream for host connection!!!\n");
delete con;
return NULL;
}
if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
LOGE("Failed to connect to host !!!\n");
delete con;
return NULL;
if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
LOGE("Failed to connect to host !!!\n");
delete con;
return NULL;
}
con->m_stream = stream;
}
LOGD("Host Connection established \n");
con->m_stream = stream;
tinfo->hostConn = con;
}

View File

@@ -0,0 +1,184 @@
/*
* 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 "QemuPipeStream.h"
#include <hardware/qemu_pipe.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
QemuPipeStream::QemuPipeStream(size_t bufSize) :
IOStream(bufSize),
m_sock(-1),
m_bufsize(bufSize),
m_buf(NULL)
{
}
QemuPipeStream::QemuPipeStream(int sock, size_t bufSize) :
IOStream(bufSize),
m_sock(sock),
m_bufsize(bufSize),
m_buf(NULL)
{
}
QemuPipeStream::~QemuPipeStream()
{
if (m_sock >= 0) {
::close(m_sock);
}
if (m_buf != NULL) {
free(m_buf);
}
}
int QemuPipeStream::connect(void)
{
m_sock = qemu_pipe_open("opengles");
if (!valid()) return -1;
return 0;
}
void *QemuPipeStream::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 QemuPipeStream::commitBuffer(size_t size)
{
return writeFully(m_buf, size);
}
int QemuPipeStream::writeFully(const void *buf, size_t len)
{
if (!valid()) return -1;
size_t res = len;
int retval = 0;
while (res > 0) {
ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res);
if (stat > 0) {
res -= stat;
continue;
}
if (stat == 0) { /* EOF */
ERR("QemuPipeStream::writeFully failed: premature EOF\n");
retval = -1;
break;
}
if (errno == EINTR) {
continue;
}
retval = stat;
ERR("QemuPipeStream::writeFully failed: %s\n", strerror(errno));
break;
}
return retval;
}
const unsigned char *QemuPipeStream::readFully(void *buf, size_t len)
{
if (!valid()) return NULL;
if (!buf) {
ERR("QemuPipeStream::readFully failed, buf=NULL");
return NULL; // do not allow NULL buf in that implementation
}
size_t res = len;
while (res > 0) {
ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, len);
if (stat == 0) {
// client shutdown;
return NULL;
} else if (stat < 0) {
if (errno == EINTR) {
continue;
} else {
ERR("QemuPipeStream::readFully failed (buf %p): %s\n",
buf, strerror(errno));
return NULL;
}
} else {
res -= stat;
}
}
return (const unsigned char *)buf;
}
const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len)
{
if (!valid()) return NULL;
if (!buf) {
ERR("QemuPipeStream::read failed, buf=NULL");
return NULL; // do not allow NULL buf in that implementation
}
int n = recv(buf, *inout_len);
if (n > 0) {
*inout_len = n;
return (const unsigned char *)buf;
}
return NULL;
}
int QemuPipeStream::recv(void *buf, size_t len)
{
if (!valid()) return int(ERR_INVALID_SOCKET);
char* p = (char *)buf;
int ret = 0;
while(len > 0) {
int res = ::read(m_sock, p, len);
if (res > 0) {
p += res;
ret += res;
len -= res;
continue;
}
if (res == 0) { /* EOF */
break;
}
if (errno == EINTR)
continue;
/* A real error */
if (ret == 0)
ret = -1;
break;
}
return ret;
}

View File

@@ -0,0 +1,52 @@
/*
* 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 __QEMU_PIPE_STREAM_H
#define __QEMU_PIPE_STREAM_H
/* This file implements an IOStream that uses a QEMU fast-pipe
* to communicate with the emulator's 'opengles' service. See
* <hardware/qemu_pipe.h> for more details.
*/
#include <stdlib.h>
#include "IOStream.h"
class QemuPipeStream : public IOStream {
public:
typedef enum { ERR_INVALID_SOCKET = -1000 } QemuPipeStreamError;
explicit QemuPipeStream(size_t bufsize = 10000);
~QemuPipeStream();
int connect(void);
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);
private:
int writeFully(const void *buf, size_t len);
private:
int m_sock;
size_t m_bufsize;
unsigned char *m_buf;
QemuPipeStream(int sock, size_t bufSize);
};
#endif

View File

@@ -32,7 +32,8 @@ LOCAL_MODULE := gralloc.goldfish
LOCAL_STATIC_LIBRARIES := \
libOpenglSystemCommon \
libOpenglCodecCommon
libOpenglCodecCommon \
libqemu
LOCAL_SHARED_LIBRARIES := \
libcutils \

View File

@@ -102,6 +102,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
LOCAL_C_INCLUDES := $(emulatorOpengl)/shared/OpenglCodecCommon \
$(emulatorOpengl)/host/include/libOpenglRender \
$(emulatorOpengl)/system/OpenglSystemCommon \
$(call intermediates-dir-for, SHARED_LIBRARIES, libut_rendercontrol_enc) \
$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv1_enc) \
$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv2_enc) \
@@ -127,7 +128,7 @@ LOCAL_SHARED_LIBRARIES := libdl \
libGLESv1_enc \
libGLESv2_enc \
libut_rendercontrol_enc
LOCAL_STATIC_LIBRARIES := libOpenglCodecCommon
LOCAL_STATIC_LIBRARIES := libOpenglCodecCommon libOpenglSystemCommon libqemu
include $(BUILD_SHARED_LIBRARY)

View File

@@ -16,6 +16,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "ServerConnection.h"
#include "TcpStream.h"
#include "QemuPipeStream.h"
#include <cutils/log.h>
#include "ThreadInfo.h"
@@ -72,24 +74,44 @@ ServerConnection::~ServerConnection()
int ServerConnection::create(size_t bufsize,
const char *defaultServer)
{
/* XXX: Make configurable through system property */
int useQemuPipe = 1;
if (m_stream != NULL) delete(m_stream);
m_stream = new TcpStream(bufsize);
char *s = getenv(ENV_RGL_SERVER);
char *hostname;
if (s == NULL) {
hostname = strdup(defaultServer);
} else {
hostname = strdup(s);
if (useQemuPipe) {
QemuPipeStream* pipeStream = new QemuPipeStream(bufsize);
if (pipeStream->connect() < 0) {
LOGE("couldn't connect to host server\n");
delete pipeStream;
return -1;
}
m_stream = pipeStream;
}
else /* !useQemuPipe */
{
TcpStream* tcpStream = new TcpStream(bufsize);
if (m_stream->connect(hostname, CODEC_SERVER_PORT) < 0) {
LOGE("couldn't connect to %s\n", hostname);
char *s = getenv(ENV_RGL_SERVER);
char *hostname;
if (s == NULL) {
hostname = strdup(defaultServer);
} else {
hostname = strdup(s);
}
if (tcpStream->connect(hostname, CODEC_SERVER_PORT) < 0) {
LOGE("couldn't connect to %s\n", hostname);
free(hostname);
delete tcpStream;
return -1;
}
LOGI("connecting to server %s\n", hostname);
free(hostname);
return -1;
m_stream = tcpStream;
}
LOGI("connecting to server %s\n", hostname);
free(hostname);
m_glEnc = new GLEncoder(m_stream);
m_glEnc->setContextAccessor(s_getGlContext);

View File

@@ -18,7 +18,7 @@
#include "GLEncoder.h"
#include "GL2Encoder.h"
#include "TcpStream.h"
#include "IOStream.h"
#include "codec_defs.h"
#include "ut_rendercontrol_enc.h"
#include <pthread.h>
@@ -44,7 +44,7 @@ private:
static pthread_key_t s_glKey;
static pthread_key_t s_connectionKey;
static void s_initKeys();
TcpStream *m_stream;
IOStream *m_stream;
GLEncoder *m_glEnc;
GL2Encoder *m_gl2Enc;
ut_rendercontrol_encoder_context_t *m_ut_enc;