1274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen/*
2274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Copyright (C) 2011 The Android Open Source Project
3274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen *
4274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
5274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * you may not use this file except in compliance with the License.
6274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * You may obtain a copy of the License at
7274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen *
8274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
9274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen *
10274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Unless required by applicable law or agreed to in writing, software
11274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
12274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * See the License for the specific language governing permissions and
14274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * limitations under the License.
15274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen */
16274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen
171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include "Renderer.h"
181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
19274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "mosaic/Log.h"
20274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#define LOG_TAG "Renderer"
211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
22274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <GLES2/gl2ext.h>
231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalRenderer::Renderer()
251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal      : mGlProgram(0),
261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureName(-1),
271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureWidth(0),
281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureHeight(0),
291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth(0),
301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight(0)
311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    InitializeGLContext();
331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalRenderer::~Renderer() {
361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalGLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint shader = glCreateShader(shaderType);
401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (shader) {
411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glShaderSource(shader, 1, &pSource, NULL);
421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glCompileShader(shader);
431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        GLint compiled = 0;
441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!compiled) {
461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            GLint infoLen = 0;
471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (infoLen) {
491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                char* buf = (char*) malloc(infoLen);
501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                if (buf) {
511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    LOGE("Could not compile shader %d:\n%s\n",
531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                            shaderType, buf);
541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    free(buf);
551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                }
561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                glDeleteShader(shader);
571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                shader = 0;
581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return shader;
621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalGLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (!vertexShader)
681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        return 0;
701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (!pixelShader)
741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        return 0;
761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint program = glCreateProgram();
791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (program)
801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glAttachShader(program, vertexShader);
821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glAttachShader");
831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glAttachShader(program, pixelShader);
841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glAttachShader");
851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glLinkProgram(program);
871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        GLint linkStatus = GL_FALSE;
881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        LOGI("Program Linked!");
911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (linkStatus != GL_TRUE)
931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            GLint bufLength = 0;
951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (bufLength)
971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                char* buf = (char*) malloc(bufLength);
991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                if (buf)
1001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                {
1011e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    glGetProgramInfoLog(program, bufLength, NULL, buf);
1021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    LOGE("Could not link program:\n%s\n", buf);
1031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    free(buf);
1041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                }
1051e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
1061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glDeleteProgram(program);
1071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            program = 0;
1081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
1091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
1101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return program;
1111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Set this renderer to use the default frame-buffer (screen) and
1141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// set the viewport size to be the given width and height (pixels).
1151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::SetupGraphics(int width, int height)
1161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (mGlProgram == 0)
1201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
1211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (!InitializeGLProgram())
1221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
1231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal              break;
1241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
1251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
1261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUseProgram(mGlProgram);
1271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glUseProgram")) break;
1281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindFramebuffer(GL_FRAMEBUFFER, 0);
1301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = NULL;
1321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth = width;
1331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight = height;
1341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
1361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glViewport")) break;
1371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Set this renderer to use the specified FBO and
1451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// set the viewport size to be the width and height of this FBO.
1461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::SetupGraphics(FrameBuffer* buffer)
1471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (mGlProgram == 0)
1511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
1521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (!InitializeGLProgram())
1531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
1541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal              break;
1551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
1561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
1571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUseProgram(mGlProgram);
1581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glUseProgram")) break;
1591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
1611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = buffer;
1631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth = mFrameBuffer->GetWidth();
1641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight = mFrameBuffer->GetHeight();
1651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
1671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glViewport")) break;
1681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::Clear(float r, float g, float b, float a)
1751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        bool rt = (mFrameBuffer == NULL)?
1791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
1801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mFrameBuffer);
1811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if(!rt)
1831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            break;
1841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glClearColor(r, g, b, a);
1861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glClear(GL_COLOR_BUFFER_BIT);
1871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::InitializeGLContext()
1951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if(mFrameBuffer != NULL)
1971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
1981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        delete mFrameBuffer;
1991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = NULL;
2001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
2011e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureName = -1;
2031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureType = GL_TEXTURE_2D;
2041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mGlProgram = 0;
2051e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalint Renderer::GetTextureName()
2081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return mInputTextureName;
2101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureName(GLuint textureName)
2131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureName = textureName;
2151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureType(GLenum textureType)
2181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureType = textureType;
2201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureDimensions(int width, int height)
2231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureWidth = width;
2251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureHeight = height;
2261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
227