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
17eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include "WarpRenderer.h"
18eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
19eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include <GLES2/gl2ext.h>
20eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
21eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalconst GLfloat g_vVertices[] = {
221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    -1.f, 1.f, 0.0f, 1.0f,  // Position 0
23eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    0.0f,  1.0f,         // TexCoord 0
241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal     1.f, 1.f, 0.0f, 1.0f, // Position 1
25eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    1.0f,  1.0f,         // TexCoord 1
261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    -1.f, -1.f, 0.0f, 1.0f, // Position 2
27eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    0.0f,  0.0f,         // TexCoord 2
281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    1.f,  -1.f, 0.0f, 1.0f, // Position 3
29eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    1.0f,  0.0f          // TexCoord 3
30eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal};
31eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
32eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalconst int VERTEX_STRIDE = 6 * sizeof(GLfloat);
33eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
34eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalGLushort g_iIndices[] = { 0, 1, 2, 3 };
35eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
361e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalWarpRenderer::WarpRenderer() : Renderer()
37a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal{
38eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
39eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
40eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalWarpRenderer::~WarpRenderer() {
41eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
42eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid WarpRenderer::SetViewportMatrix(int w, int h, int W, int H)
44eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{
451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    for(int i=0; i<16; i++)
46eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    {
471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mViewportMatrix[i] = 0.0f;
48eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    }
49eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[0] = float(w)/float(W);
511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[5] = float(h)/float(H);
521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[10] = 1.0f;
531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[12] = -1.0f + float(w)/float(W);
541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[13] = -1.0f + float(h)/float(H);
551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mViewportMatrix[15] = 1.0f;
561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
57eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid WarpRenderer::SetScalingMatrix(float xscale, float yscale)
591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    for(int i=0; i<16; i++)
61eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    {
621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mScalingMatrix[i] = 0.0f;
63eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    }
641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mScalingMatrix[0] = xscale;
661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mScalingMatrix[5] = yscale;
671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mScalingMatrix[10] = 1.0f;
681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    mScalingMatrix[15] = 1.0f;
69eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
70eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
71eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalbool WarpRenderer::InitializeGLProgram()
72eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{
73eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    bool succeeded = false;
74eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    do {
75eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        GLuint glProgram;
76eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glProgram = createProgram(VertexShaderSource(),
77eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal                FragmentShaderSource());
78eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        if (!glProgram) {
79eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal            break;
80eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        }
81eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
82eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glUseProgram(glProgram);
83eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        if (!checkGlError("glUseProgram")) break;
84eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
85eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // Get attribute locations
86eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mPositionLoc     = glGetAttribLocation(glProgram, "a_position");
87eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mAffinetransLoc  = glGetUniformLocation(glProgram, "u_affinetrans");
88eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mViewporttransLoc = glGetUniformLocation(glProgram, "u_viewporttrans");
89eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans");
90eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
91eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
92eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // Get sampler location
93eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
94eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
95eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mGlProgram = glProgram;
96eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        succeeded = true;
97eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    } while (false);
98eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
99eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    if (!succeeded && (mGlProgram != 0))
100eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    {
101eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glDeleteProgram(mGlProgram);
102eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        checkGlError("glDeleteProgram");
103eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        mGlProgram = 0;
104eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    }
105eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    return succeeded;
106eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
107eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
108eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalbool WarpRenderer::DrawTexture(GLfloat *affine)
109eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{
110eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    bool succeeded = false;
111eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    do {
112eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        bool rt = (mFrameBuffer == NULL)?
113eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
114eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal                SetupGraphics(mFrameBuffer);
115eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
116eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        if(!rt)
117eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal            break;
118eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
119eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glDisable(GL_BLEND);
120eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
121eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glActiveTexture(GL_TEXTURE0);
122eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        if (!checkGlError("glActiveTexture")) break;
123eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
124eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        const GLenum texture_type = InputTextureType();
125eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glBindTexture(texture_type, mInputTextureName);
126eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        if (!checkGlError("glBindTexture")) break;
127eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
128eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // Set the sampler texture unit to 0
129eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glUniform1i(mSamplerLoc, 0);
130eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
131eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // Load the vertex position
132eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
133eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal                GL_FALSE, VERTEX_STRIDE, g_vVertices);
134eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
135eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // Load the texture coordinate
136eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
137eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
138eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
139eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glEnableVertexAttribArray(mPositionLoc);
140eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glEnableVertexAttribArray(mTexCoordLoc);
141eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
142eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // pass matrix information to the vertex shader
143eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glUniformMatrix4fv(mAffinetransLoc, 1, GL_FALSE, affine);
144eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glUniformMatrix4fv(mViewporttransLoc, 1, GL_FALSE, mViewportMatrix);
145eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix);
146eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
147eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        // And, finally, execute the GL draw command.
148eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices);
149eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
150eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        checkGlError("glDrawElements");
151eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
152eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        glBindFramebuffer(GL_FRAMEBUFFER, 0);
153eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal        succeeded = true;
154eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    } while (false);
155eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    return succeeded;
156eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
157eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
158eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalconst char* WarpRenderer::VertexShaderSource() const
159eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{
1601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    static const char gVertexShader[] =
1611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "uniform mat4 u_affinetrans;  \n"
1621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "uniform mat4 u_viewporttrans;  \n"
1631e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "uniform mat4 u_scalingtrans;  \n"
1641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "attribute vec4 a_position;   \n"
1651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "attribute vec2 a_texCoord;   \n"
1661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "varying vec2 v_texCoord;     \n"
1671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "void main()                  \n"
1681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "{                            \n"
1691e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "   gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n"
1701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "   v_texCoord = a_texCoord;  \n"
1711e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "}                            \n";
1721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
173eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    return gVertexShader;
174eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
175eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal
176eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalconst char* WarpRenderer::FragmentShaderSource() const
177eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{
1781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    static const char gFragmentShader[] =
1791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "precision mediump float;                            \n"
1801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "varying vec2 v_texCoord;                            \n"
1811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "uniform sampler2D s_texture;                        \n"
1821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "void main()                                         \n"
1831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "{                                                   \n"
1841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  vec4 color;                                       \n"
1851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  color = texture2D(s_texture, v_texCoord);       \n"
1861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "  gl_FragColor = color;                             \n"
1871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        "}                                                   \n";
1881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
189eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal    return gFragmentShader;
190eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}
191