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