/*
 * Copyright (C) 2007 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.
 */

#define LOG_TAG "SurfaceFlinger"

#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/Log.h>

#include <GLES/gl.h>
#include <GLES/glext.h>

#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"

namespace android {
// ---------------------------------------------------------------------------

const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8;
const char* const LayerBlur::typeID = "LayerBlur";

// ---------------------------------------------------------------------------

LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
        Client* client, int32_t i)
     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
     mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
{
}

LayerBlur::~LayerBlur()
{
    if (mTextureName != -1U) {
        //glDeleteTextures(1, &mTextureName);
        deletedTextures.add(mTextureName);
    }
}

void LayerBlur::setVisibleRegion(const Region& visibleRegion)
{
    LayerBaseClient::setVisibleRegion(visibleRegion);
    if (visibleRegionScreen.isEmpty()) {
        if (mTextureName != -1U) {
            // We're not visible, free the texture up.
            glBindTexture(GL_TEXTURE_2D, 0);
            glDeleteTextures(1, &mTextureName);
            mTextureName = -1U;
        }
    }
}

uint32_t LayerBlur::doTransaction(uint32_t flags)
{
    // we're doing a transaction, refresh the cache!
    if (!mFlinger->isFrozen()) {
        mRefreshCache = true;
        mCacheDirty = true;
        flags |= eVisibleRegion;
        this->contentDirty = true;
    }
    return LayerBase::doTransaction(flags);    
}

void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
{
    // this code-path must be as tight as possible, it's called each time
    // the screen is composited.
    if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
        // if anything visible below us is invalidated, the cache becomes dirty
        if (!mCacheDirty && 
                !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
            mCacheDirty = true;
        }
        if (mCacheDirty) {
            if (!mFlinger->isFrozen()) {
                // update everything below us that is visible
                outDirtyRegion.orSelf(visibleRegionScreen);
                nsecs_t now = systemTime();
                if ((now - mCacheAge) >= ms2ns(500)) {
                    mCacheAge = now;
                    mRefreshCache = true;
                    mCacheDirty = false;
                } else {
                    if (!mAutoRefreshPending) {
                        mFlinger->signalDelayedEvent(ms2ns(500));
                        mAutoRefreshPending = true;
                    }
                }
            }
        }
    }
    LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
}

void LayerBlur::onDraw(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    int x = mTransformedBounds.left;
    int y = mTransformedBounds.top;
    int w = mTransformedBounds.width();
    int h = mTransformedBounds.height();
    GLint X = x;
    GLint Y = fbHeight - (y + h);
    if (X < 0) {
        w += X;
        X = 0;
    }
    if (Y < 0) {
        h += Y;
        Y = 0;
    }
    if (w<0 || h<0) {
        // we're outside of the framebuffer
        return;
    }

    if (mTextureName == -1U) {
        // create the texture name the first time
        // can't do that in the ctor, because it runs in another thread.
        glGenTextures(1, &mTextureName);
    }

    Region::iterator iterator(clip);
    if (iterator) {
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, mTextureName);
    
        if (mRefreshCache) {
            mRefreshCache = false;
            mAutoRefreshPending = false;
            
            // allocate enough memory for 4-bytes (2 pixels) aligned data
            const int32_t s = (w + 1) & ~1;
            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);

            // This reads the frame-buffer, so a h/w GL would have to
            // finish() its rendering first. we don't want to do that
            // too often. Read data is 4-bytes aligned.
            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
            
            // blur that texture.
            GGLSurface bl;
            bl.version = sizeof(GGLSurface);
            bl.width = w;
            bl.height = h;
            bl.stride = s;
            bl.format = GGL_PIXEL_FORMAT_RGB_565;
            bl.data = (GGLubyte*)pixels;            
            blurFilter(&bl, 8, 2);
            
            // NOTE: this works only because we have POT. we'd have to round the
            // texture size up, otherwise.
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);

            free((void*)pixels);
        }
        
        const State& s = drawingState();
        if (UNLIKELY(s.alpha < 0xFF)) {
            const GGLfixed alpha = (s.alpha << 16)/255;
            glColor4x(0, 0, 0, alpha);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        } else {
            glDisable(GL_BLEND);
        }

        glDisable(GL_DITHER);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        if (UNLIKELY(transformed()
                || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) {
            // This is a very rare scenario.
            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            glScalef(1.0f/w, -1.0f/h, 1);
            glTranslatef(-x, -y, 0);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glVertexPointer(2, GL_FIXED, 0, mVertices);
            glTexCoordPointer(2, GL_FIXED, 0, mVertices);
            Rect r;
            while (iterator.iterate(&r)) {
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
            }       
        } else {
            Region::iterator iterator(clip);
            if (iterator) {
                // NOTE: this is marginally faster with the software gl, because
                // glReadPixels() reads the fb bottom-to-top, however we'll
                // skip all the jaccobian computations.
                Rect r;
                GLint crop[4] = { 0, 0, w, h };
                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
                y = fbHeight - (y + h);
                while (iterator.iterate(&r)) {
                    const GLint sy = fbHeight - (r.top + r.height());
                    glScissor(r.left, sy, r.width(), r.height());
                    glDrawTexiOES(x, y, 0, w, h);
                }
            }
        }
    }

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

// ---------------------------------------------------------------------------

}; // namespace android
