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