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