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> 2298d608dba6a0b3c15fb08f1fa2c8b9d170124c7cChris Craik#include <SkColor.h> 23c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPaint.h> 24c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPath.h> 25c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkRect.h> 26a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 27c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/JenkinsHash.h> 28c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/Trace.h> 29ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 30ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy#include "Caches.h" 317fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy#include "PathCache.h" 32c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 33c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/Signal.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 43e2bb380bc26749782c873e5488cfdf4e42b27346Chris CraikPathDescription::PathDescription() 44e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik : type(kShapeNone) 45e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , join(SkPaint::kDefault_Join) 46e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , cap(SkPaint::kDefault_Cap) 47e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , style(SkPaint::kFill_Style) 48e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , miter(4.0f) 49e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , strokeWidth(1.0f) 50e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , pathEffect(nullptr) { 51c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy memset(&shape, 0, sizeof(Shape)); 52c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 53c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 54e2bb380bc26749782c873e5488cfdf4e42b27346Chris CraikPathDescription::PathDescription(ShapeType type, const SkPaint* paint) 55e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik : type(type) 56e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , join(paint->getStrokeJoin()) 57e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , cap(paint->getStrokeCap()) 58e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , style(paint->getStyle()) 59e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , miter(paint->getStrokeMiter()) 60e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , strokeWidth(paint->getStrokeWidth()) 61e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , 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 Guy/////////////////////////////////////////////////////////////////////////////// 78c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Utilities 79c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 80c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 81d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikbool PathCache::canDrawAsConvexPath(SkPath* path, const SkPaint* paint) { 82c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // NOTE: This should only be used after PathTessellator handles joins properly 83d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik return paint->getPathEffect() == nullptr && path->getConvexity() == SkPath::kConvex_Convexity; 84c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 85c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 86c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computePathBounds(const SkPath* path, const SkPaint* paint, 87c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 88c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkRect& bounds = path->getBounds(); 89c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathCache::computeBounds(bounds, paint, left, top, offset, width, height); 90c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 91c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 92c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computeBounds(const SkRect& bounds, const SkPaint* paint, 93c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 94e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik const float pathWidth = std::max(bounds.width(), 1.0f); 95e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik const float pathHeight = std::max(bounds.height(), 1.0f); 96c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 97c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy left = bounds.fLeft; 98c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy top = bounds.fTop; 99c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 100e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik offset = (int) floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); 101c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 102c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy width = uint32_t(pathWidth + offset * 2.0 + 0.5); 103c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy height = uint32_t(pathHeight + offset * 2.0 + 0.5); 104c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 105c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 106c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) { 107b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed bitmap.allocPixels(SkImageInfo::MakeA8(width, height)); 108c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy bitmap.eraseColor(0); 109c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 110c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 111c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initPaint(SkPaint& paint) { 112c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Make sure the paint is opaque, color, alpha, filter, etc. 113c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // will be applied later when compositing the alpha8 texture 11498d608dba6a0b3c15fb08f1fa2c8b9d170124c7cChris Craik paint.setColor(SK_ColorBLACK); 115c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setAlpha(255); 116d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setColorFilter(nullptr); 117d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setMaskFilter(nullptr); 118d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setShader(nullptr); 119c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode); 120c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkSafeUnref(paint.setXfermode(mode)); 121c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 122c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 123c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, 124c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, float top, float offset, uint32_t width, uint32_t height) { 125c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initBitmap(bitmap, width, height); 126c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 127c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPaint pathPaint(*paint); 128c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initPaint(pathPaint); 129c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 130c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkCanvas canvas(bitmap); 131c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.translate(-left + offset, -top + offset); 132c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.drawPath(*path, pathPaint); 133c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 134c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 135c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 136c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Cache constructor/destructor 137c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 138c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 139c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathCache::PathCache(): 140c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity), 141c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) { 142c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy char property[PROPERTY_VALUE_MAX]; 143d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) { 144c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy INIT_LOGD(" Setting %s cache size to %sMB", name, property); 14542455fc9182cfe0c9f91c77712541888ca61df9eChris Craik mMaxSize = MB(atof(property)); 146c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } else { 147c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_PATH_CACHE_SIZE); 148c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 149c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 150c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.setOnEntryRemovedListener(this); 151c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 152c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy GLint maxTextureSize; 153c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 154c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mMaxTextureSize = maxTextureSize; 155c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 1562507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik mDebugEnabled = Properties::debugLevel & kDebugCaches; 157c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 158c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 15905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikPathCache::~PathCache() { 16005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 16105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 16205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 163c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 164c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Size management 165c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 166c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 167c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getSize() { 168c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mSize; 169c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 170c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 171c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getMaxSize() { 172c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mMaxSize; 173c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 174c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 175c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 176c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Callbacks 177c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 178c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 17964bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampevoid PathCache::operator()(PathDescription& entry, PathTexture*& texture) { 180c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy removeTexture(texture); 181c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 182c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 183c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 184c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Caching 185c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 186c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 187c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::removeTexture(PathTexture* texture) { 188c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (texture) { 189c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const uint32_t size = texture->width * texture->height; 1905d923200846ed59e813373bde789d97d4ccc40b5Romain Guy 1915d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task we must wait for it to return 1925d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // before attempting our cleanup 1935d923200846ed59e813373bde789d97d4ccc40b5Romain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 194d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (task != nullptr) { 1951e19674107e1aa2224c2b8c7d12bfa057efe80eaAndreas Gampe task->getResult(); 1965d923200846ed59e813373bde789d97d4ccc40b5Romain Guy texture->clearTask(); 1975d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } else { 1985d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task, the path was not added 1995d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // to the cache and the size wasn't increased 2005d923200846ed59e813373bde789d97d4ccc40b5Romain Guy if (size > mSize) { 2015d923200846ed59e813373bde789d97d4ccc40b5Romain Guy ALOGE("Removing path texture of size %d will leave " 2025d923200846ed59e813373bde789d97d4ccc40b5Romain Guy "the cache in an inconsistent state", size); 2035d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 2045d923200846ed59e813373bde789d97d4ccc40b5Romain Guy mSize -= size; 2055d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 206c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 207c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", 208c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->id, size, mSize); 209c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (mDebugEnabled) { 210c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGD("Shape deleted, size = %d", size); 211c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 212c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 213c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (texture->id) { 21444eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik Caches::getInstance().textureState().deleteTexture(texture->id); 215c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 216c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy delete texture; 217c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 218c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 219c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 220c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::purgeCache(uint32_t width, uint32_t height) { 221c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const uint32_t size = width * height; 222c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 223c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (size < mMaxSize) { 224c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize + size > mMaxSize) { 225c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 226c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 227c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 228c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 229c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 230c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::trim() { 231c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize > mMaxSize) { 232c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 233c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 234c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 235c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 236c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *path, 237c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkPaint* paint) { 23870850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik ATRACE_NAME("Generate Path Texture"); 239c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 240c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, top, offset; 241c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t width, height; 242c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy computePathBounds(path, paint, left, top, offset, width, height); 243c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 244d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (!checkTextureSize(width, height)) return nullptr; 245c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 246c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy purgeCache(width, height); 247c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 248c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkBitmap bitmap; 249c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy drawPath(path, paint, bitmap, left, top, offset, width, height); 250c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 251e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik PathTexture* texture = new PathTexture(Caches::getInstance(), 252e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik left, top, offset, width, height, 253c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path->getGenerationID()); 2544500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, &bitmap, texture); 255c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 256c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 257c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 258c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 2594500a8d5d7fbec9dba5e693212da160849e401ffRomain Guyvoid PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap, 2604500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy PathTexture* texture, bool addToCache) { 261c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy generateTexture(*bitmap, texture); 262c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 26342455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // Note here that we upload to a texture even if it's bigger than mMaxSize. 26442455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // Such an entry in mCache will only be temporary, since it will be evicted 26542455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // immediately on trim, or on any other Path entering the cache. 266c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t size = texture->width * texture->height; 26742455fc9182cfe0c9f91c77712541888ca61df9eChris Craik mSize += size; 26842455fc9182cfe0c9f91c77712541888ca61df9eChris Craik PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", 26942455fc9182cfe0c9f91c77712541888ca61df9eChris Craik texture->id, size, mSize); 27042455fc9182cfe0c9f91c77712541888ca61df9eChris Craik if (mDebugEnabled) { 27142455fc9182cfe0c9f91c77712541888ca61df9eChris Craik ALOGD("Shape created, size = %d", size); 27242455fc9182cfe0c9f91c77712541888ca61df9eChris Craik } 27342455fc9182cfe0c9f91c77712541888ca61df9eChris Craik if (addToCache) { 27442455fc9182cfe0c9f91c77712541888ca61df9eChris Craik mCache.put(entry, texture); 275c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 276c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 277c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 278c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::clear() { 279c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.clear(); 280c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 281c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 282c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { 283cf8426c4eb60924d2387e0769d6cdc426178a31fChris Craik ATRACE_NAME("Upload Path Texture"); 284c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkAutoLockPixels alp(bitmap); 285c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!bitmap.readyToDraw()) { 286c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGE("Cannot generate texture from bitmap"); 287c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return; 288c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 289c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 290c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glGenTextures(1, &texture->id); 291c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 29244eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik Caches::getInstance().textureState().bindTexture(texture->id); 293c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Textures are Alpha8 294c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 295c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 296c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->blend = true; 297c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, 298c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels()); 299c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 300c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->setFilter(GL_LINEAR); 301c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE); 302c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 303c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 304c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 305ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy// Path precaching 306ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/////////////////////////////////////////////////////////////////////////////// 307ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 3085dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyPathCache::PathProcessor::PathProcessor(Caches& caches): 3095dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) { 310fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy} 31133f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3125dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guyvoid PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) { 31305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTask* t = static_cast<PathTask*>(task.get()); 3145dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy ATRACE_NAME("pathPrecache"); 3155dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3165dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy float left, top, offset; 3175dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy uint32_t width, height; 318906d47fd2bcedb9674b5765d01bd9c758069074cChris Craik PathCache::computePathBounds(&t->path, &t->paint, left, top, offset, width, height); 3195dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3205dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy PathTexture* texture = t->texture; 3215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->left = left; 3225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->top = top; 3235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->offset = offset; 3245dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->width = width; 3255dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->height = height; 3265dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3275dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (width <= mMaxTextureSize && height <= mMaxTextureSize) { 3285dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = new SkBitmap(); 329906d47fd2bcedb9674b5765d01bd9c758069074cChris Craik drawPath(&t->path, &t->paint, *bitmap, left, top, offset, width, height); 3305dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy t->setResult(bitmap); 3315dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } else { 3320f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy texture->width = 0; 3330f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy texture->height = 0; 334d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik t->setResult(nullptr); 335ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 33633f6beb10f98e8ba96250e284876d607055d278dRomain Guy} 33733f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3387fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 339c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Paths 3407fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 3417fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 342ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenbergervoid PathCache::removeDeferred(const SkPath* path) { 343ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy Mutex::Autolock l(mLock); 344ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger mGarbage.push(path->getGenerationID()); 345fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 346fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 347fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid PathCache::clearGarbage() { 348e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Vector<PathDescription> pathsToRemove; 349e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 350e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy { // scope for the mutex 351e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock l(mLock); 352e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy size_t count = mGarbage.size(); 353e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < count; i++) { 354ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger const uint32_t generationID = mGarbage.itemAt(i); 355ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger 356ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger LruCache<PathDescription, PathTexture*>::Iterator iter(mCache); 357ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger while (iter.next()) { 358ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger const PathDescription& key = iter.key(); 359ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger if (key.type == kShapePath && key.shape.path.mGenerationID == generationID) { 360ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger pathsToRemove.push(key); 361ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger } 362ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger } 363e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 364e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mGarbage.clear(); 365e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 366e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 367e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < pathsToRemove.size(); i++) { 368e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mCache.remove(pathsToRemove.itemAt(i)); 369fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 370a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy} 371a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 372d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { 373c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapePath, paint); 374ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger entry.shape.path.mGenerationID = path->getGenerationID(); 375c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 3767fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy PathTexture* texture = mCache.get(entry); 3777fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 3787fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (!texture) { 3797fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy texture = addTexture(entry, path, paint); 380ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 381ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // A bitmap is attached to the texture, this means we need to 382ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // upload it as a GL texture 3835dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 384d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (task != nullptr) { 385ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // But we must first wait for the worker thread to be done 386ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // producing the bitmap, so let's wait 3875dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = task->getResult(); 388ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (bitmap) { 3894500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, bitmap, texture, false); 3905dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 391ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 3920f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy ALOGW("Path too large to be rendered into a texture"); 3935dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 394d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik texture = nullptr; 395ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.remove(entry); 396ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 397ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 398ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 399ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 400ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy return texture; 401ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy} 402ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 403d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid PathCache::precache(const SkPath* path, const SkPaint* paint) { 4045dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (!Caches::getInstance().tasks.canRunTasks()) { 4055dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy return; 4065dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 4075dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 408c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapePath, paint); 409ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger entry.shape.path.mGenerationID = path->getGenerationID(); 410c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 411ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy PathTexture* texture = mCache.get(entry); 412ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 413ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy bool generate = false; 414ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (!texture) { 415ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy generate = true; 4167fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy } 4177fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 418ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (generate) { 419ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // It is important to specify the generation ID so we do not 420ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // attempt to precache the same path several times 421e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik texture = new PathTexture(Caches::getInstance(), path->getGenerationID()); 4225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy sp<PathTask> task = new PathTask(path, paint, texture); 4235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->setTask(task); 424ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 425ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // During the precaching phase we insert path texture objects into 426ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // the cache that do not point to any GL texture. They are instead 427ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // treated as a task for the precaching worker thread. This is why 428ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // we do not check the cache limit when inserting these objects. 429ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // The conversion into GL texture will happen in get(), when a client 430ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // asks for a path texture. This is also when the cache limit will 431ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // be enforced. 432ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.put(entry, texture); 4335dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 434d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (mProcessor == nullptr) { 4355dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy mProcessor = new PathProcessor(Caches::getInstance()); 4365dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 437dee66b6d99dec8bc97843542d5388e50ebd0f6eeChris Craik mProcessor->add(task); 438ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 4397fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy} 4407fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 441c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 442c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rounded rects 443c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 444c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 445c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getRoundRect(float width, float height, 446d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik float rx, float ry, const SkPaint* paint) { 447c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeRoundRect, paint); 448c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mWidth = width; 449c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mHeight = height; 450c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRx = rx; 451c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRy = ry; 452c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 453c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 454c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 455c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 456c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 457c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 458c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 459c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 460c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 461c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 462c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 463c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 464c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 465c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 466c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 467c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 468c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Circles 469c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 470c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 471d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getCircle(float radius, const SkPaint* paint) { 472c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeCircle, paint); 473c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.circle.mRadius = radius; 474c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 475c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 476c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 477c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 478c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 479c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addCircle(radius, radius, radius, SkPath::kCW_Direction); 480c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 481c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 482c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 483c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 484c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 485c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 486c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 487c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 488c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Ovals 489c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 490c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 491d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) { 492c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeOval, paint); 493c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mWidth = width; 494c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mHeight = height; 495c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 496c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 497c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 498c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 499c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 500c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 501c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 502c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addOval(r, SkPath::kCW_Direction); 503c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 504c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 505c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 506c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 507c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 508c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 509c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 510c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 511c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rects 512c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 513c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 514d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) { 515c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeRect, paint); 516c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mWidth = width; 517c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mHeight = height; 518c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 519c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 520c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 521c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 522c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 523c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 524c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 525c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRect(r, SkPath::kCW_Direction); 526c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 527c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 528c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 529c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 530c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 531c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 532c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 533c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 534c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Arcs 535c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 536c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 537c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getArc(float width, float height, 538d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { 539c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathDescription entry(kShapeArc, paint); 540c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mWidth = width; 541c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mHeight = height; 542c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mStartAngle = startAngle; 543c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mSweepAngle = sweepAngle; 544c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mUseCenter = useCenter; 545c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 546c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 547c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 548c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 549c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 550c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 551c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 552c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 553c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.moveTo(r.centerX(), r.centerY()); 554c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 555c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.arcTo(r, startAngle, sweepAngle, !useCenter); 556c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 557c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.close(); 558c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 559c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 560c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 561c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 562c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 563c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 564c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 565c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 5667fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace uirenderer 5677fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace android 568