|  | /* | 
|  | * 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 |