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" 232dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "Patch.h" 24f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#include "PatchCache.h" 25fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h" 2696a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "renderstate/RenderState.h" 27f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 28f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace android { 29f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace uirenderer { 30f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 31f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 32f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Constructors/destructor 33f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 34f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 3596a5c4c7bab6718524de7253da8309143ab48befChris CraikPatchCache::PatchCache(RenderState& renderState) 3696a5c4c7bab6718524de7253da8309143ab48befChris Craik : mRenderState(renderState) 3796a5c4c7bab6718524de7253da8309143ab48befChris Craik , mSize(0) 3896a5c4c7bab6718524de7253da8309143ab48befChris Craik , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity) 3996a5c4c7bab6718524de7253da8309143ab48befChris Craik , mMeshBuffer(0) 4096a5c4c7bab6718524de7253da8309143ab48befChris Craik , mFreeBlocks(nullptr) 4196a5c4c7bab6718524de7253da8309143ab48befChris Craik , mGenerationId(0) { 423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy char property[PROPERTY_VALUE_MAX]; 43d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, nullptr) > 0) { 443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy INIT_LOGD(" Setting patch cache size to %skB", property); 453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mMaxSize = KB(atoi(property)); 463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } else { 473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy INIT_LOGD(" Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE); 483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE); 493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 50f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 51f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 52f7f93556c8fcc640ab5adef79d021a80a72a645aRomain GuyPatchCache::~PatchCache() { 53f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy clear(); 54f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 55f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 5696a5c4c7bab6718524de7253da8309143ab48befChris Craikvoid PatchCache::init() { 577d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy bool created = false; 587d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy if (!mMeshBuffer) { 597d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy glGenBuffers(1, &mMeshBuffer); 607d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy created = true; 617d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy } 627d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy 6396a5c4c7bab6718524de7253da8309143ab48befChris Craik mRenderState.meshState().bindMeshBuffer(mMeshBuffer); 6496a5c4c7bab6718524de7253da8309143ab48befChris Craik mRenderState.meshState().resetVertexPointers(); 653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 667d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy if (created) { 674c2547fa9244e78115cde0a259291053108c3dc7Romain Guy createVertexBuffer(); 687d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy } 693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 71f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 72f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Caching 73f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 74f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyhash_t PatchCache::PatchDescription::hash() const { 763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch)); 773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mBitmapWidth); 783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mBitmapHeight); 793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mPixelWidth); 803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mPixelHeight); 813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return JenkinsHashWhiten(hash); 823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 8313ba0054846ce630ca31e8f26169fd9388faee02Romain Guy 843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyint PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs, 853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const PatchCache::PatchDescription& rhs) { 863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return memcmp(&lhs, &rhs, sizeof(PatchDescription)); 8713ba0054846ce630ca31e8f26169fd9388faee02Romain Guy} 8813ba0054846ce630ca31e8f26169fd9388faee02Romain Guy 89f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyvoid PatchCache::clear() { 903b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy clearCache(); 917d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy 927d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy if (mMeshBuffer) { 9396a5c4c7bab6718524de7253da8309143ab48befChris Craik mRenderState.meshState().unbindMeshBuffer(); 947d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy glDeleteBuffers(1, &mMeshBuffer); 957d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy mMeshBuffer = 0; 967d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy mSize = 0; 977d9b1b3c02eb1ffd99742ecb7b69e3ab97d2ba18Romain Guy } 983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 993b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid PatchCache::clearCache() { 1013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy LruCache<PatchDescription, Patch*>::Iterator i(mCache); 1023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy while (i.next()) { 1033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy delete i.value(); 1042728f961614a385df1f056fc24803a9f65c90fabRomain Guy } 105f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy mCache.clear(); 106e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 107e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy BufferBlock* block = mFreeBlocks; 108e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy while (block) { 109e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy BufferBlock* next = block->next; 110e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy delete block; 111e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block = next; 112e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 113d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik mFreeBlocks = nullptr; 114e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 115e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 116e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) { 117e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy LruCache<PatchDescription, Patch*>::Iterator i(mCache); 118e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy while (i.next()) { 119e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy const PatchDescription& key = i.key(); 120e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (key.getPatch() == patch) { 121e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy patchesToRemove.push(patch_pair_t(&key, i.value())); 122e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 123e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 124e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 125e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 126e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::removeDeferred(Res_png_9patch* patch) { 127e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock _l(mLock); 1286056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin 1296056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin // Assert that patch is not already garbage 1306056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin size_t count = mGarbage.size(); 1316056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin for (size_t i = 0; i < count; i++) { 1326056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin if (patch == mGarbage[i]) { 133d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik patch = nullptr; 1346056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin break; 1356056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin } 1366056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin } 137d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik LOG_ALWAYS_FATAL_IF(patch == nullptr); 1386056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin 139e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mGarbage.push(patch); 140e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 141e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 142e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PatchCache::clearGarbage() { 143e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Vector<patch_pair_t> patchesToRemove; 144e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 145e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy { // scope for the mutex 146e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock _l(mLock); 147e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy size_t count = mGarbage.size(); 148e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < count; i++) { 14936fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee Res_png_9patch* patch = mGarbage[i]; 15036fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee remove(patchesToRemove, patch); 15136fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // A Res_png_9patch is actually an array of byte that's larger 15236fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // than sizeof(Res_png_9patch). It must be freed as an array. 15336fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee delete[] (int8_t*) patch; 154e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 155e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mGarbage.clear(); 156e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 157e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 158e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // TODO: We could sort patchesToRemove by offset to merge 159e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // adjacent free blocks 160e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < patchesToRemove.size(); i++) { 161e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy const patch_pair_t& pair = patchesToRemove[i]; 162e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 1636056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin // Release the patch and mark the space in the free list 1646056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin Patch* patch = pair.getSecond(); 1658820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik BufferBlock* block = new BufferBlock(patch->positionOffset, patch->getSize()); 166e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block->next = mFreeBlocks; 167e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mFreeBlocks = block; 168e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 169e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mSize -= patch->getSize(); 170e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 171e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mCache.remove(*pair.getFirst()); 1726056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin delete patch; 173e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 174e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 175e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#if DEBUG_PATCHES 176e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (patchesToRemove.size() > 0) { 177e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy dumpFreeBlocks("Removed garbage"); 178e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 179e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy#endif 180f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 181f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 1824c2547fa9244e78115cde0a259291053108c3dc7Romain Guyvoid PatchCache::createVertexBuffer() { 183d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik glBufferData(GL_ARRAY_BUFFER, mMaxSize, nullptr, GL_DYNAMIC_DRAW); 1844c2547fa9244e78115cde0a259291053108c3dc7Romain Guy mSize = 0; 185e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mFreeBlocks = new BufferBlock(0, mMaxSize); 1864c2547fa9244e78115cde0a259291053108c3dc7Romain Guy mGenerationId++; 1874c2547fa9244e78115cde0a259291053108c3dc7Romain Guy} 1884c2547fa9244e78115cde0a259291053108c3dc7Romain Guy 189e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy/** 190e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * Sets the mesh's offsets and copies its associated vertices into 191e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * the mesh buffer (VBO). 192e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy */ 1938820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craikvoid PatchCache::setupMesh(Patch* newMesh) { 194e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // This call ensures the VBO exists and that it is bound 19596a5c4c7bab6718524de7253da8309143ab48befChris Craik init(); 196e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 197e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // If we're running out of space, let's clear the entire cache 198e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy uint32_t size = newMesh->getSize(); 199e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (mSize + size > mMaxSize) { 200e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy clearCache(); 201e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy createVertexBuffer(); 202e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 203e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 204e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // Find a block where we can fit the mesh 205d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik BufferBlock* previous = nullptr; 206e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy BufferBlock* block = mFreeBlocks; 207e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy while (block) { 208e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // The mesh fits 209e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (block->size >= size) { 210e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy break; 211e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 212e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy previous = block; 213e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block = block->next; 214e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 215e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 216e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // We have enough space left in the buffer, but it's 217e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // too fragmented, let's clear the cache 218e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (!block) { 219e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy clearCache(); 220e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy createVertexBuffer(); 221d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik previous = nullptr; 222e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block = mFreeBlocks; 223e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 224e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 225e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // Copy the 9patch mesh in the VBO 2268820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik newMesh->positionOffset = (GLintptr) (block->offset); 2278820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset; 2288820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik glBufferSubData(GL_ARRAY_BUFFER, newMesh->positionOffset, size, newMesh->vertices.get()); 229e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 230e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // Remove the block since we've used it entirely 231e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (block->size == size) { 232e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (previous) { 233e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy previous->next = block->next; 234e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } else { 235e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mFreeBlocks = block->next; 236e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 2376056e1027107aaa15f51a5ed775ff14c6b664ca3Jens Gulin delete block; 238e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } else { 239e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy // Resize the block now that it's occupied 240e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block->offset += size; 241e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy block->size -= size; 242e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 243e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 244e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mSize += size; 245e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 246e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 2478820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craikstatic const UvMapper sIdentity; 2488820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik 2493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyconst Patch* PatchCache::get(const AssetAtlas::Entry* entry, 2503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const uint32_t bitmapWidth, const uint32_t bitmapHeight, 2513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) { 2524bb942083a0d4db746adf95349108dd8ef842e32Romain Guy 2533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch); 2543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const Patch* mesh = mCache.get(description); 2554bb942083a0d4db746adf95349108dd8ef842e32Romain Guy 2563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!mesh) { 2578820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik const UvMapper& mapper = entry ? entry->uvMapper : sIdentity; 2588820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik Patch* newMesh = new Patch(bitmapWidth, bitmapHeight, 2598820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik pixelWidth, pixelHeight, mapper, patch); 2602728f961614a385df1f056fc24803a9f65c90fabRomain Guy 2618820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik if (newMesh->vertices) { 2628820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik setupMesh(newMesh); 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) { 2818820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik dump.appendFormat("->(%d, %d)", block->positionOffset, 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