1fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy/*
2fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * Copyright (C) 2010 The Android Open Source Project
3fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy *
4fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * you may not use this file except in compliance with the License.
6fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * You may obtain a copy of the License at
7fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy *
8fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy *
10fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * Unless required by applicable law or agreed to in writing, software
11fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * See the License for the specific language governing permissions and
14fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy * limitations under the License.
15fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy */
16fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
17fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy#define LOG_TAG "OpenGLRenderer"
18fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
196820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy#include <cmath>
20fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
214bb942083a0d4db746adf95349108dd8ef842e32Romain Guy#include <utils/Log.h>
224bb942083a0d4db746adf95349108dd8ef842e32Romain Guy
2303750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy#include "Caches.h"
243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "Patch.h"
25a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy#include "Properties.h"
263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "UvMapper.h"
27fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
28fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guynamespace android {
29fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guynamespace uirenderer {
30fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
31fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
32fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy// Constructors/destructor
33fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
34fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
3503c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain GuyPatch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) {
36fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
37fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
38fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain GuyPatch::~Patch() {
396056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    delete[] vertices;
40fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
41fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
42fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Vertices management
446f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy///////////////////////////////////////////////////////////////////////////////
456f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyuint32_t Patch::getSize() const {
473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    return verticesCount * sizeof(TextureVertex);
486f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy}
496f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain GuyTextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
5103c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        float width, float height, const Res_png_9patch* patch) {
523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    UvMapper mapper;
5303c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy    return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch);
546f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy}
556f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain GuyTextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
5703c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) {
5803c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy    if (vertices) return vertices;
595341cead27070656458750a789ba211a505b57b5Romain Guy
603b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    int8_t emptyQuads = 0;
616381dd4ff212a95be30d2b445d40ff419ab076b4Narayan Kamath    mColors = patch->getColors();
623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
636cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy    const int8_t numColors = patch->numColors;
643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        for (int8_t i = 0; i < numColors; i++) {
666cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy            if (mColors[i] == 0x0) {
673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy                emptyQuads++;
683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            }
693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        }
706f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy    }
716f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    hasEmptyQuads = emptyQuads > 0;
736f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t xCount = patch->numXDivs;
753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t yCount = patch->numYDivs;
766f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy
773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    if (maxVertices == 0) return NULL;
79fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
80f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    TextureVertex* tempVertices = new TextureVertex[maxVertices];
81f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    TextureVertex* vertex = tempVertices;
82a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy
836381dd4ff212a95be30d2b445d40ff419ab076b4Narayan Kamath    const int32_t* xDivs = patch->getXDivs();
846381dd4ff212a95be30d2b445d40ff419ab076b4Narayan Kamath    const int32_t* yDivs = patch->getYDivs();
855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    const uint32_t xStretchCount = (xCount + 1) >> 1;
873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    const uint32_t yStretchCount = (yCount + 1) >> 1;
88fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
896820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float stretchX = 0.0f;
9041d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy    float stretchY = 0.0f;
9141d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy
9241d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy    float rescaleX = 1.0f;
9341d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy    float rescaleY = 1.0f;
94fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
95fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (xStretchCount > 0) {
96fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        for (uint32_t i = 1; i < xCount; i += 2) {
983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            stretchSize += xDivs[i] - xDivs[i - 1];
99fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
1006820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float xStretchTex = stretchSize;
101fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapWidth - stretchSize;
10203c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        const float xStretch = fmaxf(width - fixed, 0.0f);
1036820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        stretchX = xStretch / xStretchTex;
10403c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f);
105fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
106fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
107fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (yStretchCount > 0) {
108fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        for (uint32_t i = 1; i < yCount; i += 2) {
1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            stretchSize += yDivs[i] - yDivs[i - 1];
111fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
1126820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float yStretchTex = stretchSize;
113fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapHeight - stretchSize;
11403c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        const float yStretch = fmaxf(height - fixed, 0.0f);
1156820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        stretchY = yStretch / yStretchTex;
11603c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f);
117fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
118fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1194bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    uint32_t quadCount = 0;
120fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1216820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float previousStepY = 0.0f;
122fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1236820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float y1 = 0.0f;
124f504a2fa144504ca1efd39a4ef9208e3d4d336c5Romain Guy    float y2 = 0.0f;
1256820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float v1 = 0.0f;
1266820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    mUvMapper = mapper;
1283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    for (uint32_t i = 0; i < yCount; i++) {
1303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        float stepY = yDivs[i];
1315e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        const float segment = stepY - previousStepY;
1326820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1336820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        if (i & 1) {
1348ab4079ca27e36e5c584495bcd71b573598ac021Romain Guy            y2 = y1 + floorf(segment * stretchY + 0.5f);
135fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
13641d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy            y2 = y1 + segment * rescaleY;
137fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
1385e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy
1395e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        float vOffset = y1 == y2 ? 0.0f : 0.5 - (0.5 * segment / (y2 - y1));
1405e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        float v2 = fmax(0.0f, stepY - vOffset) / bitmapHeight;
1415e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        v1 += vOffset / bitmapHeight;
1426820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
143eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy        if (stepY > 0.0f) {
1443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX,
14503c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                    width, bitmapWidth, quadCount);
146eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy        }
1476820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1486820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        y1 = y2;
1495e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        v1 = stepY / bitmapHeight;
1506820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1516820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        previousStepY = stepY;
152fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
153fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
154fdbec3e4828f93bfa5cde758ad0e77b89c5c2ecdRomain Guy    if (previousStepY != bitmapHeight) {
15503c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy        y2 = height;
1563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX,
15703c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                width, bitmapWidth, quadCount);
1586f72bebe92a4db7b5dc83f4ac5b5fd02e3b4e2cdRomain Guy    }
159a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy
160f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    if (verticesCount == maxVertices) {
161f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        vertices = tempVertices;
162f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    } else {
163f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        vertices = new TextureVertex[verticesCount];
164f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        memcpy(vertices, tempVertices, verticesCount * sizeof(TextureVertex));
165f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        delete[] tempVertices;
166f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    }
167f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy
1683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    return vertices;
169fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
170fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
1723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        float y1, float y2, float v1, float v2, float stretchX, float rescaleX,
1733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        float width, float bitmapWidth, uint32_t& quadCount) {
1746820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float previousStepX = 0.0f;
1756820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1766820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float x1 = 0.0f;
177f504a2fa144504ca1efd39a4ef9208e3d4d336c5Romain Guy    float x2 = 0.0f;
1786820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float u1 = 0.0f;
179fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1806820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    // Generate the row quad by quad
1813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    for (uint32_t i = 0; i < xCount; i++) {
1823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        float stepX = xDivs[i];
1835e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        const float segment = stepX - previousStepX;
184fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1856820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        if (i & 1) {
1868ab4079ca27e36e5c584495bcd71b573598ac021Romain Guy            x2 = x1 + floorf(segment * stretchX + 0.5f);
187fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
18841d35aef06c2a570a45474a01ca95a6cb9c29d9eRomain Guy            x2 = x1 + segment * rescaleX;
189fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
1905e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy
1915e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        float uOffset = x1 == x2 ? 0.0f : 0.5 - (0.5 * segment / (x2 - x1));
1925e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        float u2 = fmax(0.0f, stepX - uOffset) / bitmapWidth;
1935e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        u1 += uOffset / bitmapWidth;
194fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
195eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy        if (stepX > 0.0f) {
196eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy            generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
197eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy        }
1986820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1996820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        x1 = x2;
2005e7c469c7a3039af7696789a797f8d91a45227ebRomain Guy        u1 = stepX / bitmapWidth;
2016820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
2026820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        previousStepX = stepX;
203fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
204fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
205fdbec3e4828f93bfa5cde758ad0e77b89c5c2ecdRomain Guy    if (previousStepX != bitmapWidth) {
206f504a2fa144504ca1efd39a4ef9208e3d4d336c5Romain Guy        x2 = width;
207f504a2fa144504ca1efd39a4ef9208e3d4d336c5Romain Guy        generateQuad(vertex, x1, y1, x2, y2, u1, v1, 1.0f, v2, quadCount);
208fdbec3e4828f93bfa5cde758ad0e77b89c5c2ecdRomain Guy    }
209fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
210fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
2117444da512680df0c52af39ea521e35adbe0c167dRomain Guyvoid Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
212eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy            float u1, float v1, float u2, float v2, uint32_t& quadCount) {
213a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy    const uint32_t oldQuadCount = quadCount;
214eb6a4a17a07f1aa41bd58d418b2982cddb97685aRomain Guy    quadCount++;
215bd41a11078e94b755c8b6f78e1e4242c715fccd4Romain Guy
21670561df470c31513056df181571632851fd0d081Romain Guy    if (x1 < 0.0f) x1 = 0.0f;
21770561df470c31513056df181571632851fd0d081Romain Guy    if (x2 < 0.0f) x2 = 0.0f;
21870561df470c31513056df181571632851fd0d081Romain Guy    if (y1 < 0.0f) y1 = 0.0f;
21970561df470c31513056df181571632851fd0d081Romain Guy    if (y2 < 0.0f) y2 = 0.0f;
22070561df470c31513056df181571632851fd0d081Romain Guy
221a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy    // Skip degenerate and transparent (empty) quads
2226cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy    if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
223fb13abd800cd610c7f46815848545feff83e5748Romain Guy#if DEBUG_PATCHES_EMPTY_VERTICES
224fb13abd800cd610c7f46815848545feff83e5748Romain Guy        PATCH_LOGD("    quad %d (empty)", oldQuadCount);
2256cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy        PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
2266cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy        PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
227fb13abd800cd610c7f46815848545feff83e5748Romain Guy#endif
2287444da512680df0c52af39ea521e35adbe0c167dRomain Guy        return;
2294bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    }
2304bb942083a0d4db746adf95349108dd8ef842e32Romain Guy
231a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy    // Record all non empty quads
2325b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    if (hasEmptyQuads) {
2335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        Rect bounds(x1, y1, x2, y2);
2345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        quads.add(bounds);
2355b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    }
2365b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
2373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    mUvMapper.map(u1, v1, u2, v2);
2383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
2396820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x1, y1, u1, v1);
2406820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x2, y1, u2, v1);
2416820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x1, y2, u1, v2);
2426820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x2, y2, u2, v2);
243a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy
2443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    verticesCount += 4;
2453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    indexCount += 6;
246a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy
247a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy#if DEBUG_PATCHES_VERTICES
248a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy    PATCH_LOGD("    quad %d", oldQuadCount);
2496cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy    PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
2506cad75744ed3b81cf2c96f545368067b62c726ecRomain Guy    PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
251a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy#endif
252fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
253fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
254fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace uirenderer
255fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace android
256