/* * 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 "libOpenglRender/render_api.h" #include "IOStream.h" #include "FrameBuffer.h" #include "RenderServer.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" static RenderServer *s_renderThread = NULL; static char s_renderAddr[256]; static IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags); int initLibrary(void) { // // Load EGL Plugin // if (!init_egl_dispatch()) { // Failed to load EGL printf("Failed to init_egl_dispatch\n"); return false; } // // Load GLES Plugin // if (!init_gl_dispatch()) { // Failed to load GLES ERR("Failed to init_gl_dispatch\n"); return false; } /* failure to init the GLES2 dispatch table is not fatal */ init_gl2_dispatch(); return true; } int initOpenGLRenderer(int width, int height, char* addr, size_t addrLen) { // // Fail if renderer is already initialized // if (s_renderThread) { return false; } // // initialize the renderer and listen to connections // on a thread in the current process. // bool inited = FrameBuffer::initialize(width, height); if (!inited) { return false; } s_renderThread = RenderServer::create(addr, addrLen); if (!s_renderThread) { return false; } strncpy(s_renderAddr, addr, sizeof(s_renderAddr)); s_renderThread->start(); return true; } void setPostCallback(OnPostFn onPost, void* onPostContext) { FrameBuffer* fb = FrameBuffer::getFB(); if (fb) { fb->setPostCallback(onPost, onPostContext); } } void getHardwareStrings(const char** vendor, const char** renderer, const char** version) { FrameBuffer* fb = FrameBuffer::getFB(); if (fb) { fb->getGLStrings(vendor, renderer, version); } else { *vendor = *renderer = *version = NULL; } } int stopOpenGLRenderer(void) { bool ret = false; // open a dummy connection to the renderer to make it // realize the exit request. // (send the exit request in clientFlags) IOStream *dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER); if (!dummy) return false; if (s_renderThread) { // wait for the thread to exit ret = s_renderThread->wait(NULL); delete s_renderThread; s_renderThread = NULL; } return ret; } int createOpenGLSubwindow(FBNativeWindowType window, int x, int y, int width, int height, float zRot) { if (s_renderThread) { return FrameBuffer::setupSubWindow(window,x,y,width,height, zRot); } else { // // XXX: should be implemented by sending the renderer process // a request ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__); } return false; } int destroyOpenGLSubwindow(void) { if (s_renderThread) { return FrameBuffer::removeSubWindow(); } else { // // XXX: should be implemented by sending the renderer process // a request ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__); return false; } } void setOpenGLDisplayRotation(float zRot) { if (s_renderThread) { FrameBuffer *fb = FrameBuffer::getFB(); if (fb) { fb->setDisplayRotation(zRot); } } else { // // XXX: should be implemented by sending the renderer process // a request ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__); } } void repaintOpenGLDisplay(void) { if (s_renderThread) { FrameBuffer *fb = FrameBuffer::getFB(); if (fb) { fb->repost(); } } else { // // XXX: should be implemented by sending the renderer process // a request ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__); } } /* 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) { 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(s_renderAddr) < 0) { ERR("createRenderThread failed to connect\n"); delete stream; return NULL; } // // send clientFlags to the renderer // 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 false; } gRendererStreamMode = mode; return true; }