| /* |
| * 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 (%d)!", program); |
| |
| 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; |
| } |