copybit.cpp revision 42bf621e801183028066e6947fdd22eae8693a02
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#include "gralloc_priv.h"
361473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
3703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
3803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian#define DEBUG_COPYBIT true
3903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
401473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian// ----------------------------------------------------------------------------
411473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
421473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopiannamespace android {
431473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
44350d651706d8f484d9aeb539d491526f822fa84aMathias Agopianstatic void textureToCopyBitImage(
45350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian        const GGLSurface* surface, buffer_handle_t buffer, copybit_image_t* img)
46350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian{
47350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    // we know private_handle_t is good here
48350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    private_handle_t* hnd = (private_handle_t*)buffer;
491473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->w      = surface->stride;
501473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->h      = surface->height;
511473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->format = surface->format;
52350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    img->offset = hnd->offset;
531473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    img->base   = surface->data;
54350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    img->fd     = hnd->fd;
551473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
561473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
571473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstruct clipRectRegion : public copybit_region_t {
584d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    clipRectRegion(ogles_context_t* c)
594d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    {
604d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        scissor_t const* scissor = &c->rasterizer.state.scissor;
614d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.l = scissor->left;
624d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.t = scissor->top;
634d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.r = scissor->right;
644d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        r.b = scissor->bottom;
654d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        next = iterate;
661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
671473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianprivate:
681473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
694d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        *rect = static_cast<clipRectRegion const*>(self)->r;
704d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        const_cast<copybit_region_t *>(self)->next = iterate_done;
714d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian        return 1;
724d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    }
734d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
741473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return 0;
751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
764d63fb113b542f0474c16d8f2c8a1240b44f0ca2Mathias Agopian    copybit_rect_t r;
771473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian};
781473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
791473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool supportedCopybitsFormat(int format) {
801473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    switch (format) {
811473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_8888:
821473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGB_565:
831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_BGRA_8888:
841473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_5551:
851473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_4444:
861473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_YCbCr_422_SP:
871473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_YCbCr_420_SP:
881473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
891473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    default:
901473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
911473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
921473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
941473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool hasAlpha(int format) {
951473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    switch (format) {
961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_8888:
971473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_BGRA_8888:
981473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_5551:
991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case COPYBIT_FORMAT_RGBA_4444:
1001473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
1011473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    default:
1021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1041473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic inline int fixedToByte(GGLfixed val) {
1071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    return (val - (val >> 8)) >> 8;
1081473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1091473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/**
1111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Performs a quick check of the rendering state. If this function returns
1121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * false we cannot use the copybit driver.
1131473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
1141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool checkContext(ogles_context_t* c) {
1161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
117350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian	// By convention copybitQuickCheckContext() has already returned true.
1181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian	// avoid checking the same information again.
1191473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
12003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (c->copybits.blitEngine == NULL) {
12103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "no copybit hal");
12203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        return false;
12303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    }
12403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
12503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (c->rasterizer.state.enables
12603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
12703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog");
1281473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1291473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
131350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    // Note: The drawSurfaceBuffer is only set for destination
1321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // surfaces types that are supported by the hardware and
1331473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // do not have an alpha channel. So we don't have to re-check that here.
1341473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1351473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static const int tmu = 0;
1361473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    texture_unit_t& u(c->textures.tmu[tmu]);
1371473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    EGLTextureObject* textureObject = u.texture;
1381473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1391473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (!supportedCopybitsFormat(textureObject->surface.format)) {
14003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texture format not supported");
1411473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1421473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1431473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    return true;
1441473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
1451473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1461473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1471473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianstatic bool copybit(GLint x, GLint y,
1481473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        GLint w, GLint h,
1491473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        EGLTextureObject* textureObject,
1501473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        const GLint* crop_rect,
1511473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        int transform,
1521473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        ogles_context_t* c)
1531473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian{
1541473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // We assume checkContext has already been called and has already
1551473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // returned true.
1561473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1571473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
1581473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1591473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    y = cbSurface.height - (y + h);
1601473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1611473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Ucr = crop_rect[0];
1621473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Vcr = crop_rect[1];
1631473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Wcr = crop_rect[2];
1641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GLint Hcr = crop_rect[3];
1651473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int32_t dsdx = (Wcr << 16) / w;   // dsdx =  ((Wcr/w)/Wt)*Wt
1671473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int32_t dtdy = ((-Hcr) <<  16) / h;   // dtdy = -((Hcr/h)/Ht)*Ht
1681473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
1691473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
1701473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
1711473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // The requested scale is out of the range the hardware
1721473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // can support.
17303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT,
17403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian                "scale out of range dsdx=%08x, dtdy=%08x", dsdx, dtdy);
1751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1761473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1771473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
17842bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // copybit doesn't say anything about filtering, so we can't
17942bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // discriminate. On msm7k, copybit will always filter.
18042bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // the code below handles min/mag filters, we keep it as a reference.
18142bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
18242bf621e801183028066e6947fdd22eae8693a02Mathias Agopian#ifdef MIN_MAG_FILTER
1831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int32_t texelArea = gglMulx(dtdy, dsdx);
1841473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
1851473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Non-linear filtering on a texture enlargement.
18603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR");
1871473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1881473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
1891473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
1901473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Non-linear filtering on an texture shrink.
19103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR");
1921473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
1931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
19442bf621e801183028066e6947fdd22eae8693a02Mathias Agopian#endif
19542bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
1961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const uint32_t enables = c->rasterizer.state.enables;
1971473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    int planeAlpha = 255;
1981473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    static const int tmu = 0;
1991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    texture_t& tev(c->rasterizer.state.texture[tmu]);
2001473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
2011473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    switch (tev.env) {
2021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case GGL_REPLACE:
2041473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        if (!srcTextureHasAlpha) {
2051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            planeAlpha = fixedToByte(c->currentColorClamped.a);
2061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        break;
2081473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2091473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    case GGL_MODULATE:
2101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        if (! (c->currentColorClamped.r == FIXED_ONE
2111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->currentColorClamped.g == FIXED_ONE
2121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->currentColorClamped.b == FIXED_ONE)) {
21303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            LOGD_IF(DEBUG_COPYBIT, "MODULATE and non white color");
2141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            return false;
2151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        planeAlpha = fixedToByte(c->currentColorClamped.a);
2171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        break;
2181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2191473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    default:
2201473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Incompatible texture environment.
22103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
2221473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
2231473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2241473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2251473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    bool blending = false;
2261473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2271473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if ((enables & GGL_ENABLE_BLENDING)
2281473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            && !(c->rasterizer.state.blend.src == GL_ONE
2291473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                    && c->rasterizer.state.blend.dst == GL_ZERO)) {
2301473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Blending is OK if it is
2311473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // the exact kind of blending that the copybits hardware supports.
2321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Note: The hardware only supports
2331473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
2341473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
2351473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
2361473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // because the performance is worth it, even if the results are
2371473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // not correct.
2381473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
2391473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                || c->rasterizer.state.blend.src == GL_ONE)
2401473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
2411473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian                && c->rasterizer.state.blend.alpha_separate == 0)) {
2421473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            // Incompatible blend mode.
24303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode");
2441473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            return false;
2451473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2461473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        blending = true;
2471473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    } else {
2481473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // No blending is OK if we are not using alpha.
2491473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        if (srcTextureHasAlpha || planeAlpha != 255) {
2501473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            // Incompatible alpha
25103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            LOGD_IF(DEBUG_COPYBIT, "incompatible alpha");
2521473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            return false;
2531473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        }
2541473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2551473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2561473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if (srcTextureHasAlpha && planeAlpha != 255) {
2571473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        // Can't do two types of alpha at once.
25803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "src alpha and plane alpha");
2591473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
2601473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2611473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2621473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // LOGW("calling copybits");
2631473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_device_t* copybit = c->copybits.blitEngine;
265350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian
2661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_image_t dst;
267350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
268350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    textureToCopyBitImage(&cbSurface, target_hnd, &dst);
2691473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_rect_t drect = {x, y, x+w, y+h};
2701473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
271350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    // we know private_handle_t is good here
2721473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_image_t src;
273350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    buffer_handle_t source_hnd = textureObject->buffer->handle;
274350d651706d8f484d9aeb539d491526f822fa84aMathias Agopian    textureToCopyBitImage(&textureObject->surface, source_hnd, &src);
2751473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
2761473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2771473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
2781473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
2791473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit->set_parameter(copybit, COPYBIT_DITHER,
2801473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian            (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
2811473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2821473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    clipRectRegion it(c);
2831473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
2841473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    return true;
2851473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
2861473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2871473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/*
2881473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Try to draw a triangle fan with copybit, return false if we fail.
2891473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
29003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopianbool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count)
29103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian{
29203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (!checkContext(c)) {
2931473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
2941473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
2951473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
2961473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
2971473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
29803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // we detect if we're dealing with a rectangle, by comparing the
29903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // rectangles {v0,v2} and {v1,v3} which should be identical.
30003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
30142bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // NOTE: we should check that the rectangle is window aligned, however
30242bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // if we do that, the optimization won't be taken in a lot of cases.
30342bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // Since this code is intended to be used with SurfaceFlinger only,
30442bf621e801183028066e6947fdd22eae8693a02Mathias Agopian    // so it's okay...
30542bf621e801183028066e6947fdd22eae8693a02Mathias Agopian
30603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v0 = c->vc.vBuffer[0].window;
30703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v1 = c->vc.vBuffer[1].window;
30803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v2 = c->vc.vBuffer[2].window;
30903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& v3 = c->vc.vBuffer[3].window;
31003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int l = min(v0.x, v2.x);
31103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int b = min(v0.y, v2.y);
31203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int r = max(v0.x, v2.x);
31303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int t = max(v0.y, v2.y);
31403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) ||
31503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) {
31603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle");
31703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        return false;
3181473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
31903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
32003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t0 = c->vc.vBuffer[0].texture[0];
32103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t1 = c->vc.vBuffer[1].texture[0];
32203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t2 = c->vc.vBuffer[2].texture[0];
32303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const vec4_t& t3 = c->vc.vBuffer[3].texture[0];
32403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txl = min(t0.x, t2.x);
32503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txb = min(t0.y, t2.y);
32603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txr = max(t0.x, t2.x);
32703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int txt = max(t0.y, t2.y);
32803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) ||
32903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) {
33003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle");
3311473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
3321473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
33303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if ((txl != 0) || (txb != 0) ||
33403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        (txr != FIXED_ONE) || (txt != FIXED_ONE)) {
33503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // we could probably handle this case, if we wanted to
33603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        LOGD_IF(DEBUG_COPYBIT, "texture is cropped");
3371473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
3381473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
3391473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
34003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // at this point, we know we are dealing with a rectangle, so we
34103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // only need to consider 3 vertices for computing the jacobians
34203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
34303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dx01 = v1.x - v0.x;
34403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dy01 = v1.y - v0.y;
34503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dx02 = v2.x - v0.x;
34603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dy02 = v2.y - v0.y;
34703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int ds01 = t1.S - t0.S;
34803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dt01 = t1.T - t0.T;
34903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int ds02 = t2.S - t0.S;
35003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int dt02 = t2.T - t0.T;
35103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    const int area = dx01*dy02 - dy01*dx02;
35203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int dsdx, dsdy, dtdx, dtdy;
35303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (area >= 0) {
35403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdx = ds01*dy02 - ds02*dy01;
35503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdy = ds02*dx01 - ds01*dx02;
35603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdx = dt01*dy02 - dt02*dy01;
35703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdy = dt02*dx01 - dt01*dx02;
35803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    } else {
35903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdx = ds02*dy01 - ds01*dy02;
36003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dsdy = ds01*dx02 - ds02*dx01;
36103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdx = dt02*dy01 - dt01*dy02;
36203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        dtdy = dt01*dx02 - dt02*dx01;
36303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    }
3641473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
36503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // here we rely on the fact that we know the transform is
36603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // a rigid-body transform AND that it can only rotate in 90 degrees
36703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    // increments
36803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian
36903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int transform = 0;
37003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (dsdx == 0) {
37103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // 90 deg rotation case
37203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ 0    dtdx  ]
37303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ dsdx    0  ]
37403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        transform |= COPYBIT_TRANSFORM_ROT_90;
37503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted
37603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dtdx > 0)
37703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_H;
37803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dsdy < 0)
37903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_V;
38003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    } else {
38103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ dsdx    0  ]
38203a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        // [ 0     dtdy ]
38303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dsdx < 0)
38403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_H;
38503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian        if (dtdy < 0)
38603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian            transform |= COPYBIT_TRANSFORM_FLIP_V;
3871473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
3881473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
38903a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform);
39003a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //LOGD("A=%f\tB=%f\nC=%f\tD=%f",
39103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    //      dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0);
3921473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
39303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int x = l >> 4;
39403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int y = b >> 4;
39503a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int w = (r-l) >> 4;
39603a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    int h = (t-b) >> 4;
39703a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    texture_unit_t& u(c->textures.tmu[0]);
39803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    EGLTextureObject* textureObject = u.texture;
3991473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint tWidth = textureObject->surface.width;
4001473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint tHeight = textureObject->surface.height;
4011473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
4021473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
4031473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    y = cbSurface.height - (y + h);
40403a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    return copybit(x, y, w, h, textureObject, crop_rect, transform, c);
4051473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
4061473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
4071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian/*
4081473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian * Try to drawTexiOESWithCopybit, return false if we fail.
4091473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian */
4101473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
4111473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopianbool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
4121473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        GLint w, GLint h, ogles_context_t* c)
4131473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian{
4141473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    // quickly process empty rects
4151473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    if ((w|h) <= 0) {
4161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return true;
4171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
41803a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    if (!checkContext(c)) {
4191473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian        return false;
4201473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    }
42103a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    texture_unit_t& u(c->textures.tmu[0]);
4221473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    EGLTextureObject* textureObject = u.texture;
42303a1b0116b115c214c16fa1a02a46999312fd0f2Mathias Agopian    return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c);
4241473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian}
4251473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
4261473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian} // namespace android
4271473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian
428