Caches.cpp revision eca0ca2424afc1e98912405906edfc32f7733e16
1dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase/*
2dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * Copyright (C) 2010 The Android Open Source Project
3dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase *
4dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * you may not use this file except in compliance with the License.
6dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * You may obtain a copy of the License at
7dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase *
8dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase *
10dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * Unless required by applicable law or agreed to in writing, software
11dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * See the License for the specific language governing permissions and
14dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase * limitations under the License.
15dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase */
16dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
17dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase#define LOG_TAG "OpenGLRenderer"
18dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
19c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include <utils/Log.h>
209c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#include <utils/String8.h>
21c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy
22dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase#include "Caches.h"
23e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy#include "Properties.h"
2409b7c91de73b59aa3f679b3ae3ba299f82ec9f8aRomain Guy#include "LayerRenderer.h"
25dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
26dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haasenamespace android {
27dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
28dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase#ifdef USE_OPENGL_RENDERER
29dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haaseusing namespace uirenderer;
30dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet HaaseANDROID_SINGLETON_STATIC_INSTANCE(Caches);
31dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase#endif
32dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
33dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haasenamespace uirenderer {
34dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
35dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase///////////////////////////////////////////////////////////////////////////////
36bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy// Macros
37bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy///////////////////////////////////////////////////////////////////////////////
38bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
39bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy#if DEBUG_CACHE_FLUSH
40bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    #define FLUSH_LOGD(...) LOGD(__VA_ARGS__)
41bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy#else
42bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    #define FLUSH_LOGD(...)
43bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy#endif
44bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
45bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy///////////////////////////////////////////////////////////////////////////////
46dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase// Constructors/destructor
47dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase///////////////////////////////////////////////////////////////////////////////
48dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
49dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet HaaseCaches::Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO),
50dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase        lastDstMode(GL_ZERO), currentProgram(NULL) {
51dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    GLint maxTextureUnits;
52dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
53dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
54dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase        LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
55dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    }
56dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
57dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    glGenBuffers(1, &meshBuffer);
58dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
59dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
60dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
61746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
62746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy
639bca4793a33d2714b306d69ceb870925a588fe71Romain Guy    mCurrentBuffer = meshBuffer;
645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    mRegionMesh = NULL;
65e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy
66e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy    mDebugLevel = readDebugLevel();
67e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy    LOGD("Enabling debug mode %d", mDebugLevel);
687230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy
697230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy#if RENDER_LAYERS_AS_REGIONS
7002ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy    INIT_LOGD("Layers will be composited as regions");
717230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy#endif
72dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}
73dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain GuyCaches::~Caches() {
755b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    delete[] mRegionMesh;
765b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy}
775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
785b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy///////////////////////////////////////////////////////////////////////////////
79c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy// Debug
80c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy///////////////////////////////////////////////////////////////////////////////
81c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy
82c15008e72ec00ca20a271c3006dac649fd07533bRomain Guyvoid Caches::dumpMemoryUsage() {
839c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    String8 stringLog;
849c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    dumpMemoryUsage(stringLog);
859c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    LOGD("%s", stringLog.string());
869c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase}
879c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase
889c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haasevoid Caches::dumpMemoryUsage(String8 &log) {
899c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("Current memory usage / total memory usage (bytes):\n");
909c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  TextureCache         %8d / %8d\n",
919c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            textureCache.getSize(), textureCache.getMaxSize());
929c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  LayerCache           %8d / %8d\n",
939c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            layerCache.getSize(), layerCache.getMaxSize());
949c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  GradientCache        %8d / %8d\n",
959c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            gradientCache.getSize(), gradientCache.getMaxSize());
969c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  PathCache            %8d / %8d\n",
979c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            pathCache.getSize(), pathCache.getMaxSize());
989c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  CircleShapeCache     %8d / %8d\n",
9901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            circleShapeCache.getSize(), circleShapeCache.getMaxSize());
1009c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  OvalShapeCache       %8d / %8d\n",
1012fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy            ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
1029c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  RoundRectShapeCache  %8d / %8d\n",
10301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
1049c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  RectShapeCache       %8d / %8d\n",
1052fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy            rectShapeCache.getSize(), rectShapeCache.getMaxSize());
1069c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  ArcShapeCache        %8d / %8d\n",
1072fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy            arcShapeCache.getSize(), arcShapeCache.getMaxSize());
1089c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
109c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy            dropShadowCache.getMaxSize());
110c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
111c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy        const uint32_t size = fontRenderer.getFontRendererSize(i);
1129c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase        log.appendFormat("  FontRenderer %d       %8d / %8d\n", i, size, size);
113c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    }
114d2ba50ab861ec0950bda18dd0f463b687e66249fRomain Guy    log.appendFormat("Other:\n");
1159c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  FboCache             %8d / %8d\n",
1169c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            fboCache.getSize(), fboCache.getMaxSize());
1179c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  PatchCache           %8d / %8d\n",
1189c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase            patchCache.getSize(), patchCache.getMaxSize());
119c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy
120c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    uint32_t total = 0;
121c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    total += textureCache.getSize();
122c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    total += layerCache.getSize();
123c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    total += gradientCache.getSize();
124c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    total += pathCache.getSize();
125c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    total += dropShadowCache.getSize();
1262fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    total += roundRectShapeCache.getSize();
1272fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    total += circleShapeCache.getSize();
1282fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    total += ovalShapeCache.getSize();
1292fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    total += rectShapeCache.getSize();
1302fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    total += arcShapeCache.getSize();
131c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
132c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy        total += fontRenderer.getFontRendererSize(i);
133c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy    }
134c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy
1359c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("Total memory usage:\n");
1369c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase    log.appendFormat("  %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
137c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy}
138c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy
139c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy///////////////////////////////////////////////////////////////////////////////
140fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy// Memory management
141fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy///////////////////////////////////////////////////////////////////////////////
142fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy
143fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid Caches::clearGarbage() {
144fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    textureCache.clearGarbage();
145fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    pathCache.clearGarbage();
14657066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy
14757066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy    Mutex::Autolock _l(mGarbageLock);
14857066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy
149ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    size_t count = mLayerGarbage.size();
15057066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy    for (size_t i = 0; i < count; i++) {
151ada830f639591b99c3e40de22b07296c7932a33fRomain Guy        Layer* layer = mLayerGarbage.itemAt(i);
15209b7c91de73b59aa3f679b3ae3ba299f82ec9f8aRomain Guy        LayerRenderer::destroyLayer(layer);
15357066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy    }
154ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    mLayerGarbage.clear();
15557066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy}
15657066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy
157ada830f639591b99c3e40de22b07296c7932a33fRomain Guyvoid Caches::deleteLayerDeferred(Layer* layer) {
15857066eb64c9a190d1afc87bb060bbb2d31e5b86cRomain Guy    Mutex::Autolock _l(mGarbageLock);
159ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    mLayerGarbage.push(layer);
160fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy}
161fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy
162bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guyvoid Caches::flush(FlushMode mode) {
163bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    FLUSH_LOGD("Flushing caches (mode %d)", mode);
164bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
165bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    clearGarbage();
166bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
167bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    switch (mode) {
168bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy        case kFlushMode_Full:
169bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            textureCache.clear();
170bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            patchCache.clear();
171bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            dropShadowCache.clear();
172bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            gradientCache.clear();
173eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy            fontRenderer.clear();
174bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            // fall through
175bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy        case kFlushMode_Moderate:
176eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy            fontRenderer.flush();
177eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy            textureCache.flush();
178bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            pathCache.clear();
179bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            roundRectShapeCache.clear();
180bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            circleShapeCache.clear();
181bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            ovalShapeCache.clear();
182bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            rectShapeCache.clear();
183bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            arcShapeCache.clear();
1846d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            // fall through
1856d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        case kFlushMode_Layers:
1866d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            layerCache.clear();
187bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            break;
188bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    }
189bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy}
190bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
191fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy///////////////////////////////////////////////////////////////////////////////
1925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy// VBO
1935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy///////////////////////////////////////////////////////////////////////////////
1945b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
195dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haasevoid Caches::bindMeshBuffer() {
196dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    bindMeshBuffer(meshBuffer);
197dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}
198dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
199dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haasevoid Caches::bindMeshBuffer(const GLuint buffer) {
2009bca4793a33d2714b306d69ceb870925a588fe71Romain Guy    if (mCurrentBuffer != buffer) {
201dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase        glBindBuffer(GL_ARRAY_BUFFER, buffer);
2029bca4793a33d2714b306d69ceb870925a588fe71Romain Guy        mCurrentBuffer = buffer;
203dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    }
204dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}
205dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
206dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haasevoid Caches::unbindMeshBuffer() {
2079bca4793a33d2714b306d69ceb870925a588fe71Romain Guy    if (mCurrentBuffer) {
208dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase        glBindBuffer(GL_ARRAY_BUFFER, 0);
2099bca4793a33d2714b306d69ceb870925a588fe71Romain Guy        mCurrentBuffer = 0;
210dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase    }
211dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}
212dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase
2135b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain GuyTextureVertex* Caches::getRegionMesh() {
2145b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
2155b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    if (!mRegionMesh) {
2165b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        mRegionMesh = new TextureVertex[REGION_MESH_QUAD_COUNT * 4];
2175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
2185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        uint16_t* regionIndices = new uint16_t[REGION_MESH_QUAD_COUNT * 6];
2195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        for (int i = 0; i < REGION_MESH_QUAD_COUNT; i++) {
2205b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            uint16_t quad = i * 4;
2215b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            int index = i * 6;
2225b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index    ] = quad;       // top-left
2235b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index + 1] = quad + 1;   // top-right
2245b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index + 2] = quad + 2;   // bottom-left
2255b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index + 3] = quad + 2;   // bottom-left
2265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index + 4] = quad + 1;   // top-right
2275b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            regionIndices[index + 5] = quad + 3;   // bottom-right
2285b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        }
2295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
2305b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        glGenBuffers(1, &mRegionMeshIndices);
2315b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
2325b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        glBufferData(GL_ELEMENT_ARRAY_BUFFER, REGION_MESH_QUAD_COUNT * 6 * sizeof(uint16_t),
2335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy                regionIndices, GL_STATIC_DRAW);
2345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
2355b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        delete[] regionIndices;
2365b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    } else {
2375b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
2385b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    }
2395b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
2405b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    return mRegionMesh;
2415b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy}
2425b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
243dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}; // namespace uirenderer
244dd78ccacff83f0714ad90be98b58ad85f5d08c66Chet Haase}; // namespace android
245