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 <GLES2/gl2.h>
18#include <GLES2/gl2ext.h>
19
20#include "Flatland.h"
21#include "GLHelper.h"
22
23namespace android {
24
25class Blitter {
26public:
27
28    bool setUp(GLHelper* helper) {
29        bool result;
30
31        result = helper->getShaderProgram("Blit", &mBlitPgm);
32        if (!result) {
33            return false;
34        }
35
36        mPosAttribLoc = glGetAttribLocation(mBlitPgm, "position");
37        mUVAttribLoc = glGetAttribLocation(mBlitPgm, "uv");
38        mUVToTexUniformLoc = glGetUniformLocation(mBlitPgm, "uvToTex");
39        mObjToNdcUniformLoc = glGetUniformLocation(mBlitPgm, "objToNdc");
40        mBlitSrcSamplerLoc = glGetUniformLocation(mBlitPgm, "blitSrc");
41        mModColorUniformLoc = glGetUniformLocation(mBlitPgm, "modColor");
42
43        return true;
44    }
45
46    bool blit(GLuint texName, const float* texMatrix,
47            int32_t x, int32_t y, uint32_t w, uint32_t h) {
48        float modColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
49        return modBlit(texName, texMatrix, modColor, x, y, w, h);
50    }
51
52    bool modBlit(GLuint texName, const float* texMatrix, float* modColor,
53            int32_t x, int32_t y, uint32_t w, uint32_t h) {
54        glUseProgram(mBlitPgm);
55
56        GLint vp[4];
57        glGetIntegerv(GL_VIEWPORT, vp);
58        float screenToNdc[16] = {
59            2.0f/float(vp[2]),  0.0f,               0.0f,   0.0f,
60            0.0f,               -2.0f/float(vp[3]), 0.0f,   0.0f,
61            0.0f,               0.0f,               1.0f,   0.0f,
62            -1.0f,              1.0f,               0.0f,   1.0f,
63        };
64        const float pos[] = {
65            float(x),   float(y),
66            float(x+w), float(y),
67            float(x),   float(y+h),
68            float(x+w), float(y+h),
69        };
70        const float uv[] = {
71            0.0f, 0.0f,
72            1.0f, 0.0f,
73            0.0f, 1.0f,
74            1.0f, 1.0f,
75        };
76
77        glVertexAttribPointer(mPosAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, pos);
78        glVertexAttribPointer(mUVAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, uv);
79        glEnableVertexAttribArray(mPosAttribLoc);
80        glEnableVertexAttribArray(mUVAttribLoc);
81
82        glUniformMatrix4fv(mObjToNdcUniformLoc, 1, GL_FALSE, screenToNdc);
83        glUniformMatrix4fv(mUVToTexUniformLoc, 1, GL_FALSE, texMatrix);
84        glUniform4fv(mModColorUniformLoc, 1, modColor);
85
86        glActiveTexture(GL_TEXTURE0);
87        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName);
88        glUniform1i(mBlitSrcSamplerLoc, 0);
89
90        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
91
92        glDisableVertexAttribArray(mPosAttribLoc);
93        glDisableVertexAttribArray(mUVAttribLoc);
94
95        if (glGetError() != GL_NO_ERROR) {
96            fprintf(stderr, "GL error!\n");
97        }
98
99        return true;
100    }
101
102private:
103    GLuint mBlitPgm;
104    GLint mPosAttribLoc;
105    GLint mUVAttribLoc;
106    GLint mUVToTexUniformLoc;
107    GLint mObjToNdcUniformLoc;
108    GLint mBlitSrcSamplerLoc;
109    GLint mModColorUniformLoc;
110};
111
112class ComposerBase : public Composer {
113public:
114    virtual ~ComposerBase() {}
115
116    virtual bool setUp(const LayerDesc& desc,
117            GLHelper* helper) {
118        mLayerDesc = desc;
119        return setUp(helper);
120    }
121
122    virtual void tearDown() {
123    }
124
125    virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
126        return true;
127    }
128
129protected:
130    virtual bool setUp(GLHelper* helper) {
131        return true;
132    }
133
134    LayerDesc mLayerDesc;
135};
136
137Composer* nocomp() {
138    class NoComp : public ComposerBase {
139    };
140    return new NoComp();
141}
142
143Composer* opaque() {
144    class OpaqueComp : public ComposerBase {
145        virtual bool setUp(GLHelper* helper) {
146            return mBlitter.setUp(helper);
147        }
148
149        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
150            float texMatrix[16];
151            glc->getTransformMatrix(texMatrix);
152
153            int32_t x = mLayerDesc.x;
154            int32_t y = mLayerDesc.y;
155            int32_t w = mLayerDesc.width;
156            int32_t h = mLayerDesc.height;
157
158            return mBlitter.blit(texName, texMatrix, x, y, w, h);
159        }
160
161        Blitter mBlitter;
162    };
163    return new OpaqueComp();
164}
165
166Composer* opaqueShrink() {
167    class OpaqueComp : public ComposerBase {
168        virtual bool setUp(GLHelper* helper) {
169            mParity = false;
170            return mBlitter.setUp(helper);
171        }
172
173        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
174            float texMatrix[16];
175            glc->getTransformMatrix(texMatrix);
176
177            int32_t x = mLayerDesc.x;
178            int32_t y = mLayerDesc.y;
179            int32_t w = mLayerDesc.width;
180            int32_t h = mLayerDesc.height;
181
182            mParity = !mParity;
183            if (mParity) {
184                x += w / 128;
185                y += h / 128;
186                w -= w / 64;
187                h -= h / 64;
188            }
189
190            return mBlitter.blit(texName, texMatrix, x, y, w, h);
191        }
192
193        Blitter mBlitter;
194        bool mParity;
195    };
196    return new OpaqueComp();
197}
198
199Composer* blend() {
200    class BlendComp : public ComposerBase {
201        virtual bool setUp(GLHelper* helper) {
202            return mBlitter.setUp(helper);
203        }
204
205        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
206            bool result;
207
208            float texMatrix[16];
209            glc->getTransformMatrix(texMatrix);
210
211            float modColor[4] = { .75f, .75f, .75f, .75f };
212
213            int32_t x = mLayerDesc.x;
214            int32_t y = mLayerDesc.y;
215            int32_t w = mLayerDesc.width;
216            int32_t h = mLayerDesc.height;
217
218            glEnable(GL_BLEND);
219            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
220
221            result = mBlitter.modBlit(texName, texMatrix, modColor,
222                    x, y, w, h);
223            if (!result) {
224                return false;
225            }
226
227            glDisable(GL_BLEND);
228
229            return true;
230        }
231
232        Blitter mBlitter;
233    };
234    return new BlendComp();
235}
236
237Composer* blendShrink() {
238    class BlendShrinkComp : public ComposerBase {
239        virtual bool setUp(GLHelper* helper) {
240            mParity = false;
241            return mBlitter.setUp(helper);
242        }
243
244        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
245            bool result;
246
247            float texMatrix[16];
248            glc->getTransformMatrix(texMatrix);
249
250            float modColor[4] = { .75f, .75f, .75f, .75f };
251
252            int32_t x = mLayerDesc.x;
253            int32_t y = mLayerDesc.y;
254            int32_t w = mLayerDesc.width;
255            int32_t h = mLayerDesc.height;
256
257            mParity = !mParity;
258            if (mParity) {
259                x += w / 128;
260                y += h / 128;
261                w -= w / 64;
262                h -= h / 64;
263            }
264
265            glEnable(GL_BLEND);
266            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
267
268            result = mBlitter.modBlit(texName, texMatrix, modColor,
269                    x, y, w, h);
270            if (!result) {
271                return false;
272            }
273
274            glDisable(GL_BLEND);
275
276            return true;
277        }
278
279        Blitter mBlitter;
280        bool mParity;
281    };
282    return new BlendShrinkComp();
283}
284
285} // namespace android
286