/*
**
** Copyright 2009, 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 <stdlib.h>
#include <stdio.h>

#include "context.h"
#include "fp.h"
#include "state.h"
#include "matrix.h"
#include "vertex.h"
#include "light.h"
#include "primitives.h"
#include "texture.h"
#include "BufferObjectManager.h"

#include "TextureObjectManager.h"
#include <hardware/gralloc.h>
#include <hardware/copybit.h>
#include "gralloc_priv.h"

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

namespace android {

static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) {
    img->w      = surface->stride;
    img->h      = surface->height;
    img->format = surface->format;
    img->offset = 0;
    img->base   = surface->data;
    img->fd     = fd;
}

struct clipRectRegion : public copybit_region_t {
    clipRectRegion(ogles_context_t* c) {
        next = iterate;
        int x = c->viewport.scissor.x;
        int y = c->viewport.scissor.y;
        r.l = x;
        r.t = y;
        r.r = x + c->viewport.scissor.w;
        r.b = y + c->viewport.scissor.h;
        firstTime = true;
    }
private:
    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
        clipRectRegion* myself = (clipRectRegion*) self;
        if (myself->firstTime) {
            myself->firstTime = false;
            *rect = myself->r;
            return 1;
        }
        return 0;
    }
    mutable copybit_rect_t r;
    mutable bool firstTime;
};

static bool supportedCopybitsFormat(int format) {
    switch (format) {
    case COPYBIT_FORMAT_RGBA_8888:
    case COPYBIT_FORMAT_RGB_565:
    case COPYBIT_FORMAT_BGRA_8888:
    case COPYBIT_FORMAT_RGBA_5551:
    case COPYBIT_FORMAT_RGBA_4444:
    case COPYBIT_FORMAT_YCbCr_422_SP:
    case COPYBIT_FORMAT_YCbCr_420_SP:
        return true;
    default:
        return false;
    }
}

static bool hasAlpha(int format) {
    switch (format) {
    case COPYBIT_FORMAT_RGBA_8888:
    case COPYBIT_FORMAT_BGRA_8888:
    case COPYBIT_FORMAT_RGBA_5551:
    case COPYBIT_FORMAT_RGBA_4444:
        return true;
    default:
        return false;
    }
}

static inline int fixedToByte(GGLfixed val) {
    return (val - (val >> 8)) >> 8;
}

/**
 * Performs a quick check of the rendering state. If this function returns
 * false we cannot use the copybit driver.
 */

static bool checkContext(ogles_context_t* c) {

	// By convenction copybitQuickCheckContext() has already returned true.
	// avoid checking the same information again.
	
    if (c->copybits.blitEngine == NULL
            || (c->rasterizer.state.enables
                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) {
        return false;
    }

    // Note: The drawSurfaceFd is only set for destination
    // surfaces types that are supported by the hardware and
    // do not have an alpha channel. So we don't have to re-check that here.

    static const int tmu = 0;
    texture_unit_t& u(c->textures.tmu[tmu]);
    EGLTextureObject* textureObject = u.texture;

    if (!supportedCopybitsFormat(textureObject->surface.format)) {
        return false;
    }
    return true;
}


static bool copybit(GLint x, GLint y,
        GLint w, GLint h,
        EGLTextureObject* textureObject,
        const GLint* crop_rect,
        int transform,
        ogles_context_t* c)
{
    // We assume checkContext has already been called and has already
    // returned true.

    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;

    y = cbSurface.height - (y + h);

    const GLint Ucr = crop_rect[0];
    const GLint Vcr = crop_rect[1];
    const GLint Wcr = crop_rect[2];
    const GLint Hcr = crop_rect[3];

    int32_t dsdx = (Wcr << 16) / w;   // dsdx =  ((Wcr/w)/Wt)*Wt
    int32_t dtdy = ((-Hcr) <<  16) / h;   // dtdy = -((Hcr/h)/Ht)*Ht

    if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
            || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
        // The requested scale is out of the range the hardware
        // can support.
        return false;
    }

    int32_t texelArea = gglMulx(dtdy, dsdx);
    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
        // Non-linear filtering on a texture enlargement.
        return false;
    }

    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
        // Non-linear filtering on an texture shrink.
        return false;
    }

    const uint32_t enables = c->rasterizer.state.enables;
    int planeAlpha = 255;
    static const int tmu = 0;
    texture_t& tev(c->rasterizer.state.texture[tmu]);
    bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
    switch (tev.env) {

    case GGL_REPLACE:
        if (!srcTextureHasAlpha) {
            planeAlpha = fixedToByte(c->currentColorClamped.a);
        }
        break;

    case GGL_MODULATE:
        if (! (c->currentColorClamped.r == FIXED_ONE
                && c->currentColorClamped.g == FIXED_ONE
                && c->currentColorClamped.b == FIXED_ONE)) {
            return false;
        }
        planeAlpha = fixedToByte(c->currentColorClamped.a);
        break;

    default:
        // Incompatible texture environment.
        return false;
    }

    bool blending = false;

    if ((enables & GGL_ENABLE_BLENDING)
            && !(c->rasterizer.state.blend.src == GL_ONE
                    && c->rasterizer.state.blend.dst == GL_ZERO)) {
        // Blending is OK if it is
        // the exact kind of blending that the copybits hardware supports.
        // Note: The hardware only supports
        // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
        // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
        // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
        // because the performance is worth it, even if the results are
        // not correct.
        if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
                || c->rasterizer.state.blend.src == GL_ONE)
                && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
                && c->rasterizer.state.blend.alpha_separate == 0)) {
            // Incompatible blend mode.
            return false;
        }
        blending = true;
    } else {
        // No blending is OK if we are not using alpha.
        if (srcTextureHasAlpha || planeAlpha != 255) {
            // Incompatible alpha
            return false;
        }
    }

    if (srcTextureHasAlpha && planeAlpha != 255) {
        // Can't do two types of alpha at once.
        return false;
    }

    // LOGW("calling copybits");

    copybit_device_t* copybit = c->copybits.blitEngine;
    copybit_image_t dst;
    textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst);
    copybit_rect_t drect = {x, y, x+w, y+h};

    copybit_image_t src;
    textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd,
            &src);
    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };

    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);

    copybit->set_parameter(copybit, COPYBIT_DITHER,
            (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);

    clipRectRegion it(c);
    copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
    return true;
}

/*
 * Try to draw a triangle fan with copybit, return false if we fail.
 */
bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) {
    if (! checkContext(c)) {
        return false;
    }

    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
    // Is the result a screen aligned rectangle?
    int sx[4];
    int sy[4];
    for (int i = 0; i < 4; i++) {
        GLfixed x = c->vc.vBuffer[i].window.x;
        GLfixed y = c->vc.vBuffer[i].window.y;
        if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) {
            return false;
        }
        sx[i] = x >> 4;
        sy[i] = y >> 4;
    }

    /*
     * This is the pattern we're looking for:
     *    (2)--(3)
     *     |\   |
     *     | \  |
     *     |  \ |
     *     |   \|
     *    (1)--(0)
     *
     */
    int dx[4];
    int dy[4];
    for (int i = 0; i < 4; i++) {
        int i1 = (i + 1) & 3;
        dx[i] = sx[i] - sx[i1];
        dy[i] = sy[i] - sy[i1];
    }
    if (dx[1] | dx[3] | dy[0] | dy[2]) {
        return false;
    }
    if (dx[0] != -dx[2] || dy[1] != -dy[3]) {
        return false;
    }

    int x = sx[1];
    int y = sy[1];
    int w = dx[0];
    int h = dy[3];

    // We expect the texture coordinates to always be the unit square:

    static const GLfixed kExpectedUV[8] = {
        0, 0,
        0, FIXED_ONE,
        FIXED_ONE, FIXED_ONE,
        FIXED_ONE, 0
    };
    {
        const GLfixed* pExpected = &kExpectedUV[0];
        for (int i = 0; i < 4; i++) {
            GLfixed u = c->vc.vBuffer[i].texture[0].x;
            GLfixed v = c->vc.vBuffer[i].texture[0].y;
            if (u != *pExpected++ || v != *pExpected++) {
                return false;
            }
        }
    }

    static const int tmu = 0;
    texture_unit_t& u(c->textures.tmu[tmu]);
    EGLTextureObject* textureObject = u.texture;

    GLint tWidth = textureObject->surface.width;
    GLint tHeight = textureObject->surface.height;
    GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};

    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
    y = cbSurface.height - (y + h);

    return copybit(x, y, w, h, textureObject, crop_rect,
            COPYBIT_TRANSFORM_ROT_90, c);
}

/*
 * Try to drawTexiOESWithCopybit, return false if we fail.
 */

bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
        GLint w, GLint h, ogles_context_t* c)
{
    // quickly process empty rects
    if ((w|h) <= 0) {
        return true;
    }

    if (! checkContext(c)) {
        return false;
    }

    static const int tmu = 0;
    texture_unit_t& u(c->textures.tmu[tmu]);
    EGLTextureObject* textureObject = u.texture;

    return copybit(x, y, w, h, textureObject, textureObject->crop_rect,
            0, c);
}

} // namespace android

