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 17c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkBitmap.h> 18c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkCanvas.h> 1998d608dba6a0b3c15fb08f1fa2c8b9d170124c7cChris Craik#include <SkColor.h> 20c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPaint.h> 21c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkPath.h> 227224e2b624daea67b5653285c9640f170c096bdbsergeyv#include <SkPathEffect.h> 23c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <SkRect.h> 24a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 25c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/JenkinsHash.h> 26c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/Trace.h> 27ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 28ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy#include "Caches.h" 297fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy#include "PathCache.h" 30c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 31c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/Signal.h" 32c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include "thread/TaskProcessor.h" 337fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 346b50780363d3bb8db600c770183fa07677509ae8John Reck#include <cutils/properties.h> 356b50780363d3bb8db600c770183fa07677509ae8John Reck 367fbcc0492fca03857e3c45064f4aa040af817d55Romain Guynamespace android { 377fbcc0492fca03857e3c45064f4aa040af817d55Romain Guynamespace uirenderer { 387fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 397224e2b624daea67b5653285c9640f170c096bdbsergeyvtemplate <class T> 407224e2b624daea67b5653285c9640f170c096bdbsergeyvstatic bool compareWidthHeight(const T& lhs, const T& rhs) { 417224e2b624daea67b5653285c9640f170c096bdbsergeyv return (lhs.mWidth == rhs.mWidth) && (lhs.mHeight == rhs.mHeight); 427224e2b624daea67b5653285c9640f170c096bdbsergeyv} 437224e2b624daea67b5653285c9640f170c096bdbsergeyv 447224e2b624daea67b5653285c9640f170c096bdbsergeyvstatic bool compareRoundRects(const PathDescription::Shape::RoundRect& lhs, 457224e2b624daea67b5653285c9640f170c096bdbsergeyv const PathDescription::Shape::RoundRect& rhs) { 467224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareWidthHeight(lhs, rhs) && lhs.mRx == rhs.mRx && lhs.mRy == rhs.mRy; 477224e2b624daea67b5653285c9640f170c096bdbsergeyv} 487224e2b624daea67b5653285c9640f170c096bdbsergeyv 497224e2b624daea67b5653285c9640f170c096bdbsergeyvstatic bool compareArcs(const PathDescription::Shape::Arc& lhs, const PathDescription::Shape::Arc& rhs) { 507224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareWidthHeight(lhs, rhs) && lhs.mStartAngle == rhs.mStartAngle && 517224e2b624daea67b5653285c9640f170c096bdbsergeyv lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter; 527224e2b624daea67b5653285c9640f170c096bdbsergeyv} 537224e2b624daea67b5653285c9640f170c096bdbsergeyv 54ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/////////////////////////////////////////////////////////////////////////////// 55c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Cache entries 56c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 57c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 58e2bb380bc26749782c873e5488cfdf4e42b27346Chris CraikPathDescription::PathDescription() 597224e2b624daea67b5653285c9640f170c096bdbsergeyv : type(ShapeType::None) 60e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , join(SkPaint::kDefault_Join) 61e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , cap(SkPaint::kDefault_Cap) 62e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , style(SkPaint::kFill_Style) 63e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , miter(4.0f) 64e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , strokeWidth(1.0f) 65e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , pathEffect(nullptr) { 667224e2b624daea67b5653285c9640f170c096bdbsergeyv // Shape bits should be set to zeroes, because they are used for hash calculation. 67c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy memset(&shape, 0, sizeof(Shape)); 68c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 69c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 70e2bb380bc26749782c873e5488cfdf4e42b27346Chris CraikPathDescription::PathDescription(ShapeType type, const SkPaint* paint) 71e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik : type(type) 72e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , join(paint->getStrokeJoin()) 73e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , cap(paint->getStrokeCap()) 74e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , style(paint->getStyle()) 75e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , miter(paint->getStrokeMiter()) 76e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , strokeWidth(paint->getStrokeWidth()) 77e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , pathEffect(paint->getPathEffect()) { 787224e2b624daea67b5653285c9640f170c096bdbsergeyv // Shape bits should be set to zeroes, because they are used for hash calculation. 79c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy memset(&shape, 0, sizeof(Shape)); 80c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 81c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 82c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyhash_t PathDescription::hash() const { 837224e2b624daea67b5653285c9640f170c096bdbsergeyv uint32_t hash = JenkinsHashMix(0, static_cast<int>(type)); 84c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, join); 85c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, cap); 86c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, style); 87c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(miter)); 88c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); 89c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMix(hash, android::hash_type(pathEffect)); 90c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); 91c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return JenkinsHashWhiten(hash); 92c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 93c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 947224e2b624daea67b5653285c9640f170c096bdbsergeyvbool PathDescription::operator==(const PathDescription& rhs) const { 957224e2b624daea67b5653285c9640f170c096bdbsergeyv if (type != rhs.type) return false; 967224e2b624daea67b5653285c9640f170c096bdbsergeyv if (join != rhs.join) return false; 977224e2b624daea67b5653285c9640f170c096bdbsergeyv if (cap != rhs.cap) return false; 987224e2b624daea67b5653285c9640f170c096bdbsergeyv if (style != rhs.style) return false; 997224e2b624daea67b5653285c9640f170c096bdbsergeyv if (miter != rhs.miter) return false; 1007224e2b624daea67b5653285c9640f170c096bdbsergeyv if (strokeWidth != rhs.strokeWidth) return false; 1017224e2b624daea67b5653285c9640f170c096bdbsergeyv if (pathEffect != rhs.pathEffect) return false; 1027224e2b624daea67b5653285c9640f170c096bdbsergeyv switch (type) { 1037224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::None: 1047224e2b624daea67b5653285c9640f170c096bdbsergeyv return 0; 1057224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::Rect: 1067224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareWidthHeight(shape.rect, rhs.shape.rect); 1077224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::RoundRect: 1087224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareRoundRects(shape.roundRect, rhs.shape.roundRect); 1097224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::Circle: 1107224e2b624daea67b5653285c9640f170c096bdbsergeyv return shape.circle.mRadius == rhs.shape.circle.mRadius; 1117224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::Oval: 1127224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareWidthHeight(shape.oval, rhs.shape.oval); 1137224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::Arc: 1147224e2b624daea67b5653285c9640f170c096bdbsergeyv return compareArcs(shape.arc, rhs.shape.arc); 1157224e2b624daea67b5653285c9640f170c096bdbsergeyv case ShapeType::Path: 1167224e2b624daea67b5653285c9640f170c096bdbsergeyv return shape.path.mGenerationID == rhs.shape.path.mGenerationID; 1177224e2b624daea67b5653285c9640f170c096bdbsergeyv } 1187224e2b624daea67b5653285c9640f170c096bdbsergeyv} 1197224e2b624daea67b5653285c9640f170c096bdbsergeyv 120c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 121c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Utilities 122c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 123c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 124d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikbool PathCache::canDrawAsConvexPath(SkPath* path, const SkPaint* paint) { 125c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // NOTE: This should only be used after PathTessellator handles joins properly 126d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik return paint->getPathEffect() == nullptr && path->getConvexity() == SkPath::kConvex_Convexity; 127c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 128c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 129c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computePathBounds(const SkPath* path, const SkPaint* paint, 130c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 131c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkRect& bounds = path->getBounds(); 132c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathCache::computeBounds(bounds, paint, left, top, offset, width, height); 133c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 134c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 135c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::computeBounds(const SkRect& bounds, const SkPaint* paint, 136c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { 137e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik const float pathWidth = std::max(bounds.width(), 1.0f); 138e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik const float pathHeight = std::max(bounds.height(), 1.0f); 139c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 140c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy left = bounds.fLeft; 141c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy top = bounds.fTop; 142c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 143e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik offset = (int) floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); 144c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 145c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy width = uint32_t(pathWidth + offset * 2.0 + 0.5); 146c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy height = uint32_t(pathHeight + offset * 2.0 + 0.5); 147c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 148c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 149c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) { 150b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed bitmap.allocPixels(SkImageInfo::MakeA8(width, height)); 151c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy bitmap.eraseColor(0); 152c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 153c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 154c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void initPaint(SkPaint& paint) { 155c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Make sure the paint is opaque, color, alpha, filter, etc. 156c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // will be applied later when compositing the alpha8 texture 15798d608dba6a0b3c15fb08f1fa2c8b9d170124c7cChris Craik paint.setColor(SK_ColorBLACK); 158c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy paint.setAlpha(255); 159d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setColorFilter(nullptr); 160d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setMaskFilter(nullptr); 161d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik paint.setShader(nullptr); 162c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode); 163c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkSafeUnref(paint.setXfermode(mode)); 164c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 165c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 166c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guystatic void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, 167c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, float top, float offset, uint32_t width, uint32_t height) { 168c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initBitmap(bitmap, width, height); 169c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 170c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPaint pathPaint(*paint); 171c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy initPaint(pathPaint); 172c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 173c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkCanvas canvas(bitmap); 174c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.translate(-left + offset, -top + offset); 175c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy canvas.drawPath(*path, pathPaint); 176c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 177c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 178c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 179c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Cache constructor/destructor 180c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 181c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 18248a8f431fa52ae2ee25ffba9d20676f03bb710ffChris CraikPathCache::PathCache() 18348a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik : mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity) 18448a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik , mSize(0) 18548a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik , mMaxSize(Properties::pathCacheSize) { 186c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.setOnEntryRemovedListener(this); 187c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 188c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy GLint maxTextureSize; 189c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 190c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mMaxTextureSize = maxTextureSize; 191c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 1922507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik mDebugEnabled = Properties::debugLevel & kDebugCaches; 193c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 194c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 19505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris CraikPathCache::~PathCache() { 19605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik mCache.clear(); 19705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik} 19805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik 199c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 200c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Size management 201c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 202c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 203c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getSize() { 204c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mSize; 205c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 206c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 207c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyuint32_t PathCache::getMaxSize() { 208c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return mMaxSize; 209c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 210c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 211c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 212c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Callbacks 213c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 214c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 21564bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampevoid PathCache::operator()(PathDescription& entry, PathTexture*& texture) { 216c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy removeTexture(texture); 217c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 218c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 219c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 220c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Caching 221c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 222c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 223c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::removeTexture(PathTexture* texture) { 224c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (texture) { 22538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const uint32_t size = texture->width() * texture->height(); 2265d923200846ed59e813373bde789d97d4ccc40b5Romain Guy 2275d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task we must wait for it to return 2285d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // before attempting our cleanup 2295d923200846ed59e813373bde789d97d4ccc40b5Romain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 230d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (task != nullptr) { 2311e19674107e1aa2224c2b8c7d12bfa057efe80eaAndreas Gampe task->getResult(); 2325d923200846ed59e813373bde789d97d4ccc40b5Romain Guy texture->clearTask(); 2335d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } else { 2345d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // If there is a pending task, the path was not added 2355d923200846ed59e813373bde789d97d4ccc40b5Romain Guy // to the cache and the size wasn't increased 2365d923200846ed59e813373bde789d97d4ccc40b5Romain Guy if (size > mSize) { 2375d923200846ed59e813373bde789d97d4ccc40b5Romain Guy ALOGE("Removing path texture of size %d will leave " 2385d923200846ed59e813373bde789d97d4ccc40b5Romain Guy "the cache in an inconsistent state", size); 2395d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 2405d923200846ed59e813373bde789d97d4ccc40b5Romain Guy mSize -= size; 2415d923200846ed59e813373bde789d97d4ccc40b5Romain Guy } 242c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 243c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", 244c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->id, size, mSize); 245c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (mDebugEnabled) { 246c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy ALOGD("Shape deleted, size = %d", size); 247c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 248c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 24938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck texture->deleteTexture(); 250c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy delete texture; 251c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 252c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 253c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 254c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::purgeCache(uint32_t width, uint32_t height) { 255c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const uint32_t size = width * height; 256c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy // Don't even try to cache a bitmap that's bigger than the cache 257c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (size < mMaxSize) { 258c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize + size > mMaxSize) { 259c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 260c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 261c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 262c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 263c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 264c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::trim() { 265c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy while (mSize > mMaxSize) { 266c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.removeOldest(); 267c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 268c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 269c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 270c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *path, 271c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const SkPaint* paint) { 27270850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik ATRACE_NAME("Generate Path Texture"); 273c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 274c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy float left, top, offset; 275c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy uint32_t width, height; 276c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy computePathBounds(path, paint, left, top, offset, width, height); 277c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 278d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (!checkTextureSize(width, height)) return nullptr; 279c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 280c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy purgeCache(width, height); 281c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 282c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkBitmap bitmap; 283c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy drawPath(path, paint, bitmap, left, top, offset, width, height); 284c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 285e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik PathTexture* texture = new PathTexture(Caches::getInstance(), 28638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck left, top, offset, path->getGenerationID()); 2874500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, &bitmap, texture); 288c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 289c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 290c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 291c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 2924500a8d5d7fbec9dba5e693212da160849e401ffRomain Guyvoid PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap, 2934500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy PathTexture* texture, bool addToCache) { 294c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy generateTexture(*bitmap, texture); 295c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 29642455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // Note here that we upload to a texture even if it's bigger than mMaxSize. 29742455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // Such an entry in mCache will only be temporary, since it will be evicted 29842455fc9182cfe0c9f91c77712541888ca61df9eChris Craik // immediately on trim, or on any other Path entering the cache. 29938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck uint32_t size = texture->width() * texture->height(); 30042455fc9182cfe0c9f91c77712541888ca61df9eChris Craik mSize += size; 30142455fc9182cfe0c9f91c77712541888ca61df9eChris Craik PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", 30242455fc9182cfe0c9f91c77712541888ca61df9eChris Craik texture->id, size, mSize); 30342455fc9182cfe0c9f91c77712541888ca61df9eChris Craik if (mDebugEnabled) { 30442455fc9182cfe0c9f91c77712541888ca61df9eChris Craik ALOGD("Shape created, size = %d", size); 30542455fc9182cfe0c9f91c77712541888ca61df9eChris Craik } 30642455fc9182cfe0c9f91c77712541888ca61df9eChris Craik if (addToCache) { 30742455fc9182cfe0c9f91c77712541888ca61df9eChris Craik mCache.put(entry, texture); 308c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 309c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 310c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 311c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::clear() { 312c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCache.clear(); 313c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 314c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 315c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { 316cf8426c4eb60924d2387e0769d6cdc426178a31fChris Craik ATRACE_NAME("Upload Path Texture"); 31738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck texture->upload(bitmap); 318c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture->setFilter(GL_LINEAR); 319c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 320c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 321c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 322ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy// Path precaching 323ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy/////////////////////////////////////////////////////////////////////////////// 324ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 3255dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyPathCache::PathProcessor::PathProcessor(Caches& caches): 3265dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) { 327fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy} 32833f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3295dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guyvoid PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) { 33005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik PathTask* t = static_cast<PathTask*>(task.get()); 3315dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy ATRACE_NAME("pathPrecache"); 3325dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3335dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy float left, top, offset; 3345dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy uint32_t width, height; 335906d47fd2bcedb9674b5765d01bd9c758069074cChris Craik PathCache::computePathBounds(&t->path, &t->paint, left, top, offset, width, height); 3365dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3375dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy PathTexture* texture = t->texture; 3385dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->left = left; 3395dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->top = top; 3405dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->offset = offset; 3415dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 3425dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (width <= mMaxTextureSize && height <= mMaxTextureSize) { 3435dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = new SkBitmap(); 344906d47fd2bcedb9674b5765d01bd9c758069074cChris Craik drawPath(&t->path, &t->paint, *bitmap, left, top, offset, width, height); 3455dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy t->setResult(bitmap); 3465dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } else { 347d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik t->setResult(nullptr); 348ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 34933f6beb10f98e8ba96250e284876d607055d278dRomain Guy} 35033f6beb10f98e8ba96250e284876d607055d278dRomain Guy 3517fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 352c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Paths 3537fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy/////////////////////////////////////////////////////////////////////////////// 3547fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 355ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenbergervoid PathCache::removeDeferred(const SkPath* path) { 356ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy Mutex::Autolock l(mLock); 357272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mGarbage.push_back(path->getGenerationID()); 358fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy} 359fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 360fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guyvoid PathCache::clearGarbage() { 361e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Vector<PathDescription> pathsToRemove; 362e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 363e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy { // scope for the mutex 364e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock l(mLock); 365272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck for (const uint32_t generationID : mGarbage) { 366ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger LruCache<PathDescription, PathTexture*>::Iterator iter(mCache); 367ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger while (iter.next()) { 368ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger const PathDescription& key = iter.key(); 3697224e2b624daea67b5653285c9640f170c096bdbsergeyv if (key.type == ShapeType::Path && key.shape.path.mGenerationID == generationID) { 370ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger pathsToRemove.push(key); 371ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger } 372ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger } 373e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 374e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mGarbage.clear(); 375e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 376e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 377e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy for (size_t i = 0; i < pathsToRemove.size(); i++) { 378e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy mCache.remove(pathsToRemove.itemAt(i)); 379fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy } 380a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy} 381a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 382d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { 3837224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Path, paint); 384ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger entry.shape.path.mGenerationID = path->getGenerationID(); 385c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 3867fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy PathTexture* texture = mCache.get(entry); 3877fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 3887fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (!texture) { 3897fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy texture = addTexture(entry, path, paint); 390ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 391ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // A bitmap is attached to the texture, this means we need to 392ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // upload it as a GL texture 3935dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy const sp<Task<SkBitmap*> >& task = texture->task(); 394d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (task != nullptr) { 395ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // But we must first wait for the worker thread to be done 396ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // producing the bitmap, so let's wait 3975dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy SkBitmap* bitmap = task->getResult(); 398ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (bitmap) { 3994500a8d5d7fbec9dba5e693212da160849e401ffRomain Guy generateTexture(entry, bitmap, texture, false); 4005dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 401ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } else { 4020f809f3b794174f044366bf421f8d0c72d9afc14Romain Guy ALOGW("Path too large to be rendered into a texture"); 4035dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->clearTask(); 404d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik texture = nullptr; 405ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.remove(entry); 406ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 407ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 408ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 409ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 410ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy return texture; 411ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy} 412ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 4137224e2b624daea67b5653285c9640f170c096bdbsergeyvvoid PathCache::remove(const SkPath* path, const SkPaint* paint) { 4147224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Path, paint); 4152e4f67c388aff0def50dd619388624f1dbe359adDigish Pandya entry.shape.path.mGenerationID = path->getGenerationID(); 4162e4f67c388aff0def50dd619388624f1dbe359adDigish Pandya mCache.remove(entry); 4172e4f67c388aff0def50dd619388624f1dbe359adDigish Pandya} 4182e4f67c388aff0def50dd619388624f1dbe359adDigish Pandya 419d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid PathCache::precache(const SkPath* path, const SkPaint* paint) { 4205dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy if (!Caches::getInstance().tasks.canRunTasks()) { 4215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy return; 4225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 4235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 4247224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Path, paint); 425ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger entry.shape.path.mGenerationID = path->getGenerationID(); 426c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 427ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy PathTexture* texture = mCache.get(entry); 428ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 429ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy bool generate = false; 430ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (!texture) { 431ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy generate = true; 4327fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy } 4337fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 434ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (generate) { 435ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // It is important to specify the generation ID so we do not 436ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // attempt to precache the same path several times 437e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik texture = new PathTexture(Caches::getInstance(), path->getGenerationID()); 4385dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy sp<PathTask> task = new PathTask(path, paint, texture); 4395dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy texture->setTask(task); 440ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 441ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // During the precaching phase we insert path texture objects into 442ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // the cache that do not point to any GL texture. They are instead 443ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // treated as a task for the precaching worker thread. This is why 444ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // we do not check the cache limit when inserting these objects. 445ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // The conversion into GL texture will happen in get(), when a client 446ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // asks for a path texture. This is also when the cache limit will 447ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // be enforced. 448ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCache.put(entry, texture); 4495dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy 450d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (mProcessor == nullptr) { 4515dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy mProcessor = new PathProcessor(Caches::getInstance()); 4525dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy } 453dee66b6d99dec8bc97843542d5388e50ebd0f6eeChris Craik mProcessor->add(task); 454ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 4557fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy} 4567fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 457c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 458c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rounded rects 459c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 460c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 461c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getRoundRect(float width, float height, 462d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik float rx, float ry, const SkPaint* paint) { 4637224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::RoundRect, paint); 464c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mWidth = width; 465c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mHeight = height; 466c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRx = rx; 467c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.roundRect.mRy = ry; 468c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 469c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 470c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 471c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 472c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 473c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 474c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 475c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 476c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 477c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 478c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 479c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 480c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 481c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 482c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 483c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 484c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Circles 485c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 486c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 487d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getCircle(float radius, const SkPaint* paint) { 4887224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Circle, paint); 489c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.circle.mRadius = radius; 490c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 491c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 492c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 493c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 494c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 495c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addCircle(radius, radius, radius, SkPath::kCW_Direction); 496c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 497c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 498c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 499c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 500c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 501c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 502c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 503c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 504c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Ovals 505c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 506c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 507d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) { 5087224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Oval, paint); 509c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mWidth = width; 510c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.oval.mHeight = height; 511c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 512c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 513c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 514c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 515c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 516c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 517c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 518c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addOval(r, SkPath::kCW_Direction); 519c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 520c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 521c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 522c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 523c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 524c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 525c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 526c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 527c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Rects 528c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 529c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 530d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikPathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) { 5317224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Rect, paint); 532c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mWidth = width; 533c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.rect.mHeight = height; 534c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 535c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 536c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 537c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 538c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 539c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 540c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 541c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.addRect(r, SkPath::kCW_Direction); 542c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 543c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 544c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 545c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 546c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 547c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 548c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 549c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 550c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy// Arcs 551c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy/////////////////////////////////////////////////////////////////////////////// 552c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 553c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain GuyPathTexture* PathCache::getArc(float width, float height, 554d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { 5557224e2b624daea67b5653285c9640f170c096bdbsergeyv PathDescription entry(ShapeType::Arc, paint); 556c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mWidth = width; 557c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mHeight = height; 558c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mStartAngle = startAngle; 559c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mSweepAngle = sweepAngle; 560c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy entry.shape.arc.mUseCenter = useCenter; 561c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 562c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTexture* texture = get(entry); 563c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 564c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (!texture) { 565c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkPath path; 566c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect r; 567c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy r.set(0.0f, 0.0f, width, height); 568c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 569c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.moveTo(r.centerX(), r.centerY()); 570c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 571c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.arcTo(r, startAngle, sweepAngle, !useCenter); 572c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (useCenter) { 573c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy path.close(); 574c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 575c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 576c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy texture = addTexture(entry, &path, paint); 577c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 578c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 579c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy return texture; 580c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy} 581c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy 5827fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace uirenderer 5837fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy}; // namespace android 584