C++程序  |  166行  |  4.32 KB

/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "RenderThread.h"
#include "RenderControl.h"
#include "ThreadInfo.h"
#include "ReadBuffer.h"
#include "TimeUtils.h"
#include "GLDispatch.h"
#include "GL2Dispatch.h"
#include "EGLDispatch.h"
#include "FrameBuffer.h"

#define STREAM_BUFFER_SIZE 4*1024*1024

RenderThread::RenderThread() :
    osUtils::Thread(),
    m_stream(NULL),
    m_finished(false)
{
}

RenderThread::~RenderThread()
{
    delete m_stream;
}

RenderThread *RenderThread::create(IOStream *p_stream)
{
    RenderThread *rt = new RenderThread();
    if (!rt) {
        return NULL;
    }

    rt->m_stream = p_stream;

    return rt;
}

int RenderThread::Main()
{
    RenderThreadInfo tInfo;

    //
    // initialize decoders
    //
    tInfo.m_glDec.initGL( gl_dispatch_get_proc_func, NULL );
    tInfo.m_gl2Dec.initGL( gl2_dispatch_get_proc_func, NULL );
    initRenderControlContext( &m_rcDec );

    ReadBuffer readBuf(m_stream, STREAM_BUFFER_SIZE);

    int stats_totalBytes = 0;
    long long stats_t0 = GetCurrentTimeMS();

    //
    // open dump file if RENDER_DUMP_DIR is defined
    //
    const char *dump_dir = getenv("RENDERER_DUMP_DIR");
    FILE *dumpFP = NULL;
    if (dump_dir) {
        size_t bsize = strlen(dump_dir) + 32;
        char *fname = new char[bsize];
        snprintf(fname,bsize,"%s/stream_%p", dump_dir, this);
        dumpFP = fopen(fname, "wb");
        if (!dumpFP) {
            fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname);
        }
        delete [] fname;
    }

    while (1) {

        int stat = readBuf.getData();
        if (stat <= 0) {
            break;
        }

        //
        // log received bandwidth statistics
        //
        stats_totalBytes += readBuf.validData();
        long long dt = GetCurrentTimeMS() - stats_t0;
        if (dt > 1000) {
            float dts = (float)dt / 1000.0f;
            //printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
            stats_totalBytes = 0;
            stats_t0 = GetCurrentTimeMS();
        }

        //
        // dump stream to file if needed
        //
        if (dumpFP) {
            int skip = readBuf.validData() - stat;
            fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP);
            fflush(dumpFP);
        }

        bool progress;
        do {
            progress = false;

            //
            // try to process some of the command buffer using the GLESv1 decoder
            //
            size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the GLESv2 decoder
            //
            last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the
            // renderControl decoder
            //
            last = m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                readBuf.consume(last);
                progress = true;
            }

        } while( progress );

    }

    if (dumpFP) {
        fclose(dumpFP);
    }

    //
    // Release references to the current thread's context/surfaces if any
    //
    FrameBuffer::getFB()->bindContext(0, 0, 0);
    if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
        fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n");
    }

    //
    // flag that this thread has finished execution
    m_finished = true;

    return 0;
}