Home | History | Annotate | Download | only in libOpenglRender
      1 /*
      2 * Copyright (C) 2011 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 #include "libOpenglRender/render_api.h"
     17 #include "IOStream.h"
     18 #include "FrameBuffer.h"
     19 #include "RenderServer.h"
     20 #include "osProcess.h"
     21 #include "TimeUtils.h"
     22 
     23 #include "TcpStream.h"
     24 #ifdef _WIN32
     25 #include "Win32PipeStream.h"
     26 #else
     27 #include "UnixStream.h"
     28 #endif
     29 
     30 #include "EGLDispatch.h"
     31 #include "GLDispatch.h"
     32 #include "GL2Dispatch.h"
     33 
     34 static osUtils::childProcess *s_renderProc = NULL;
     35 static RenderServer *s_renderThread = NULL;
     36 static int s_renderPort = 0;
     37 
     38 static IOStream *createRenderThread(int p_stream_buffer_size,
     39                                     unsigned int clientFlags);
     40 
     41 //
     42 // For now run the renderer as a thread inside the calling
     43 // process instead as running it in a separate process for all
     44 // platforms.
     45 // at the future we want it to run as a seperate process except for
     46 // Mac OS X since it is imposibble on this platform to make one process
     47 // render to a window created by another process.
     48 //
     49 //#ifdef __APPLE__
     50 #define  RENDER_API_USE_THREAD
     51 //#endif
     52 
     53 bool initLibrary(void)
     54 {
     55     //
     56     // Load EGL Plugin
     57     //
     58     if (!init_egl_dispatch()) {
     59         // Failed to load EGL
     60         printf("Failed to init_egl_dispatch\n");
     61         return false;
     62     }
     63 
     64     //
     65     // Load GLES Plugin
     66     //
     67     if (!init_gl_dispatch()) {
     68         // Failed to load GLES
     69         ERR("Failed to init_gl_dispatch\n");
     70         return false;
     71     }
     72 
     73     /* failure to init the GLES2 dispatch table is not fatal */
     74     init_gl2_dispatch();
     75 
     76     return true;
     77 }
     78 
     79 bool initOpenGLRenderer(int width, int height, int portNum)
     80 {
     81 
     82     //
     83     // Fail if renderer is already initialized
     84     //
     85     if (s_renderProc || s_renderThread) {
     86         return false;
     87     }
     88 
     89     s_renderPort = portNum;
     90 
     91 #ifdef RENDER_API_USE_THREAD  // should be defined for mac
     92     //
     93     // initialize the renderer and listen to connections
     94     // on a thread in the current process.
     95     //
     96     bool inited = FrameBuffer::initialize(width, height);
     97     if (!inited) {
     98         return false;
     99     }
    100 
    101     s_renderThread = RenderServer::create(portNum);
    102     if (!s_renderThread) {
    103         return false;
    104     }
    105 
    106     s_renderThread->start();
    107 
    108 #else
    109     //
    110     // Launch emulator_renderer
    111     //
    112     char cmdLine[128];
    113     snprintf(cmdLine, 128, "emulator_renderer -windowid %d -port %d -x %d -y %d -width %d -height %d",
    114              (int)window, portNum, x, y, width, height);
    115 
    116     s_renderProc = osUtils::childProcess::create(cmdLine, NULL);
    117     if (!s_renderProc) {
    118         return false;
    119     }
    120 
    121     //
    122     // try to connect to the renderer in order to check it
    123     // was successfully initialized.
    124     //
    125     int nTrys = 0;
    126     IOStream *dummy = NULL;
    127     do {
    128         ++nTrys;
    129 
    130         //
    131         // Wait a bit to make the renderer process a chance to be
    132         // initialized.
    133         // On Windows we need during this time to handle windows
    134         // events since the renderer generates a subwindow of this
    135         // process's window, we need to be responsive for windows
    136         // during this time to let the renderer generates this subwindow.
    137         //
    138 #ifndef _WIN32
    139         TimeSleepMS(300);
    140 #else
    141         long long t0 = GetCurrentTimeMS();
    142         while( (GetCurrentTimeMS() - t0) < 300 ) {
    143             MSG msg;
    144             int n = 0;
    145             while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    146             {
    147                 n++;
    148                 TranslateMessage( &msg );
    149                 DispatchMessage( &msg );
    150             }
    151             if (n == 0) TimeSleepMS(10);
    152         }
    153 #endif
    154 
    155         dummy = createRenderThread(8, 0);
    156 
    157         if (!dummy) {
    158             // stop if the process is no longer running
    159             if (!osUtils::isProcessRunning(s_renderProc->getPID())) {
    160                 break;
    161             }
    162         }
    163     } while(!dummy && nTrys < 10); // give up after 3 seconds, XXX: ???
    164 
    165     if (!dummy) {
    166         //
    167         // Failed - make sure the process is killed
    168         //
    169         osUtils::KillProcess(s_renderProc->getPID(), true);
    170         delete s_renderProc;
    171         s_renderProc = NULL;
    172         return false;
    173     }
    174 
    175     // destroy the dummy connection
    176     delete dummy;
    177 #endif
    178 
    179     return true;
    180 }
    181 
    182 bool stopOpenGLRenderer()
    183 {
    184     bool ret = false;
    185 
    186     // open a dummy connection to the renderer to make it
    187     // realize the exit request.
    188     // (send the exit request in clientFlags)
    189     IOStream *dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER);
    190     if (!dummy) return false;
    191 
    192     if (s_renderProc) {
    193         //
    194         // wait for the process to exit
    195         //
    196         int exitStatus;
    197         ret = s_renderProc->wait(&exitStatus);
    198 
    199         delete s_renderProc;
    200         s_renderProc = NULL;
    201     }
    202     else if (s_renderThread) {
    203 
    204         // wait for the thread to exit
    205         int status;
    206         ret = s_renderThread->wait(&status);
    207 
    208         delete s_renderThread;
    209         s_renderThread = NULL;
    210     }
    211 
    212     return ret;
    213 }
    214 
    215 bool createOpenGLSubwindow(FBNativeWindowType window,
    216                            int x, int y, int width, int height, float zRot)
    217 {
    218     if (s_renderThread) {
    219         return FrameBuffer::setupSubWindow(window,x,y,width,height, zRot);
    220     }
    221     else {
    222         //
    223         // XXX: should be implemented by sending the renderer process
    224         //      a request
    225         ERR("%s not implemented for separate renderer process !!!\n",
    226             __FUNCTION__);
    227     }
    228     return false;
    229 }
    230 
    231 bool destroyOpenGLSubwindow()
    232 {
    233     if (s_renderThread) {
    234         return FrameBuffer::removeSubWindow();
    235     }
    236     else {
    237         //
    238         // XXX: should be implemented by sending the renderer process
    239         //      a request
    240         ERR("%s not implemented for separate renderer process !!!\n",
    241                 __FUNCTION__);
    242         return false;
    243     }
    244 }
    245 
    246 void setOpenGLDisplayRotation(float zRot)
    247 {
    248     if (s_renderThread) {
    249         FrameBuffer *fb = FrameBuffer::getFB();
    250         if (fb) {
    251             fb->setDisplayRotation(zRot);
    252         }
    253     }
    254     else {
    255         //
    256         // XXX: should be implemented by sending the renderer process
    257         //      a request
    258         ERR("%s not implemented for separate renderer process !!!\n",
    259                 __FUNCTION__);
    260     }
    261 }
    262 
    263 void repaintOpenGLDisplay()
    264 {
    265     if (s_renderThread) {
    266         FrameBuffer *fb = FrameBuffer::getFB();
    267         if (fb) {
    268             fb->repost();
    269         }
    270     }
    271     else {
    272         //
    273         // XXX: should be implemented by sending the renderer process
    274         //      a request
    275         ERR("%s not implemented for separate renderer process !!!\n",
    276                 __FUNCTION__);
    277     }
    278 }
    279 
    280 
    281 /* NOTE: For now, always use TCP mode by default, until the emulator
    282  *        has been updated to support Unix and Win32 pipes
    283  */
    284 #define  DEFAULT_STREAM_MODE  STREAM_MODE_TCP
    285 
    286 int gRendererStreamMode = DEFAULT_STREAM_MODE;
    287 
    288 IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
    289 {
    290     SocketStream*  stream = NULL;
    291 
    292     if (gRendererStreamMode == STREAM_MODE_TCP) {
    293         stream = new TcpStream(p_stream_buffer_size);
    294     } else {
    295 #ifdef _WIN32
    296         stream = new Win32PipeStream(p_stream_buffer_size);
    297 #else /* !_WIN32 */
    298         stream = new UnixStream(p_stream_buffer_size);
    299 #endif
    300     }
    301 
    302     if (!stream) {
    303         ERR("createRenderThread failed to create stream\n");
    304         return NULL;
    305     }
    306     if (stream->connect(s_renderPort) < 0) {
    307         ERR("createRenderThread failed to connect\n");
    308         delete stream;
    309         return NULL;
    310     }
    311 
    312     //
    313     // send clientFlags to the renderer
    314     //
    315     unsigned int *pClientFlags =
    316                 (unsigned int *)stream->allocBuffer(sizeof(unsigned int));
    317     *pClientFlags = clientFlags;
    318     stream->commitBuffer(sizeof(unsigned int));
    319 
    320     return stream;
    321 }
    322 
    323 int
    324 setStreamMode(int mode)
    325 {
    326     switch (mode) {
    327         case STREAM_MODE_DEFAULT:
    328             mode = DEFAULT_STREAM_MODE;
    329             break;
    330 
    331         case STREAM_MODE_TCP:
    332             break;
    333 
    334 #ifndef _WIN32
    335         case STREAM_MODE_UNIX:
    336             break;
    337 #else /* _WIN32 */
    338         case STREAM_MODE_PIPE:
    339             break;
    340 #endif /* _WIN32 */
    341         default:
    342             // Invalid stream mode
    343             return -1;
    344     }
    345     gRendererStreamMode = mode;
    346     return 0;
    347 }
    348