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