| /* | 
 |  * Copyright (C) 2012 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include <GLES2/gl2.h> | 
 | #include <GLES2/gl2ext.h> | 
 |  | 
 | #include "Flatland.h" | 
 | #include "GLHelper.h" | 
 |  | 
 | namespace android { | 
 |  | 
 | class Blitter { | 
 | public: | 
 |  | 
 |     bool setUp(GLHelper* helper) { | 
 |         bool result; | 
 |  | 
 |         result = helper->getShaderProgram("Blit", &mBlitPgm); | 
 |         if (!result) { | 
 |             return false; | 
 |         } | 
 |  | 
 |         mPosAttribLoc = glGetAttribLocation(mBlitPgm, "position"); | 
 |         mUVAttribLoc = glGetAttribLocation(mBlitPgm, "uv"); | 
 |         mUVToTexUniformLoc = glGetUniformLocation(mBlitPgm, "uvToTex"); | 
 |         mObjToNdcUniformLoc = glGetUniformLocation(mBlitPgm, "objToNdc"); | 
 |         mBlitSrcSamplerLoc = glGetUniformLocation(mBlitPgm, "blitSrc"); | 
 |         mModColorUniformLoc = glGetUniformLocation(mBlitPgm, "modColor"); | 
 |  | 
 |         return true; | 
 |     } | 
 |  | 
 |     bool blit(GLuint texName, const float* texMatrix, | 
 |             int32_t x, int32_t y, uint32_t w, uint32_t h) { | 
 |         float modColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; | 
 |         return modBlit(texName, texMatrix, modColor, x, y, w, h); | 
 |     } | 
 |  | 
 |     bool modBlit(GLuint texName, const float* texMatrix, float* modColor, | 
 |             int32_t x, int32_t y, uint32_t w, uint32_t h) { | 
 |         glUseProgram(mBlitPgm); | 
 |  | 
 |         GLint vp[4]; | 
 |         glGetIntegerv(GL_VIEWPORT, vp); | 
 |         float screenToNdc[16] = { | 
 |             2.0f/float(vp[2]),  0.0f,               0.0f,   0.0f, | 
 |             0.0f,               -2.0f/float(vp[3]), 0.0f,   0.0f, | 
 |             0.0f,               0.0f,               1.0f,   0.0f, | 
 |             -1.0f,              1.0f,               0.0f,   1.0f, | 
 |         }; | 
 |         const float pos[] = { | 
 |             float(x),   float(y), | 
 |             float(x+w), float(y), | 
 |             float(x),   float(y+h), | 
 |             float(x+w), float(y+h), | 
 |         }; | 
 |         const float uv[] = { | 
 |             0.0f, 0.0f, | 
 |             1.0f, 0.0f, | 
 |             0.0f, 1.0f, | 
 |             1.0f, 1.0f, | 
 |         }; | 
 |  | 
 |         glVertexAttribPointer(mPosAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, pos); | 
 |         glVertexAttribPointer(mUVAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, uv); | 
 |         glEnableVertexAttribArray(mPosAttribLoc); | 
 |         glEnableVertexAttribArray(mUVAttribLoc); | 
 |  | 
 |         glUniformMatrix4fv(mObjToNdcUniformLoc, 1, GL_FALSE, screenToNdc); | 
 |         glUniformMatrix4fv(mUVToTexUniformLoc, 1, GL_FALSE, texMatrix); | 
 |         glUniform4fv(mModColorUniformLoc, 1, modColor); | 
 |  | 
 |         glActiveTexture(GL_TEXTURE0); | 
 |         glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName); | 
 |         glUniform1i(mBlitSrcSamplerLoc, 0); | 
 |  | 
 |         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 
 |  | 
 |         glDisableVertexAttribArray(mPosAttribLoc); | 
 |         glDisableVertexAttribArray(mUVAttribLoc); | 
 |  | 
 |         if (glGetError() != GL_NO_ERROR) { | 
 |             fprintf(stderr, "GL error!\n"); | 
 |         } | 
 |  | 
 |         return true; | 
 |     } | 
 |  | 
 | private: | 
 |     GLuint mBlitPgm; | 
 |     GLint mPosAttribLoc; | 
 |     GLint mUVAttribLoc; | 
 |     GLint mUVToTexUniformLoc; | 
 |     GLint mObjToNdcUniformLoc; | 
 |     GLint mBlitSrcSamplerLoc; | 
 |     GLint mModColorUniformLoc; | 
 | }; | 
 |  | 
 | class ComposerBase : public Composer { | 
 | public: | 
 |     virtual ~ComposerBase() {} | 
 |  | 
 |     virtual bool setUp(const LayerDesc& desc, | 
 |             GLHelper* helper) { | 
 |         mLayerDesc = desc; | 
 |         return setUp(helper); | 
 |     } | 
 |  | 
 |     virtual void tearDown() { | 
 |     } | 
 |  | 
 |     virtual bool compose(GLuint /*texName*/, const sp<GLConsumer>& /*glc*/) { | 
 |         return true; | 
 |     } | 
 |  | 
 | protected: | 
 |     virtual bool setUp(GLHelper* /*helper*/) { | 
 |         return true; | 
 |     } | 
 |  | 
 |     LayerDesc mLayerDesc; | 
 | }; | 
 |  | 
 | Composer* nocomp() { | 
 |     class NoComp : public ComposerBase { | 
 |     }; | 
 |     return new NoComp(); | 
 | } | 
 |  | 
 | Composer* opaque() { | 
 |     class OpaqueComp : public ComposerBase { | 
 |         virtual bool setUp(GLHelper* helper) { | 
 |             return mBlitter.setUp(helper); | 
 |         } | 
 |  | 
 |         virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) { | 
 |             float texMatrix[16]; | 
 |             glc->getTransformMatrix(texMatrix); | 
 |  | 
 |             int32_t x = mLayerDesc.x; | 
 |             int32_t y = mLayerDesc.y; | 
 |             int32_t w = mLayerDesc.width; | 
 |             int32_t h = mLayerDesc.height; | 
 |  | 
 |             return mBlitter.blit(texName, texMatrix, x, y, w, h); | 
 |         } | 
 |  | 
 |         Blitter mBlitter; | 
 |     }; | 
 |     return new OpaqueComp(); | 
 | } | 
 |  | 
 | Composer* opaqueShrink() { | 
 |     class OpaqueComp : public ComposerBase { | 
 |         virtual bool setUp(GLHelper* helper) { | 
 |             mParity = false; | 
 |             return mBlitter.setUp(helper); | 
 |         } | 
 |  | 
 |         virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) { | 
 |             float texMatrix[16]; | 
 |             glc->getTransformMatrix(texMatrix); | 
 |  | 
 |             int32_t x = mLayerDesc.x; | 
 |             int32_t y = mLayerDesc.y; | 
 |             int32_t w = mLayerDesc.width; | 
 |             int32_t h = mLayerDesc.height; | 
 |  | 
 |             mParity = !mParity; | 
 |             if (mParity) { | 
 |                 x += w / 128; | 
 |                 y += h / 128; | 
 |                 w -= w / 64; | 
 |                 h -= h / 64; | 
 |             } | 
 |  | 
 |             return mBlitter.blit(texName, texMatrix, x, y, w, h); | 
 |         } | 
 |  | 
 |         Blitter mBlitter; | 
 |         bool mParity; | 
 |     }; | 
 |     return new OpaqueComp(); | 
 | } | 
 |  | 
 | Composer* blend() { | 
 |     class BlendComp : public ComposerBase { | 
 |         virtual bool setUp(GLHelper* helper) { | 
 |             return mBlitter.setUp(helper); | 
 |         } | 
 |  | 
 |         virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) { | 
 |             bool result; | 
 |  | 
 |             float texMatrix[16]; | 
 |             glc->getTransformMatrix(texMatrix); | 
 |  | 
 |             float modColor[4] = { .75f, .75f, .75f, .75f }; | 
 |  | 
 |             int32_t x = mLayerDesc.x; | 
 |             int32_t y = mLayerDesc.y; | 
 |             int32_t w = mLayerDesc.width; | 
 |             int32_t h = mLayerDesc.height; | 
 |  | 
 |             glEnable(GL_BLEND); | 
 |             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | 
 |  | 
 |             result = mBlitter.modBlit(texName, texMatrix, modColor, | 
 |                     x, y, w, h); | 
 |             if (!result) { | 
 |                 return false; | 
 |             } | 
 |  | 
 |             glDisable(GL_BLEND); | 
 |  | 
 |             return true; | 
 |         } | 
 |  | 
 |         Blitter mBlitter; | 
 |     }; | 
 |     return new BlendComp(); | 
 | } | 
 |  | 
 | Composer* blendShrink() { | 
 |     class BlendShrinkComp : public ComposerBase { | 
 |         virtual bool setUp(GLHelper* helper) { | 
 |             mParity = false; | 
 |             return mBlitter.setUp(helper); | 
 |         } | 
 |  | 
 |         virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) { | 
 |             bool result; | 
 |  | 
 |             float texMatrix[16]; | 
 |             glc->getTransformMatrix(texMatrix); | 
 |  | 
 |             float modColor[4] = { .75f, .75f, .75f, .75f }; | 
 |  | 
 |             int32_t x = mLayerDesc.x; | 
 |             int32_t y = mLayerDesc.y; | 
 |             int32_t w = mLayerDesc.width; | 
 |             int32_t h = mLayerDesc.height; | 
 |  | 
 |             mParity = !mParity; | 
 |             if (mParity) { | 
 |                 x += w / 128; | 
 |                 y += h / 128; | 
 |                 w -= w / 64; | 
 |                 h -= h / 64; | 
 |             } | 
 |  | 
 |             glEnable(GL_BLEND); | 
 |             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | 
 |  | 
 |             result = mBlitter.modBlit(texName, texMatrix, modColor, | 
 |                     x, y, w, h); | 
 |             if (!result) { | 
 |                 return false; | 
 |             } | 
 |  | 
 |             glDisable(GL_BLEND); | 
 |  | 
 |             return true; | 
 |         } | 
 |  | 
 |         Blitter mBlitter; | 
 |         bool mParity; | 
 |     }; | 
 |     return new BlendShrinkComp(); | 
 | } | 
 |  | 
 | } // namespace android |