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