blob: 7ca289d87a3e572cf736f637276b76a451b6edd3 [file] [log] [blame]
Romain Guyfb5e23c2010-07-09 13:52:56 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
Romain Guy6820ac82010-09-15 18:11:50 -070019#include <cmath>
Romain Guyfb5e23c2010-07-09 13:52:56 -070020
Romain Guy4bb94202010-10-12 15:59:26 -070021#include <utils/Log.h>
22
Romain Guyfb5e23c2010-07-09 13:52:56 -070023#include "Patch.h"
Romain Guy03750a02010-10-18 14:06:08 -070024#include "Caches.h"
Romain Guyfb5e23c2010-07-09 13:52:56 -070025
26namespace android {
27namespace uirenderer {
28
29///////////////////////////////////////////////////////////////////////////////
30// Constructors/destructor
31///////////////////////////////////////////////////////////////////////////////
32
Romain Guy6f72beb2010-11-30 12:04:14 -080033Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads):
34 mXCount(xCount), mYCount(yCount) {
Romain Guyfb5e23c2010-07-09 13:52:56 -070035 // 2 triangles per patch, 3 vertices per triangle
Romain Guy4bb94202010-10-12 15:59:26 -070036 verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
Romain Guy03750a02010-10-18 14:06:08 -070037 mVertices = new TextureVertex[verticesCount];
Romain Guy5b3b3522010-10-27 18:57:51 -070038 hasEmptyQuads = emptyQuads > 0;
Romain Guy6f72beb2010-11-30 12:04:14 -080039 mUploaded = false;
40
41 mColorKey = 0;
42 mXDivs = new int32_t[mXCount];
43 mYDivs = new int32_t[mYCount];
Romain Guy03750a02010-10-18 14:06:08 -070044
45 glGenBuffers(1, &meshBuffer);
Romain Guyfb5e23c2010-07-09 13:52:56 -070046}
47
48Patch::~Patch() {
Romain Guy03750a02010-10-18 14:06:08 -070049 delete[] mVertices;
Romain Guy6f72beb2010-11-30 12:04:14 -080050 delete[] mXDivs;
51 delete[] mYDivs;
Romain Guy03750a02010-10-18 14:06:08 -070052 glDeleteBuffers(1, &meshBuffer);
Romain Guyfb5e23c2010-07-09 13:52:56 -070053}
54
55///////////////////////////////////////////////////////////////////////////////
Romain Guy6f72beb2010-11-30 12:04:14 -080056// Patch management
57///////////////////////////////////////////////////////////////////////////////
58
59void Patch::copy(const int32_t* xDivs, const int32_t* yDivs) {
60 memcpy(mXDivs, xDivs, mXCount * sizeof(int32_t));
61 memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
62}
63
64void Patch::copy(const int32_t* yDivs) {
65 memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
66}
67
68void Patch::updateColorKey(const uint32_t colorKey) {
69 mColorKey = colorKey;
70}
71
72bool Patch::matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey) {
73 if (mColorKey != colorKey) {
74 updateColorKey(colorKey);
75 copy(xDivs, yDivs);
76 return false;
77 }
78
79 for (uint32_t i = 0; i < mXCount; i++) {
80 if (mXDivs[i] != xDivs[i]) {
81 // The Y divs may or may not match, copy everything
82 copy(xDivs, yDivs);
83 return false;
84 }
85 }
86
87 for (uint32_t i = 0; i < mYCount; i++) {
88 if (mYDivs[i] != yDivs[i]) {
89 // We know all the X divs match, copy only Y divs
90 copy(yDivs);
91 return false;
92 }
93 }
94
95 return true;
96}
97
98///////////////////////////////////////////////////////////////////////////////
Romain Guyfb5e23c2010-07-09 13:52:56 -070099// Vertices management
100///////////////////////////////////////////////////////////////////////////////
101
Romain Guy759ea802010-09-16 20:49:46 -0700102void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
Romain Guy6f72beb2010-11-30 12:04:14 -0800103 float left, float top, float right, float bottom) {
Romain Guy5b3b3522010-10-27 18:57:51 -0700104 if (hasEmptyQuads) quads.clear();
105
Romain Guy6f72beb2010-11-30 12:04:14 -0800106 const uint32_t xStretchCount = (mXCount + 1) >> 1;
107 const uint32_t yStretchCount = (mYCount + 1) >> 1;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700108
Romain Guy6820ac82010-09-15 18:11:50 -0700109 float stretchX = 0.0f;
110 float stretchY = 0.0;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700111
112 const float meshWidth = right - left;
113
Romain Guyfb5e23c2010-07-09 13:52:56 -0700114 if (xStretchCount > 0) {
115 uint32_t stretchSize = 0;
Romain Guy6f72beb2010-11-30 12:04:14 -0800116 for (uint32_t i = 1; i < mXCount; i += 2) {
117 stretchSize += mXDivs[i] - mXDivs[i - 1];
Romain Guyfb5e23c2010-07-09 13:52:56 -0700118 }
Romain Guy6820ac82010-09-15 18:11:50 -0700119 const float xStretchTex = stretchSize;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700120 const float fixed = bitmapWidth - stretchSize;
Romain Guy6820ac82010-09-15 18:11:50 -0700121 const float xStretch = right - left - fixed;
122 stretchX = xStretch / xStretchTex;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700123 }
124
125 if (yStretchCount > 0) {
126 uint32_t stretchSize = 0;
Romain Guy6f72beb2010-11-30 12:04:14 -0800127 for (uint32_t i = 1; i < mYCount; i += 2) {
128 stretchSize += mYDivs[i] - mYDivs[i - 1];
Romain Guyfb5e23c2010-07-09 13:52:56 -0700129 }
Romain Guy6820ac82010-09-15 18:11:50 -0700130 const float yStretchTex = stretchSize;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700131 const float fixed = bitmapHeight - stretchSize;
Romain Guy6820ac82010-09-15 18:11:50 -0700132 const float yStretch = bottom - top - fixed;
133 stretchY = yStretch / yStretchTex;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700134 }
135
Romain Guy03750a02010-10-18 14:06:08 -0700136 TextureVertex* vertex = mVertices;
Romain Guy4bb94202010-10-12 15:59:26 -0700137 uint32_t quadCount = 0;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700138
Romain Guy6820ac82010-09-15 18:11:50 -0700139 float previousStepY = 0.0f;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700140
Romain Guy6820ac82010-09-15 18:11:50 -0700141 float y1 = 0.0f;
142 float v1 = 0.0f;
143
Romain Guy6f72beb2010-11-30 12:04:14 -0800144 for (uint32_t i = 0; i < mYCount; i++) {
145 float stepY = mYDivs[i];
Romain Guy6820ac82010-09-15 18:11:50 -0700146
147 float y2 = 0.0f;
148 if (i & 1) {
149 const float segment = stepY - previousStepY;
150 y2 = y1 + segment * stretchY;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700151 } else {
Romain Guy6820ac82010-09-15 18:11:50 -0700152 y2 = y1 + stepY - previousStepY;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700153 }
Romain Guy6820ac82010-09-15 18:11:50 -0700154 float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;
155
Romain Guy6f72beb2010-11-30 12:04:14 -0800156 generateRow(vertex, y1, y2, v1, v2, stretchX, right - left, bitmapWidth, quadCount);
Romain Guy6820ac82010-09-15 18:11:50 -0700157
158 y1 = y2;
159 v1 = (stepY + 0.5f) / bitmapHeight;
160
161 previousStepY = stepY;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700162 }
163
Romain Guy6f72beb2010-11-30 12:04:14 -0800164 generateRow(vertex, y1, bottom - top, v1, 1.0f, stretchX, right - left,
165 bitmapWidth, quadCount);
Romain Guy03750a02010-10-18 14:06:08 -0700166
167 Caches::getInstance().bindMeshBuffer(meshBuffer);
Romain Guy6f72beb2010-11-30 12:04:14 -0800168 if (!mUploaded) {
169 glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
170 mVertices, GL_DYNAMIC_DRAW);
171 mUploaded = true;
172 } else {
173 glBufferSubData(GL_ARRAY_BUFFER, 0,
174 sizeof(TextureVertex) * verticesCount, mVertices);
175 }
Romain Guyfb5e23c2010-07-09 13:52:56 -0700176}
177
Romain Guy5b3b3522010-10-27 18:57:51 -0700178void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
Romain Guy6f72beb2010-11-30 12:04:14 -0800179 float stretchX, float width, float bitmapWidth, uint32_t& quadCount) {
Romain Guy6820ac82010-09-15 18:11:50 -0700180 float previousStepX = 0.0f;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700181
Romain Guy6820ac82010-09-15 18:11:50 -0700182 float x1 = 0.0f;
183 float u1 = 0.0f;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700184
Romain Guy6820ac82010-09-15 18:11:50 -0700185 // Generate the row quad by quad
Romain Guy6f72beb2010-11-30 12:04:14 -0800186 for (uint32_t i = 0; i < mXCount; i++) {
187 float stepX = mXDivs[i];
Romain Guy6820ac82010-09-15 18:11:50 -0700188
189 float x2 = 0.0f;
190 if (i & 1) {
191 const float segment = stepX - previousStepX;
192 x2 = x1 + segment * stretchX;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700193 } else {
Romain Guy6820ac82010-09-15 18:11:50 -0700194 x2 = x1 + stepX - previousStepX;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700195 }
Romain Guy6820ac82010-09-15 18:11:50 -0700196 float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700197
Romain Guy6f72beb2010-11-30 12:04:14 -0800198 generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
Romain Guy6820ac82010-09-15 18:11:50 -0700199
200 x1 = x2;
201 u1 = (stepX + 0.5f) / bitmapWidth;
202
203 previousStepX = stepX;
Romain Guyfb5e23c2010-07-09 13:52:56 -0700204 }
205
Romain Guy6f72beb2010-11-30 12:04:14 -0800206 generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
Romain Guyfb5e23c2010-07-09 13:52:56 -0700207}
208
Romain Guy5b3b3522010-10-27 18:57:51 -0700209void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
Romain Guy6f72beb2010-11-30 12:04:14 -0800210 float u1, float v1, float u2, float v2, uint32_t& quadCount) {
211 if (((mColorKey >> quadCount++) & 0x1) == 1) {
Romain Guy4bb94202010-10-12 15:59:26 -0700212 return;
213 }
214
Romain Guy5b3b3522010-10-27 18:57:51 -0700215 if (hasEmptyQuads) {
216 Rect bounds(x1, y1, x2, y2);
217 quads.add(bounds);
218 }
219
Romain Guy6820ac82010-09-15 18:11:50 -0700220 // Left triangle
221 TextureVertex::set(vertex++, x1, y1, u1, v1);
222 TextureVertex::set(vertex++, x2, y1, u2, v1);
223 TextureVertex::set(vertex++, x1, y2, u1, v2);
Romain Guyfb5e23c2010-07-09 13:52:56 -0700224
Romain Guy6820ac82010-09-15 18:11:50 -0700225 // Right triangle
226 TextureVertex::set(vertex++, x1, y2, u1, v2);
227 TextureVertex::set(vertex++, x2, y1, u2, v1);
228 TextureVertex::set(vertex++, x2, y2, u2, v2);
Romain Guyfb5e23c2010-07-09 13:52:56 -0700229}
230
231}; // namespace uirenderer
232}; // namespace android