/*
* 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 "YVURenderer.h"
#include <GLES2/gl2ext.h>
const GLfloat g_vVertices[] = {
-1.f, 1.f, 0.0f, 1.0f, // Position 0
0.0f, 1.0f, // TexCoord 0
1.f, 1.f, 0.0f, 1.0f, // Position 1
1.0f, 1.0f, // TexCoord 1
-1.f, -1.f, 0.0f, 1.0f, // Position 2
0.0f, 0.0f, // TexCoord 2
1.f, -1.f, 0.0f, 1.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
GLushort g_iIndices3[] = { 0, 1, 2, 3 };
YVURenderer::YVURenderer() : Renderer()
{
}
YVURenderer::~YVURenderer() {
}
bool YVURenderer::InitializeGLProgram()
{
bool succeeded = false;
do {
GLuint glProgram;
glProgram = createProgram(VertexShaderSource(),
FragmentShaderSource());
if (!glProgram) {
break;
}
glUseProgram(glProgram);
if (!checkGlError("glUseProgram")) break;
// Get attribute locations
mPositionLoc = glGetAttribLocation(glProgram, "a_Position");
mTexCoordLoc = glGetAttribLocation(glProgram, "a_texCoord");
// Get sampler location
mSamplerLoc = glGetUniformLocation(glProgram, "s_texture");
mGlProgram = glProgram;
succeeded = true;
} while (false);
if (!succeeded && (mGlProgram != 0))
{
glDeleteProgram(mGlProgram);
checkGlError("glDeleteProgram");
mGlProgram = 0;
}
return succeeded;
}
bool YVURenderer::DrawTexture()
{
bool succeeded = false;
do {
bool rt = (mFrameBuffer == NULL)?
SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
SetupGraphics(mFrameBuffer);
if(!rt)
break;
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
if (!checkGlError("glActiveTexture")) break;
const GLenum texture_type = InputTextureType();
glBindTexture(texture_type, mInputTextureName);
if (!checkGlError("glBindTexture")) break;
// Set the sampler texture unit to 0
glUniform1i(mSamplerLoc, 0);
// Load the vertex position
glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
GL_FALSE, VERTEX_STRIDE, g_vVertices);
// Load the texture coordinate
glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
glEnableVertexAttribArray(mPositionLoc);
glEnableVertexAttribArray(mTexCoordLoc);
// And, finally, execute the GL draw command.
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3);
checkGlError("glDrawElements");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
succeeded = true;
} while (false);
return succeeded;
}
const char* YVURenderer::VertexShaderSource() const
{
// All this really does is copy the coordinates into
// variables for the fragment shader to pick up.
static const char gVertexShader[] =
"attribute vec4 a_Position;\n"
"attribute vec2 a_texCoord;\n"
"varying vec2 v_texCoord;\n"
"void main() {\n"
" gl_Position = a_Position;\n"
" v_texCoord = a_texCoord;\n"
"}\n";
return gVertexShader;
}
const char* YVURenderer::FragmentShaderSource() const
{
static const char gFragmentShader[] =
"precision mediump float;\n"
"uniform sampler2D s_texture;\n"
"const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n"
"const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n"
"const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n"
"varying vec2 v_texCoord;\n"
"void main() {\n"
" vec4 p;\n"
" p = texture2D(s_texture, v_texCoord);\n"
" gl_FragColor[0] = dot(p, coeff_y);\n"
" p = texture2D(s_texture, v_texCoord);\n"
" gl_FragColor[1] = dot(p, coeff_v);\n"
" p = texture2D(s_texture, v_texCoord);\n"
" gl_FragColor[2] = dot(p, coeff_u);\n"
" p = texture2D(s_texture, v_texCoord);\n"
" gl_FragColor[3] = dot(p, coeff_y);\n"
"}\n";
return gFragmentShader;
}