OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkBitmapCache.h" | 9 #include "SkBitmapCache.h" |
10 #include "SkImage_Base.h" | 10 #include "SkImage_Base.h" |
11 #include "SkImageCacherator.h" | 11 #include "SkImageCacherator.h" |
12 #include "SkMallocPixelRef.h" | 12 #include "SkMallocPixelRef.h" |
13 #include "SkNextID.h" | 13 #include "SkNextID.h" |
14 #include "SkPixelRef.h" | 14 #include "SkPixelRef.h" |
15 #include "SkResourceCache.h" | 15 #include "SkResourceCache.h" |
| 16 #include <SkCanvas.h> |
16 | 17 |
17 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
18 #include "GrContext.h" | 19 #include "GrContext.h" |
19 #include "GrGpuResourcePriv.h" | 20 #include "GrGpuResourcePriv.h" |
20 #include "GrResourceKey.h" | 21 #include "GrResourceKey.h" |
21 #include "GrTextureParams.h" | 22 #include "GrTextureParams.h" |
22 #include "GrYUVProvider.h" | 23 #include "GrYUVProvider.h" |
23 #include "SkGr.h" | 24 #include "SkGr.h" |
24 #include "SkGrPriv.h" | 25 #include "SkGrPriv.h" |
25 #endif | 26 #endif |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { | 77 static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { |
77 SkASSERT(bitmap.getGenerationID() == expectedID); | 78 SkASSERT(bitmap.getGenerationID() == expectedID); |
78 SkASSERT(bitmap.isImmutable()); | 79 SkASSERT(bitmap.isImmutable()); |
79 SkASSERT(bitmap.getPixels()); | 80 SkASSERT(bitmap.getPixels()); |
80 return true; | 81 return true; |
81 } | 82 } |
82 | 83 |
83 // Note, this returns a new, mutable, bitmap, with a new genID. | 84 // Note, this returns a new, mutable, bitmap, with a new genID. |
84 // If you want the immutable bitmap with the same ID as our cacherator, call try
LockAsBitmap() | 85 // If you want the immutable bitmap with the same ID as our cacherator, call try
LockAsBitmap() |
85 // | 86 // |
86 bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { | 87 bool SkImageCacherator::generateBitmap(SkBitmap* bitmap, SkScalar scaleHint) { |
87 SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); | 88 SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); |
88 | 89 |
89 ScopedGenerator generator(this); | 90 ScopedGenerator generator(this); |
90 const SkImageInfo& genInfo = generator->getInfo(); | 91 SkImageInfo genInfo = generator->getInfo(); |
91 if (fInfo.dimensions() == genInfo.dimensions()) { | 92 if (fInfo.dimensions() == genInfo.dimensions()) { |
92 SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); | 93 SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); |
93 // fast-case, no copy needed | 94 SkISize size; |
94 return generator->tryGenerateBitmap(bitmap, fInfo, allocator); | 95 SkImageGenerator::Result res = generator->canDecodeAndScale(kRGB_565_SkC
olorType, scaleHint, &size, nullptr); |
| 96 if (!(res & SkImageGenerator::kScale)) |
| 97 size = genInfo.dimensions(); |
| 98 if (res & SkImageGenerator::kDecode) { |
| 99 genInfo = genInfo.Make(size.width(), size.height(), kRGB_565_SkColor
Type, |
| 100 kOpaque_SkAlphaType, genInfo.profileType()); |
| 101 } else { |
| 102 genInfo = genInfo.makeWH(size.width(), size.height()); |
| 103 } |
| 104 return generator->tryGenerateBitmap(bitmap, genInfo, allocator); |
95 } else { | 105 } else { |
96 // need to handle subsetting, so we first generate the full size version
, and then | 106 // need to handle subsetting, so we first generate the full size version
, and then |
97 // "read" from it to get our subset. See skbug.com/4213 | 107 // "read" from it to get our subset. See skbug.com/4213 |
98 | 108 // TODO SkImageGenerator::getPixels with smaller size implies downscalli
ng, not a subset |
99 SkBitmap full; | 109 SkBitmap full; |
100 if (!generator->tryGenerateBitmap(&full, genInfo, allocator)) { | 110 if (!generator->tryGenerateBitmap(&full, genInfo, allocator)) { |
101 return false; | 111 return false; |
102 } | 112 } |
103 if (!bitmap->tryAllocPixels(fInfo, nullptr, full.getColorTable())) { | 113 if (!bitmap->tryAllocPixels(fInfo, nullptr, full.getColorTable())) { |
104 return false; | 114 return false; |
105 } | 115 } |
106 return full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowB
ytes(), | 116 return full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowB
ytes(), |
107 fOrigin.x(), fOrigin.y()); | 117 fOrigin.x(), fOrigin.y()); |
108 } | 118 } |
109 } | 119 } |
110 | 120 |
111 ////////////////////////////////////////////////////////////////////////////////
////////////////// | 121 ////////////////////////////////////////////////////////////////////////////////
////////////////// |
112 | 122 |
113 bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client)
{ | 123 static bool bitmap_fits_scale(const SkISize &fullSize, const SkBitmap *scaled, c
onst SkScalar scaleHint) { |
114 if (SkBitmapCache::Find(fUniqueID, bitmap)) { | 124 // This optimization is about memory and required quality - it is not about
sample cost of large textures on GPU: |
115 return check_output_bitmap(*bitmap, fUniqueID); | 125 // if the bitmap is already available and larger than hinted, use it. |
| 126 if (scaled->width() < SkScalarFloorToInt(scaleHint * SkIntToScalar(fullSize.
width()))) |
| 127 return false; |
| 128 return true; |
| 129 } |
| 130 |
| 131 bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client,
const SkScalar scaleHint) { |
| 132 bool foundInCache = SkBitmapCache::Find(fUniqueID, bitmap); |
| 133 if (foundInCache) { |
| 134 if (bitmap_fits_scale(info().dimensions(), bitmap, scaleHint)) { |
| 135 return check_output_bitmap(*bitmap, fUniqueID); |
| 136 } |
| 137 // if it doesn't fit the size, generate new one |
116 } | 138 } |
117 | 139 |
118 if (!this->generateBitmap(bitmap)) { | 140 if (!this->generateBitmap(bitmap, scaleHint)) { |
119 return false; | 141 return false; |
120 } | 142 } |
121 | 143 |
122 bitmap->pixelRef()->setImmutableWithID(fUniqueID); | 144 bitmap->pixelRef()->setImmutableWithID(fUniqueID); |
| 145 // if inadequate scale was in cache, remove it from cache first |
| 146 if (foundInCache) |
| 147 SkNotifyBitmapGenIDIsStale(fUniqueID); |
123 SkBitmapCache::Add(fUniqueID, *bitmap); | 148 SkBitmapCache::Add(fUniqueID, *bitmap); |
124 if (client) { | 149 if (client) { |
125 as_IB(client)->notifyAddedToCache(); | 150 as_IB(client)->notifyAddedToCache(); |
126 } | 151 } |
127 | 152 |
128 return true; | 153 return true; |
129 } | 154 } |
130 | 155 |
131 bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client) { | 156 bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, Sk
Scalar scaleHint) { |
132 if (this->tryLockAsBitmap(bitmap, client)) { | 157 if (this->tryLockAsBitmap(bitmap, client, scaleHint)) { |
133 return check_output_bitmap(*bitmap, fUniqueID); | 158 return check_output_bitmap(*bitmap, fUniqueID); |
134 } | 159 } |
135 | 160 |
136 #if SK_SUPPORT_GPU | 161 #if SK_SUPPORT_GPU |
137 // Try to get a texture and read it back to raster (and then cache that with
our ID) | 162 // Try to get a texture and read it back to raster (and then cache that with
our ID) |
138 SkAutoTUnref<GrTexture> tex; | 163 SkAutoTUnref<GrTexture> tex; |
139 | 164 |
140 { | 165 { |
141 ScopedGenerator generator(this); | 166 ScopedGenerator generator(this); |
142 SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width
(), fInfo.height()); | 167 SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width
(), fInfo.height()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 | 202 |
178 static GrTexture* load_compressed_into_texture(GrContext* ctx, SkData* data, GrS
urfaceDesc desc) { | 203 static GrTexture* load_compressed_into_texture(GrContext* ctx, SkData* data, GrS
urfaceDesc desc) { |
179 const void* rawStart; | 204 const void* rawStart; |
180 GrPixelConfig config = GrIsCompressedTextureDataSupported(ctx, data, desc.fW
idth, desc.fHeight, | 205 GrPixelConfig config = GrIsCompressedTextureDataSupported(ctx, data, desc.fW
idth, desc.fHeight, |
181 &rawStart); | 206 &rawStart); |
182 if (kUnknown_GrPixelConfig == config) { | 207 if (kUnknown_GrPixelConfig == config) { |
183 return nullptr; | 208 return nullptr; |
184 } | 209 } |
185 | 210 |
186 desc.fConfig = config; | 211 desc.fConfig = config; |
| 212 |
187 return ctx->textureProvider()->createTexture(desc, true, rawStart, 0); | 213 return ctx->textureProvider()->createTexture(desc, true, rawStart, 0); |
188 } | 214 } |
189 | 215 |
190 class Generator_GrYUVProvider : public GrYUVProvider { | 216 class Generator_GrYUVProvider : public GrYUVProvider { |
191 SkImageGenerator* fGen; | 217 SkImageGenerator* fGen; |
192 | 218 |
193 public: | 219 public: |
194 Generator_GrYUVProvider(SkImageGenerator* gen) : fGen(gen) {} | 220 Generator_GrYUVProvider(SkImageGenerator* gen) : fGen(gen) {} |
195 | 221 |
196 uint32_t onGetID() override { return fGen->uniqueID(); } | 222 uint32_t onGetID() override { return fGen->uniqueID(); } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 } | 357 } |
332 | 358 |
333 #else | 359 #else |
334 | 360 |
335 GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, const GrTextureParam
s&, | 361 GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, const GrTextureParam
s&, |
336 const SkImage* client) { | 362 const SkImage* client) { |
337 return nullptr; | 363 return nullptr; |
338 } | 364 } |
339 | 365 |
340 #endif | 366 #endif |
OLD | NEW |