Renderer.cpp revision 1e762b1f935c9d4a06af6dd56121590ca81d48b1
11e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include "Renderer.h"
21e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
31e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include <GLES2/gl2ext.h>
41e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
51e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include <android/log.h>
61e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#define  LOG_TAG    "Renderer"
71e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
81e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
91e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalRenderer::Renderer()
111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal      : mGlProgram(0),
121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureName(-1),
131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureWidth(0),
141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mInputTextureHeight(0),
151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth(0),
161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight(0)
171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    InitializeGLContext();
191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalRenderer::~Renderer() {
221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalGLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint shader = glCreateShader(shaderType);
261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (shader) {
271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glShaderSource(shader, 1, &pSource, NULL);
281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glCompileShader(shader);
291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        GLint compiled = 0;
301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!compiled) {
321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            GLint infoLen = 0;
331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (infoLen) {
351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                char* buf = (char*) malloc(infoLen);
361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                if (buf) {
371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    LOGE("Could not compile shader %d:\n%s\n",
391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                            shaderType, buf);
401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    free(buf);
411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                }
421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                glDeleteShader(shader);
431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                shader = 0;
441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return shader;
481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalGLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (!vertexShader)
541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        return 0;
561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    LOGI("VertexShader Loaded!");
581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (!pixelShader)
611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        return 0;
631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    LOGI("FragmentShader Loaded!");
651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    GLuint program = glCreateProgram();
671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (program)
681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glAttachShader(program, vertexShader);
701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glAttachShader");
711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glAttachShader(program, pixelShader);
721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glAttachShader");
731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        LOGI("Shaders Attached!");
751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glLinkProgram(program);
771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        GLint linkStatus = GL_FALSE;
781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        LOGI("Program Linked!");
811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (linkStatus != GL_TRUE)
831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            GLint bufLength = 0;
851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (bufLength)
871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                char* buf = (char*) malloc(bufLength);
891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                if (buf)
901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                {
911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    glGetProgramInfoLog(program, bufLength, NULL, buf);
921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    LOGE("Could not link program:\n%s\n", buf);
931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                    free(buf);
941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                }
951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            glDeleteProgram(program);
971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            program = 0;
981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
1001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return program;
1011e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Set this renderer to use the default frame-buffer (screen) and
1041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// set the viewport size to be the given width and height (pixels).
1051e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::SetupGraphics(int width, int height)
1061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (mGlProgram == 0)
1101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
1111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (!InitializeGLProgram())
1121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
1131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal              break;
1141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
1151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
1161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUseProgram(mGlProgram);
1171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glUseProgram")) break;
1181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindFramebuffer(GL_FRAMEBUFFER, 0);
1201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = NULL;
1221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth = width;
1231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight = height;
1241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
1261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glViewport")) break;
1271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Set this renderer to use the specified FBO and
1351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// set the viewport size to be the width and height of this FBO.
1361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::SetupGraphics(FrameBuffer* buffer)
1371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (mGlProgram == 0)
1411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        {
1421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            if (!InitializeGLProgram())
1431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            {
1441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal              break;
1451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            }
1461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
1471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUseProgram(mGlProgram);
1481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glUseProgram")) break;
1491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
1511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = buffer;
1531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceWidth = mFrameBuffer->GetWidth();
1541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSurfaceHeight = mFrameBuffer->GetHeight();
1551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
1571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glViewport")) break;
1581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool Renderer::Clear(float r, float g, float b, float a)
1651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
1671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
1681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        bool rt = (mFrameBuffer == NULL)?
1691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
1701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mFrameBuffer);
1711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if(!rt)
1731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            break;
1741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glClearColor(r, g, b, a);
1761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glClear(GL_COLOR_BUFFER_BIT);
1771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::InitializeGLContext()
1851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if(mFrameBuffer != NULL)
1871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
1881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        delete mFrameBuffer;
1891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mFrameBuffer = NULL;
1901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
1911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureName = -1;
1931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureType = GL_TEXTURE_2D;
1941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mGlProgram = 0;
1951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalint Renderer::GetTextureName()
1981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return mInputTextureName;
2001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2011e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureName(GLuint textureName)
2031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureName = textureName;
2051e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureType(GLenum textureType)
2081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureType = textureType;
2101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
2111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
2121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Renderer::SetInputTextureDimensions(int width, int height)
2131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
2141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureWidth = width;
2151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mInputTextureHeight = height;
2161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
217