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 "RenderServer.h"
     17 #include "TcpStream.h"
     18 #ifdef _WIN32
     19 #include "Win32PipeStream.h"
     20 #else
     21 #include "UnixStream.h"
     22 #endif
     23 #include "RenderThread.h"
     24 #include "FrameBuffer.h"
     25 #include <set>
     26 
     27 typedef std::set<RenderThread *> RenderThreadsSet;
     28 
     29 RenderServer::RenderServer() :
     30     m_listenSock(NULL),
     31     m_exiting(false)
     32 {
     33 }
     34 
     35 RenderServer::~RenderServer()
     36 {
     37     delete m_listenSock;
     38 }
     39 
     40 
     41 extern "C" int gRendererStreamMode;
     42 
     43 RenderServer *RenderServer::create(char* addr, size_t addrLen)
     44 {
     45     RenderServer *server = new RenderServer();
     46     if (!server) {
     47         return NULL;
     48     }
     49 
     50     if (gRendererStreamMode == STREAM_MODE_TCP) {
     51         server->m_listenSock = new TcpStream();
     52     } else {
     53 #ifdef _WIN32
     54         server->m_listenSock = new Win32PipeStream();
     55 #else
     56         server->m_listenSock = new UnixStream();
     57 #endif
     58     }
     59 
     60     char addrstr[SocketStream::MAX_ADDRSTR_LEN];
     61     if (server->m_listenSock->listen(addrstr) < 0) {
     62         ERR("RenderServer::create failed to listen\n");
     63         delete server;
     64         return NULL;
     65     }
     66 
     67     size_t len = strlen(addrstr) + 1;
     68     if (len > addrLen) {
     69         ERR("RenderServer address name too big for provided buffer: %zu > %zu\n",
     70                 len, addrLen);
     71         delete server;
     72         return NULL;
     73     }
     74     memcpy(addr, addrstr, len);
     75 
     76     return server;
     77 }
     78 
     79 int RenderServer::Main()
     80 {
     81     RenderThreadsSet threads;
     82 
     83     while(1) {
     84         SocketStream *stream = m_listenSock->accept();
     85         if (!stream) {
     86             fprintf(stderr,"Error accepting connection, aborting\n");
     87             break;
     88         }
     89 
     90         unsigned int clientFlags;
     91         if (!stream->readFully(&clientFlags, sizeof(unsigned int))) {
     92             fprintf(stderr,"Error reading clientFlags\n");
     93             delete stream;
     94             continue;
     95         }
     96 
     97         DBG("RenderServer: Got new stream!\n");
     98 
     99         // check if we have been requested to exit while waiting on accept
    100         if ((clientFlags & IOSTREAM_CLIENT_EXIT_SERVER) != 0) {
    101             m_exiting = true;
    102             break;
    103         }
    104 
    105         RenderThread *rt = RenderThread::create(stream);
    106         if (!rt) {
    107             fprintf(stderr,"Failed to create RenderThread\n");
    108             delete stream;
    109             stream = NULL;
    110         } else if (!rt->start()) {
    111             fprintf(stderr,"Failed to start RenderThread\n");
    112             delete rt;
    113             rt = NULL;
    114         }
    115 
    116         //
    117         // remove from the threads list threads which are
    118         // no longer running
    119         //
    120         for (RenderThreadsSet::iterator n,t = threads.begin();
    121              t != threads.end();
    122              t = n) {
    123             // first find next iterator
    124             n = t;
    125             n++;
    126 
    127             // delete and erase the current iterator
    128             // if thread is no longer running
    129             if ((*t)->isFinished()) {
    130                 delete (*t);
    131                 threads.erase(t);
    132             }
    133         }
    134 
    135         // if the thread has been created and started, insert it to the list
    136         if (rt) {
    137             threads.insert(rt);
    138             DBG("Started new RenderThread\n");
    139         }
    140     }
    141 
    142     //
    143     // Wait for all threads to finish
    144     //
    145     for (RenderThreadsSet::iterator t = threads.begin();
    146          t != threads.end();
    147          t++) {
    148         int exitStatus;
    149         (*t)->wait(&exitStatus);
    150         delete (*t);
    151     }
    152     threads.clear();
    153 
    154     //
    155     // de-initialize the FrameBuffer object
    156     //
    157     FrameBuffer::finalize();
    158     return 0;
    159 }
    160