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 "WarpRenderer.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_iIndices[] = { 0, 1, 2, 3 };
35
36WarpRenderer::WarpRenderer() : Renderer()
37{
38}
39
40WarpRenderer::~WarpRenderer() {
41}
42
43void WarpRenderer::SetViewportMatrix(int w, int h, int W, int H)
44{
45    for(int i=0; i<16; i++)
46    {
47        mViewportMatrix[i] = 0.0f;
48    }
49
50    mViewportMatrix[0] = float(w)/float(W);
51    mViewportMatrix[5] = float(h)/float(H);
52    mViewportMatrix[10] = 1.0f;
53    mViewportMatrix[12] = -1.0f + float(w)/float(W);
54    mViewportMatrix[13] = -1.0f + float(h)/float(H);
55    mViewportMatrix[15] = 1.0f;
56}
57
58void WarpRenderer::SetScalingMatrix(float xscale, float yscale)
59{
60    for(int i=0; i<16; i++)
61    {
62        mScalingMatrix[i] = 0.0f;
63    }
64
65    mScalingMatrix[0] = xscale;
66    mScalingMatrix[5] = yscale;
67    mScalingMatrix[10] = 1.0f;
68    mScalingMatrix[15] = 1.0f;
69}
70
71bool WarpRenderer::InitializeGLProgram()
72{
73    bool succeeded = false;
74    do {
75        GLuint glProgram;
76        glProgram = createProgram(VertexShaderSource(),
77                FragmentShaderSource());
78        if (!glProgram) {
79            break;
80        }
81
82        glUseProgram(glProgram);
83        if (!checkGlError("glUseProgram")) break;
84
85        // Get attribute locations
86        mPositionLoc     = glGetAttribLocation(glProgram, "a_position");
87        mAffinetransLoc  = glGetUniformLocation(glProgram, "u_affinetrans");
88        mViewporttransLoc = glGetUniformLocation(glProgram, "u_viewporttrans");
89        mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans");
90        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
91
92        // Get sampler location
93        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
94
95        mGlProgram = glProgram;
96        succeeded = true;
97    } while (false);
98
99    if (!succeeded && (mGlProgram != 0))
100    {
101        glDeleteProgram(mGlProgram);
102        checkGlError("glDeleteProgram");
103        mGlProgram = 0;
104    }
105    return succeeded;
106}
107
108bool WarpRenderer::DrawTexture(GLfloat *affine)
109{
110    bool succeeded = false;
111    do {
112        bool rt = (mFrameBuffer == NULL)?
113                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
114                SetupGraphics(mFrameBuffer);
115
116        if(!rt)
117            break;
118
119        glDisable(GL_BLEND);
120
121        glActiveTexture(GL_TEXTURE0);
122        if (!checkGlError("glActiveTexture")) break;
123
124        const GLenum texture_type = InputTextureType();
125        glBindTexture(texture_type, mInputTextureName);
126        if (!checkGlError("glBindTexture")) break;
127
128        // Set the sampler texture unit to 0
129        glUniform1i(mSamplerLoc, 0);
130
131        // Load the vertex position
132        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
133                GL_FALSE, VERTEX_STRIDE, g_vVertices);
134
135        // Load the texture coordinate
136        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
137                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
138
139        glEnableVertexAttribArray(mPositionLoc);
140        glEnableVertexAttribArray(mTexCoordLoc);
141
142        // pass matrix information to the vertex shader
143        glUniformMatrix4fv(mAffinetransLoc, 1, GL_FALSE, affine);
144        glUniformMatrix4fv(mViewporttransLoc, 1, GL_FALSE, mViewportMatrix);
145        glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix);
146
147        // And, finally, execute the GL draw command.
148        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices);
149
150        checkGlError("glDrawElements");
151
152        glBindFramebuffer(GL_FRAMEBUFFER, 0);
153        succeeded = true;
154    } while (false);
155    return succeeded;
156}
157
158const char* WarpRenderer::VertexShaderSource() const
159{
160    static const char gVertexShader[] =
161        "uniform mat4 u_affinetrans;  \n"
162        "uniform mat4 u_viewporttrans;  \n"
163        "uniform mat4 u_scalingtrans;  \n"
164        "attribute vec4 a_position;   \n"
165        "attribute vec2 a_texCoord;   \n"
166        "varying vec2 v_texCoord;     \n"
167        "void main()                  \n"
168        "{                            \n"
169        "   gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n"
170        "   v_texCoord = a_texCoord;  \n"
171        "}                            \n";
172
173    return gVertexShader;
174}
175
176const char* WarpRenderer::FragmentShaderSource() const
177{
178    static const char gFragmentShader[] =
179        "precision mediump float;                            \n"
180        "varying vec2 v_texCoord;                            \n"
181        "uniform sampler2D s_texture;                        \n"
182        "void main()                                         \n"
183        "{                                                   \n"
184        "  vec4 color;                                       \n"
185        "  color = texture2D(s_texture, v_texCoord);       \n"
186        "  gl_FragColor = color;                             \n"
187        "}                                                   \n";
188
189    return gFragmentShader;
190}
191