1/*
2 * Copyright (C) 2012 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 "Flatland.h"
18#include "GLHelper.h"
19
20namespace android {
21
22static float colors[][4] = {
23    { .85f, .14f, .44f, 1.0f },
24    { .91f, .72f, .10f, 1.0f },
25    { .04f, .66f, .42f, 1.0f },
26    { .84f, .39f, .68f, 1.0f },
27    { .38f, .53f, .78f, 1.0f },
28};
29
30static size_t g_colorIndex;
31
32const float* genColor() {
33    float* color = colors[g_colorIndex];
34    g_colorIndex = (g_colorIndex + 1) % NELEMS(colors);
35    return color;
36}
37
38void resetColorGenerator() {
39    g_colorIndex = 0;
40}
41
42class GradientRenderer {
43
44public:
45
46    bool setUp(GLHelper* helper) {
47        bool result;
48
49        result = helper->getShaderProgram("Gradient", &mGradPgm);
50        if (!result) {
51            return false;
52        }
53
54        result = helper->getDitherTexture(&mDitherTexName);
55        if (!result) {
56            return false;
57        }
58
59        mPosAttribLoc = glGetAttribLocation(mGradPgm, "position");
60        mUVAttribLoc = glGetAttribLocation(mGradPgm, "uv");
61        mUVToInterpUniformLoc = glGetUniformLocation(mGradPgm, "uvToInterp");
62        mObjToNdcUniformLoc = glGetUniformLocation(mGradPgm, "objToNdc");
63        mDitherKernelSamplerLoc = glGetUniformLocation(mGradPgm, "ditherKernel");
64        mInvDitherKernelSizeUniformLoc = glGetUniformLocation(mGradPgm,
65                "invDitherKernelSize");
66        mInvDitherKernelSizeSqUniformLoc = glGetUniformLocation(mGradPgm,
67                "invDitherKernelSizeSq");
68        mColor0UniformLoc = glGetUniformLocation(mGradPgm, "color0");
69        mColor1UniformLoc = glGetUniformLocation(mGradPgm, "color1");
70
71        return true;
72    }
73
74    void tearDown() {
75    }
76
77    bool drawGradient() {
78        float identity[16] = {
79            1.0f,   0.0f,   0.0f,   0.0f,
80            0.0f,   1.0f,   0.0f,   0.0f,
81            0.0f,   0.0f,   1.0f,   0.0f,
82            0.0f,   0.0f,   0.0f,   1.0f,
83        };
84        const float pos[] = {
85            -1.0f,  -1.0f,
86            1.0f,   -1.0f,
87            -1.0f,  1.0f,
88            1.0f,   1.0f,
89        };
90        const float uv[] = {
91            0.0f, 0.0f,
92            1.0f, 0.0f,
93            0.0f, 1.0f,
94            1.0f, 1.0f,
95        };
96        const float* color0 = genColor();
97        const float* color1 = genColor();
98
99        glUseProgram(mGradPgm);
100
101        glVertexAttribPointer(mPosAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, pos);
102        glVertexAttribPointer(mUVAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, uv);
103        glEnableVertexAttribArray(mPosAttribLoc);
104        glEnableVertexAttribArray(mUVAttribLoc);
105
106        float invDitherKernelSize = 1.0f / float(GLHelper::DITHER_KERNEL_SIZE);
107        float invDitherKernelSizeSq = invDitherKernelSize * invDitherKernelSize;
108
109        glUniformMatrix4fv(mObjToNdcUniformLoc, 1, GL_FALSE, identity);
110        glUniformMatrix4fv(mUVToInterpUniformLoc, 1, GL_FALSE, identity);
111        glUniform1f(mInvDitherKernelSizeUniformLoc, invDitherKernelSize);
112        glUniform1f(mInvDitherKernelSizeSqUniformLoc, invDitherKernelSizeSq);
113        glUniform4fv(mColor0UniformLoc, 1, color0);
114        glUniform4fv(mColor1UniformLoc, 1, color1);
115
116        if (glGetError() != GL_NO_ERROR) {
117            fprintf(stderr, "GL error! 0\n");
118        }
119
120        glActiveTexture(GL_TEXTURE0);
121        glBindTexture(GL_TEXTURE_2D, mDitherTexName);
122
123        if (glGetError() != GL_NO_ERROR) {
124            fprintf(stderr, "GL error! 1\n");
125        }
126
127        glUniform1i(mDitherKernelSamplerLoc, 0);
128
129        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
130
131        glDisableVertexAttribArray(mPosAttribLoc);
132        glDisableVertexAttribArray(mUVAttribLoc);
133
134        if (glGetError() != GL_NO_ERROR) {
135            fprintf(stderr, "GL error! 2\n");
136        }
137
138        return true;
139    }
140
141    GLuint mGradPgm;
142    GLuint mDitherTexName;
143    GLuint mPosAttribLoc;
144    GLuint mUVAttribLoc;
145    GLuint mObjToNdcUniformLoc;
146    GLuint mUVToInterpUniformLoc;
147    GLuint mDitherKernelSamplerLoc;
148    GLuint mInvDitherKernelSizeUniformLoc;
149    GLuint mInvDitherKernelSizeSqUniformLoc;
150    GLuint mColor0UniformLoc;
151    GLuint mColor1UniformLoc;
152};
153
154Renderer* staticGradient() {
155    class NoRenderer : public Renderer {
156        virtual bool setUp(GLHelper* helper) {
157            mIsFirstFrame = true;
158            mGLHelper = helper;
159            return mGradientRenderer.setUp(helper);
160        }
161
162        virtual void tearDown() {
163            mGradientRenderer.tearDown();
164        }
165
166        virtual bool render(EGLSurface surface) {
167            if (mIsFirstFrame) {
168                bool result;
169                mIsFirstFrame = false;
170
171                result = mGLHelper->makeCurrent(surface);
172                if (!result) {
173                    return false;
174                }
175
176                result = mGradientRenderer.drawGradient();
177                if (!result) {
178                    return false;
179                }
180
181                result = mGLHelper->swapBuffers(surface);
182                if (!result) {
183                    return false;
184                }
185            }
186            return true;
187        }
188
189        bool mIsFirstFrame;
190        GLHelper* mGLHelper;
191        GradientRenderer mGradientRenderer;
192    };
193    return new NoRenderer;
194}
195
196
197} // namespace android
198