Android emulator opengl - unit test host side renderer

This adds 'ut_renderer' - a host side unit test renderer. ut_renderer is used to
take a command stream over a socket connection and render it into an opengl window.
The renderer uses the GLESv1_dec decoder library and the ut_rendercontrol api to parse
the command stream.
The ut_renderer uses an external (plug-in) opengl impelementation.

Change-Id: I77794044ca9ca8a75a66a95a248eac384710aafe
This commit is contained in:
Jacky Romano
2011-03-27 18:13:21 +02:00
parent a4205ba264
commit faa8994f17
20 changed files with 1591 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
LOCAL_PATH:=$(call my-dir)
# ut_renderer test program ###########################
include $(CLEAR_VARS)
ifeq ($(HOST_OS), linux)
emulatorOpengl := $(LOCAL_PATH)/../..
LOCAL_MODULE := ut_renderer
LOCAL_MODULE_TAGS := debug
# add additional depencies to ensure that the generated code that we depend on
# is generated
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(HOST_OUT_SHARED_LIBRARIES)/libut_rendercontrol_dec$(HOST_SHLIB_SUFFIX) \
$(HOST_OUT_SHARED_LIBRARIES)/libGLESv1_dec$(HOST_SHLIB_SUFFIX)
LOCAL_SRC_FILES := ut_renderer.cpp \
RenderingThread.cpp \
ReadBuffer.cpp \
Renderer.cpp \
RendererContext.cpp \
RendererSurface.cpp \
X11Windowing.cpp \
TimeUtils.cpp
# define PVR_WAR to support imgtec PVR opengl-ES implementation
#
# specifically this MACRO enables code that work arounds a bug
# in the implementation where glTextureParameter(...,GL_TEXTURE_RECT,...)
# is called would cause a crash if the texture dimensions have not been
# defined yet.
LOCAL_CFLAGS := -DPVR_WAR
#LOCAL_CFLAGS += -g -O0
LOCAL_C_INCLUDES := $(emulatorOpengl)/system/OpenglCodecCommon \
$(call intermediates-dir-for, SHARED_LIBRARIES, libut_rendercontrol_dec, HOST) \
$(call intermediates-dir-for, SHARED_LIBRARIES, libGLESv1_dec, HOST) \
$(emulatorOpengl)/host/libs/GLESv1_dec \
$(emulatorOpengl)/system/GLESv1_enc \
$(emulatorOpengl)/tests/ut_rendercontrol_enc
LOCAL_SHARED_LIBRARIES := libut_rendercontrol_dec libGLESv1_dec libEGL_host_wrapper
LOCAL_STATIC_LIBRARIES := libOpenglCodecCommon
LOCAL_LDLIBS := -lpthread -lX11 -lrt
include $(BUILD_HOST_EXECUTABLE)
endif # HOST_OS == linux

View File

@@ -0,0 +1,28 @@
/*
* 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 _NATIVE_WINDOWING_H
#define _NATIVE_WINDOWING_H
#include <EGL/egl.h>
class NativeWindowing {
public:
virtual NativeDisplayType getNativeDisplay() = 0;
virtual NativeWindowType createNativeWindow(NativeDisplayType dpy, int width, int height) = 0;
virtual int destroyNativeWindow(NativeDisplayType dpy, NativeWindowType win) = 0;
};
#endif

View File

@@ -0,0 +1,53 @@
/*
* 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 "ReadBuffer.h"
#include <string.h>
#include <assert.h>
ReadBuffer::ReadBuffer(TcpStream *stream, size_t bufsize)
{
m_size = bufsize;
m_stream = stream;
m_buf = new unsigned char[m_size];
m_validData = 0;
m_readPtr = m_buf;
}
ReadBuffer::~ReadBuffer()
{
delete m_buf;
}
int ReadBuffer::getData()
{
if (m_validData > 0) {
memcpy(m_buf, m_readPtr, m_validData);
}
m_readPtr = m_buf;
// get fresh data into the buffer;
int stat = m_stream->recv(m_buf + m_validData, m_size - m_validData);
if (stat > 0) {
m_validData += (size_t) stat;
}
return stat;
}
void ReadBuffer::consume(size_t amount)
{
assert(amount <= m_validData);
m_validData -= amount;
m_readPtr += amount;
}

View File

@@ -0,0 +1,36 @@
/*
* 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 _READ_BUFFER_H
#define _READ_BUFFER_H
#include "TcpStream.h"
class ReadBuffer {
public:
ReadBuffer(TcpStream *stream, size_t bufSize);
~ReadBuffer();
int getData(); // get fresh data from the stream
unsigned char *buf() { return m_readPtr; } // return the next read location
size_t validData() { return m_validData; } // return the amount of valid data in readptr
void consume(size_t amount); // notify that 'amount' data has been consumed;
private:
unsigned char *m_buf;
unsigned char *m_readPtr;
size_t m_size;
size_t m_validData;
TcpStream *m_stream;
};
#endif

View File

@@ -0,0 +1,181 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "RenderingThread.h"
#include "Renderer.h"
// include operating-system dependent windowing system impelemntation
#ifdef _WIN32
# error "WINDOWS IS NOT SUPPORTED AT THE MOMENT"
#elif defined __APPLE__
# error "Apple OS-X IS NOT SUPPORTED"
#elif defined (__unix__)
# include "X11Windowing.h"
#endif
Renderer * Renderer::m_instance = NULL;
Renderer * Renderer::instance()
{
if (m_instance == NULL) m_instance = new Renderer;
return m_instance;
}
Renderer::Renderer()
{
// Unix specific, use your platform specific windowing implementation
#ifdef __unix__
m_nw = new X11Windowing;
#endif
m_dpy = eglGetDisplay(m_nw->getNativeDisplay());
EGLint major, minor;
eglInitialize(m_dpy, &major, &minor);
fprintf(stderr, "egl initialized : %d.%d\n", major, minor);
}
int Renderer::createSurface(RenderingThread *thread, const ClientHandle & handle)
{
android::Mutex::Autolock(this->m_mutex);
assert(m_surfaces.find(handle) == m_surfaces.end());
if (handle.handle == 0) {
fprintf(stderr, "trying to create surface for EGL_NO_SURFACE !!!\n");
return -1;
} else {
RendererSurface *surface = RendererSurface::create(m_dpy, RendererSurface::CONFIG_DEPTH, m_nw);
if (surface == NULL) {
printf("failed to create surface !!\n");
return -1;
}
m_surfaces.insert(SurfaceMap::value_type(handle, surface));
}
return 0;
}
int Renderer::destroySurface(RenderingThread *thread, const ClientHandle &handle)
{
android::Mutex::Autolock(this->m_mutex);
SurfaceMap::iterator i = m_surfaces.find(handle);
if (i == m_surfaces.end()) {
printf("removing surface that doesn't exists\n");
return -1;
}
if (i->second->destroy(m_nw)) {
m_surfaces.erase(handle);
}
return 0;
}
int Renderer::createContext(RenderingThread *thread, const ClientHandle &handle, ClientHandle shareCtx)
{
android::Mutex::Autolock(this->m_mutex);
assert(m_ctxs.find(handle) == m_ctxs.end());
RendererContext *shared = NULL;
if (shareCtx.handle != 0) {
ContextMap::iterator sctx = m_ctxs.find(shareCtx);
if (sctx != m_ctxs.end()) {
shared = sctx->second;
}
}
RendererContext *ctx =
RendererContext::create(m_dpy,
RendererSurface::getEglConfig(m_dpy, RendererSurface::CONFIG_DEPTH),
shared);
if (ctx == NULL) {
fprintf(stderr, "failed to create context\n");
return -1;
}
m_ctxs.insert(ContextMap::value_type(handle, ctx));
return 0;
}
int Renderer::destroyContext(RenderingThread *thread, const ClientHandle &handle)
{
android::Mutex::Autolock(this->m_mutex);
ContextMap::iterator i = m_ctxs.find(handle);
if (i == m_ctxs.end()) {
printf("removing context that doesn't exists\n");
return -1;
}
if (i->second->destroy()) {
m_ctxs.erase(handle);
}
return 0;
}
int Renderer::makeCurrent(RenderingThread *thread,
const ClientHandle &drawSurface,
const ClientHandle &readSurface,
const ClientHandle & ctx)
{
android::Mutex::Autolock(this->m_mutex);
RendererContext *currentContext = thread->currentContext();
ContextMap::iterator c = m_ctxs.find(ctx);
EGLContext eglContext;
if (ctx.handle != 0 && c != m_ctxs.end()) {
if (c->second != currentContext) {
// new context is set
if (currentContext != NULL) currentContext->unref();
c->second->ref();
eglContext = c->second->eglContext();
thread->setCurrentContext(c->second);
thread->glDecoder().setContextData(&c->second->decoderContextData());
} else {
// same context is already set
eglContext = c->second->eglContext();
}
} else {
eglContext = EGL_NO_CONTEXT;
if (currentContext != NULL) currentContext->unref();
thread->setCurrentContext(NULL);
thread->glDecoder().setContextData(NULL);
}
EGLSurface draw = EGL_NO_SURFACE;
EGLSurface read = EGL_NO_SURFACE;
SurfaceMap::iterator i;
i = m_surfaces.find(drawSurface); if (i != m_surfaces.end()) draw = i->second->eglSurface();
i = m_surfaces.find(readSurface); if (i != m_surfaces.end()) read = i->second->eglSurface();
return eglMakeCurrent(m_dpy, draw, read, eglContext);
}
int Renderer::swapBuffers(RenderingThread *thread,
const ClientHandle &surface)
{
android::Mutex::Autolock(this->m_mutex);
SurfaceMap::iterator s = m_surfaces.find(surface);
if (s == m_surfaces.end()) {
fprintf(stderr, "swapping buffers for non existing surface\n");
return -1;
}
return eglSwapBuffers(m_dpy, s->second->eglSurface());
}

View File

@@ -0,0 +1,62 @@
/*
* 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 _RENDERER_H_
#define _RENDERER_H_
#include <map>
#include "RendererSurface.h"
#include "RendererContext.h"
#include "NativeWindowing.h"
#include <utils/threads.h>
class RenderingThread;
class Renderer {
public:
class ClientHandle {
public:
unsigned int pid;
unsigned int handle;
ClientHandle(unsigned int _pid, unsigned int _handle) : pid(_pid), handle(_handle) {}
bool operator< (const ClientHandle & p) const {
bool val = (pid == p.pid) ? handle < p.handle : pid < p.pid;
return val;
}
};
static Renderer *instance();
int createSurface(RenderingThread *thread, const ClientHandle & handle);
int destroySurface(RenderingThread *thread, const ClientHandle &handle);
int createContext(RenderingThread *thread, const ClientHandle & ctx, const ClientHandle shareCtx);
int destroyContext(RenderingThread *thread,const ClientHandle & ctx);
int makeCurrent(RenderingThread *thread,
const ClientHandle & drawSurface, const ClientHandle & readSurface, const ClientHandle & ctx);
int swapBuffers(RenderingThread *thread, const ClientHandle & surface);
private:
typedef std::map<ClientHandle, RendererSurface *> SurfaceMap;
typedef std::map<ClientHandle, RendererContext *> ContextMap;
static Renderer *m_instance;
Renderer();
SurfaceMap m_surfaces;
ContextMap m_ctxs;
NativeWindowing *m_nw;
EGLDisplay m_dpy;
android::Mutex m_mutex; // single global mutex for the renderer class;
};
#endif

View File

@@ -0,0 +1,62 @@
/*
* 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 "RendererContext.h"
#include <stdio.h>
#include <stdlib.h>
RendererContext * RendererContext::create(EGLDisplay dpy, EGLConfig config, RendererContext *shareCtx)
{
EGLContext ctx;
EGLContext shared = shareCtx == NULL ? EGL_NO_CONTEXT : shareCtx->eglContext();
ctx = eglCreateContext(dpy, config, shared, NULL);
if (eglGetError() != EGL_SUCCESS) return NULL;
return new RendererContext(dpy, ctx);
}
int RendererContext::destroy()
{
if (count() <= 0) {
eglDestroyContext(m_dpy, m_ctx);
return 1;
}
return 0;
}
#ifdef PVR_WAR
void RendererContext::setActiveTexture(GLenum texture)
{
m_activeTexture = texture - GL_TEXTURE0;
}
void RendererContext::setTex2DBind(GLuint texture)
{
m_tex2DBind[m_activeTexture] = texture;
}
GLuint RendererContext::getTex2DBind()
{
return m_tex2DBind[m_activeTexture];
}
void RendererContext::addPendingCropRect(int *rect)
{
PendingCropRect *r = new PendingCropRect;
r->texture = m_tex2DBind[m_activeTexture];
memcpy(r->rect, rect, 4*sizeof(int));
m_pendingCropRects.insert(r);
}
#endif

View File

@@ -0,0 +1,125 @@
/*
* 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 _RENDERER_CONTEXT_H_
#define _RENDERER_CONTEXT_H_
#include "RendererObject.h"
#include "GLDecoderContextData.h"
#include <EGL/egl.h>
#define GL_API
#define GL_APIENTRY
#include <GLES/gl.h>
#include <string.h>
#ifdef PVR_WAR
#include <set>
struct PendingCropRect
{
GLuint texture;
int rect[4];
};
typedef std::set<PendingCropRect *> PendingCropRectSet;
#endif
class RendererContext : public RendererObject {
public:
static RendererContext *create(EGLDisplay dpy, EGLConfig config, RendererContext *shareCtx);
EGLContext eglContext() { return m_ctx; }
int destroy();
GLDecoderContextData & decoderContextData() { return m_contextData; }
#ifdef PVR_WAR
void setActiveTexture(GLenum texture);
GLenum getActiveTexture() { return GL_TEXTURE0 + m_activeTexture; }
void setTex2DBind(GLuint texture);
void setTex2DEnable(bool enable) {
m_tex2DEnable[m_activeTexture] = enable;
}
bool isTex2DEnable(int texunit) { return m_tex2DEnable[texunit]; }
GLuint getTex2DBind();
void addPendingCropRect(int *rect);
PendingCropRectSet &getPendingCropRects() { return m_pendingCropRects; }
void setClientActiveTexture(GLenum texture) { m_clientActiveTexture = texture - GL_TEXTURE0; }
GLenum getClientActiveTexture() { return m_clientActiveTexture + GL_TEXTURE0; }
void enableClientState(GLenum cap, bool enable) {
switch(cap) {
case GL_VERTEX_ARRAY:
m_clientStateEnable[0] = enable;
break;
case GL_NORMAL_ARRAY:
m_clientStateEnable[1] = enable;
break;
case GL_COLOR_ARRAY:
m_clientStateEnable[2] = enable;
break;
case GL_POINT_SIZE_ARRAY_OES:
m_clientStateEnable[3] = enable;
break;
case GL_TEXTURE_COORD_ARRAY:
m_clientStateEnable[4 + m_clientActiveTexture] = enable;
break;
}
}
bool getClientState(GLenum cap, int texUnit) {
switch(cap) {
case GL_VERTEX_ARRAY:
return m_clientStateEnable[0];
case GL_NORMAL_ARRAY:
return m_clientStateEnable[1];
case GL_COLOR_ARRAY:
return m_clientStateEnable[2];
case GL_POINT_SIZE_ARRAY_OES:
return m_clientStateEnable[3];
break;
case GL_TEXTURE_COORD_ARRAY:
return m_clientStateEnable[4 + texUnit];
break;
}
return false;
}
#endif
private:
EGLDisplay m_dpy;
EGLContext m_ctx;
GLDecoderContextData m_contextData;
RendererContext(EGLDisplay dpy, EGLContext ctx) :
m_dpy(dpy),
m_ctx(ctx)
{
#ifdef PVR_WAR
m_activeTexture = 0;
m_clientActiveTexture = 0;
memset(m_tex2DBind, 0, 8*sizeof(GLuint));
memset(m_tex2DEnable, 0, 8*sizeof(bool));
memset(m_clientStateEnable, 0, 16*sizeof(bool));
#endif
}
#ifdef PVR_WAR
int m_tex2DBind[8];
bool m_tex2DEnable[8];
int m_activeTexture;
int m_clientActiveTexture;
bool m_clientStateEnable[16];
PendingCropRectSet m_pendingCropRects;
#endif
};
#endif

View File

@@ -0,0 +1,29 @@
/*
* 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 _RENDERER_OBJECT_H_
#define _RENDERER_OBJECT_H_
class RendererObject {
public:
RendererObject() { m_count = 0; }
int count() { return m_count; }
void ref() { m_count++; }
void unref() { m_count--; }
private:
int m_count;
};
#endif

View File

@@ -0,0 +1,91 @@
/*
* 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 "RendererSurface.h"
#include <stdio.h>
#include <stdlib.h>
#include "NativeWindowing.h"
#define MAX_ATTRIB 100
EGLConfig RendererSurface::getEglConfig(EGLDisplay eglDisplay, SurfaceConfig config)
{
EGLConfig eglConfig;
int nConfigs;
EGLint attrib[MAX_ATTRIB];
int pos =0;
attrib[pos++] = EGL_SURFACE_TYPE; attrib[pos++] = EGL_WINDOW_BIT;
if (config & CONFIG_DEPTH) {attrib[pos++] = EGL_DEPTH_SIZE; attrib[pos++] = 1;}
attrib[pos++] = EGL_NONE;
if (!eglChooseConfig(eglDisplay, attrib, &eglConfig, 1, &nConfigs)) {
return 0;
}
/***/
int ibuf;
if (eglGetConfigAttrib(eglDisplay, eglConfig, EGL_BUFFER_SIZE, &ibuf)) {
fprintf(stderr, "EGL COLOR Buffer size: %d\n", ibuf);
} else {
fprintf(stderr, "eglGetConfigAttrib error: %d\n", eglGetError());
}
if (eglGetConfigAttrib(eglDisplay, eglConfig, EGL_DEPTH_SIZE, &ibuf)) {
fprintf(stderr, "EGL DEPTH Buffer size: %d\n", ibuf);
} else {
fprintf(stderr, "eglGetConfigAttrib error: %d\n", eglGetError());
}
/***/
if (nConfigs != 1) {
return 0;
}
return eglConfig;
}
RendererSurface * RendererSurface::create(EGLDisplay eglDisplay, SurfaceConfig config, NativeWindowing *nw)
{
EGLConfig eglConfig = getEglConfig(eglDisplay, config);
if (eglConfig == 0) {
return NULL;
}
NativeWindowType window = nw->createNativeWindow(nw->getNativeDisplay(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
if (window == 0) {
return NULL;
}
EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay,
eglConfig,
window, NULL);
if (eglGetError() != EGL_SUCCESS) {
return NULL;
}
return new RendererSurface(eglDisplay, window, eglSurface, eglConfig);
}
int RendererSurface::destroy(NativeWindowing *nw)
{
eglDestroySurface(m_eglDisplay, m_eglSurface);
nw->destroyNativeWindow(nw->getNativeDisplay(), m_window);
return 1;
}

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 _RENDERER_SURFACE_H_
#define _RENDERER_SURFACE_H_
#include <EGL/egl.h>
#include "NativeWindowing.h"
#include "RendererObject.h"
#define DEFAULT_HEIGHT 480
#define DEFAULT_WIDTH 320
class RendererSurface : public RendererObject {
public:
typedef enum { CONFIG_DEPTH = 1 << 0 } SurfaceConfig;
EGLSurface eglSurface() { return m_eglSurface; }
EGLConfig eglConfig() { return m_config; }
EGLDisplay eglDisplay() { return m_eglDisplay; }
static RendererSurface * create(EGLDisplay eglDisplay, SurfaceConfig config, NativeWindowing *nw);
static EGLConfig getEglConfig(EGLDisplay eglDisplay, SurfaceConfig config);
int destroy(NativeWindowing *nw);
private:
RendererSurface(EGLDisplay display, NativeWindowType window, EGLSurface surface, EGLConfig config) :
m_eglDisplay(display),
m_config(config),
m_window(window),
m_eglSurface(surface)
{}
EGLDisplay m_eglDisplay;
EGLConfig m_config;
NativeWindowType m_window;
EGLSurface m_eglSurface;
};
#endif

View File

@@ -0,0 +1,376 @@
/*
* 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 "RenderingThread.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include "ReadBuffer.h"
#include "Renderer.h"
#include "TimeUtils.h"
#include <GLES/glext.h>
__thread RenderingThread * RenderingThread::m_tls;
#ifdef PVR_WAR
void RenderingThread::s_glTexParameteriv(GLenum target, GLenum param, int *p)
{
if (target == GL_TEXTURE_2D && param == GL_TEXTURE_CROP_RECT_OES) {
m_tls->m_currentContext->addPendingCropRect(p);
} else {
m_tls->m_glTexParameteriv(target, param, p);
}
}
void RenderingThread::s_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexfOES(x, y, z, w, h);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort w, GLshort h)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexsOES(x, y, z, w, h);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexiOES(x, y, z, w, h);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexxOES(x, y, z, w, h);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexfvOES(GLfloat *coords)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexfvOES(coords);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexsvOES(GLshort *coords)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexsvOES(coords);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexivOES(GLint *coords)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexivOES(coords);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glDrawTexxvOES(GLfixed *coords)
{
m_tls->applyPendingCropRects();
m_tls->m_glDrawTexxvOES(coords);
m_tls->fixTextureEnable();
}
void RenderingThread::s_glActiveTexture(GLenum texture)
{
if (texture - GL_TEXTURE0 >= m_tls->m_backendCaps.maxTextureUnits) return;
m_tls->m_currentContext->setActiveTexture(texture);
m_tls->m_glActiveTexture(texture);
}
void RenderingThread::s_glBindTexture(GLenum target, GLuint texture)
{
if (target == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DBind(texture);
m_tls->m_glBindTexture(target, texture);
}
void RenderingThread::s_glEnable(GLenum cap)
{
if (cap == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DEnable(true);
m_tls->m_glEnable(cap);
}
void RenderingThread::s_glDisable(GLenum cap)
{
if (cap == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DEnable(false);
m_tls->m_glDisable(cap);
}
void RenderingThread::s_glClientActiveTexture(GLenum texture)
{
if (texture - GL_TEXTURE0 >= m_tls->m_backendCaps.maxTextureUnits) return;
m_tls->m_currentContext->setClientActiveTexture(texture);
m_tls->m_glClientActiveTexture(texture);
}
void RenderingThread::s_glEnableClientState(GLenum cap)
{
m_tls->m_currentContext->enableClientState(cap, true);
m_tls->m_glEnableClientState(cap);
}
void RenderingThread::s_glDisableClientState(GLenum cap)
{
m_tls->m_currentContext->enableClientState(cap, false);
m_tls->m_glDisableClientState(cap);
}
void RenderingThread::applyPendingCropRects()
{
PendingCropRectSet &rset = m_currentContext->getPendingCropRects();
if (rset.size() > 0) {
GLuint currBindedTex = m_currentContext->getTex2DBind();
for (PendingCropRectSet::iterator i = rset.begin();
i != rset.end();
i++) {
m_glBindTexture(GL_TEXTURE_2D, (*i)->texture);
m_glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, (int *)(*i)->rect);
delete (*i);
}
m_glBindTexture(GL_TEXTURE_2D, currBindedTex);
rset.clear();
}
}
void RenderingThread::fixTextureEnable()
{
// restore texture units enable state
for (unsigned int i=0; i<m_backendCaps.maxTextureUnits; i++) {
m_glActiveTexture(GL_TEXTURE0 + i);
if (m_currentContext->isTex2DEnable(i)) {
m_glEnable(GL_TEXTURE_2D);
}
else {
m_glDisable(GL_TEXTURE_2D);
}
m_glClientActiveTexture(GL_TEXTURE0 + i);
if (m_currentContext->getClientState(GL_TEXTURE_COORD_ARRAY, i)) {
m_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else {
m_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
// restore current active texture
m_glActiveTexture(m_currentContext->getActiveTexture());
m_glClientActiveTexture(m_currentContext->getClientActiveTexture());
// restore other client state enable bits
if (m_currentContext->getClientState(GL_VERTEX_ARRAY, 0)) {
m_glEnableClientState(GL_VERTEX_ARRAY);
}
else {
m_glDisableClientState(GL_VERTEX_ARRAY);
}
if (m_currentContext->getClientState(GL_NORMAL_ARRAY, 0)) {
m_glEnableClientState(GL_NORMAL_ARRAY);
}
else {
m_glDisableClientState(GL_NORMAL_ARRAY);
}
if (m_currentContext->getClientState(GL_COLOR_ARRAY, 0)) {
m_glEnableClientState(GL_COLOR_ARRAY);
}
else {
m_glDisableClientState(GL_COLOR_ARRAY);
}
if (m_currentContext->getClientState(GL_POINT_SIZE_ARRAY_OES, 0)) {
m_glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
}
else {
m_glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
}
}
#endif
int RenderingThread::s_createContext(uint32_t pid, uint32_t handle, uint32_t shareCtx)
{
return Renderer::instance()->createContext(m_tls, Renderer::ClientHandle(pid, handle),
Renderer::ClientHandle(pid, shareCtx));
}
int RenderingThread::s_createSurface(uint32_t pid, uint32_t handle)
{
return Renderer::instance()->createSurface(m_tls, Renderer::ClientHandle(pid, handle));
}
int RenderingThread::s_destroySurface(uint32_t pid, uint32_t handle)
{
return Renderer::instance()->destroySurface(m_tls, Renderer::ClientHandle(pid, handle));
}
int RenderingThread::s_destroyContext(uint32_t pid, uint32_t handle)
{
return Renderer::instance()->destroyContext(m_tls, Renderer::ClientHandle(pid, handle));
}
int RenderingThread::s_makeCurrent(uint32_t pid, uint32_t drawSurface, uint32_t readSurface, uint32_t ctx)
{
int ret = Renderer::instance()->makeCurrent(m_tls,
Renderer::ClientHandle(pid, drawSurface),
Renderer::ClientHandle(pid, readSurface),
Renderer::ClientHandle(pid, ctx));
if (ret && ctx) {
m_tls->initBackendCaps();
}
return ret;
}
void RenderingThread::s_swapBuffers(uint32_t pid, uint32_t surface)
{
Renderer::instance()->swapBuffers(m_tls, Renderer::ClientHandle(pid, surface));
}
RenderingThread::RenderingThread(TcpStream *stream) :
m_stream(stream),
m_currentContext(NULL)
{
m_backendCaps.initialized = false;
}
int RenderingThread::start(void)
{
if (pthread_create(&m_thread, NULL, s_thread, this) < 0) {
perror("pthread_create");
return -1;
}
return 0;
}
void * RenderingThread::s_thread(void *data)
{
RenderingThread *self = (RenderingThread *)data;
m_tls = self;
return self->thread();
}
void RenderingThread::initBackendCaps()
{
if (m_backendCaps.initialized) return;
m_glDec.glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *)&m_backendCaps.maxTextureUnits);
m_backendCaps.initialized = true;
}
void *RenderingThread::thread()
{
// initialize our decoders;
m_glDec.initGL();
#ifdef PVR_WAR
m_glTexParameteriv = m_glDec.set_glTexParameteriv(s_glTexParameteriv);
m_glDrawTexfOES = m_glDec.set_glDrawTexfOES(s_glDrawTexfOES);
m_glDrawTexsOES = m_glDec.set_glDrawTexsOES(s_glDrawTexsOES);
m_glDrawTexiOES = m_glDec.set_glDrawTexiOES(s_glDrawTexiOES);
m_glDrawTexxOES = m_glDec.set_glDrawTexxOES(s_glDrawTexxOES);
m_glDrawTexfvOES = m_glDec.set_glDrawTexfvOES(s_glDrawTexfvOES);
m_glDrawTexsvOES = m_glDec.set_glDrawTexsvOES(s_glDrawTexsvOES);
m_glDrawTexivOES = m_glDec.set_glDrawTexivOES(s_glDrawTexivOES);
m_glDrawTexxvOES = m_glDec.set_glDrawTexxvOES(s_glDrawTexxvOES);
m_glActiveTexture = m_glDec.set_glActiveTexture(s_glActiveTexture);
m_glBindTexture = m_glDec.set_glBindTexture(s_glBindTexture);
m_glEnable = m_glDec.set_glEnable(s_glEnable);
m_glDisable = m_glDec.set_glDisable(s_glDisable);
m_glClientActiveTexture = m_glDec.set_glClientActiveTexture(s_glClientActiveTexture);
m_glEnableClientState = m_glDec.set_glEnableClientState(s_glEnableClientState);
m_glDisableClientState = m_glDec.set_glDisableClientState(s_glDisableClientState);
#endif
m_utDec.set_swapBuffers(s_swapBuffers);
m_utDec.set_createContext(s_createContext);
m_utDec.set_destroyContext(s_destroyContext);
m_utDec.set_createSurface(s_createSurface);
m_utDec.set_destroySurface(s_destroySurface);
m_utDec.set_makeCurrentContext(s_makeCurrent);
ReadBuffer readBuf(m_stream, DECODER_BUF_SIZE);
int stats_totalBytes = 0;
long long stats_t0 = GetCurrentTimeMS();
while (1) {
int stat = readBuf.getData();
if (stat == 0) {
fprintf(stderr, "client shutdown\n");
break;
} else if (stat < 0) {
perror("getData");
break;
}
//
// log received bandwidth statistics
//
stats_totalBytes += readBuf.validData();
long long dt = GetCurrentTimeMS() - stats_t0;
if (dt > 1000) {
float dts = (float)dt / 1000.0f;
printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
stats_totalBytes = 0;
stats_t0 = GetCurrentTimeMS();
}
bool progress = true;
while (progress) {
progress = false;
// we need at least one header (8 bytes) in our buffer
if (readBuf.validData() >= 8) {
size_t last = m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
if (last > 0) {
progress = true;
readBuf.consume(last);
}
}
if (readBuf.validData() >= 8) {
size_t last = m_utDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
if (last > 0) {
readBuf.consume(last);
progress = true;
}
}
}
}
// shutdown
if (m_currentContext != NULL) {
m_currentContext->unref();
}
return NULL;
}

View File

@@ -0,0 +1,113 @@
/*
* 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 _RENDERING_THREAD_H_
#define _RENDERING_THREAD_H_
#include "TcpStream.h"
#include "GLDecoder.h"
#include "ut_rendercontrol_dec.h"
#include <pthread.h>
#define GL_API
#define GL_APIENTRY
#include <GLES/egl.h>
#include <GLES/gl.h>
#define WINDOW_WIDTH 320
#define WINDOW_HEIGHT 480
#define DECODER_BUF_SIZE (4 * 1024 * 1024)
class RendererContext;
class RenderingThread {
public:
RenderingThread(TcpStream *stream);
int start();
void *thread();
RendererContext *currentContext() { return m_currentContext; }
void setCurrentContext(RendererContext *ctx) { m_currentContext = ctx; }
GLDecoder & glDecoder() { return m_glDec; }
private:
void initBackendCaps();
private:
GLDecoder m_glDec;
ut_rendercontrol_decoder_context_t m_utDec;
TcpStream *m_stream;
pthread_t m_thread;
RendererContext * m_currentContext;
struct BackendCaps {
bool initialized;
GLuint maxTextureUnits;
} m_backendCaps;
static void * s_thread(void *data);
static __thread RenderingThread *m_tls;
static int s_createContext(uint32_t pid, uint32_t handle, uint32_t shareCtx);
static int s_createSurface(uint32_t pid, uint32_t handle);
static int s_destroySurface(uint32_t pid, uint32_t handle);
static int s_destroyContext(uint32_t pid, uint32_t handle);
static int s_makeCurrent(uint32_t pid, uint32_t drawSurface, uint32_t readSurface, uint32_t ctx);
static void s_swapBuffers(uint32_t pid, uint32_t surface);
#ifdef PVR_WAR
static void s_glTexParameteriv(GLenum target, GLenum param, int *p);
static void s_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h);
static void s_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort w, GLshort h);
static void s_glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h);
static void s_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h);
static void s_glDrawTexfvOES(GLfloat *coords);
static void s_glDrawTexsvOES(GLshort *coords);
static void s_glDrawTexivOES(GLint *coords);
static void s_glDrawTexxvOES(GLfixed *coords);
static void s_glActiveTexture(GLenum texture);
static void s_glBindTexture(GLenum target, GLuint texture);
static void s_glEnable(GLenum cap);
static void s_glDisable(GLenum cap);
static void s_glClientActiveTexture(GLenum texture);
static void s_glEnableClientState(GLenum cap);
static void s_glDisableClientState(GLenum cap);
void applyPendingCropRects();
void fixTextureEnable();
glTexParameteriv_server_proc_t m_glTexParameteriv;
glDrawTexfOES_server_proc_t m_glDrawTexfOES;
glDrawTexiOES_server_proc_t m_glDrawTexiOES;
glDrawTexsOES_server_proc_t m_glDrawTexsOES;
glDrawTexxOES_server_proc_t m_glDrawTexxOES;
glDrawTexfvOES_server_proc_t m_glDrawTexfvOES;
glDrawTexivOES_server_proc_t m_glDrawTexivOES;
glDrawTexsvOES_server_proc_t m_glDrawTexsvOES;
glDrawTexxvOES_server_proc_t m_glDrawTexxvOES;
glActiveTexture_server_proc_t m_glActiveTexture;
glBindTexture_server_proc_t m_glBindTexture;
glEnable_server_proc_t m_glEnable;
glDisable_server_proc_t m_glDisable;
glClientActiveTexture_server_proc_t m_glClientActiveTexture;
glEnableClientState_server_proc_t m_glEnableClientState;
glDisableClientState_server_proc_t m_glDisableClientState;
#endif
};
#endif

View File

@@ -0,0 +1,55 @@
/*
* 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 "TimeUtils.h"
#ifdef _WIN32
#include <Windows.h>
#include <time.h>
#include <stdio.h>
#elif defined(__linux__)
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#else
#error "Unsupported platform"
#endif
long long GetCurrentTimeMS()
{
#ifdef _WIN32
static LARGE_INTEGER freq;
static bool bNotInit = true;
if ( bNotInit ) {
bNotInit = (QueryPerformanceFrequency( &freq ) == FALSE);
}
LARGE_INTEGER currVal;
QueryPerformanceCounter( &currVal );
return currVal.QuadPart / (freq.QuadPart / 1000);
#elif defined(__linux__)
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
long long iDiff = (now.tv_sec * 1000LL) + now.tv_nsec/1000000LL;
return iDiff;
#else
#error "Unsupported platform"
#endif
}

View File

@@ -0,0 +1,21 @@
/*
* 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 _TIME_UTILS_H
#define _TIME_UTILS_H
long long GetCurrentTimeMS();
#endif

View File

@@ -0,0 +1,69 @@
/*
* 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 "X11RendererSurface.h"
NativeDisplayType X11RendererSurface::getNativeDisplay()
{
if (m_display == NULL) {
m_display = XOpenDisplay(NULL);
}
return NativeDisplayType(m_display);
}
int X11RendererSurface::destoryNativeWindow(NativeWindowType win)
{
if (m_display == NULL) return -1;
Window x11Window = (Window)(win);
return XDestroyWindow(m_display, x11Window);
}
NativeWindowType GlesX11Win::createNativeWindow()
{
getNativeDisplay();
if (m_display == NULL) {
return -1;
}
long defaultScreen = DefaultScreen( dpy );
Window rootWindow = RootWindow(dpy, defaultScreen);
int depth = DefaultDepth(dpy, defaultScreen);
XVisualInfo *visualInfo = new XVisualInfo;
XMatchVisualInfo(m_display, defaultScreen, , dpeth, TrueColor, visualInfo);
if (visualInfo == NULL) {
fprintf(stderr, "couldn't find matching visual\n");
return -1;
}
Colormap x11Colormap = XCreateColormap(m_display, rootWindow, visualInfo->visual, AllocNone);
XSetWindowAttributes sWA;
sWA.Colormap = x11Colormap;
sWA.event_mask = StructureNotifyMask | ExposureMask;
unsigned int eventMask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
Window win = XCreateWindow( m_display,
rootWindow,
0, 0, width, height,
0, CopyFromParent, InputOutput,
CopyFromParent, eventMask, &sWA);
XMapWindow(m_display, win);
XFlush(m_display);
return NativeWindowType(win);
}

View File

@@ -0,0 +1,37 @@
/*
* 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 _X11_RENDERER_SURFACE_H_
#define _X11_RENDERER_SURFACE_H_
#include <X11/Xutil.h>
#include <X11/Xlib.h>
#include <EGL/egl.h>
include "RendererSurface.h"
class X11RendererSurface : public RendererSurface
{
public:
X11RendererSurface() : RendererSurface() {
m_display = NULL;
}
NativeDisplayType getNativeDisplay();
NativeWindowType createNativeWindow();
int destroyNativeWindow(NativeWindowType win);
private:
Display m_display;
};
#endif

View File

@@ -0,0 +1,70 @@
/*
* 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 "X11Windowing.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
NativeDisplayType X11Windowing::getNativeDisplay()
{
Display *dpy = XOpenDisplay(NULL);
return (NativeDisplayType)dpy;
}
NativeWindowType X11Windowing::createNativeWindow(NativeDisplayType _dpy, int width, int height)
{
Display *dpy = (Display *) _dpy;
long defaultScreen = DefaultScreen( dpy );
Window rootWindow = RootWindow(dpy, defaultScreen);
int depth = DefaultDepth(dpy, defaultScreen);
XVisualInfo *visualInfo = new XVisualInfo;
XMatchVisualInfo(dpy, defaultScreen, depth, TrueColor, visualInfo);
if (visualInfo == NULL) {
fprintf(stderr, "couldn't find matching visual\n");
return NULL;
}
Colormap x11Colormap = XCreateColormap(dpy, rootWindow, visualInfo->visual, AllocNone);
XSetWindowAttributes sWA;
sWA.colormap = x11Colormap;
sWA.event_mask = StructureNotifyMask | ExposureMask;
sWA.background_pixel = 0;
sWA.border_pixel = 0;
unsigned int attributes_mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
Window win = XCreateWindow( dpy,
rootWindow,
0, 0, width, height,
0, CopyFromParent, InputOutput,
CopyFromParent, attributes_mask, &sWA);
XMapWindow(dpy, win);
XFlush(dpy);
return NativeWindowType(win);
}
int X11Windowing::destroyNativeWindow(NativeDisplayType _dpy, NativeWindowType _win)
{
Display *dpy = (Display *)_dpy;
Window win = (Window)_win;
XDestroyWindow(dpy, win);
XFlush(dpy);
return 0;
}

View File

@@ -0,0 +1,27 @@
/*
* 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 _X11WINDOWING_H_
#define _X11WINDOWING_H_
#include "NativeWindowing.h"
class X11Windowing : public NativeWindowing {
NativeDisplayType getNativeDisplay();
NativeWindowType createNativeWindow(NativeDisplayType _dpy, int width, int height);
int destroyNativeWindow(NativeDisplayType dpy, NativeWindowType win);
};
#endif

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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "codec_defs.h"
#include "RenderingThread.h"
#include "TcpStream.h"
int main(int argc, char **argv)
{
TcpStream *socket = new TcpStream;
if (socket->listen(CODEC_SERVER_PORT) < 0) {
perror("listen");
exit(1);
}
printf("waiting for client connection on port: %d\n", CODEC_SERVER_PORT);
while (1) {
// wait for client connection
TcpStream *glStream = socket->accept();
if (glStream == NULL) {
printf("failed to get client.. aborting\n");
exit(3);
}
printf("Got client connection, creating a rendering thread;\n");
// create a thread to handle this connection
RenderingThread *rt = new RenderingThread(glStream);
rt->start();
}
return 0;
}