Patch.cpp revision 4bb942083a0d4db746adf95349108dd8ef842e32
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
23fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy#include "Patch.h"
24fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
25fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guynamespace android {
26fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guynamespace uirenderer {
27fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
28fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
29fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy// Constructors/destructor
30fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
31fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
324bb942083a0d4db746adf95349108dd8ef842e32Romain GuyPatch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads) {
33fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    // 2 triangles per patch, 3 vertices per triangle
344bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
356820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    vertices = new TextureVertex[verticesCount];
36fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
37fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
38fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain GuyPatch::~Patch() {
3931529ff7918ce891fba9a660d0a861eb313ea554Romain Guy    delete[] vertices;
40fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
41fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
42fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
43fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy// Vertices management
44fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
45fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
46759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
47759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        float left, float top, float right, float bottom,
484bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        const int32_t* xDivs, const int32_t* yDivs,
494bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        const uint32_t width, const uint32_t height, const uint32_t colorKey) {
50fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t xStretchCount = (width + 1) >> 1;
51fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t yStretchCount = (height + 1) >> 1;
52fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
536820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float stretchX = 0.0f;
546820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float stretchY = 0.0;
55fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
56fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const float meshWidth = right - left;
57fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
58fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (xStretchCount > 0) {
59fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
60fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t i = 1; i < width; i += 2) {
61fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            stretchSize += xDivs[i] - xDivs[i - 1];
62fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
636820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float xStretchTex = stretchSize;
64fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapWidth - stretchSize;
656820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float xStretch = right - left - fixed;
666820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        stretchX = xStretch / xStretchTex;
67fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
68fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
69fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (yStretchCount > 0) {
70fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
71fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t i = 1; i < height; i += 2) {
72fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            stretchSize += yDivs[i] - yDivs[i - 1];
73fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
746820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float yStretchTex = stretchSize;
75fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapHeight - stretchSize;
766820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        const float yStretch = bottom - top - fixed;
776820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        stretchY = yStretch / yStretchTex;
78fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
79fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
80fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    TextureVertex* vertex = vertices;
814bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    uint32_t quadCount = 0;
82fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
836820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float previousStepY = 0.0f;
84fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
856820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float y1 = 0.0f;
866820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float v1 = 0.0f;
876820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
886820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    for (uint32_t i = 0; i < height; i++) {
896820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float stepY = yDivs[i];
906820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
916820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float y2 = 0.0f;
926820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        if (i & 1) {
936820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            const float segment = stepY - previousStepY;
946820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            y2 = y1 + segment * stretchY;
95fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
966820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            y2 = y1 + stepY - previousStepY;
97fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
986820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;
996820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1006820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        generateRow(vertex, y1, y2, v1, v2, xDivs, width, stretchX,
1014bb942083a0d4db746adf95349108dd8ef842e32Romain Guy                right - left, bitmapWidth, quadCount, colorKey);
1026820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1036820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        y1 = y2;
1046820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        v1 = (stepY + 0.5f) / bitmapHeight;
1056820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1066820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        previousStepY = stepY;
107fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
108fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1096820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    generateRow(vertex, y1, bottom - top, v1, 1.0f, xDivs, width, stretchX,
1104bb942083a0d4db746adf95349108dd8ef842e32Romain Guy            right - left, bitmapWidth, quadCount, colorKey);
111fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
112fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1136820ac8b14b4558f5d8b833dde80895306a3e137Romain Guyinline void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
1144bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        const int32_t xDivs[], uint32_t xCount, float stretchX, float width, float bitmapWidth,
1154bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        uint32_t& quadCount, const uint32_t colorKey) {
1166820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float previousStepX = 0.0f;
1176820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1186820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float x1 = 0.0f;
1196820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    float u1 = 0.0f;
120fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1216820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    // Generate the row quad by quad
1226820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    for (uint32_t i = 0; i < xCount; i++) {
1236820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float stepX = xDivs[i];
124fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1256820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float x2 = 0.0f;
1266820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        if (i & 1) {
1276820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            const float segment = stepX - previousStepX;
1286820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            x2 = x1 + segment * stretchX;
129fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
1306820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy            x2 = x1 + stepX - previousStepX;
131fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
1326820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
133fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1344bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount, colorKey);
1356820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1366820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        x1 = x2;
1376820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        u1 = (stepX + 0.5f) / bitmapWidth;
1386820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1396820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy        previousStepX = stepX;
140fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
141fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1424bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount, colorKey);
143fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
144fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
1456820ac8b14b4558f5d8b833dde80895306a3e137Romain Guyinline void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
1464bb942083a0d4db746adf95349108dd8ef842e32Romain Guy            float u1, float v1, float u2, float v2, uint32_t& quadCount, const uint32_t colorKey) {
1474bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    if (((colorKey >> quadCount++) & 0x1) == 1) {
1484bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        return;
1494bb942083a0d4db746adf95349108dd8ef842e32Romain Guy    }
1504bb942083a0d4db746adf95349108dd8ef842e32Romain Guy
1516820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    // Left triangle
1526820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x1, y1, u1, v1);
1536820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x2, y1, u2, v1);
1546820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x1, y2, u1, v2);
1556820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy
1566820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    // Right triangle
1576820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x1, y2, u1, v2);
1586820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x2, y1, u2, v1);
1596820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy    TextureVertex::set(vertex++, x2, y2, u2, v2);
160fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
161fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
162fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace uirenderer
163fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace android
164