Home | History | Annotate | Download | only in ut_renderer
      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 "RenderingThread.h"
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 #include <string.h>
     20 #include <pthread.h>
     21 #include "ReadBuffer.h"
     22 #include "Renderer.h"
     23 #include "TimeUtils.h"
     24 
     25 #include <GLES/glext.h>
     26 
     27 __thread RenderingThread * RenderingThread::m_tls;
     28 
     29 #ifdef PVR_WAR
     30 void RenderingThread::s_glTexParameteriv(GLenum target, GLenum param, const int *p)
     31 {
     32     if (target == GL_TEXTURE_2D && param == GL_TEXTURE_CROP_RECT_OES) {
     33         m_tls->m_currentContext->addPendingCropRect(p);
     34     } else {
     35         m_tls->m_glTexParameteriv(target, param, p);
     36     }
     37 }
     38 
     39 void RenderingThread::s_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h)
     40 {
     41     m_tls->applyPendingCropRects();
     42     m_tls->m_glDrawTexfOES(x, y, z, w, h);
     43     m_tls->fixTextureEnable();
     44 }
     45 
     46 void RenderingThread::s_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort w, GLshort h)
     47 {
     48     m_tls->applyPendingCropRects();
     49     m_tls->m_glDrawTexsOES(x, y, z, w, h);
     50     m_tls->fixTextureEnable();
     51 }
     52 
     53 void RenderingThread::s_glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h)
     54 {
     55     m_tls->applyPendingCropRects();
     56     m_tls->m_glDrawTexiOES(x, y, z, w, h);
     57     m_tls->fixTextureEnable();
     58 }
     59 
     60 void RenderingThread::s_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h)
     61 {
     62     m_tls->applyPendingCropRects();
     63     m_tls->m_glDrawTexxOES(x, y, z, w, h);
     64     m_tls->fixTextureEnable();
     65 }
     66 
     67 void RenderingThread::s_glDrawTexfvOES(const GLfloat *coords)
     68 {
     69     m_tls->applyPendingCropRects();
     70     m_tls->m_glDrawTexfvOES(coords);
     71     m_tls->fixTextureEnable();
     72 }
     73 
     74 void RenderingThread::s_glDrawTexsvOES(const GLshort *coords)
     75 {
     76     m_tls->applyPendingCropRects();
     77     m_tls->m_glDrawTexsvOES(coords);
     78     m_tls->fixTextureEnable();
     79 }
     80 
     81 void RenderingThread::s_glDrawTexivOES(const GLint *coords)
     82 {
     83     m_tls->applyPendingCropRects();
     84     m_tls->m_glDrawTexivOES(coords);
     85     m_tls->fixTextureEnable();
     86 }
     87 
     88 void RenderingThread::s_glDrawTexxvOES(const GLfixed *coords)
     89 {
     90     m_tls->applyPendingCropRects();
     91     m_tls->m_glDrawTexxvOES(coords);
     92     m_tls->fixTextureEnable();
     93 }
     94 
     95 
     96 void RenderingThread::s_glActiveTexture(GLenum texture)
     97 {
     98     if (texture - GL_TEXTURE0 >= m_tls->m_backendCaps.maxTextureUnits) return;
     99 
    100     m_tls->m_currentContext->setActiveTexture(texture);
    101     m_tls->m_glActiveTexture(texture);
    102 }
    103 
    104 void RenderingThread::s_glBindTexture(GLenum target, GLuint texture)
    105 {
    106     if (target == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DBind(texture);
    107     m_tls->m_glBindTexture(target, texture);
    108 }
    109 
    110 void RenderingThread::s_glEnable(GLenum cap)
    111 {
    112     if (cap == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DEnable(true);
    113     m_tls->m_glEnable(cap);
    114 }
    115 
    116 void RenderingThread::s_glDisable(GLenum cap)
    117 {
    118     if (cap == GL_TEXTURE_2D) m_tls->m_currentContext->setTex2DEnable(false);
    119     m_tls->m_glDisable(cap);
    120 }
    121 
    122 void RenderingThread::s_glClientActiveTexture(GLenum texture)
    123 {
    124     if (texture - GL_TEXTURE0 >= m_tls->m_backendCaps.maxTextureUnits) return;
    125     m_tls->m_currentContext->setClientActiveTexture(texture);
    126     m_tls->m_glClientActiveTexture(texture);
    127 }
    128 
    129 void RenderingThread::s_glEnableClientState(GLenum cap)
    130 {
    131     m_tls->m_currentContext->enableClientState(cap, true);
    132     m_tls->m_glEnableClientState(cap);
    133 }
    134 
    135 void RenderingThread::s_glDisableClientState(GLenum cap)
    136 {
    137     m_tls->m_currentContext->enableClientState(cap, false);
    138     m_tls->m_glDisableClientState(cap);
    139 }
    140 
    141 void RenderingThread::applyPendingCropRects()
    142 {
    143     PendingCropRectSet &rset = m_currentContext->getPendingCropRects();
    144     if (rset.size() > 0) {
    145         GLuint currBindedTex = m_currentContext->getTex2DBind();
    146         for (PendingCropRectSet::iterator i = rset.begin();
    147              i != rset.end();
    148              i++) {
    149             m_glBindTexture(GL_TEXTURE_2D, (*i)->texture);
    150             m_glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, (int *)(*i)->rect);
    151             delete (*i);
    152         }
    153         m_glBindTexture(GL_TEXTURE_2D, currBindedTex);
    154         rset.clear();
    155     }
    156 }
    157 
    158 void RenderingThread::fixTextureEnable()
    159 {
    160     // restore texture units enable state
    161     for (unsigned int i=0; i<m_backendCaps.maxTextureUnits; i++) {
    162         m_glActiveTexture(GL_TEXTURE0 + i);
    163         if (m_currentContext->isTex2DEnable(i)) {
    164             m_glEnable(GL_TEXTURE_2D);
    165         }
    166         else {
    167             m_glDisable(GL_TEXTURE_2D);
    168         }
    169         m_glClientActiveTexture(GL_TEXTURE0 + i);
    170         if (m_currentContext->getClientState(GL_TEXTURE_COORD_ARRAY, i)) {
    171             m_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    172         }
    173         else {
    174             m_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    175         }
    176     }
    177     // restore current active texture
    178     m_glActiveTexture(m_currentContext->getActiveTexture());
    179     m_glClientActiveTexture(m_currentContext->getClientActiveTexture());
    180 
    181     // restore other client state enable bits
    182     if (m_currentContext->getClientState(GL_VERTEX_ARRAY, 0)) {
    183         m_glEnableClientState(GL_VERTEX_ARRAY);
    184     }
    185     else {
    186         m_glDisableClientState(GL_VERTEX_ARRAY);
    187     }
    188 
    189     if (m_currentContext->getClientState(GL_NORMAL_ARRAY, 0)) {
    190         m_glEnableClientState(GL_NORMAL_ARRAY);
    191     }
    192     else {
    193         m_glDisableClientState(GL_NORMAL_ARRAY);
    194     }
    195 
    196     if (m_currentContext->getClientState(GL_COLOR_ARRAY, 0)) {
    197         m_glEnableClientState(GL_COLOR_ARRAY);
    198     }
    199     else {
    200         m_glDisableClientState(GL_COLOR_ARRAY);
    201     }
    202 
    203     if (m_currentContext->getClientState(GL_POINT_SIZE_ARRAY_OES, 0)) {
    204         m_glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
    205     }
    206     else {
    207         m_glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
    208     }
    209 }
    210 #endif
    211 
    212 
    213 int RenderingThread::s_createContext(uint32_t pid, uint32_t handle, uint32_t shareCtx, int version)
    214 {
    215     return Renderer::instance()->createContext(m_tls, Renderer::ClientHandle(pid, handle),
    216                                                Renderer::ClientHandle(pid, shareCtx),
    217                                                version);
    218 
    219 }
    220 
    221 
    222 int RenderingThread::s_createSurface(uint32_t pid, uint32_t handle)
    223 {
    224     return Renderer::instance()->createSurface(m_tls, Renderer::ClientHandle(pid, handle));
    225 }
    226 
    227 int RenderingThread::s_destroySurface(uint32_t pid, uint32_t handle)
    228 {
    229     return Renderer::instance()->destroySurface(m_tls, Renderer::ClientHandle(pid, handle));
    230 }
    231 
    232 int RenderingThread::s_destroyContext(uint32_t pid, uint32_t handle)
    233 {
    234     return Renderer::instance()->destroyContext(m_tls, Renderer::ClientHandle(pid, handle));
    235 }
    236 
    237 
    238 int RenderingThread::s_makeCurrent(uint32_t pid, uint32_t drawSurface, uint32_t readSurface, uint32_t ctx)
    239 {
    240     int ret = Renderer::instance()->makeCurrent(m_tls,
    241                                              Renderer::ClientHandle(pid, drawSurface),
    242                                              Renderer::ClientHandle(pid, readSurface),
    243                                              Renderer::ClientHandle(pid, ctx));
    244 
    245     if (ret && ctx) {
    246         m_tls->initBackendCaps();
    247     }
    248 
    249     return ret;
    250 }
    251 
    252 void RenderingThread::s_swapBuffers(uint32_t pid, uint32_t surface)
    253 {
    254     Renderer::instance()->swapBuffers(m_tls, Renderer::ClientHandle(pid, surface));
    255 }
    256 
    257 
    258 RenderingThread::RenderingThread(SocketStream *stream) :
    259     m_stream(stream),
    260     m_currentContext(NULL)
    261 {
    262     m_backendCaps.initialized = false;
    263 }
    264 
    265 int RenderingThread::start(void)
    266 {
    267     if (pthread_create(&m_thread, NULL, s_thread, this) < 0) {
    268         perror("pthread_create");
    269         return -1;
    270     }
    271     return 0;
    272 }
    273 
    274 
    275 void * RenderingThread::s_thread(void *data)
    276 {
    277     RenderingThread *self = (RenderingThread *)data;
    278     m_tls = self;
    279     return self->thread();
    280 }
    281 
    282 void RenderingThread::initBackendCaps()
    283 {
    284     if (m_backendCaps.initialized) return;
    285 
    286     m_glDec.glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *)&m_backendCaps.maxTextureUnits);
    287     m_backendCaps.initialized = true;
    288 }
    289 
    290 void *RenderingThread::thread()
    291 {
    292 
    293     // initialize our decoders;
    294     m_glDec.initGL();
    295 
    296 #ifdef PVR_WAR
    297     m_glTexParameteriv = m_glDec.set_glTexParameteriv(s_glTexParameteriv);
    298     m_glDrawTexfOES = m_glDec.set_glDrawTexfOES(s_glDrawTexfOES);
    299     m_glDrawTexsOES = m_glDec.set_glDrawTexsOES(s_glDrawTexsOES);
    300     m_glDrawTexiOES = m_glDec.set_glDrawTexiOES(s_glDrawTexiOES);
    301     m_glDrawTexxOES = m_glDec.set_glDrawTexxOES(s_glDrawTexxOES);
    302     m_glDrawTexfvOES = m_glDec.set_glDrawTexfvOES(s_glDrawTexfvOES);
    303     m_glDrawTexsvOES = m_glDec.set_glDrawTexsvOES(s_glDrawTexsvOES);
    304     m_glDrawTexivOES = m_glDec.set_glDrawTexivOES(s_glDrawTexivOES);
    305     m_glDrawTexxvOES = m_glDec.set_glDrawTexxvOES(s_glDrawTexxvOES);
    306     m_glActiveTexture = m_glDec.set_glActiveTexture(s_glActiveTexture);
    307     m_glBindTexture = m_glDec.set_glBindTexture(s_glBindTexture);
    308     m_glEnable = m_glDec.set_glEnable(s_glEnable);
    309     m_glDisable = m_glDec.set_glDisable(s_glDisable);
    310     m_glClientActiveTexture = m_glDec.set_glClientActiveTexture(s_glClientActiveTexture);
    311     m_glEnableClientState = m_glDec.set_glEnableClientState(s_glEnableClientState);
    312     m_glDisableClientState = m_glDec.set_glDisableClientState(s_glDisableClientState);
    313 #endif
    314 
    315     m_gl2Dec.initGL();
    316 
    317     m_utDec.set_swapBuffers(s_swapBuffers);
    318     m_utDec.set_createContext(s_createContext);
    319     m_utDec.set_destroyContext(s_destroyContext);
    320     m_utDec.set_createSurface(s_createSurface);
    321     m_utDec.set_destroySurface(s_destroySurface);
    322     m_utDec.set_makeCurrentContext(s_makeCurrent);
    323 
    324     ReadBuffer readBuf(m_stream, DECODER_BUF_SIZE);
    325 
    326     int stats_totalBytes = 0;
    327     long long stats_t0 = GetCurrentTimeMS();
    328 
    329     while (1) {
    330 
    331         int stat = readBuf.getData();
    332         if (stat == 0) {
    333             fprintf(stderr, "client shutdown\n");
    334             break;
    335         } else if (stat < 0) {
    336             perror("getData");
    337             break;
    338         }
    339 
    340         //
    341         // log received bandwidth statistics
    342         //
    343         stats_totalBytes += readBuf.validData();
    344         long long dt = GetCurrentTimeMS() - stats_t0;
    345         if (dt > 1000) {
    346             float dts = (float)dt / 1000.0f;
    347             printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
    348             stats_totalBytes = 0;
    349             stats_t0 = GetCurrentTimeMS();
    350         }
    351 
    352         bool progress = true;
    353         while (progress) {
    354             progress = false;
    355             // we need at least one header (8 bytes) in our buffer
    356             if (readBuf.validData() >= 8) {
    357                 size_t last = m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
    358                 if (last > 0) {
    359                     progress = true;
    360                     readBuf.consume(last);
    361                 }
    362             }
    363 
    364             if (readBuf.validData() >= 8) {
    365                 size_t last = m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
    366                 if (last > 0) {
    367                     readBuf.consume(last);
    368                     progress = true;
    369                 }
    370             }
    371 
    372             if (readBuf.validData() >= 8) {
    373                 size_t last = m_utDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
    374                 if (last > 0) {
    375                     readBuf.consume(last);
    376                     progress = true;
    377                 }
    378             }
    379         }
    380     }
    381     // shutdown
    382     if (m_currentContext != NULL) {
    383         m_currentContext->unref();
    384     }
    385 
    386     return NULL;
    387 }
    388