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 "RenderThread.h"
17#include "RenderControl.h"
18#include "ThreadInfo.h"
19#include "ReadBuffer.h"
20#include "TimeUtils.h"
21#include "GLDispatch.h"
22#include "GL2Dispatch.h"
23#include "EGLDispatch.h"
24
25#define STREAM_BUFFER_SIZE 4*1024*1024
26
27RenderThread::RenderThread() :
28    osUtils::Thread(),
29    m_stream(NULL),
30    m_finished(false)
31{
32}
33
34RenderThread *RenderThread::create(IOStream *p_stream)
35{
36    RenderThread *rt = new RenderThread();
37    if (!rt) {
38        return NULL;
39    }
40
41    rt->m_stream = p_stream;
42
43    return rt;
44}
45
46int RenderThread::Main()
47{
48    RenderThreadInfo * tInfo = getRenderThreadInfo();
49    //
50    // initialize decoders
51    //
52    tInfo->m_glDec.initGL( gl_dispatch_get_proc_func, NULL );
53    tInfo->m_gl2Dec.initGL( gl2_dispatch_get_proc_func, NULL );
54    initRenderControlContext( &m_rcDec );
55
56    ReadBuffer readBuf(m_stream, STREAM_BUFFER_SIZE);
57
58    int stats_totalBytes = 0;
59    long long stats_t0 = GetCurrentTimeMS();
60
61    //
62    // open dump file if RENDER_DUMP_DIR is defined
63    //
64    const char *dump_dir = getenv("RENDERER_DUMP_DIR");
65    FILE *dumpFP = NULL;
66    if (dump_dir) {
67        size_t bsize = strlen(dump_dir) + 32;
68        char *fname = new char[bsize];
69        snprintf(fname,bsize,"%s/stream_%p", dump_dir, this);
70        dumpFP = fopen(fname, "wb");
71        if (!dumpFP) {
72            fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname);
73        }
74        delete [] fname;
75    }
76
77    while (1) {
78
79        int stat = readBuf.getData();
80        if (stat <= 0) {
81            break;
82        }
83
84        //
85        // log received bandwidth statistics
86        //
87        stats_totalBytes += readBuf.validData();
88        long long dt = GetCurrentTimeMS() - stats_t0;
89        if (dt > 1000) {
90            float dts = (float)dt / 1000.0f;
91            //printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
92            stats_totalBytes = 0;
93            stats_t0 = GetCurrentTimeMS();
94        }
95
96        //
97        // dump stream to file if needed
98        //
99        if (dumpFP) {
100            int skip = readBuf.validData() - stat;
101            fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP);
102            fflush(dumpFP);
103        }
104
105        bool progress;
106        do {
107            progress = false;
108
109            //
110            // try to process some of the command buffer using the GLESv1 decoder
111            //
112            size_t last = tInfo->m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
113            if (last > 0) {
114                progress = true;
115                readBuf.consume(last);
116            }
117
118            //
119            // try to process some of the command buffer using the GLESv2 decoder
120            //
121            last = tInfo->m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
122            if (last > 0) {
123                progress = true;
124                readBuf.consume(last);
125            }
126
127            //
128            // try to process some of the command buffer using the
129            // renderControl decoder
130            //
131            last = m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
132            if (last > 0) {
133                readBuf.consume(last);
134                progress = true;
135            }
136
137        } while( progress );
138
139    }
140
141    if (dumpFP) {
142        fclose(dumpFP);
143    }
144
145    //
146    // release the thread from any EGL context
147    // if bound to context.
148    //
149    EGLDisplay eglDpy = s_egl.eglGetCurrentDisplay();
150    if (eglDpy != EGL_NO_DISPLAY) {
151        s_egl.eglMakeCurrent(eglDpy,
152                             EGL_NO_SURFACE,
153                             EGL_NO_SURFACE,
154                             EGL_NO_CONTEXT);
155    }
156
157    //
158    // flag that this thread has finished execution
159    m_finished = true;
160
161    return 0;
162}
163