Patch.cpp revision fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6c
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
19fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy#include <cstring>
20fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
21fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy#include <utils/Log.h>
22fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain 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
32fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain GuyPatch::Patch(const uint32_t xCount, const uint32_t yCount):
33fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        xCount(xCount + 2), yCount(yCount + 2) {
34fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    verticesCount = (xCount + 2) * (yCount + 2);
35fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    vertices = new TextureVertex[verticesCount];
36fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
37fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    // 2 triangles per patch, 3 vertices per triangle
38fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    indicesCount = (xCount + 1) * (yCount + 1) * 2 * 3;
39fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    indices = new uint16_t[indicesCount];
40fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
41fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t xNum = xCount + 1;
42fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t yNum = yCount + 1;
43fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
44fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    uint16_t* startIndices = indices;
45fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    uint32_t n = 0;
46fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    for (uint32_t y = 0; y < yNum; y++) {
47fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t x = 0; x < xNum; x++) {
48fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n;
49fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n + 1;
50fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n + xNum + 2;
51fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
52fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n;
53fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n + xNum + 2;
54fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            *startIndices++ = n + xNum + 1;
55fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
56fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            n += 1;
57fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
58fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        n += 1;
59fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
60fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
61fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
62fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain GuyPatch::~Patch() {
63fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    delete indices;
64fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    delete vertices;
65fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
66fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
67fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
68fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy// Vertices management
69fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
70fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
71fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guyvoid Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float right,
72fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        float bottom, const int32_t* xDivs,  const int32_t* yDivs, const uint32_t width,
73fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const uint32_t height) {
74fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t xStretchCount = (width + 1) >> 1;
75fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const uint32_t yStretchCount = (height + 1) >> 1;
76fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
77fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float xStretch = 0;
78fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float yStretch = 0;
79fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float xStretchTex = 0;
80fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float yStretchTex = 0;
81fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
82fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const float meshWidth = right - left;
83fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
84fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const float bitmapWidth = float(bitmap->width());
85fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    const float bitmapHeight = float(bitmap->height());
86fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
87fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (xStretchCount > 0) {
88fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
89fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t i = 1; i < width; i += 2) {
90fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            stretchSize += xDivs[i] - xDivs[i - 1];
91fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
92fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        xStretchTex = (stretchSize / bitmapWidth) / xStretchCount;
93fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapWidth - stretchSize;
94fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        xStretch = (right - left - fixed) / xStretchCount;
95fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
96fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
97fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    if (yStretchCount > 0) {
98fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t stretchSize = 0;
99fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t i = 1; i < height; i += 2) {
100fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            stretchSize += yDivs[i] - yDivs[i - 1];
101fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
102fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        yStretchTex = (stretchSize / bitmapHeight) / yStretchCount;
103fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const float fixed = bitmapHeight - stretchSize;
104fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        yStretch = (bottom - top - fixed) / yStretchCount;
105fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
106fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
107fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float vy = 0.0f;
108fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float ty = 0.0f;
109fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    TextureVertex* vertex = vertices;
110fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
111fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    generateVertices(vertex, 0.0f, 0.0f, xDivs, width, xStretch, xStretchTex,
112fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            meshWidth, bitmapWidth);
113fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    vertex += width + 2;
114fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
115fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    for (uint32_t y = 0; y < height; y++) {
116fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        if (y & 1) {
117fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            vy += yStretch;
118fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            ty += yStretchTex;
119fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
120fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            const float step = float(yDivs[y]);
121fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            vy += step;
122fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            ty += step / bitmapHeight;
123fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
124fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        generateVertices(vertex, vy, ty, xDivs, width, xStretch, xStretchTex,
125fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy                meshWidth, bitmapWidth);
126fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        vertex += width + 2;
127fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
128fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
129fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    generateVertices(vertex, bottom - top, 1.0f, xDivs, width, xStretch, xStretchTex,
130fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            meshWidth, bitmapWidth);
131fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
132fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
133fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guyinline void Patch::generateVertices(TextureVertex* vertex, float y, float v,
134fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        const int32_t xDivs[], uint32_t xCount, float xStretch, float xStretchTex,
135fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        float width, float widthTex) {
136fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float vx = 0.0f;
137fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    float tx = 0.0f;
138fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
139fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    TextureVertex::set(vertex, vx, y, tx, v);
140fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    vertex++;
141fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
142fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    for (uint32_t x = 0; x < xCount; x++) {
143fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        if (x & 1) {
144fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            vx += xStretch;
145fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            tx += xStretchTex;
146fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        } else {
147fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            const float step = float(xDivs[x]);
148fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            vx += step;
149fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            tx += step / widthTex;
150fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
151fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
152fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        TextureVertex::set(vertex, vx, y, tx, v);
153fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        vertex++;
154fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
155fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
156fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    TextureVertex::set(vertex, width, y, 1.0f, v);
157fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    vertex++;
158fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
159fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
160fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
161fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy// Debug tools
162fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy///////////////////////////////////////////////////////////////////////////////
163fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
164fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guyvoid Patch::dump() {
165fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    LOGD("Vertices [");
166fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    for (uint32_t y = 0; y < yCount; y++) {
167fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        char buffer[512];
168fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        buffer[0] = '\0';
169fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        uint32_t offset = 0;
170fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        for (uint32_t x = 0; x < xCount; x++) {
171fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            TextureVertex* v = &vertices[y * xCount + x];
172fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy            offset += sprintf(&buffer[offset], " (%.4f,%.4f)-(%.4f,%.4f)",
173fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy                    v->position[0], v->position[1], v->texture[0], v->texture[1]);
174fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        }
175fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        LOGD("  [%s ]", buffer);
176fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
177fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    LOGD("]\nIndices [ ");
178fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    char buffer[4096];
179fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    buffer[0] = '\0';
180fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    uint32_t offset = 0;
181fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    for (uint32_t i = 0; i < indicesCount; i++) {
182fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy        offset += sprintf(&buffer[offset], "%d ", indices[i]);
183fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    }
184fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy    LOGD("  %s\n]", buffer);
185fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}
186fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy
187fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace uirenderer
188fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy}; // namespace android
189