/*
**
** 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 <private/ui/android_natives_priv.h>

#include <ui/GraphicBuffer.h>
#include <ui/Region.h>
#include <ui/Rect.h>


#define DEBUG_COPYBIT false

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

namespace android {

static void textureToCopyBitImage(
        const GGLSurface* surface, int32_t opFormat, 
        android_native_buffer_t* buffer, copybit_image_t* img)
{
    uint32_t vstride = 0;
    if (opFormat == COPYBIT_FORMAT_YCbCr_422_SP ||
            opFormat == COPYBIT_FORMAT_YCbCr_420_SP) {
        // NOTE: this static_cast is really not safe b/c we can't know for
        // sure the buffer passed is of the right type.
        // However, since we do this only for YUV formats, we should be safe
        // since only SurfaceFlinger makes use of them.
        GraphicBuffer* graphicBuffer = static_cast<GraphicBuffer*>(buffer);
        vstride = graphicBuffer->getVerticalStride();
    }

    img->w      = surface->stride;
    img->h      = vstride ? vstride : surface->height;
    img->format = opFormat;
    img->base   = surface->data;
    img->handle = (native_handle_t *)buffer->handle;
}

struct clipRectRegion : public copybit_region_t {
    clipRectRegion(ogles_context_t* c) 
    {
        scissor_t const* scissor = &c->rasterizer.state.scissor;
        r.l = scissor->left;
        r.t = scissor->top;
        r.r = scissor->right;
        r.b = scissor->bottom;
        next = iterate; 
    }
private:
    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
        *rect = static_cast<clipRectRegion const*>(self)->r;
        const_cast<copybit_region_t *>(self)->next = iterate_done;
        return 1;
    }
    static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
        return 0;
    }
public:
    copybit_rect_t r;
};

static bool supportedCopybitsFormat(int format) {
    switch (format) {
    case COPYBIT_FORMAT_RGBA_8888:
    case COPYBIT_FORMAT_RGBX_8888:
    case COPYBIT_FORMAT_RGB_888:
    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 convention copybitQuickCheckContext() has already returned true.
	// avoid checking the same information again.
	
    if (c->copybits.blitEngine == NULL) {
        LOGD_IF(DEBUG_COPYBIT, "no copybit hal");
        return false;
    }

    if (c->rasterizer.state.enables
                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
        LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog");
        return false;
    }

    // Note: The drawSurfaceBuffer 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)) {
        LOGD_IF(DEBUG_COPYBIT, "texture format not supported");
        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)
{
    status_t err = NO_ERROR;

    // 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];

    GLint screen_w = w;
    GLint screen_h = h;
    int32_t dsdx = Wcr << 16;   // dsdx =  ((Wcr/screen_w)/Wt)*Wt
    int32_t dtdy = Hcr << 16;   // dtdy = -((Hcr/screen_h)/Ht)*Ht
    if (transform & COPYBIT_TRANSFORM_ROT_90) {
        swap(screen_w, screen_h);
    }
    if (dsdx!=screen_w || dtdy!=screen_h) {
        // in most cases the divide is not needed
        dsdx /= screen_w;
        dtdy /= screen_h;
    }
    dtdy = -dtdy; // see equation of dtdy above

    // copybit doesn't say anything about filtering, so we can't
    // discriminate. On msm7k, copybit will always filter.
    // the code below handles min/mag filters, we keep it as a reference.
    
#ifdef MIN_MAG_FILTER
    int32_t texelArea = gglMulx(dtdy, dsdx);
    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
        // Non-linear filtering on a texture enlargement.
        LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR");
        return false;
    }
    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
        // Non-linear filtering on an texture shrink.
        LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR");
        return false;
    }
#endif
    
    const uint32_t enables = c->rasterizer.state.enables;
    int planeAlpha = 255;
    bool alphaPlaneWorkaround = false;
    static const int tmu = 0;
    texture_t& tev(c->rasterizer.state.texture[tmu]);
    int32_t opFormat = textureObject->surface.format;
    const bool srcTextureHasAlpha = hasAlpha(opFormat);
    if (!srcTextureHasAlpha) {
        planeAlpha = fixedToByte(c->currentColorClamped.a);
    }

    const bool cbHasAlpha = hasAlpha(cbSurface.format);
    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.
            LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode");
            return false;
        }
        blending = true;
    } else {
        if (cbHasAlpha) {
            // NOTE: the result will be slightly wrong in this case because
            // the destination alpha channel will be set to 1.0 instead of
            // the iterated alpha value. *shrug*.
        }
        // disable plane blending and src blending for supported formats
        planeAlpha = 255;
        if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
            opFormat = COPYBIT_FORMAT_RGBX_8888;
        } else {
            if (srcTextureHasAlpha) {
                LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
                return false;
            }
        }
    }

    switch (tev.env) {
    case GGL_REPLACE:
        break;
    case GGL_MODULATE:
        // only cases allowed is:
        // RGB  source, color={1,1,1,a} -> can be done with GL_REPLACE
        // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
        if (blending) {
            if (c->currentColorClamped.r == c->currentColorClamped.a &&
                c->currentColorClamped.g == c->currentColorClamped.a &&
                c->currentColorClamped.b == c->currentColorClamped.a) {
                // TODO: RGBA source, color={1,1,1,a} / regular-blending
                // is equivalent
                alphaPlaneWorkaround = true;
                break;
            }
        }
        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
        return false;
    default:
        // Incompatible texture environment.
        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
        return false;
    }

    copybit_device_t* copybit = c->copybits.blitEngine;
    copybit_image_t src;
    textureToCopyBitImage(&textureObject->surface, opFormat,
            textureObject->buffer, &src);
    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };

    /*
     *  Below we perform extra passes needed to emulate things the h/w
     * cannot do.
     */

    const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
    const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);

    sp<GraphicBuffer> tempBitmap;

    if (dsdx < maxScaleInv || dsdx > minScaleInv ||
        dtdy < maxScaleInv || dtdy > minScaleInv)
    {
        // The requested scale is out of the range the hardware
        // can support.
        LOGD_IF(DEBUG_COPYBIT,
                "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
                "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
                dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);

        int32_t xscale=0x10000, yscale=0x10000;
        if (dsdx > minScaleInv)         xscale = c->copybits.minScale;
        else if (dsdx < maxScaleInv)    xscale = c->copybits.maxScale;
        if (dtdy > minScaleInv)         yscale = c->copybits.minScale;
        else if (dtdy < maxScaleInv)    yscale = c->copybits.maxScale;
        dsdx = gglMulx(dsdx, xscale);
        dtdy = gglMulx(dtdy, yscale);

        /* we handle only one step of resizing below. Handling an arbitrary
         * number is relatively easy (replace "if" above by "while"), but requires
         * two intermediate buffers and so far we never had the need.
         */

        if (dsdx < maxScaleInv || dsdx > minScaleInv ||
            dtdy < maxScaleInv || dtdy > minScaleInv) {
            LOGD_IF(DEBUG_COPYBIT,
                    "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
                    "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
                    dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
            return false;
        }

        const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
        const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);

        LOGD_IF(DEBUG_COPYBIT,
                "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
                xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);

        tempBitmap = new GraphicBuffer(
                    tmp_w, tmp_h, src.format,
                    GraphicBuffer::USAGE_HW_2D);

        err = tempBitmap->initCheck();
        if (err == NO_ERROR) {
            copybit_image_t tmp_dst;
            copybit_rect_t tmp_rect;
            tmp_dst.w = tmp_w;
            tmp_dst.h = tmp_h;
            tmp_dst.format = tempBitmap->format;
            tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
            tmp_rect.l = 0;
            tmp_rect.t = 0;
            tmp_rect.r = tmp_dst.w;
            tmp_rect.b = tmp_dst.h;
            region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.b)));
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
            err = copybit->stretch(copybit,
                    &tmp_dst, &src, &tmp_rect, &srect, &tmp_it);
            src = tmp_dst;
            srect = tmp_rect;
        }
    }

    copybit_image_t dst;
    textureToCopyBitImage(&cbSurface, cbSurface.format,
            c->copybits.drawSurfaceBuffer, &dst);
    copybit_rect_t drect = {x, y, x+w, y+h};


    /* and now the alpha-plane hack. This handles the "Fade" case of a
     * texture with an alpha channel.
     */
    if (alphaPlaneWorkaround) {
        sp<GraphicBuffer> tempCb = new GraphicBuffer(
                    w, h, COPYBIT_FORMAT_RGB_565,
                    GraphicBuffer::USAGE_HW_2D);

        err = tempCb->initCheck();

        copybit_image_t tmpCbImg;
        copybit_rect_t tmpCbRect;
        copybit_rect_t tmpdrect = drect;
        tmpCbImg.w = w;
        tmpCbImg.h = h;
        tmpCbImg.format = tempCb->format;
        tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle;
        tmpCbRect.l = 0;
        tmpCbRect.t = 0;

        if (drect.l < 0) {
            tmpCbRect.l = -tmpdrect.l;
            tmpdrect.l = 0;
        }
        if (drect.t < 0) {
            tmpCbRect.t = -tmpdrect.t;
            tmpdrect.t = 0;
        }
        if (drect.l + tmpCbImg.w > dst.w) {
            tmpCbImg.w = dst.w - drect.l;
            tmpdrect.r = dst.w;
        }
        if (drect.t + tmpCbImg.h > dst.h) {
            tmpCbImg.h = dst.h - drect.t;
            tmpdrect.b = dst.h;
        }

        tmpCbRect.r = tmpCbImg.w;
        tmpCbRect.b = tmpCbImg.h;

        if (!err) {
            // first make a copy of the destination buffer
            region_iterator tmp_it(Region(Rect(w, h)));
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
            err = copybit->stretch(copybit,
                    &tmpCbImg, &dst, &tmpCbRect, &tmpdrect, &tmp_it);
        }
        if (!err) {
            // then proceed as usual, but without the alpha plane
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
            copybit->set_parameter(copybit, COPYBIT_DITHER,
                    (enables & GGL_ENABLE_DITHER) ?
                            COPYBIT_ENABLE : COPYBIT_DISABLE);
            clipRectRegion it(c);
            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
        }
        if (!err) {
            // finally copy back the destination on top with 1-alphaplane
            int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a);
            clipRectRegion it(c);
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha);
            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
            err = copybit->stretch(copybit,
                    &dst, &tmpCbImg, &tmpdrect, &tmpCbRect, &it);
        }
    } else {
        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);

        LOGD_IF(0,
             "dst={%d, %d, %d, %p, %p}, "
             "src={%d, %d, %d, %p, %p}, "
             "drect={%d,%d,%d,%d}, "
             "srect={%d,%d,%d,%d}, "
             "it={%d,%d,%d,%d}, " ,
             dst.w, dst.h, dst.format, dst.base, dst.handle,
             src.w, src.h, src.format, src.base, src.handle,
             drect.l, drect.t, drect.r, drect.b,
             srect.l, srect.t, srect.r, srect.b,
             it.r.l, it.r.t, it.r.r, it.r.b
        );

        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
    }
    if (err != NO_ERROR) {
        c->textures.tmu[0].texture->try_copybit = false;
    }
    return err == NO_ERROR ? true : false;
}

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

    // FIXME: we should handle culling  here
    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);

    // we detect if we're dealing with a rectangle, by comparing the
    // rectangles {v0,v2} and {v1,v3} which should be identical.
    
    // NOTE: we should check that the rectangle is window aligned, however
    // if we do that, the optimization won't be taken in a lot of cases.
    // Since this code is intended to be used with SurfaceFlinger only,
    // so it's okay...
    
    const vec4_t& v0 = c->vc.vBuffer[0].window;
    const vec4_t& v1 = c->vc.vBuffer[1].window;
    const vec4_t& v2 = c->vc.vBuffer[2].window;
    const vec4_t& v3 = c->vc.vBuffer[3].window;
    int l = min(v0.x, v2.x);
    int b = min(v0.y, v2.y);
    int r = max(v0.x, v2.x);
    int t = max(v0.y, v2.y);
    if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) ||
        (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) {
        LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle");
        return false;
    }

    // fetch and transform texture coordinates
    // NOTE: maybe it would be better to have a "compileElementsAll" method
    // that would ensure all vertex data are fetched and transformed
    const transform_t& tr = c->transforms.texture[0].transform; 
    for (size_t i=0 ; i<4 ; i++) {
        const GLubyte* tp = c->arrays.texture[0].element(i);
        vertex_t* const v = &c->vc.vBuffer[i];
        c->arrays.texture[0].fetch(c, v->texture[0].v, tp);
        // FIXME: we should bail if q!=1
        c->arrays.tex_transform[0](&tr, &v->texture[0], &v->texture[0]);
    }
    
    const vec4_t& t0 = c->vc.vBuffer[0].texture[0];
    const vec4_t& t1 = c->vc.vBuffer[1].texture[0];
    const vec4_t& t2 = c->vc.vBuffer[2].texture[0];
    const vec4_t& t3 = c->vc.vBuffer[3].texture[0];
    int txl = min(t0.x, t2.x);
    int txb = min(t0.y, t2.y);
    int txr = max(t0.x, t2.x);
    int txt = max(t0.y, t2.y);
    if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) ||
        (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) {
        LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle");
        return false;
    }
    if ((txl != 0) || (txb != 0) ||
        (txr != FIXED_ONE) || (txt != FIXED_ONE)) {
        // we could probably handle this case, if we wanted to
        LOGD_IF(DEBUG_COPYBIT, "texture is cropped: %08x,%08x,%08x,%08x",
                txl, txb, txr, txt);
        return false;
    }

    // at this point, we know we are dealing with a rectangle, so we 
    // only need to consider 3 vertices for computing the jacobians
    
    const int dx01 = v1.x - v0.x;
    const int dx02 = v2.x - v0.x;
    const int dy01 = v1.y - v0.y;
    const int dy02 = v2.y - v0.y;
    const int ds01 = t1.S - t0.S;
    const int ds02 = t2.S - t0.S;
    const int dt01 = t1.T - t0.T;
    const int dt02 = t2.T - t0.T;
    const int area = dx01*dy02 - dy01*dx02;
    int dsdx, dsdy, dtdx, dtdy;
    if (area >= 0) {
        dsdx = ds01*dy02 - ds02*dy01;
        dtdx = dt01*dy02 - dt02*dy01;
        dsdy = ds02*dx01 - ds01*dx02;
        dtdy = dt02*dx01 - dt01*dx02;
    } else {
        dsdx = ds02*dy01 - ds01*dy02;
        dtdx = dt02*dy01 - dt01*dy02;
        dsdy = ds01*dx02 - ds02*dx01;
        dtdy = dt01*dx02 - dt02*dx01;
    }

    // here we rely on the fact that we know the transform is
    // a rigid-body transform AND that it can only rotate in 90 degrees
    // increments

    int transform = 0;
    if (dsdx == 0) {
        // 90 deg rotation case
        // [ 0    dtdx  ]
        // [ dsdx    0  ]
        transform |= COPYBIT_TRANSFORM_ROT_90;
        // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted
        if (dtdx > 0)
            transform |= COPYBIT_TRANSFORM_FLIP_H;
        if (dsdy < 0)
            transform |= COPYBIT_TRANSFORM_FLIP_V;
    } else {
        // [ dsdx    0  ]
        // [ 0     dtdy ]
        if (dsdx < 0)
            transform |= COPYBIT_TRANSFORM_FLIP_H;
        if (dtdy < 0)
            transform |= COPYBIT_TRANSFORM_FLIP_V;
    }

    //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform);
    //LOGD("A=%f\tB=%f\nC=%f\tD=%f",
    //      dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0);

    int x = l >> 4;
    int y = b >> 4;
    int w = (r-l) >> 4;
    int h = (t-b) >> 4;
    texture_unit_t& u(c->textures.tmu[0]);
    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, transform, 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;
    }
    texture_unit_t& u(c->textures.tmu[0]);
    EGLTextureObject* textureObject = u.texture;
    return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c);
}

} // namespace android

