/*
* 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 "Renderer.h"
#include "mosaic/Log.h"
#define LOG_TAG "Renderer"
#include <GLES2/gl2ext.h>
Renderer::Renderer()
: mGlProgram(0),
mInputTextureName(-1),
mInputTextureWidth(0),
mInputTextureHeight(0),
mSurfaceWidth(0),
mSurfaceHeight(0)
{
InitializeGLContext();
}
Renderer::~Renderer() {
}
GLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
GLuint shader = glCreateShader(shaderType);
if (shader) {
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* buf = (char*) malloc(infoLen);
if (buf) {
glGetShaderInfoLog(shader, infoLen, NULL, buf);
LOGE("Could not compile shader %d:\n%s\n",
shaderType, buf);
free(buf);
}
glDeleteShader(shader);
shader = 0;
}
}
}
return shader;
}
GLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
{
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
if (!vertexShader)
{
return 0;
}
GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
if (!pixelShader)
{
return 0;
}
GLuint program = glCreateProgram();
if (program)
{
glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
LOGI("Program Linked!");
if (linkStatus != GL_TRUE)
{
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
if (bufLength)
{
char* buf = (char*) malloc(bufLength);
if (buf)
{
glGetProgramInfoLog(program, bufLength, NULL, buf);
LOGE("Could not link program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}
// Set this renderer to use the default frame-buffer (screen) and
// set the viewport size to be the given width and height (pixels).
bool Renderer::SetupGraphics(int width, int height)
{
bool succeeded = false;
do {
if (mGlProgram == 0)
{
if (!InitializeGLProgram())
{
break;
}
}
glUseProgram(mGlProgram);
if (!checkGlError("glUseProgram")) break;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
mFrameBuffer = NULL;
mSurfaceWidth = width;
mSurfaceHeight = height;
glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
if (!checkGlError("glViewport")) break;
succeeded = true;
} while (false);
return succeeded;
}
// Set this renderer to use the specified FBO and
// set the viewport size to be the width and height of this FBO.
bool Renderer::SetupGraphics(FrameBuffer* buffer)
{
bool succeeded = false;
do {
if (mGlProgram == 0)
{
if (!InitializeGLProgram())
{
break;
}
}
glUseProgram(mGlProgram);
if (!checkGlError("glUseProgram")) break;
glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
mFrameBuffer = buffer;
mSurfaceWidth = mFrameBuffer->GetWidth();
mSurfaceHeight = mFrameBuffer->GetHeight();
glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
if (!checkGlError("glViewport")) break;
succeeded = true;
} while (false);
return succeeded;
}
bool Renderer::Clear(float r, float g, float b, float a)
{
bool succeeded = false;
do {
bool rt = (mFrameBuffer == NULL)?
SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
SetupGraphics(mFrameBuffer);
if(!rt)
break;
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
succeeded = true;
} while (false);
return succeeded;
}
void Renderer::InitializeGLContext()
{
if(mFrameBuffer != NULL)
{
delete mFrameBuffer;
mFrameBuffer = NULL;
}
mInputTextureName = -1;
mInputTextureType = GL_TEXTURE_2D;
mGlProgram = 0;
}
int Renderer::GetTextureName()
{
return mInputTextureName;
}
void Renderer::SetInputTextureName(GLuint textureName)
{
mInputTextureName = textureName;
}
void Renderer::SetInputTextureType(GLenum textureType)
{
mInputTextureType = textureType;
}
void Renderer::SetInputTextureDimensions(int width, int height)
{
mInputTextureWidth = width;
mInputTextureHeight = height;
}