1f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/*
2f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Copyright (C) 2010 The Android Open Source Project
3f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy *
4f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * you may not use this file except in compliance with the License.
6f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * You may obtain a copy of the License at
7f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy *
8f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy *
10f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Unless required by applicable law or agreed to in writing, software
11f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * See the License for the specific language governing permissions and
14f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * limitations under the License.
15f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy */
16f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
17f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#define LOG_TAG "OpenGLRenderer"
18f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <utils/JenkinsHash.h>
20f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#include <utils/Log.h>
21f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "Caches.h"
23f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#include "PatchCache.h"
24fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h"
25f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
26f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace android {
27f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace uirenderer {
28f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
29f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy///////////////////////////////////////////////////////////////////////////////
30f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Constructors/destructor
31f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy///////////////////////////////////////////////////////////////////////////////
32f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
334c2547fa9244e78115cde0a259291053108c3dc7Romain GuyPatchCache::PatchCache():
344c2547fa9244e78115cde0a259291053108c3dc7Romain Guy        mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity),
35e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        mMeshBuffer(0), mFreeBlocks(NULL), mGenerationId(0) {
363b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    char property[PROPERTY_VALUE_MAX];
373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) {
383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        INIT_LOGD("  Setting patch cache size to %skB", property);
393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMaxSize = KB(atoi(property));
403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    } else {
413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        INIT_LOGD("  Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE);
423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE);
433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
44f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}
45f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
46f7f93556c8fcc640ab5adef79d021a80a72a645aRomain GuyPatchCache::~PatchCache() {
47f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    clear();
48f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}
49f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid PatchCache::init(Caches& caches) {
517d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    bool created = false;
527d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    if (!mMeshBuffer) {
537d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        glGenBuffers(1, &mMeshBuffer);
547d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        created = true;
557d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    }
567d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy
573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    caches.bindMeshBuffer(mMeshBuffer);
583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    caches.resetVertexPointers();
593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
607d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    if (created) {
614c2547fa9244e78115cde0a259291053108c3dc7Romain Guy        createVertexBuffer();
627d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    }
633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}
643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
65f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy///////////////////////////////////////////////////////////////////////////////
66f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Caching
67f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy///////////////////////////////////////////////////////////////////////////////
68f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyhash_t PatchCache::PatchDescription::hash() const {
703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch));
713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    hash = JenkinsHashMix(hash, mBitmapWidth);
723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    hash = JenkinsHashMix(hash, mBitmapHeight);
733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    hash = JenkinsHashMix(hash, mPixelWidth);
743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    hash = JenkinsHashMix(hash, mPixelHeight);
753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    return JenkinsHashWhiten(hash);
763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}
7713ba0054846ce630ca31e8f26169fd9388faee02Romain Guy
783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyint PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            const PatchCache::PatchDescription& rhs) {
803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    return memcmp(&lhs, &rhs, sizeof(PatchDescription));
8113ba0054846ce630ca31e8f26169fd9388faee02Romain Guy}
8213ba0054846ce630ca31e8f26169fd9388faee02Romain Guy
83f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyvoid PatchCache::clear() {
843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    clearCache();
857d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy
867d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    if (mMeshBuffer) {
877d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        Caches::getInstance().unbindMeshBuffer();
887d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        glDeleteBuffers(1, &mMeshBuffer);
897d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        mMeshBuffer = 0;
907d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy        mSize = 0;
917d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy    }
923b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}
933b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
943b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid PatchCache::clearCache() {
953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    LruCache<PatchDescription, Patch*>::Iterator i(mCache);
963b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    while (i.next()) {
973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        delete i.value();
982728f961614a385df1f056fc24803a9f65c90fabRomain Guy    }
99f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    mCache.clear();
100e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
101e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    BufferBlock* block = mFreeBlocks;
102e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    while (block) {
103e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        BufferBlock* next = block->next;
104e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        delete block;
105e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block = next;
106e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
107e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    mFreeBlocks = NULL;
108e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy}
109e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
110e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) {
111e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    LruCache<PatchDescription, Patch*>::Iterator i(mCache);
112e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    while (i.next()) {
113e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        const PatchDescription& key = i.key();
114e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        if (key.getPatch() == patch) {
115e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            patchesToRemove.push(patch_pair_t(&key, i.value()));
116e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        }
117e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
118e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy}
119e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
120e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::removeDeferred(Res_png_9patch* patch) {
121e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    Mutex::Autolock _l(mLock);
1226056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin
1236056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    // Assert that patch is not already garbage
1246056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    size_t count = mGarbage.size();
1256056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    for (size_t i = 0; i < count; i++) {
1266056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        if (patch == mGarbage[i]) {
1276056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin            patch = NULL;
1286056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin            break;
1296056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        }
1306056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    }
1316056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin    LOG_ALWAYS_FATAL_IF(patch == NULL);
1326056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin
133e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    mGarbage.push(patch);
134e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy}
135e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
136e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::clearGarbage() {
137e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    Vector<patch_pair_t> patchesToRemove;
138e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
139e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    { // scope for the mutex
140e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        Mutex::Autolock _l(mLock);
141e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        size_t count = mGarbage.size();
142e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        for (size_t i = 0; i < count; i++) {
14336fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee            Res_png_9patch* patch = mGarbage[i];
14436fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee            remove(patchesToRemove, patch);
14536fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee            // A Res_png_9patch is actually an array of byte that's larger
14636fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee            // than sizeof(Res_png_9patch). It must be freed as an array.
14736fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee            delete[] (int8_t*) patch;
148e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        }
149e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        mGarbage.clear();
150e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
151e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
152e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // TODO: We could sort patchesToRemove by offset to merge
153e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // adjacent free blocks
154e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    for (size_t i = 0; i < patchesToRemove.size(); i++) {
155e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        const patch_pair_t& pair = patchesToRemove[i];
156e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
1576056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        // Release the patch and mark the space in the free list
1586056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        Patch* patch = pair.getSecond();
159e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
160e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block->next = mFreeBlocks;
161e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        mFreeBlocks = block;
162e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
163e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        mSize -= patch->getSize();
164e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
165e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        mCache.remove(*pair.getFirst());
1666056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        delete patch;
167e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
168e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
169e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#if DEBUG_PATCHES
170e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    if (patchesToRemove.size() > 0) {
171e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        dumpFreeBlocks("Removed garbage");
172e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
173e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#endif
174f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}
175f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
1764c2547fa9244e78115cde0a259291053108c3dc7Romain Guyvoid PatchCache::createVertexBuffer() {
1774c2547fa9244e78115cde0a259291053108c3dc7Romain Guy    glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW);
1784c2547fa9244e78115cde0a259291053108c3dc7Romain Guy    mSize = 0;
179e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    mFreeBlocks = new BufferBlock(0, mMaxSize);
1804c2547fa9244e78115cde0a259291053108c3dc7Romain Guy    mGenerationId++;
1814c2547fa9244e78115cde0a259291053108c3dc7Romain Guy}
1824c2547fa9244e78115cde0a259291053108c3dc7Romain Guy
183e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy/**
184e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * Sets the mesh's offsets and copies its associated vertices into
185e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * the mesh buffer (VBO).
186e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy */
187e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
188e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // This call ensures the VBO exists and that it is bound
189e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    init(Caches::getInstance());
190e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
191e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // If we're running out of space, let's clear the entire cache
192e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    uint32_t size = newMesh->getSize();
193e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    if (mSize + size > mMaxSize) {
194e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        clearCache();
195e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        createVertexBuffer();
196e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
197e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
198e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // Find a block where we can fit the mesh
199e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    BufferBlock* previous = NULL;
200e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    BufferBlock* block = mFreeBlocks;
201e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    while (block) {
202e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        // The mesh fits
203e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        if (block->size >= size) {
204e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            break;
205e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        }
206e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        previous = block;
207e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block = block->next;
208e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
209e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
210e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // We have enough space left in the buffer, but it's
211e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // too fragmented, let's clear the cache
212e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    if (!block) {
213e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        clearCache();
214e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        createVertexBuffer();
215e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        previous = NULL;
216e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block = mFreeBlocks;
217e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
218e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
219e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // Copy the 9patch mesh in the VBO
220e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    newMesh->offset = (GLintptr) (block->offset);
221e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
222e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
223e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
224e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    // Remove the block since we've used it entirely
225e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    if (block->size == size) {
226e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        if (previous) {
227e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            previous->next = block->next;
228e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        } else {
229e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            mFreeBlocks = block->next;
230e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        }
2316056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin        delete block;
232e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    } else {
233e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        // Resize the block now that it's occupied
234e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block->offset += size;
235e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block->size -= size;
236e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
237e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
238e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    mSize += size;
239e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy}
240e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
2413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyconst Patch* PatchCache::get(const AssetAtlas::Entry* entry,
2423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        const uint32_t bitmapWidth, const uint32_t bitmapHeight,
2433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
2444bb942083a0d4db746adf95349108dd8ef842e32Romain Guy
2453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
2463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    const Patch* mesh = mCache.get(description);
2474bb942083a0d4db746adf95349108dd8ef842e32Romain Guy
2483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    if (!mesh) {
2493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        Patch* newMesh = new Patch();
2503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        TextureVertex* vertices;
2513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
2523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (entry) {
253e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            // An atlas entry has a UV mapper
2543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
25503c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                    pixelWidth, pixelHeight, entry->uvMapper, patch);
2563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        } else {
2573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
25803c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                    pixelWidth, pixelHeight, patch);
2594bb942083a0d4db746adf95349108dd8ef842e32Romain Guy        }
2602728f961614a385df1f056fc24803a9f65c90fabRomain Guy
2613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (vertices) {
262e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            setupMesh(newMesh, vertices);
2632728f961614a385df1f056fc24803a9f65c90fabRomain Guy        }
2642728f961614a385df1f056fc24803a9f65c90fabRomain Guy
265e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#if DEBUG_PATCHES
266e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        dumpFreeBlocks("Adding patch");
267e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#endif
268e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
2693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mCache.put(description, newMesh);
2703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        return newMesh;
271f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    }
272f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
273f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    return mesh;
274f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}
275f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy
276e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#if DEBUG_PATCHES
277e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::dumpFreeBlocks(const char* prefix) {
278e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    String8 dump;
279e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    BufferBlock* block = mFreeBlocks;
280e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    while (block) {
281e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        dump.appendFormat("->(%d, %d)", block->offset, block->size);
282e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        block = block->next;
283e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
284e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    ALOGD("%s: Free blocks%s", prefix, dump.string());
285e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy}
286e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#endif
287e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
288f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}; // namespace uirenderer
289f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}; // namespace android
290