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