PathCache.cpp revision 5d923200846ed59e813373bde789d97d4ccc40b5
17fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/* 2c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy * Copyright (C) 2013 The Android Open Source Project 37fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * 47fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 57fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * you may not use this file except in compliance with the License. 67fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * You may obtain a copy of the License at 77fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * 87fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 97fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * 107fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * Unless required by applicable law or agreed to in writing, software 117fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 127fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * See the License for the specific language governing permissions and 147fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy * limitations under the License. 157fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy */ 167fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 177fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy#define LOG_TAG "OpenGLRenderer" 18c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#define ATRACE_TAG ATRACE_TAG_VIEW 197fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 20c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkBitmap.h> 21c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkCanvas.h> 22c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPaint.h> 23c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPath.h> 24c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkRect.h> 25a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 26c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/JenkinsHash.h> 27c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/Trace.h> 28ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 29ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy#include "Caches.h" 307fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy#include "PathCache.h" 31c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 32c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/Signal.h" 33c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/Task.h" 34c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/TaskProcessor.h" 357fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 367fbcc0492fca03857e3c45064f4aa040af817d55Romain Guynamespace android { 377fbcc0492fca03857e3c45064f4aa040af817d55Romain Guynamespace uirenderer { 387fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 39ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/////////////////////////////////////////////////////////////////////////////// 40c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Cache entries 41c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 42c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 43c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathDescription::PathDescription(): 44c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy type(kShapeNone), 45c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy join(SkPaint::kDefault_Join), 46c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy cap(SkPaint::kDefault_Cap), 47c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy style(SkPaint::kFill_Style), 48c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy miter(4.0f), 49c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy strokeWidth(1.0f), 50c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy pathEffect(NULL) { 51c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy memset(&shape, 0, sizeof(Shape)); 52c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 53c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 54c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathDescription::PathDescription(ShapeType type, SkPaint* paint): 55c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy type(type), 56c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy join(paint->getStrokeJoin()), 57c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy cap(paint->getStrokeCap()), 58c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy style(paint->getStyle()), 59c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy miter(paint->getStrokeMiter()), 60c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy strokeWidth(paint->getStrokeWidth()), 61c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy pathEffect(paint->getPathEffect()) { 62c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy memset(&shape, 0, sizeof(Shape)); 63c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 64c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 65c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyhash_t PathDescription::hash() const { 66c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t hash = JenkinsHashMix(0, type); 67c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, join); 68c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, cap); 69c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, style); 70c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(miter)); 71c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); 72c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(pathEffect)); 73c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); 74c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return JenkinsHashWhiten(hash); 75c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 76c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 77c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyint PathDescription::compare(const PathDescription& rhs) const { 78c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return memcmp(this, &rhs, sizeof(PathDescription)); 79c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 80c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 81c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 82c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Utilities 83c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 84c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 85c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guybool PathCache::canDrawAsConvexPath(SkPath* path, SkPaint* paint) { 86c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // NOTE: This should only be used after PathTessellator handles joins properly 87c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return paint->getPathEffect() == NULL && path->getConvexity() == SkPath::kConvex_Convexity; 88c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 89c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 90c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computePathBounds(const SkPath* path, const SkPaint* paint, 91c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 92c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkRect& bounds = path->getBounds(); 93c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathCache::computeBounds(bounds, paint, left, top, offset, width, height); 94c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 95c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 96c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computeBounds(const SkRect& bounds, const SkPaint* paint, 97c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 98c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const float pathWidth = fmax(bounds.width(), 1.0f); 99c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const float pathHeight = fmax(bounds.height(), 1.0f); 100c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 101c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy left = bounds.fLeft; 102c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy top = bounds.fTop; 103c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 104c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); 105c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 106c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy width = uint32_t(pathWidth + offset * 2.0 + 0.5); 107c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy height = uint32_t(pathHeight + offset * 2.0 + 0.5); 108c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 109c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 110c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) { 111c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy bitmap.setConfig(SkBitmap::kA8_Config, width, height); 112c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy bitmap.allocPixels(); 113c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy bitmap.eraseColor(0); 114c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 115c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 116c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initPaint(SkPaint& paint) { 117c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Make sure the paint is opaque, color, alpha, filter, etc. 118c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // will be applied later when compositing the alpha8 texture 119c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setColor(0xff000000); 120c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setAlpha(255); 121c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setColorFilter(NULL); 122c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setMaskFilter(NULL); 123c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setShader(NULL); 124c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode); 125c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkSafeUnref(paint.setXfermode(mode)); 126c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 127c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 128c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, 129c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, float top, float offset, uint32_t width, uint32_t height) { 130c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initBitmap(bitmap, width, height); 131c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 132c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPaint pathPaint(*paint); 133c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initPaint(pathPaint); 134c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 135c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkCanvas canvas(bitmap); 136c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.translate(-left + offset, -top + offset); 137c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.drawPath(*path, pathPaint); 138c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 139c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 140c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic PathTexture* createTexture(float left, float top, float offset, 141c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t width, uint32_t height, uint32_t id) { 1428aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy PathTexture* texture = new PathTexture(Caches::getInstance()); 143c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->left = left; 144c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->top = top; 145c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->offset = offset; 146c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->width = width; 147c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->height = height; 148c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->generation = id; 149c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 150c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 151c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 152c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 153c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Cache constructor/destructor 154c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 155c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 156c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathCache::PathCache(): 157c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity), 158c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) { 159c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy char property[PROPERTY_VALUE_MAX]; 160c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (property_get(PROPERTY_PATH_CACHE_SIZE, property, NULL) > 0) { 161c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy INIT_LOGD(" Setting %s cache size to %sMB", name, property); 162c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy setMaxSize(MB(atof(property))); 163c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } else { 164c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_PATH_CACHE_SIZE); 165c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 166c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy init(); 167c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 168c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 169c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathCache::~PathCache() { 170c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.clear(); 171c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 172c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 173c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::init() { 174c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.setOnEntryRemovedListener(this); 175c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 176c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy GLint maxTextureSize; 177c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 178c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mMaxTextureSize = maxTextureSize; 179c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 180c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mDebugEnabled = readDebugLevel() & kDebugCaches; 181c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 182c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 183c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 184c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Size management 185c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 186c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 187c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getSize() { 188c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mSize; 189c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 190c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 191c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getMaxSize() { 192c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mMaxSize; 193c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 194c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 195c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::setMaxSize(uint32_t maxSize) { 196c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mMaxSize = maxSize; 197c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize > mMaxSize) { 198c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 199c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 200c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 201c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 202c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 203c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Callbacks 204c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 205c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 206c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::operator()(PathDescription& entry, PathTexture*& texture) { 207c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy removeTexture(texture); 208c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 209c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 210c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 211c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Caching 212c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 213c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 214c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::removeTexture(PathTexture* texture) { 215c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (texture) { 216c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const uint32_t size = texture->width * texture->height; 2175d923200846ed59e813373bde789d97d4ccc40b5Romain Guy 2185d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task we must wait for it to return 2195d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // before attempting our cleanup 2205d923200846ed59e813373bde789d97d4ccc40b5Romain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 2215d923200846ed59e813373bde789d97d4ccc40b5Romain Guy if (task != NULL) { 2225d923200846ed59e813373bde789d97d4ccc40b5Romain Guy SkBitmap* bitmap = task->getResult(); 2235d923200846ed59e813373bde789d97d4ccc40b5Romain Guy texture->clearTask(); 2245d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } else { 2255d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task, the path was not added 2265d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // to the cache and the size wasn't increased 2275d923200846ed59e813373bde789d97d4ccc40b5Romain Guy if (size > mSize) { 2285d923200846ed59e813373bde789d97d4ccc40b5Romain Guy ALOGE("Removing path texture of size %d will leave " 2295d923200846ed59e813373bde789d97d4ccc40b5Romain Guy "the cache in an inconsistent state", size); 2305d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 2315d923200846ed59e813373bde789d97d4ccc40b5Romain Guy mSize -= size; 2325d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 233c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 234c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", 235c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->id, size, mSize); 236c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (mDebugEnabled) { 237c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGD("Shape deleted, size = %d", size); 238c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 239c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 240c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (texture->id) { 241be1b127c7bec252e0c6ab0e06ed6babed07d496fRomain Guy Caches::getInstance().deleteTexture(texture->id); 242c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 243c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy delete texture; 244c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 245c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 246c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 247c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::purgeCache(uint32_t width, uint32_t height) { 248c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const uint32_t size = width * height; 249c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 250c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (size < mMaxSize) { 251c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize + size > mMaxSize) { 252c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 253c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 254c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 255c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 256c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 257c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::trim() { 258c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize > mMaxSize) { 259c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 260c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 261c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 262c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 263c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *path, 264c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkPaint* paint) { 265c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ATRACE_CALL(); 266c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 267c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, top, offset; 268c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t width, height; 269c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy computePathBounds(path, paint, left, top, offset, width, height); 270c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 271c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!checkTextureSize(width, height)) return NULL; 272c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 273c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy purgeCache(width, height); 274c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 275c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkBitmap bitmap; 276c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy drawPath(path, paint, bitmap, left, top, offset, width, height); 277c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 278c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = createTexture(left, top, offset, width, height, 279c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path->getGenerationID()); 2804500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, &bitmap, texture); 281c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 282c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 283c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 284c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 2854500a8d5d7fbec9dba5e693212da160849e401ffRomain Guyvoid PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap, 2864500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy PathTexture* texture, bool addToCache) { 287c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy generateTexture(*bitmap, texture); 288c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 289c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t size = texture->width * texture->height; 290c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (size < mMaxSize) { 291c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mSize += size; 292c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", 293c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->id, size, mSize); 294c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (mDebugEnabled) { 295c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGD("Shape created, size = %d", size); 296c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 2974500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy if (addToCache) { 2984500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy mCache.put(entry, texture); 2994500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy } 300c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } else { 3010a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy // It's okay to add a texture that's bigger than the cache since 3020a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy // we'll trim the cache later when addToCache is set to false 3030a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy if (!addToCache) { 3040a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy mSize += size; 3050a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy } 306c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->cleanup = true; 307c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 308c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 309c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 310c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::clear() { 311c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.clear(); 312c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 313c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 314c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { 315c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkAutoLockPixels alp(bitmap); 316c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!bitmap.readyToDraw()) { 317c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGE("Cannot generate texture from bitmap"); 318c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return; 319c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 320c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 321c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glGenTextures(1, &texture->id); 322c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 3238aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Caches::getInstance().bindTexture(texture->id); 324c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Textures are Alpha8 325c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 326c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 327c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->blend = true; 328c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, 329c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels()); 330c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 331c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->setFilter(GL_LINEAR); 332c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE); 333c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 334c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 335c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 336ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy// Path precaching 337ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/////////////////////////////////////////////////////////////////////////////// 338ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 3395dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyPathCache::PathProcessor::PathProcessor(Caches& caches): 3405dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) { 341fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy} 34233f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3435dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guyvoid PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) { 3445dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy sp<PathTask> t = static_cast<PathTask* >(task.get()); 3455dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy ATRACE_NAME("pathPrecache"); 3465dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3475dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy float left, top, offset; 3485dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy uint32_t width, height; 3495dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy PathCache::computePathBounds(t->path, t->paint, left, top, offset, width, height); 3505dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3515dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy PathTexture* texture = t->texture; 3525dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->left = left; 3535dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->top = top; 3545dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->offset = offset; 3555dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->width = width; 3565dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->height = height; 3575dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3585dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (width <= mMaxTextureSize && height <= mMaxTextureSize) { 3595dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = new SkBitmap(); 360c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy drawPath(t->path, t->paint, *bitmap, left, top, offset, width, height); 3615dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy t->setResult(bitmap); 3625dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } else { 3630f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy texture->width = 0; 3640f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy texture->height = 0; 3655dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy t->setResult(NULL); 366ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 36733f6beb10f98e8ba96250e284876d607055d278dRomain Guy} 36833f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3697fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 370c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Paths 3717fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 3727fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 373e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid PathCache::remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair) { 374c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy LruCache<PathDescription, PathTexture*>::Iterator i(mCache); 375059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 376059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy while (i.next()) { 377c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const PathDescription& key = i.key(); 378c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (key.type == kShapePath && 379c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy (key.shape.path.mPath == pair.getFirst() || 380c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy key.shape.path.mPath == pair.getSecond())) { 381059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy pathsToRemove.push(key); 382a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy } 383a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy } 384fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 385fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 386fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid PathCache::removeDeferred(SkPath* path) { 387ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy Mutex::Autolock l(mLock); 388c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy mGarbage.push(path_pair_t(path, const_cast<SkPath*>(path->getSourcePath()))); 389fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 390fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 391fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid PathCache::clearGarbage() { 392e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Vector<PathDescription> pathsToRemove; 393e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 394e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy { // scope for the mutex 395e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock l(mLock); 396e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy size_t count = mGarbage.size(); 397e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < count; i++) { 398e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy remove(pathsToRemove, mGarbage.itemAt(i)); 399e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 400e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mGarbage.clear(); 401e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 402e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 403e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < pathsToRemove.size(); i++) { 404e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mCache.remove(pathsToRemove.itemAt(i)); 405fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 406a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy} 407a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 408ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/** 409ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * To properly handle path mutations at draw time we always make a copy 410ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * of paths objects when recording display lists. The source path points 411ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * to the path we originally copied the path from. This ensures we use 412ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * the original path as a cache key the first time a path is inserted 413ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * in the cache. The source path is also used to reclaim garbage when a 414ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy * Dalvik Path object is collected. 415ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy */ 416ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guystatic SkPath* getSourcePath(SkPath* path) { 4174bcb7467a174ed03a67b0c62950c555813ddf00dRomain Guy const SkPath* sourcePath = path->getSourcePath(); 4184bcb7467a174ed03a67b0c62950c555813ddf00dRomain Guy if (sourcePath && sourcePath->getGenerationID() == path->getGenerationID()) { 419ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy return const_cast<SkPath*>(sourcePath); 4204bcb7467a174ed03a67b0c62950c555813ddf00dRomain Guy } 421ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy return path; 422ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy} 423ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 424ca89e2a68703bd428e8b66547d033a6ed35b3595Romain GuyPathTexture* PathCache::get(SkPath* path, SkPaint* paint) { 425ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy path = getSourcePath(path); 4264bcb7467a174ed03a67b0c62950c555813ddf00dRomain Guy 427c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapePath, paint); 428c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.path.mPath = path; 429c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 4307fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy PathTexture* texture = mCache.get(entry); 4317fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 4327fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (!texture) { 4337fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy texture = addTexture(entry, path, paint); 434ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 435ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // A bitmap is attached to the texture, this means we need to 436ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // upload it as a GL texture 4375dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 4385dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (task != NULL) { 439ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // But we must first wait for the worker thread to be done 440ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // producing the bitmap, so let's wait 4415dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = task->getResult(); 442ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (bitmap) { 4434500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, bitmap, texture, false); 4445dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 445ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 4460f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy ALOGW("Path too large to be rendered into a texture"); 4475dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 448ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy texture = NULL; 449ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.remove(entry); 450ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 451ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else if (path->getGenerationID() != texture->generation) { 4524500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy // The size of the path might have changed so we first 4534500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy // remove the entry from the cache 454ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.remove(entry); 455ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy texture = addTexture(entry, path, paint); 456ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 457ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 458ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 459ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy return texture; 460ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy} 461ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 462ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guyvoid PathCache::precache(SkPath* path, SkPaint* paint) { 4635dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (!Caches::getInstance().tasks.canRunTasks()) { 4645dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy return; 4655dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 4665dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 467ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy path = getSourcePath(path); 468ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 469c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapePath, paint); 470c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.path.mPath = path; 471c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 472ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy PathTexture* texture = mCache.get(entry); 473ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 474ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy bool generate = false; 475ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (!texture) { 476ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy generate = true; 4777fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy } else if (path->getGenerationID() != texture->generation) { 4787fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy mCache.remove(entry); 479ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy generate = true; 4807fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy } 4817fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 482ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (generate) { 483ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // It is important to specify the generation ID so we do not 484ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // attempt to precache the same path several times 4855dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture = createTexture(0.0f, 0.0f, 0.0f, 0, 0, path->getGenerationID()); 4865dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy sp<PathTask> task = new PathTask(path, paint, texture); 4875dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->setTask(task); 488ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 489ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // During the precaching phase we insert path texture objects into 490ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // the cache that do not point to any GL texture. They are instead 491ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // treated as a task for the precaching worker thread. This is why 492ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // we do not check the cache limit when inserting these objects. 493ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // The conversion into GL texture will happen in get(), when a client 494ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // asks for a path texture. This is also when the cache limit will 495ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // be enforced. 496ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.put(entry, texture); 4975dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 4985dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (mProcessor == NULL) { 4995dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy mProcessor = new PathProcessor(Caches::getInstance()); 5005dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 5015dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy mProcessor->add(task); 502ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 5037fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy} 5047fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 505c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 506c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rounded rects 507c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 508c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 509c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getRoundRect(float width, float height, 510c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float rx, float ry, SkPaint* paint) { 511c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeRoundRect, paint); 512c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mWidth = width; 513c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mHeight = height; 514c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRx = rx; 515c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRy = ry; 516c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 517c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 518c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 519c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 520c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 521c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 522c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 523c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 524c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 525c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 526c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 527c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 528c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 529c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 530c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 531c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 532c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Circles 533c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 534c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 535c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getCircle(float radius, SkPaint* paint) { 536c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeCircle, paint); 537c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.circle.mRadius = radius; 538c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 539c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 540c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 541c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 542c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 543c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addCircle(radius, radius, radius, SkPath::kCW_Direction); 544c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 545c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 546c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 547c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 548c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 549c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 550c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 551c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 552c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Ovals 553c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 554c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 555c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getOval(float width, float height, SkPaint* paint) { 556c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeOval, paint); 557c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mWidth = width; 558c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mHeight = height; 559c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 560c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 561c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 562c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 563c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 564c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 565c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 566c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addOval(r, SkPath::kCW_Direction); 567c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 568c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 569c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 570c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 571c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 572c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 573c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 574c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 575c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rects 576c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 577c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 578c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getRect(float width, float height, SkPaint* paint) { 579c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeRect, paint); 580c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mWidth = width; 581c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mHeight = height; 582c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 583c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 584c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 585c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 586c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 587c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 588c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 589c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRect(r, SkPath::kCW_Direction); 590c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 591c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 592c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 593c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 594c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 595c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 596c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 597c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 598c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Arcs 599c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 600c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 601c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getArc(float width, float height, 602c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { 603c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeArc, paint); 604c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mWidth = width; 605c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mHeight = height; 606c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mStartAngle = startAngle; 607c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mSweepAngle = sweepAngle; 608c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mUseCenter = useCenter; 609c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 610c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 611c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 612c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 613c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 614c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 615c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 616c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 617c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.moveTo(r.centerX(), r.centerY()); 618c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 619c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.arcTo(r, startAngle, sweepAngle, !useCenter); 620c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 621c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.close(); 622c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 623c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 624c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 625c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 626c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 627c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 628c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 629c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 6307fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace uirenderer 6317fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace android 632