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