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