1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "YVURenderer.h"
18
19#include <GLES2/gl2ext.h>
20
21const GLfloat g_vVertices[] = {
22    -1.f, 1.f, 0.0f, 1.0f,  // Position 0
23    0.0f,  1.0f,         // TexCoord 0
24     1.f, 1.f, 0.0f, 1.0f, // Position 1
25    1.0f,  1.0f,         // TexCoord 1
26    -1.f, -1.f, 0.0f, 1.0f, // Position 2
27    0.0f,  0.0f,         // TexCoord 2
28    1.f,  -1.f, 0.0f, 1.0f, // Position 3
29    1.0f,  0.0f          // TexCoord 3
30};
31
32const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
33
34GLushort g_iIndices3[] = { 0, 1, 2, 3 };
35
36YVURenderer::YVURenderer() : Renderer()
37                   {
38}
39
40YVURenderer::~YVURenderer() {
41}
42
43bool YVURenderer::InitializeGLProgram()
44{
45    bool succeeded = false;
46    do {
47        GLuint glProgram;
48        glProgram = createProgram(VertexShaderSource(),
49                FragmentShaderSource());
50        if (!glProgram) {
51            break;
52        }
53
54        glUseProgram(glProgram);
55        if (!checkGlError("glUseProgram")) break;
56
57        // Get attribute locations
58        mPositionLoc     = glGetAttribLocation(glProgram, "a_Position");
59        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
60
61        // Get sampler location
62        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
63
64        mGlProgram = glProgram;
65        succeeded = true;
66    } while (false);
67
68    if (!succeeded && (mGlProgram != 0))
69    {
70        glDeleteProgram(mGlProgram);
71        checkGlError("glDeleteProgram");
72        mGlProgram = 0;
73    }
74    return succeeded;
75}
76
77bool YVURenderer::DrawTexture()
78{
79    bool succeeded = false;
80    do {
81        bool rt = (mFrameBuffer == NULL)?
82                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
83                SetupGraphics(mFrameBuffer);
84
85        if(!rt)
86            break;
87
88        glDisable(GL_BLEND);
89
90        glActiveTexture(GL_TEXTURE0);
91        if (!checkGlError("glActiveTexture")) break;
92
93        const GLenum texture_type = InputTextureType();
94        glBindTexture(texture_type, mInputTextureName);
95        if (!checkGlError("glBindTexture")) break;
96
97        // Set the sampler texture unit to 0
98        glUniform1i(mSamplerLoc, 0);
99
100        // Load the vertex position
101        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
102                GL_FALSE, VERTEX_STRIDE, g_vVertices);
103
104        // Load the texture coordinate
105        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
106                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
107
108        glEnableVertexAttribArray(mPositionLoc);
109        glEnableVertexAttribArray(mTexCoordLoc);
110
111        // And, finally, execute the GL draw command.
112        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3);
113
114        checkGlError("glDrawElements");
115
116        glBindFramebuffer(GL_FRAMEBUFFER, 0);
117        succeeded = true;
118    } while (false);
119    return succeeded;
120}
121
122const char* YVURenderer::VertexShaderSource() const
123{
124    // All this really does is copy the coordinates into
125    // variables for the fragment shader to pick up.
126    static const char gVertexShader[] =
127        "attribute vec4 a_Position;\n"
128        "attribute vec2 a_texCoord;\n"
129        "varying vec2 v_texCoord;\n"
130        "void main() {\n"
131        "  gl_Position = a_Position;\n"
132        "  v_texCoord = a_texCoord;\n"
133        "}\n";
134
135    return gVertexShader;
136}
137
138const char* YVURenderer::FragmentShaderSource() const
139{
140    static const char gFragmentShader[] =
141        "precision mediump float;\n"
142        "uniform sampler2D s_texture;\n"
143        "const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n"
144        "const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n"
145        "const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n"
146        "varying vec2 v_texCoord;\n"
147        "void main() {\n"
148        "  vec4 p;\n"
149        "  p = texture2D(s_texture, v_texCoord);\n"
150        "  gl_FragColor[0] = dot(p, coeff_y);\n"
151        "  p = texture2D(s_texture, v_texCoord);\n"
152        "  gl_FragColor[1] = dot(p, coeff_v);\n"
153        "  p = texture2D(s_texture, v_texCoord);\n"
154        "  gl_FragColor[2] = dot(p, coeff_u);\n"
155        "  p = texture2D(s_texture, v_texCoord);\n"
156        "  gl_FragColor[3] = dot(p, coeff_y);\n"
157        "}\n";
158
159    return gFragmentShader;
160}
161