diff options
Diffstat (limited to 'libs/hwui/PatchCache.cpp')
-rw-r--r-- | libs/hwui/PatchCache.cpp | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp deleted file mode 100644 index 673d73c5475d..000000000000 --- a/libs/hwui/PatchCache.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/JenkinsHash.h> -#include <utils/Log.h> - -#include "Caches.h" -#include "Patch.h" -#include "PatchCache.h" -#include "Properties.h" -#include "renderstate/RenderState.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Constructors/destructor -/////////////////////////////////////////////////////////////////////////////// - -PatchCache::PatchCache(RenderState& renderState) - : mRenderState(renderState) - , mMaxSize(KB(128)) - , mSize(0) - , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity) - , mMeshBuffer(0) - , mFreeBlocks(nullptr) {} - -PatchCache::~PatchCache() { - clear(); -} - -/////////////////////////////////////////////////////////////////////////////// -// Caching -/////////////////////////////////////////////////////////////////////////////// - -hash_t PatchCache::PatchDescription::hash() const { - uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch)); - hash = JenkinsHashMix(hash, mBitmapWidth); - hash = JenkinsHashMix(hash, mBitmapHeight); - hash = JenkinsHashMix(hash, mPixelWidth); - hash = JenkinsHashMix(hash, mPixelHeight); - return JenkinsHashWhiten(hash); -} - -int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs, - const PatchCache::PatchDescription& rhs) { - return memcmp(&lhs, &rhs, sizeof(PatchDescription)); -} - -void PatchCache::clear() { - clearCache(); - - if (mMeshBuffer) { - mRenderState.meshState().deleteMeshBuffer(mMeshBuffer); - mMeshBuffer = 0; - mSize = 0; - } -} - -void PatchCache::clearCache() { - LruCache<PatchDescription, Patch*>::Iterator i(mCache); - while (i.next()) { - delete i.value(); - } - mCache.clear(); - - BufferBlock* block = mFreeBlocks; - while (block) { - BufferBlock* next = block->next; - delete block; - block = next; - } - mFreeBlocks = nullptr; -} - -void PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) { - LruCache<PatchDescription, Patch*>::Iterator i(mCache); - while (i.next()) { - const PatchDescription& key = i.key(); - if (key.getPatch() == patch) { - patchesToRemove.push(patch_pair_t(&key, i.value())); - } - } -} - -void PatchCache::removeDeferred(Res_png_9patch* patch) { - Mutex::Autolock _l(mLock); - - // Assert that patch is not already garbage - size_t count = mGarbage.size(); - for (size_t i = 0; i < count; i++) { - if (patch == mGarbage[i]) { - patch = nullptr; - break; - } - } - LOG_ALWAYS_FATAL_IF(patch == nullptr); - - mGarbage.push(patch); -} - -void PatchCache::clearGarbage() { - Vector<patch_pair_t> patchesToRemove; - - { // scope for the mutex - Mutex::Autolock _l(mLock); - size_t count = mGarbage.size(); - for (size_t i = 0; i < count; i++) { - Res_png_9patch* patch = mGarbage[i]; - remove(patchesToRemove, patch); - // A Res_png_9patch is actually an array of byte that's larger - // than sizeof(Res_png_9patch). It must be freed as an array. - delete[](int8_t*) patch; - } - mGarbage.clear(); - } - - // TODO: We could sort patchesToRemove by offset to merge - // adjacent free blocks - for (size_t i = 0; i < patchesToRemove.size(); i++) { - const patch_pair_t& pair = patchesToRemove[i]; - - // Release the patch and mark the space in the free list - Patch* patch = pair.getSecond(); - BufferBlock* block = new BufferBlock(patch->positionOffset, patch->getSize()); - block->next = mFreeBlocks; - mFreeBlocks = block; - - mSize -= patch->getSize(); - - mCache.remove(*pair.getFirst()); - delete patch; - } - -#if DEBUG_PATCHES - if (patchesToRemove.size() > 0) { - dumpFreeBlocks("Removed garbage"); - } -#endif -} - -void PatchCache::createVertexBuffer() { - mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer, mMaxSize, nullptr, - GL_DYNAMIC_DRAW); - mSize = 0; - mFreeBlocks = new BufferBlock(0, mMaxSize); -} - -/** - * Sets the mesh's offsets and copies its associated vertices into - * the mesh buffer (VBO). - */ -void PatchCache::setupMesh(Patch* newMesh) { - // This call ensures the VBO exists and that it is bound - if (!mMeshBuffer) { - createVertexBuffer(); - } - - // If we're running out of space, let's clear the entire cache - uint32_t size = newMesh->getSize(); - if (mSize + size > mMaxSize) { - clearCache(); - createVertexBuffer(); - } - - // Find a block where we can fit the mesh - BufferBlock* previous = nullptr; - BufferBlock* block = mFreeBlocks; - while (block) { - // The mesh fits - if (block->size >= size) { - break; - } - previous = block; - block = block->next; - } - - // We have enough space left in the buffer, but it's - // too fragmented, let's clear the cache - if (!block) { - clearCache(); - createVertexBuffer(); - previous = nullptr; - block = mFreeBlocks; - } - - // Copy the 9patch mesh in the VBO - newMesh->positionOffset = (GLintptr)(block->offset); - newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset; - - mRenderState.meshState().updateMeshBufferSubData(mMeshBuffer, newMesh->positionOffset, size, - newMesh->vertices.get()); - - // Remove the block since we've used it entirely - if (block->size == size) { - if (previous) { - previous->next = block->next; - } else { - mFreeBlocks = block->next; - } - delete block; - } else { - // Resize the block now that it's occupied - block->offset += size; - block->size -= size; - } - - mSize += size; -} - -static const UvMapper sIdentity; - -const Patch* PatchCache::get(const uint32_t bitmapWidth, const uint32_t bitmapHeight, - const float pixelWidth, const float pixelHeight, - const Res_png_9patch* patch) { - const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch); - const Patch* mesh = mCache.get(description); - - if (!mesh) { - Patch* newMesh = - new Patch(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, sIdentity, patch); - - if (newMesh->vertices) { - setupMesh(newMesh); - } - -#if DEBUG_PATCHES - dumpFreeBlocks("Adding patch"); -#endif - - mCache.put(description, newMesh); - return newMesh; - } - - return mesh; -} - -#if DEBUG_PATCHES -void PatchCache::dumpFreeBlocks(const char* prefix) { - String8 dump; - BufferBlock* block = mFreeBlocks; - while (block) { - dump.appendFormat("->(%d, %d)", block->positionOffset, block->size); - block = block->next; - } - ALOGD("%s: Free blocks%s", prefix, dump.string()); -} -#endif - -}; // namespace uirenderer -}; // namespace android |