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