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 "YVURenderer.h"
181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include <GLES2/gl2ext.h>
201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalconst GLfloat g_vVertices[] = {
221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    -1.f, 1.f, 0.0f, 1.0f,  // Position 0
231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    0.0f,  1.0f,         // TexCoord 0
241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal     1.f, 1.f, 0.0f, 1.0f, // Position 1
251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    1.0f,  1.0f,         // TexCoord 1
261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    -1.f, -1.f, 0.0f, 1.0f, // Position 2
271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    0.0f,  0.0f,         // TexCoord 2
281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    1.f,  -1.f, 0.0f, 1.0f, // Position 3
291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    1.0f,  0.0f          // TexCoord 3
301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal};
311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalconst int VERTEX_STRIDE = 6 * sizeof(GLfloat);
331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalGLushort g_iIndices3[] = { 0, 1, 2, 3 };
351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalYVURenderer::YVURenderer() : Renderer()
371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                   {
381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalYVURenderer::~YVURenderer() {
411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool YVURenderer::InitializeGLProgram()
441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        GLuint glProgram;
481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glProgram = createProgram(VertexShaderSource(),
491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                FragmentShaderSource());
501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!glProgram) {
511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            break;
521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        }
531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUseProgram(glProgram);
551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glUseProgram")) break;
561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // Get attribute locations
581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mPositionLoc     = glGetAttribLocation(glProgram, "a_Position");
591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // Get sampler location
621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mGlProgram = glProgram;
651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    if (!succeeded && (mGlProgram != 0))
691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glDeleteProgram(mGlProgram);
711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glDeleteProgram");
721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mGlProgram = 0;
731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalbool YVURenderer::DrawTexture()
781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    bool succeeded = false;
801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    do {
811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        bool rt = (mFrameBuffer == NULL)?
821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                SetupGraphics(mFrameBuffer);
841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if(!rt)
861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal            break;
871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glDisable(GL_BLEND);
891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glActiveTexture(GL_TEXTURE0);
911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glActiveTexture")) break;
921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        const GLenum texture_type = InputTextureType();
941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindTexture(texture_type, mInputTextureName);
951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        if (!checkGlError("glBindTexture")) break;
961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // Set the sampler texture unit to 0
981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glUniform1i(mSamplerLoc, 0);
991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // Load the vertex position
1011e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
1021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                GL_FALSE, VERTEX_STRIDE, g_vVertices);
1031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // Load the texture coordinate
1051e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
1061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
1071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glEnableVertexAttribArray(mPositionLoc);
1091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glEnableVertexAttribArray(mTexCoordLoc);
1101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        // And, finally, execute the GL draw command.
1121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3);
1131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        checkGlError("glDrawElements");
1151e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1161e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        glBindFramebuffer(GL_FRAMEBUFFER, 0);
1171e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        succeeded = true;
1181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    } while (false);
1191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return succeeded;
1201e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalconst char* YVURenderer::VertexShaderSource() const
1231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    // All this really does is copy the coordinates into
1251e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    // variables for the fragment shader to pick up.
1261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    static const char gVertexShader[] =
1271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "attribute vec4 a_Position;\n"
1281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "attribute vec2 a_texCoord;\n"
1291e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "varying vec2 v_texCoord;\n"
1301e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "void main() {\n"
1311e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_Position = a_Position;\n"
1321e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  v_texCoord = a_texCoord;\n"
1331e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "}\n";
1341e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1351e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return gVertexShader;
1361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
1371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1381e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalconst char* YVURenderer::FragmentShaderSource() const
1391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
1401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    static const char gFragmentShader[] =
1411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "precision mediump float;\n"
1421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "uniform sampler2D s_texture;\n"
1431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n"
1441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n"
1451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n"
1461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "varying vec2 v_texCoord;\n"
1471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "void main() {\n"
1481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  vec4 p;\n"
1491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  p = texture2D(s_texture, v_texCoord);\n"
1501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_FragColor[0] = dot(p, coeff_y);\n"
1511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  p = texture2D(s_texture, v_texCoord);\n"
1521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_FragColor[1] = dot(p, coeff_v);\n"
1531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  p = texture2D(s_texture, v_texCoord);\n"
1541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_FragColor[2] = dot(p, coeff_u);\n"
1551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  p = texture2D(s_texture, v_texCoord);\n"
1561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_FragColor[3] = dot(p, coeff_y);\n"
1571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "}\n";
1581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
1591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    return gFragmentShader;
1601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
161