• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
s_glTexParameteriv(GLenum target,GLenum param,const int * p)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 
s_glDrawTexfOES(GLfloat x,GLfloat y,GLfloat z,GLfloat w,GLfloat h)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 
s_glDrawTexsOES(GLshort x,GLshort y,GLshort z,GLshort w,GLshort h)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 
s_glDrawTexiOES(GLint x,GLint y,GLint z,GLint w,GLint h)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 
s_glDrawTexxOES(GLfixed x,GLfixed y,GLfixed z,GLfixed w,GLfixed h)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 
s_glDrawTexfvOES(const GLfloat * coords)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 
s_glDrawTexsvOES(const GLshort * coords)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 
s_glDrawTexivOES(const GLint * coords)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 
s_glDrawTexxvOES(const GLfixed * coords)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 
s_glActiveTexture(GLenum texture)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 
s_glBindTexture(GLenum target,GLuint texture)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 
s_glEnable(GLenum cap)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 
s_glDisable(GLenum cap)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 
s_glClientActiveTexture(GLenum texture)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 
s_glEnableClientState(GLenum cap)129 void RenderingThread::s_glEnableClientState(GLenum cap)
130 {
131     m_tls->m_currentContext->enableClientState(cap, true);
132     m_tls->m_glEnableClientState(cap);
133 }
134 
s_glDisableClientState(GLenum cap)135 void RenderingThread::s_glDisableClientState(GLenum cap)
136 {
137     m_tls->m_currentContext->enableClientState(cap, false);
138     m_tls->m_glDisableClientState(cap);
139 }
140 
applyPendingCropRects()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 
fixTextureEnable()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 
s_createContext(uint32_t pid,uint32_t handle,uint32_t shareCtx,int version)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 
s_createSurface(uint32_t pid,uint32_t handle)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 
s_destroySurface(uint32_t pid,uint32_t handle)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 
s_destroyContext(uint32_t pid,uint32_t handle)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 
s_makeCurrent(uint32_t pid,uint32_t drawSurface,uint32_t readSurface,uint32_t ctx)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 
s_swapBuffers(uint32_t pid,uint32_t surface)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 
RenderingThread(SocketStream * stream)258 RenderingThread::RenderingThread(SocketStream *stream) :
259     m_stream(stream),
260     m_currentContext(NULL)
261 {
262     m_backendCaps.initialized = false;
263 }
264 
start(void)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 
s_thread(void * data)275 void * RenderingThread::s_thread(void *data)
276 {
277     RenderingThread *self = (RenderingThread *)data;
278     m_tls = self;
279     return self->thread();
280 }
281 
initBackendCaps()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 
thread()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