11473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/*
21473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian**
31473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** Copyright 2009, The Android Open Source Project
41473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian**
51473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** Licensed under the Apache License, Version 2.0 (the "License");
61473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** you may not use this file except in compliance with the License.
71473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** You may obtain a copy of the License at
81473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian**
91473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian**     http://www.apache.org/licenses/LICENSE-2.0
101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian**
111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** Unless required by applicable law or agreed to in writing, software
121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** distributed under the License is distributed on an "AS IS" BASIS,
131473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** See the License for the specific language governing permissions and
151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian** limitations under the License.
161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian*/
171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include <stdlib.h>
191473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include <stdio.h>
201473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
211473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "context.h"
221473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "fp.h"
231473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "state.h"
241473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "matrix.h"
251473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "vertex.h"
261473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "light.h"
271473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "primitives.h"
281473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "texture.h"
291473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "BufferObjectManager.h"
301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include "TextureObjectManager.h"
31350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian
321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include <hardware/gralloc.h>
331473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian#include <hardware/copybit.h>
34350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian#include <private/ui/android_natives_priv.h>
351473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
369042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian#include <ui/GraphicBuffer.h>
379042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian#include <ui/Region.h>
389042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian#include <ui/Rect.h>
399042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
4003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
4118ffb5493b92e2ae22d8cb01f0b9db1a8617c3f2Mathias Agopian#define DEBUG_COPYBIT false
4203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
431473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian// ----------------------------------------------------------------------------
441473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
451473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopiannamespace android {
461473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
47350d651706d8f484d9aeb539d491526f822fa84aMathias Agopianstatic void textureToCopyBitImage(
4888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        const GGLSurface* surface, int32_t opFormat,
4936d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian        android_native_buffer_t* buffer, copybit_image_t* img)
50350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian{
511473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->w      = surface->stride;
528f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian    img->h      = surface->height;
5388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    img->format = opFormat;
541473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->base   = surface->data;
5536d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian    img->handle = (native_handle_t *)buffer->handle;
561473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
571473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
581473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstruct clipRectRegion : public copybit_region_t {
594d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    clipRectRegion(ogles_context_t* c)
604d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    {
614d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        scissor_t const* scissor = &c->rasterizer.state.scissor;
624d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.l = scissor->left;
634d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.t = scissor->top;
644d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.r = scissor->right;
654d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.b = scissor->bottom;
664d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        next = iterate;
671473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
681473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianprivate:
691473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
704d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        *rect = static_cast<clipRectRegion const*>(self)->r;
714d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        const_cast<copybit_region_t *>(self)->next = iterate_done;
724d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        return 1;
734d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    }
744d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return 0;
761473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
77f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopianpublic:
784d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    copybit_rect_t r;
791473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian};
801473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
811473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool supportedCopybitsFormat(int format) {
821473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    switch (format) {
831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_8888:
84f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian    case COPYBIT_FORMAT_RGBX_8888:
85f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian    case COPYBIT_FORMAT_RGB_888:
861473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGB_565:
871473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_BGRA_8888:
881473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_5551:
891473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_4444:
901473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
911473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    default:
921473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
941473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
951473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool hasAlpha(int format) {
971473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    switch (format) {
981473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_8888:
991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_BGRA_8888:
1001473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_5551:
1011473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_4444:
1021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
1031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    default:
1041473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1081473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic inline int fixedToByte(GGLfixed val) {
1091473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    return (val - (val >> 8)) >> 8;
1101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/**
1131473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Performs a quick check of the rendering state. If this function returns
1141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * false we cannot use the copybit driver.
1151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
1161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool checkContext(ogles_context_t* c) {
1181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
119350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian	// By convention copybitQuickCheckContext() has already returned true.
1201473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian	// avoid checking the same information again.
1211473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
12203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (c->copybits.blitEngine == NULL) {
12303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "no copybit hal");
12403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        return false;
12503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    }
12603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
12703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (c->rasterizer.state.enables
12803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
12903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog");
1301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1311473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
133350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    // Note: The drawSurfaceBuffer is only set for destination
1341473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // surfaces types that are supported by the hardware and
1351473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // do not have an alpha channel. So we don't have to re-check that here.
1361473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1371473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static const int tmu = 0;
1381473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    texture_unit_t& u(c->textures.tmu[tmu]);
1391473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    EGLTextureObject* textureObject = u.texture;
1401473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1411473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (!supportedCopybitsFormat(textureObject->surface.format)) {
14203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texture format not supported");
1431473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1441473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1451473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    return true;
1461473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1471473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1481473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1491473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool copybit(GLint x, GLint y,
1501473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        GLint w, GLint h,
1511473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        EGLTextureObject* textureObject,
1521473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        const GLint* crop_rect,
1531473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        int transform,
1541473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        ogles_context_t* c)
1551473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian{
15685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    status_t err = NO_ERROR;
15785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian
1581473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // We assume checkContext has already been called and has already
1591473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // returned true.
1601473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1611473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
1621473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1631473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    y = cbSurface.height - (y + h);
1641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1651473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Ucr = crop_rect[0];
1661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Vcr = crop_rect[1];
1671473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Wcr = crop_rect[2];
1681473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Hcr = crop_rect[3];
1691473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1700f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    GLint screen_w = w;
1710f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    GLint screen_h = h;
1720f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    int32_t dsdx = Wcr << 16;   // dsdx =  ((Wcr/screen_w)/Wt)*Wt
1730f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    int32_t dtdy = Hcr << 16;   // dtdy = -((Hcr/screen_h)/Ht)*Ht
174f6c2a1ae60a190951b1c9e93f64f62a000cb51fdMathias Agopian    if (transform & COPYBIT_TRANSFORM_ROT_90) {
1750f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        swap(screen_w, screen_h);
1760f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    }
1770f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    if (dsdx!=screen_w || dtdy!=screen_h) {
1780f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        // in most cases the divide is not needed
1790f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        dsdx /= screen_w;
1800f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        dtdy /= screen_h;
181f6c2a1ae60a190951b1c9e93f64f62a000cb51fdMathias Agopian    }
1820f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    dtdy = -dtdy; // see equation of dtdy above
1831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
18442bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // copybit doesn't say anything about filtering, so we can't
18542bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // discriminate. On msm7k, copybit will always filter.
18642bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // the code below handles min/mag filters, we keep it as a reference.
18742bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
18842bf621e801183028066e6947fdd22eae8693a02Mathias Agopian#ifdef MIN_MAG_FILTER
1891473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int32_t texelArea = gglMulx(dtdy, dsdx);
1901473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
1911473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Non-linear filtering on a texture enlargement.
19203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR");
1931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1941473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1951473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
1961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Non-linear filtering on an texture shrink.
19703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR");
1981473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
20042bf621e801183028066e6947fdd22eae8693a02Mathias Agopian#endif
20142bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
2021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const uint32_t enables = c->rasterizer.state.enables;
2031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int planeAlpha = 255;
20485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    bool alphaPlaneWorkaround = false;
2051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static const int tmu = 0;
2061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    texture_t& tev(c->rasterizer.state.texture[tmu]);
20788d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    int32_t opFormat = textureObject->surface.format;
20888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    const bool srcTextureHasAlpha = hasAlpha(opFormat);
209f6c2a1ae60a190951b1c9e93f64f62a000cb51fdMathias Agopian    if (!srcTextureHasAlpha) {
210f6c2a1ae60a190951b1c9e93f64f62a000cb51fdMathias Agopian        planeAlpha = fixedToByte(c->currentColorClamped.a);
211f6c2a1ae60a190951b1c9e93f64f62a000cb51fdMathias Agopian    }
2121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
21388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    const bool cbHasAlpha = hasAlpha(cbSurface.format);
2141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    bool blending = false;
2151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if ((enables & GGL_ENABLE_BLENDING)
2161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            && !(c->rasterizer.state.blend.src == GL_ONE
2171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                    && c->rasterizer.state.blend.dst == GL_ZERO)) {
2181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Blending is OK if it is
2191473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // the exact kind of blending that the copybits hardware supports.
2201473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Note: The hardware only supports
2211473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
2221473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
2231473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
2241473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // because the performance is worth it, even if the results are
2251473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // not correct.
2261473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
2271473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                || c->rasterizer.state.blend.src == GL_ONE)
2281473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
2291473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->rasterizer.state.blend.alpha_separate == 0)) {
2301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            // Incompatible blend mode.
23103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode");
2321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            return false;
2331473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2341473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        blending = true;
2351473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    } else {
23688d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        if (cbHasAlpha) {
23788d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            // NOTE: the result will be slightly wrong in this case because
23888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            // the destination alpha channel will be set to 1.0 instead of
23988d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            // the iterated alpha value. *shrug*.
24088d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        }
24188d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        // disable plane blending and src blending for supported formats
24288d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        planeAlpha = 255;
24388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
24488d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            opFormat = COPYBIT_FORMAT_RGBX_8888;
24588d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        } else {
24688d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            if (srcTextureHasAlpha) {
24788d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian                LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
24888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian                return false;
24988d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            }
2501473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2511473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2521473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
25388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    switch (tev.env) {
25488d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    case GGL_REPLACE:
25588d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        break;
25688d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    case GGL_MODULATE:
25788d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        // only cases allowed is:
25888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        // RGB  source, color={1,1,1,a} -> can be done with GL_REPLACE
25988d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
26088d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        if (blending) {
26188d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            if (c->currentColorClamped.r == c->currentColorClamped.a &&
26288d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian                c->currentColorClamped.g == c->currentColorClamped.a &&
26388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian                c->currentColorClamped.b == c->currentColorClamped.a) {
26485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                // TODO: RGBA source, color={1,1,1,a} / regular-blending
26585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                // is equivalent
26685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                alphaPlaneWorkaround = true;
26785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                break;
26888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian            }
26988d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        }
27088d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
27188d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        return false;
27288d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian    default:
27388d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        // Incompatible texture environment.
27488d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
2751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
2761473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2771473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2789042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    copybit_device_t* copybit = c->copybits.blitEngine;
2799042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    copybit_image_t src;
28036d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian    textureToCopyBitImage(&textureObject->surface, opFormat,
28136d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian            textureObject->buffer, &src);
2829042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
2839042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
2849042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    /*
2859042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian     *  Below we perform extra passes needed to emulate things the h/w
2869042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian     * cannot do.
2879042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian     */
28888d11cfbfcde32d3212600d4e96a0c04b556c4d0Mathias Agopian
2899042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
2909042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);
2911473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2929042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    sp<GraphicBuffer> tempBitmap;
2939042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
2949042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    if (dsdx < maxScaleInv || dsdx > minScaleInv ||
2959042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        dtdy < maxScaleInv || dtdy > minScaleInv)
2969042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    {
2979042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        // The requested scale is out of the range the hardware
2989042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        // can support.
2999042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        LOGD_IF(DEBUG_COPYBIT,
3009042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
3019042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
3029042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
3039042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3049042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        int32_t xscale=0x10000, yscale=0x10000;
3059042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        if (dsdx > minScaleInv)         xscale = c->copybits.minScale;
3069042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        else if (dsdx < maxScaleInv)    xscale = c->copybits.maxScale;
3079042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        if (dtdy > minScaleInv)         yscale = c->copybits.minScale;
3089042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        else if (dtdy < maxScaleInv)    yscale = c->copybits.maxScale;
3099042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        dsdx = gglMulx(dsdx, xscale);
3109042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        dtdy = gglMulx(dtdy, yscale);
3119042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3129042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        /* we handle only one step of resizing below. Handling an arbitrary
3139042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian         * number is relatively easy (replace "if" above by "while"), but requires
3149042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian         * two intermediate buffers and so far we never had the need.
3159042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian         */
3169042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3179042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        if (dsdx < maxScaleInv || dsdx > minScaleInv ||
3189042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            dtdy < maxScaleInv || dtdy > minScaleInv) {
3199042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            LOGD_IF(DEBUG_COPYBIT,
3209042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
3219042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
3229042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
3239042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            return false;
3249042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        }
3259042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3269042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
3279042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);
3289042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3299042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        LOGD_IF(DEBUG_COPYBIT,
3309042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
3319042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);
3329042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
3339042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        tempBitmap = new GraphicBuffer(
3349042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    tmp_w, tmp_h, src.format,
3359042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    GraphicBuffer::USAGE_HW_2D);
3369042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian
33785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        err = tempBitmap->initCheck();
3389042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        if (err == NO_ERROR) {
3399042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            copybit_image_t tmp_dst;
3409042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            copybit_rect_t tmp_rect;
3419042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_dst.w = tmp_w;
3429042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_dst.h = tmp_h;
34385ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            tmp_dst.format = tempBitmap->format;
3449042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
3459042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_rect.l = 0;
3469042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_rect.t = 0;
3479042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_rect.r = tmp_dst.w;
3489042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            tmp_rect.b = tmp_dst.h;
3499042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.b)));
3509042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
3519042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
3529042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
3539042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            err = copybit->stretch(copybit,
3549042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian                    &tmp_dst, &src, &tmp_rect, &srect, &tmp_it);
3559042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            src = tmp_dst;
3569042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian            srect = tmp_rect;
3579042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian        }
3589042b4564de5477b18e680c7dce13b587a681dd9Mathias Agopian    }
359350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian
3601473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_image_t dst;
36136d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian    textureToCopyBitImage(&cbSurface, cbSurface.format,
36236d0184e089831b74de6005f01da9e7b26679bb9Mathias Agopian            c->copybits.drawSurfaceBuffer, &dst);
3631473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_rect_t drect = {x, y, x+w, y+h};
3641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
3651473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
36685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    /* and now the alpha-plane hack. This handles the "Fade" case of a
36785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian     * texture with an alpha channel.
36885ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian     */
36985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    if (alphaPlaneWorkaround) {
37085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        sp<GraphicBuffer> tempCb = new GraphicBuffer(
37185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                    w, h, COPYBIT_FORMAT_RGB_565,
37285ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                    GraphicBuffer::USAGE_HW_2D);
37385ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian
37485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        err = tempCb->initCheck();
37585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian
37685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        copybit_image_t tmpCbImg;
37785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        copybit_rect_t tmpCbRect;
378d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        copybit_rect_t tmpdrect = drect;
37985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbImg.w = w;
38085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbImg.h = h;
38185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbImg.format = tempCb->format;
38285ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle;
38385ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbRect.l = 0;
38485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        tmpCbRect.t = 0;
385d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian
386d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        if (drect.l < 0) {
387d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpCbRect.l = -tmpdrect.l;
388d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpdrect.l = 0;
389d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        }
390d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        if (drect.t < 0) {
391d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpCbRect.t = -tmpdrect.t;
392d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpdrect.t = 0;
393d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        }
394d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        if (drect.l + tmpCbImg.w > dst.w) {
395d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpCbImg.w = dst.w - drect.l;
396d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpdrect.r = dst.w;
397d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        }
398d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        if (drect.t + tmpCbImg.h > dst.h) {
399d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpCbImg.h = dst.h - drect.t;
400d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian            tmpdrect.b = dst.h;
401d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        }
402d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian
403d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        tmpCbRect.r = tmpCbImg.w;
404d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian        tmpCbRect.b = tmpCbImg.h;
40585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian
40685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        if (!err) {
40785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            // first make a copy of the destination buffer
40885ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            region_iterator tmp_it(Region(Rect(w, h)));
40985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
41085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
41185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
41285ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            err = copybit->stretch(copybit,
413d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian                    &tmpCbImg, &dst, &tmpCbRect, &tmpdrect, &tmp_it);
41485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        }
41585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        if (!err) {
41685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            // then proceed as usual, but without the alpha plane
41785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
41885ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
41985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_DITHER,
42085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                    (enables & GGL_ENABLE_DITHER) ?
42185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                            COPYBIT_ENABLE : COPYBIT_DISABLE);
42285ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            clipRectRegion it(c);
42385ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
42485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        }
42585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        if (!err) {
42685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            // finally copy back the destination on top with 1-alphaplane
42785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a);
42885ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            clipRectRegion it(c);
42985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
43085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha);
43185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
43285ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian            err = copybit->stretch(copybit,
433d09376d1e2bce635adfb9e4c5439b6ae0991cf92Mathias Agopian                    &dst, &tmpCbImg, &tmpdrect, &tmpCbRect, &it);
43485ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        }
43585ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    } else {
43685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
43785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
43885ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        copybit->set_parameter(copybit, COPYBIT_DITHER,
43985ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                (enables & GGL_ENABLE_DITHER) ?
44085ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian                        COPYBIT_ENABLE : COPYBIT_DISABLE);
44185ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        clipRectRegion it(c);
442f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian
4438c0eb9a6eb5bec699630aeeb1603e5449c45d8e1Iliyan Malchev        LOGD_IF(0,
4448c0eb9a6eb5bec699630aeeb1603e5449c45d8e1Iliyan Malchev             "dst={%d, %d, %d, %p, %p}, "
445f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             "src={%d, %d, %d, %p, %p}, "
446f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             "drect={%d,%d,%d,%d}, "
447f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             "srect={%d,%d,%d,%d}, "
448f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             "it={%d,%d,%d,%d}, " ,
449f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             dst.w, dst.h, dst.format, dst.base, dst.handle,
450f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             src.w, src.h, src.format, src.base, src.handle,
451f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             drect.l, drect.t, drect.r, drect.b,
452f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             srect.l, srect.t, srect.r, srect.b,
453f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian             it.r.l, it.r.t, it.r.r, it.r.b
454f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian        );
455f007a2faa1d765e9b53553a8214179b253e3cbbdMathias Agopian
45685ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
45785ade33edcc7d9be462ad7b8455d27f6654aca5eMathias Agopian    }
458a2fb72e08f41a67bbed534eb1035ba5bfc2df0e1Mathias Agopian    if (err != NO_ERROR) {
459a2fb72e08f41a67bbed534eb1035ba5bfc2df0e1Mathias Agopian        c->textures.tmu[0].texture->try_copybit = false;
460a2fb72e08f41a67bbed534eb1035ba5bfc2df0e1Mathias Agopian    }
4610f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    return err == NO_ERROR ? true : false;
4621473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
4631473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
4641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/*
4651473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Try to draw a triangle fan with copybit, return false if we fail.
4661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
46703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopianbool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count)
46803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian{
46903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (!checkContext(c)) {
4701473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
4711473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
4721473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
47309cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    // FIXME: we should handle culling  here
4741473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
4751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
47603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // we detect if we're dealing with a rectangle, by comparing the
47703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // rectangles {v0,v2} and {v1,v3} which should be identical.
47803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
47942bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // NOTE: we should check that the rectangle is window aligned, however
48042bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // if we do that, the optimization won't be taken in a lot of cases.
48142bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // Since this code is intended to be used with SurfaceFlinger only,
48242bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // so it's okay...
48342bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
48403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v0 = c->vc.vBuffer[0].window;
48503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v1 = c->vc.vBuffer[1].window;
48603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v2 = c->vc.vBuffer[2].window;
48703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v3 = c->vc.vBuffer[3].window;
48803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int l = min(v0.x, v2.x);
48903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int b = min(v0.y, v2.y);
49003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int r = max(v0.x, v2.x);
49103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int t = max(v0.y, v2.y);
49203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) ||
49303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) {
49403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle");
49503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        return false;
4961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
49709cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian
49809cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    // fetch and transform texture coordinates
49909cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    // NOTE: maybe it would be better to have a "compileElementsAll" method
50009cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    // that would ensure all vertex data are fetched and transformed
50109cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    const transform_t& tr = c->transforms.texture[0].transform;
50209cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    for (size_t i=0 ; i<4 ; i++) {
50309cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        const GLubyte* tp = c->arrays.texture[0].element(i);
50409cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        vertex_t* const v = &c->vc.vBuffer[i];
50509cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        c->arrays.texture[0].fetch(c, v->texture[0].v, tp);
50609cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        // FIXME: we should bail if q!=1
50709cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        c->arrays.tex_transform[0](&tr, &v->texture[0], &v->texture[0]);
50809cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian    }
50903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
51003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t0 = c->vc.vBuffer[0].texture[0];
51103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t1 = c->vc.vBuffer[1].texture[0];
51203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t2 = c->vc.vBuffer[2].texture[0];
51303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t3 = c->vc.vBuffer[3].texture[0];
51403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txl = min(t0.x, t2.x);
51503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txb = min(t0.y, t2.y);
51603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txr = max(t0.x, t2.x);
51703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txt = max(t0.y, t2.y);
51803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) ||
51903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) {
52003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle");
5211473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
5221473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
52303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((txl != 0) || (txb != 0) ||
52403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (txr != FIXED_ONE) || (txt != FIXED_ONE)) {
52503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // we could probably handle this case, if we wanted to
52609cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texture is cropped: %08x,%08x,%08x,%08x",
52709cf0ac2e9ec9e18c7099312265f9d51cdbb0f37Mathias Agopian                txl, txb, txr, txt);
5281473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
5291473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
5301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
53103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // at this point, we know we are dealing with a rectangle, so we
53203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // only need to consider 3 vertices for computing the jacobians
53303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
53403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dx01 = v1.x - v0.x;
53503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dx02 = v2.x - v0.x;
5360f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    const int dy01 = v1.y - v0.y;
53703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dy02 = v2.y - v0.y;
53803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int ds01 = t1.S - t0.S;
53903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int ds02 = t2.S - t0.S;
5400f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian    const int dt01 = t1.T - t0.T;
54103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dt02 = t2.T - t0.T;
54203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int area = dx01*dy02 - dy01*dx02;
54303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int dsdx, dsdy, dtdx, dtdy;
54403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (area >= 0) {
54503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdx = ds01*dy02 - ds02*dy01;
54603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdx = dt01*dy02 - dt02*dy01;
5470f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        dsdy = ds02*dx01 - ds01*dx02;
54803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdy = dt02*dx01 - dt01*dx02;
54903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    } else {
55003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdx = ds02*dy01 - ds01*dy02;
55103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdx = dt02*dy01 - dt01*dy02;
5520f53af13b783eafa566722eb118aabcb84d88da5Mathias Agopian        dsdy = ds01*dx02 - ds02*dx01;
55303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdy = dt01*dx02 - dt02*dx01;
55403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    }
5551473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
55603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // here we rely on the fact that we know the transform is
55703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // a rigid-body transform AND that it can only rotate in 90 degrees
55803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // increments
55903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
56003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int transform = 0;
56103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (dsdx == 0) {
56203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // 90 deg rotation case
56303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ 0    dtdx  ]
56403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ dsdx    0  ]
56503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        transform |= COPYBIT_TRANSFORM_ROT_90;
56603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted
56703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dtdx > 0)
56803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_H;
56903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dsdy < 0)
57003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_V;
57103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    } else {
57203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ dsdx    0  ]
57303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ 0     dtdy ]
57403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dsdx < 0)
57503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_H;
57603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dtdy < 0)
57703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_V;
5781473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
5791473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
58003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform);
58103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //LOGD("A=%f\tB=%f\nC=%f\tD=%f",
58203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //      dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0);
5831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
58403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int x = l >> 4;
58503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int y = b >> 4;
58603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int w = (r-l) >> 4;
58703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int h = (t-b) >> 4;
58803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    texture_unit_t& u(c->textures.tmu[0]);
58903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    EGLTextureObject* textureObject = u.texture;
5901473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint tWidth = textureObject->surface.width;
5911473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint tHeight = textureObject->surface.height;
5921473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
5931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
5941473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    y = cbSurface.height - (y + h);
59503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    return copybit(x, y, w, h, textureObject, crop_rect, transform, c);
5961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
5971473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
5981473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/*
5991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Try to drawTexiOESWithCopybit, return false if we fail.
6001473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
6011473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
6021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianbool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
6031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        GLint w, GLint h, ogles_context_t* c)
6041473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian{
6051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // quickly process empty rects
6061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if ((w|h) <= 0) {
6071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
6081473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
60903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (!checkContext(c)) {
6101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
6111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
61203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    texture_unit_t& u(c->textures.tmu[0]);
6131473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    EGLTextureObject* textureObject = u.texture;
61403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c);
6151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
6161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
6171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian} // namespace android
6181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
619