| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 "GrTextureMaker.h" |
| 8 | 9 |
| 9 #include "SkGr.h" | 10 #include "SkGr.h" |
| 10 | 11 |
| 11 #include "GrCaps.h" | 12 #include "GrCaps.h" |
| 12 #include "GrContext.h" | 13 #include "GrContext.h" |
| 13 #include "GrTextureParamsAdjuster.h" | 14 #include "GrDrawContext.h" |
| 14 #include "GrGpuResourcePriv.h" | |
| 15 #include "GrXferProcessor.h" | 15 #include "GrXferProcessor.h" |
| 16 #include "GrYUVProvider.h" | 16 #include "GrYUVProvider.h" |
| 17 | 17 |
| 18 #include "SkColorFilter.h" | 18 #include "SkColorFilter.h" |
| 19 #include "SkConfig8888.h" | 19 #include "SkConfig8888.h" |
| 20 #include "SkCanvas.h" | 20 #include "SkCanvas.h" |
| 21 #include "SkData.h" | 21 #include "SkData.h" |
| 22 #include "SkErrorInternals.h" | 22 #include "SkErrorInternals.h" |
| 23 #include "SkGrPixelRef.h" | 23 #include "SkGrPixelRef.h" |
| 24 #include "SkMessageBus.h" | 24 #include "SkMessageBus.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 41 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { | 41 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { |
| 42 GrSurfaceDesc desc; | 42 GrSurfaceDesc desc; |
| 43 desc.fFlags = kNone_GrSurfaceFlags; | 43 desc.fFlags = kNone_GrSurfaceFlags; |
| 44 desc.fWidth = info.width(); | 44 desc.fWidth = info.width(); |
| 45 desc.fHeight = info.height(); | 45 desc.fHeight = info.height(); |
| 46 desc.fConfig = SkImageInfo2GrPixelConfig(info); | 46 desc.fConfig = SkImageInfo2GrPixelConfig(info); |
| 47 desc.fSampleCnt = 0; | 47 desc.fSampleCnt = 0; |
| 48 return desc; | 48 return desc; |
| 49 } | 49 } |
| 50 | 50 |
| 51 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& ima
geBounds) { | 51 static void get_stretch(const GrCaps& caps, int width, int height, |
| 52 SkASSERT(key); | 52 const GrTextureParams& params, SkGrStretch* stretch) { |
| 53 SkASSERT(imageID); | 53 stretch->fType = SkGrStretch::kNone_Type; |
| 54 SkASSERT(!imageBounds.isEmpty()); | 54 bool doStretch = false; |
| 55 static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomai
n(); | 55 if (params.isTiled() && !caps.npotTextureTileSupport() && |
| 56 GrUniqueKey::Builder builder(key, kImageIDDomain, 5); | 56 (!SkIsPow2(width) || !SkIsPow2(height))) { |
| 57 doStretch = true; |
| 58 stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize())); |
| 59 stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize())); |
| 60 } else if (width < caps.minTextureSize() || height < caps.minTextureSize())
{ |
| 61 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them |
| 62 // up using the GPU. If issues persist we may need to CPU-stretch. |
| 63 doStretch = true; |
| 64 stretch->fWidth = SkTMax(width, caps.minTextureSize()); |
| 65 stretch->fHeight = SkTMax(height, caps.minTextureSize()); |
| 66 } |
| 67 if (doStretch) { |
| 68 switch (params.filterMode()) { |
| 69 case GrTextureParams::kNone_FilterMode: |
| 70 stretch->fType = SkGrStretch::kNearest_Type; |
| 71 break; |
| 72 case GrTextureParams::kBilerp_FilterMode: |
| 73 case GrTextureParams::kMipMap_FilterMode: |
| 74 stretch->fType = SkGrStretch::kBilerp_Type; |
| 75 break; |
| 76 } |
| 77 } else { |
| 78 stretch->fWidth = -1; |
| 79 stretch->fHeight = -1; |
| 80 stretch->fType = SkGrStretch::kNone_Type; |
| 81 } |
| 82 } |
| 83 |
| 84 static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
ct& subset) { |
| 85 SkASSERT(SkIsU16(subset.width())); |
| 86 SkASSERT(SkIsU16(subset.height())); |
| 87 |
| 88 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
| 89 GrUniqueKey::Builder builder(key, kDomain, 4); |
| 57 builder[0] = imageID; | 90 builder[0] = imageID; |
| 58 builder[1] = imageBounds.fLeft; | 91 builder[1] = subset.x(); |
| 59 builder[2] = imageBounds.fTop; | 92 builder[2] = subset.y(); |
| 60 builder[3] = imageBounds.fRight; | 93 builder[3] = subset.width() | (subset.height() << 16); |
| 61 builder[4] = imageBounds.fBottom; | 94 } |
| 95 |
| 96 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, |
| 97 const GrCaps& caps, const GrTextureParams& params) { |
| 98 SkGrStretch stretch; |
| 99 get_stretch(caps, subset.width(), subset.height(), params, &stretch); |
| 100 if (SkGrStretch::kNone_Type != stretch.fType) { |
| 101 GrUniqueKey tmpKey; |
| 102 make_unstretched_key(&tmpKey, imageID, subset); |
| 103 if (!GrMakeStretchedKey(tmpKey, stretch, key)) { |
| 104 *key = tmpKey; |
| 105 } |
| 106 } else { |
| 107 make_unstretched_key(key, imageID, subset); |
| 108 } |
| 62 } | 109 } |
| 63 | 110 |
| 64 GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, | 111 GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, |
| 65 int expectedW, int expectedH, | 112 int expectedW, int expectedH, |
| 66 const void** outStartOfDataToUp
load) { | 113 const void** outStartOfDataToUp
load) { |
| 67 *outStartOfDataToUpload = nullptr; | 114 *outStartOfDataToUpload = nullptr; |
| 68 #ifndef SK_IGNORE_ETC1_SUPPORT | 115 #ifndef SK_IGNORE_ETC1_SUPPORT |
| 69 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { | 116 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { |
| 70 return kUnknown_GrPixelConfig; | 117 return kUnknown_GrPixelConfig; |
| 71 } | 118 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 96 return kUnknown_GrPixelConfig; | 143 return kUnknown_GrPixelConfig; |
| 97 } | 144 } |
| 98 | 145 |
| 99 *outStartOfDataToUpload = ktx.pixelData(); | 146 *outStartOfDataToUpload = ktx.pixelData(); |
| 100 return kETC1_GrPixelConfig; | 147 return kETC1_GrPixelConfig; |
| 101 } | 148 } |
| 102 #endif | 149 #endif |
| 103 return kUnknown_GrPixelConfig; | 150 return kUnknown_GrPixelConfig; |
| 104 } | 151 } |
| 105 | 152 |
| 106 ////////////////////////////////////////////////////////////////////////////// | 153 /* Fill out buffer with the compressed format Ganesh expects from a colortable |
| 154 based bitmap. [palette (colortable) + indices]. |
| 107 | 155 |
| 108 /** | 156 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others |
| 109 * Fill out buffer with the compressed format Ganesh expects from a colortable | 157 we could detect that the colortable.count is <= 16, and then repack the |
| 110 * based bitmap. [palette (colortable) + indices]. | 158 indices as nibbles to save RAM, but it would take more time (i.e. a lot |
| 111 * | 159 slower than memcpy), so skipping that for now. |
| 112 * At the moment Ganesh only supports 8bit version. If Ganesh allowed we others | 160 |
| 113 * we could detect that the colortable.count is <= 16, and then repack the | 161 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big |
| 114 * indices as nibbles to save RAM, but it would take more time (i.e. a lot | 162 as the colortable.count says it is. |
| 115 * slower than memcpy), so skipping that for now. | |
| 116 * | |
| 117 * Ganesh wants a full 256 palette entry, even though Skia's ctable is only as b
ig | |
| 118 * as the colortable.count says it is. | |
| 119 */ | 163 */ |
| 120 static void build_index8_data(void* buffer, const SkBitmap& bitmap) { | 164 static void build_index8_data(void* buffer, const SkBitmap& bitmap) { |
| 121 SkASSERT(kIndex_8_SkColorType == bitmap.colorType()); | 165 SkASSERT(kIndex_8_SkColorType == bitmap.colorType()); |
| 122 | 166 |
| 123 SkAutoLockPixels alp(bitmap); | 167 SkAutoLockPixels alp(bitmap); |
| 124 if (!bitmap.readyToDraw()) { | 168 if (!bitmap.readyToDraw()) { |
| 125 SkDEBUGFAIL("bitmap not ready to draw!"); | 169 SkDEBUGFAIL("bitmap not ready to draw!"); |
| 126 return; | 170 return; |
| 127 } | 171 } |
| 128 | 172 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 156 size_t rowBytes = bitmap.rowBytes(); | 200 size_t rowBytes = bitmap.rowBytes(); |
| 157 const char* src = (const char*)bitmap.getPixels(); | 201 const char* src = (const char*)bitmap.getPixels(); |
| 158 for (int y = 0; y < bitmap.height(); y++) { | 202 for (int y = 0; y < bitmap.height(); y++) { |
| 159 memcpy(dst, src, width); | 203 memcpy(dst, src, width); |
| 160 src += rowBytes; | 204 src += rowBytes; |
| 161 dst += width; | 205 dst += width; |
| 162 } | 206 } |
| 163 } | 207 } |
| 164 } | 208 } |
| 165 | 209 |
| 166 /** | 210 //////////////////////////////////////////////////////////////////////////////// |
| 211 |
| 212 |
| 213 bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, |
| 214 GrUniqueKey* stretchedKey) { |
| 215 if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) { |
| 216 uint32_t width = SkToU16(stretch.fWidth); |
| 217 uint32_t height = SkToU16(stretch.fHeight); |
| 218 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
| 219 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2); |
| 220 builder[0] = stretch.fType; |
| 221 builder[1] = width | (height << 16); |
| 222 builder.finish(); |
| 223 return true; |
| 224 } |
| 225 SkASSERT(!stretchedKey->isValid()); |
| 226 return false; |
| 227 } |
| 228 |
| 229 namespace { |
| 230 |
| 231 // When the SkPixelRef genID changes, invalidate a corresponding GrResource desc
ribed by key. |
| 232 class BitmapInvalidator : public SkPixelRef::GenIDChangeListener { |
| 233 public: |
| 234 explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {} |
| 235 private: |
| 236 GrUniqueKeyInvalidatedMessage fMsg; |
| 237 |
| 238 void onChange() override { |
| 239 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); |
| 240 } |
| 241 }; |
| 242 |
| 243 } // namespace |
| 244 |
| 245 |
| 246 GrTexture* GrCreateTextureForPixels(GrContext* ctx, |
| 247 const GrUniqueKey& optionalKey, |
| 248 GrSurfaceDesc desc, |
| 249 SkPixelRef* pixelRefForInvalidationNotificat
ion, |
| 250 const void* pixels, |
| 251 size_t rowBytes) { |
| 252 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels
, rowBytes); |
| 253 if (result && optionalKey.isValid()) { |
| 254 if (pixelRefForInvalidationNotification) { |
| 255 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); |
| 256 pixelRefForInvalidationNotification->addGenIDChangeListener(listener
); |
| 257 } |
| 258 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result); |
| 259 } |
| 260 return result; |
| 261 } |
| 262 |
| 263 // creates a new texture that is the input texture scaled up. If optionalKey is
valid it will be |
| 264 // set on the new texture. stretch controls whether the scaling is done using ne
arest or bilerp |
| 265 // filtering and the size to stretch the texture to. |
| 266 GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch, |
| 267 SkPixelRef* pixelRef, |
| 268 const GrUniqueKey& optionalKey) { |
| 269 SkASSERT(SkGrStretch::kNone_Type != stretch.fType); |
| 270 |
| 271 GrContext* context = inputTexture->getContext(); |
| 272 SkASSERT(context); |
| 273 const GrCaps* caps = context->caps(); |
| 274 |
| 275 // Either it's a cache miss or the original wasn't cached to begin with. |
| 276 GrSurfaceDesc rtDesc = inputTexture->desc(); |
| 277 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; |
| 278 rtDesc.fWidth = stretch.fWidth; |
| 279 rtDesc.fHeight = stretch.fHeight; |
| 280 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig); |
| 281 |
| 282 // If the config isn't renderable try converting to either A8 or an 32 bit c
onfig. Otherwise, |
| 283 // fail. |
| 284 if (!caps->isConfigRenderable(rtDesc.fConfig, false)) { |
| 285 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) { |
| 286 if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { |
| 287 rtDesc.fConfig = kAlpha_8_GrPixelConfig; |
| 288 } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false))
{ |
| 289 rtDesc.fConfig = kSkia8888_GrPixelConfig; |
| 290 } else { |
| 291 return nullptr; |
| 292 } |
| 293 } else if (kRGB_GrColorComponentFlags == |
| 294 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDe
sc.fConfig))) { |
| 295 if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) { |
| 296 rtDesc.fConfig = kSkia8888_GrPixelConfig; |
| 297 } else { |
| 298 return nullptr; |
| 299 } |
| 300 } else { |
| 301 return nullptr; |
| 302 } |
| 303 } |
| 304 |
| 305 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optional
Key, rtDesc, |
| 306 pixelRef, nullptr
,0)); |
| 307 if (!stretched) { |
| 308 return nullptr; |
| 309 } |
| 310 GrPaint paint; |
| 311 |
| 312 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are |
| 313 // copies of texels from the original. |
| 314 GrTextureParams params(SkShader::kClamp_TileMode, |
| 315 SkGrStretch::kBilerp_Type == stretch.fType ? |
| 316 GrTextureParams::kBilerp_FilterMode : |
| 317 GrTextureParams::kNone_FilterMode); |
| 318 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); |
| 319 |
| 320 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); |
| 321 SkRect localRect = SkRect::MakeWH(1.f, 1.f); |
| 322 |
| 323 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(stretched->asRe
nderTarget())); |
| 324 if (!drawContext) { |
| 325 return nullptr; |
| 326 } |
| 327 |
| 328 drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), r
ect, localRect); |
| 329 |
| 330 return stretched.detach(); |
| 331 } |
| 332 |
| 333 /* |
| 167 * Once we have made SkImages handle all lazy/deferred/generated content, the Y
UV apis will | 334 * Once we have made SkImages handle all lazy/deferred/generated content, the Y
UV apis will |
| 168 * be gone from SkPixelRef, and we can remove this subclass entirely. | 335 * be gone from SkPixelRef, and we can remove this subclass entirely. |
| 169 */ | 336 */ |
| 170 class PixelRef_GrYUVProvider : public GrYUVProvider { | 337 class PixelRef_GrYUVProvider : public GrYUVProvider { |
| 171 SkPixelRef* fPR; | 338 SkPixelRef* fPR; |
| 172 | 339 |
| 173 public: | 340 public: |
| 174 PixelRef_GrYUVProvider(SkPixelRef* pr) : fPR(pr) {} | 341 PixelRef_GrYUVProvider(SkPixelRef* pr) : fPR(pr) {} |
| 175 | 342 |
| 176 uint32_t onGetID() override { return fPR->getGenerationID(); } | 343 uint32_t onGetID() override { return fPR->getGenerationID(); } |
| 177 bool onGetYUVSizes(SkISize sizes[3]) override { | 344 bool onGetYUVSizes(SkISize sizes[3]) override { |
| 178 return fPR->getYUV8Planes(sizes, nullptr, nullptr, nullptr); | 345 return fPR->getYUV8Planes(sizes, nullptr, nullptr, nullptr); |
| 179 } | 346 } |
| 180 bool onGetYUVPlanes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], | 347 bool onGetYUVPlanes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], |
| 181 SkYUVColorSpace* space) override { | 348 SkYUVColorSpace* space) override { |
| 182 return fPR->getYUV8Planes(sizes, planes, rowBytes, space); | 349 return fPR->getYUV8Planes(sizes, planes, rowBytes, space); |
| 183 } | 350 } |
| 184 }; | 351 }; |
| 185 | 352 |
| 186 static GrTexture* create_texture_from_yuv(GrContext* ctx, const SkBitmap& bm, | 353 static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKe
y, |
| 187 const GrSurfaceDesc& desc) { | 354 const SkBitmap& bm, const GrSurfaceDesc& desc
) { |
| 188 // Subsets are not supported, the whole pixelRef is loaded when using YUV de
coding | 355 // Subsets are not supported, the whole pixelRef is loaded when using YUV de
coding |
| 189 SkPixelRef* pixelRef = bm.pixelRef(); | 356 SkPixelRef* pixelRef = bm.pixelRef(); |
| 190 if ((nullptr == pixelRef) || | 357 if ((nullptr == pixelRef) || |
| 191 (pixelRef->info().width() != bm.info().width()) || | 358 (pixelRef->info().width() != bm.info().width()) || |
| 192 (pixelRef->info().height() != bm.info().height())) { | 359 (pixelRef->info().height() != bm.info().height())) { |
| 193 return nullptr; | 360 return nullptr; |
| 194 } | 361 } |
| 195 | 362 |
| 363 const bool useCache = optionalKey.isValid(); |
| 196 PixelRef_GrYUVProvider provider(pixelRef); | 364 PixelRef_GrYUVProvider provider(pixelRef); |
| 365 GrTexture* texture = provider.refAsTexture(ctx, desc, useCache); |
| 366 if (!texture) { |
| 367 return nullptr; |
| 368 } |
| 197 | 369 |
| 198 return provider.refAsTexture(ctx, desc, !bm.isVolatile()); | 370 if (useCache) { |
| 371 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); |
| 372 pixelRef->addGenIDChangeListener(listener); |
| 373 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture); |
| 374 } |
| 375 return texture; |
| 199 } | 376 } |
| 200 | 377 |
| 201 static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfac
eDesc desc) { | 378 static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalK
ey, |
| 379 const SkBitmap &bm, GrSurfaceDesc desc) { |
| 202 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); | 380 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); |
| 203 if (!data) { | 381 if (!data) { |
| 204 return nullptr; | 382 return nullptr; |
| 205 } | 383 } |
| 206 | 384 |
| 207 const void* startOfTexData; | 385 const void* startOfTexData; |
| 208 desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data, bm.width(), bm.
height(), | 386 desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data, bm.width(), bm.
height(), |
| 209 &startOfTexData); | 387 &startOfTexData); |
| 210 if (kUnknown_GrPixelConfig == desc.fConfig) { | 388 if (kUnknown_GrPixelConfig == desc.fConfig) { |
| 211 return nullptr; | 389 return nullptr; |
| 212 } | 390 } |
| 213 | 391 |
| 214 return ctx->textureProvider()->createTexture(desc, true, startOfTexData, 0); | 392 return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), start
OfTexData, 0); |
| 215 } | 393 } |
| 216 | 394 |
| 217 GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) { | 395 static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx, |
| 218 SkASSERT(!bmp.getTexture()); | 396 const SkBitmap& origBitmap, |
| 219 | 397 const GrUniqueKey& optionalK
ey) { |
| 220 if (bmp.width() < ctx->caps()->minTextureSize() || | 398 if (origBitmap.width() < ctx->caps()->minTextureSize() || |
| 221 bmp.height() < ctx->caps()->minTextureSize()) { | 399 origBitmap.height() < ctx->caps()->minTextureSize()) { |
| 222 return nullptr; | 400 return nullptr; |
| 223 } | 401 } |
| 402 SkBitmap tmpBitmap; |
| 224 | 403 |
| 225 SkBitmap tmpBitmap; | 404 const SkBitmap* bitmap = &origBitmap; |
| 226 const SkBitmap* bitmap = &bmp; | |
| 227 | 405 |
| 228 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info()); | 406 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info()); |
| 229 const GrCaps* caps = ctx->caps(); | 407 const GrCaps* caps = ctx->caps(); |
| 230 | 408 |
| 231 if (kIndex_8_SkColorType == bitmap->colorType()) { | 409 if (kIndex_8_SkColorType == bitmap->colorType()) { |
| 232 if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { | 410 if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { |
| 233 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig
, | 411 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig
, |
| 234 bitmap->width(), bitma
p->height()); | 412 bitmap->width(), bitma
p->height()); |
| 235 SkAutoMalloc storage(imageSize); | 413 SkAutoMalloc storage(imageSize); |
| 236 build_index8_data(storage.get(), bmp); | 414 build_index8_data(storage.get(), origBitmap); |
| 237 | 415 |
| 238 // our compressed data will be trimmed, so pass width() for its | 416 // our compressed data will be trimmed, so pass width() for its |
| 239 // "rowBytes", since they are the same now. | 417 // "rowBytes", since they are the same now. |
| 240 return ctx->textureProvider()->createTexture(desc, true, storage.get
(), | 418 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.p
ixelRef(), |
| 241 bitmap->width()); | 419 storage.get(), bitmap->width()); |
| 242 } else { | 420 } else { |
| 243 bmp.copyTo(&tmpBitmap, kN32_SkColorType); | 421 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType); |
| 244 // now bitmap points to our temp, which has been promoted to 32bits | 422 // now bitmap points to our temp, which has been promoted to 32bits |
| 245 bitmap = &tmpBitmap; | 423 bitmap = &tmpBitmap; |
| 246 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info()); | 424 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info()); |
| 247 } | 425 } |
| 248 } else if (!bitmap->readyToDraw()) { | 426 } else if (!bitmap->readyToDraw()) { |
| 249 // If the bitmap had compressed data and was then uncompressed, it'll st
ill return | 427 // If the bitmap had compressed data and was then uncompressed, it'll st
ill return |
| 250 // compressed data on 'refEncodedData' and upload it. Probably not good,
since if | 428 // compressed data on 'refEncodedData' and upload it. Probably not good,
since if |
| 251 // the bitmap has available pixels, then they might not be what the deco
mpressed | 429 // the bitmap has available pixels, then they might not be what the deco
mpressed |
| 252 // data is. | 430 // data is. |
| 253 | 431 GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc); |
| 254 // Really?? We aren't doing this with YUV. | |
| 255 | |
| 256 GrTexture *texture = load_etc1_texture(ctx, *bitmap, desc); | |
| 257 if (texture) { | 432 if (texture) { |
| 258 return texture; | 433 return texture; |
| 259 } | 434 } |
| 260 } | 435 } |
| 261 | 436 |
| 262 GrTexture *texture = create_texture_from_yuv(ctx, *bitmap, desc); | 437 GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc); |
| 263 if (texture) { | 438 if (texture) { |
| 264 return texture; | 439 return texture; |
| 265 } | 440 } |
| 266 | 441 |
| 267 SkAutoLockPixels alp(*bitmap); | 442 SkAutoLockPixels alp(*bitmap); |
| 268 if (!bitmap->readyToDraw()) { | 443 if (!bitmap->readyToDraw()) { |
| 269 return nullptr; | 444 return nullptr; |
| 270 } | 445 } |
| 271 | 446 |
| 272 return ctx->textureProvider()->createTexture(desc, true, bitmap->getPixels()
, | 447 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(
), |
| 273 bitmap->rowBytes()); | 448 bitmap->getPixels(), bitmap->rowBytes()); |
| 274 } | 449 } |
| 275 | 450 |
| 451 static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch)
{ |
| 452 SkBitmap stretched; |
| 453 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight); |
| 454 SkCanvas canvas(stretched); |
| 455 SkPaint paint; |
| 456 switch (stretch.fType) { |
| 457 case SkGrStretch::kNearest_Type: |
| 458 paint.setFilterQuality(kNone_SkFilterQuality); |
| 459 break; |
| 460 case SkGrStretch::kBilerp_Type: |
| 461 paint.setFilterQuality(kLow_SkFilterQuality); |
| 462 break; |
| 463 case SkGrStretch::kNone_Type: |
| 464 SkDEBUGFAIL("Shouldn't get here."); |
| 465 break; |
| 466 } |
| 467 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); |
| 468 canvas.drawBitmapRect(bmp, dstRect, &paint); |
| 469 return stretched; |
| 470 } |
| 276 | 471 |
| 277 //////////////////////////////////////////////////////////////////////////////// | 472 class Bitmap_GrTextureMaker : public GrTextureMaker { |
| 278 | |
| 279 class Bitmap_GrTextureParamsAdjuster : public GrTextureParamsAdjuster { | |
| 280 public: | 473 public: |
| 281 Bitmap_GrTextureParamsAdjuster(const SkBitmap& bitmap) | 474 Bitmap_GrTextureMaker(const SkBitmap& bitmap) |
| 282 : INHERITED(bitmap.width(), bitmap.height()) | 475 : INHERITED(bitmap.width(), bitmap.height()) |
| 283 , fBitmap(bitmap) | 476 , fBitmap(bitmap) |
| 284 { | 477 {} |
| 285 if (!bitmap.isVolatile()) { | |
| 286 SkIPoint origin = bitmap.pixelRefOrigin(); | |
| 287 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.widt
h(), | |
| 288 bitmap.height()); | |
| 289 GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGeneration
ID(), subset); | |
| 290 } | |
| 291 } | |
| 292 | 478 |
| 293 protected: | 479 protected: |
| 294 GrTexture* refOriginalTexture(GrContext* ctx) override { | 480 GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { |
| 295 GrTexture* tex = fBitmap.getTexture(); | 481 GrTexture* tex = fBitmap.getTexture(); |
| 296 if (tex) { | 482 if (tex) { |
| 297 return SkRef(tex); | 483 return SkRef(tex); |
| 298 } | 484 } |
| 299 | 485 |
| 300 if (fOriginalKey.isValid()) { | 486 GrUniqueKey unstretchedKey; |
| 301 tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(fOriginal
Key); | 487 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
| 302 if (tex) { | 488 |
| 303 return tex; | 489 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(unstretchedKey); |
| 304 } | 490 if (result) { |
| 491 return result; |
| 492 } |
| 493 return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey); |
| 494 } |
| 495 |
| 496 bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKe
y) override { |
| 497 if (fBitmap.isVolatile()) { |
| 498 return false; |
| 305 } | 499 } |
| 306 | 500 |
| 307 tex = GrUploadBitmapToTexture(ctx, fBitmap); | 501 GrUniqueKey unstretchedKey; |
| 308 if (tex && fOriginalKey.isValid()) { | 502 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
| 309 tex->resourcePriv().setUniqueKey(fOriginalKey); | 503 return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey); |
| 310 InstallInvalidator(fOriginalKey, fBitmap.pixelRef()); | |
| 311 } | |
| 312 return tex; | |
| 313 } | 504 } |
| 314 | 505 |
| 315 void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) overrid
e { | 506 void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { |
| 316 if (fOriginalKey.isValid()) { | 507 fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretch
edKey)); |
| 317 MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey); | |
| 318 } | |
| 319 } | 508 } |
| 320 | 509 |
| 321 void didCacheCopy(const GrUniqueKey& copyKey) override { | 510 bool onGetROBitmap(SkBitmap* bitmap) override { |
| 322 InstallInvalidator(copyKey, fBitmap.pixelRef()); | |
| 323 } | |
| 324 | |
| 325 bool getROBitmap(SkBitmap* bitmap) override { | |
| 326 SkASSERT(!fBitmap.getTexture()); | |
| 327 *bitmap = fBitmap; | 511 *bitmap = fBitmap; |
| 328 return true; | 512 return true; |
| 329 } | 513 } |
| 330 | 514 |
| 331 private: | 515 private: |
| 332 static void InstallInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef)
{ | 516 const SkBitmap fBitmap; |
| 333 class Invalidator : public SkPixelRef::GenIDChangeListener { | |
| 334 public: | |
| 335 explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {} | |
| 336 private: | |
| 337 GrUniqueKeyInvalidatedMessage fMsg; | |
| 338 | 517 |
| 339 void onChange() override { | 518 typedef GrTextureMaker INHERITED; |
| 340 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); | |
| 341 } | |
| 342 }; | |
| 343 Invalidator* listener = new Invalidator(key); | |
| 344 pixelRef->addGenIDChangeListener(listener); | |
| 345 } | |
| 346 | |
| 347 const SkBitmap fBitmap; | |
| 348 GrUniqueKey fOriginalKey; | |
| 349 | |
| 350 typedef GrTextureParamsAdjuster INHERITED; | |
| 351 }; | 519 }; |
| 352 | 520 |
| 353 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, | 521 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, |
| 354 const GrTextureParams& params) { | 522 const GrTextureParams& params) { |
| 355 return Bitmap_GrTextureParamsAdjuster(bitmap).refTextureForParams(ctx, param
s); | 523 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); |
| 356 } | 524 } |
| 357 | 525 |
| 358 /////////////////////////////////////////////////////////////////////////////// | 526 /////////////////////////////////////////////////////////////////////////////// |
| 359 | 527 |
| 360 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass | 528 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass |
| 361 // alpha info, that will be considered. | 529 // alpha info, that will be considered. |
| 362 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { | 530 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { |
| 363 switch (ct) { | 531 switch (ct) { |
| 364 case kUnknown_SkColorType: | 532 case kUnknown_SkColorType: |
| 365 return kUnknown_GrPixelConfig; | 533 return kUnknown_GrPixelConfig; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 } | 585 } |
| 418 if (ctOut) { | 586 if (ctOut) { |
| 419 *ctOut = ct; | 587 *ctOut = ct; |
| 420 } | 588 } |
| 421 if (ptOut) { | 589 if (ptOut) { |
| 422 *ptOut = pt; | 590 *ptOut = pt; |
| 423 } | 591 } |
| 424 return true; | 592 return true; |
| 425 } | 593 } |
| 426 | 594 |
| 595 |
| 427 ////////////////////////////////////////////////////////////////////////////////
//////////////// | 596 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 428 | 597 |
| 429 static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primi
tiveIsSrc) { | 598 static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primi
tiveIsSrc) { |
| 430 if (primitiveIsSrc) { | 599 if (primitiveIsSrc) { |
| 431 return SkXfermode::kSrc_Mode != mode; | 600 return SkXfermode::kSrc_Mode != mode; |
| 432 } else { | 601 } else { |
| 433 return SkXfermode::kDst_Mode != mode; | 602 return SkXfermode::kDst_Mode != mode; |
| 434 } | 603 } |
| 435 } | 604 } |
| 436 | 605 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 SkErrorInternals::SetError( kInvalidPaint_SkError, | 835 SkErrorInternals::SetError( kInvalidPaint_SkError, |
| 667 "Sorry, I don't understand the filtering
" | 836 "Sorry, I don't understand the filtering
" |
| 668 "mode you asked for. Falling back to " | 837 "mode you asked for. Falling back to " |
| 669 "MIPMaps."); | 838 "MIPMaps."); |
| 670 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 839 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
| 671 break; | 840 break; |
| 672 | 841 |
| 673 } | 842 } |
| 674 return textureFilterMode; | 843 return textureFilterMode; |
| 675 } | 844 } |
| 845 |
| 846 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 847 |
| 848 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam
s& params) { |
| 849 SkGrStretch stretch; |
| 850 get_stretch(*ctx->caps(), this->width(), this->height(), params, &stretch); |
| 851 |
| 852 if (SkGrStretch::kNone_Type == stretch.fType) { |
| 853 return this->onRefUnstretchedTexture(ctx); |
| 854 } |
| 855 |
| 856 GrUniqueKey stretchedKey; |
| 857 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
| 858 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(stretchedKey); |
| 859 if (result) { |
| 860 return result; |
| 861 } |
| 862 } |
| 863 |
| 864 GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch); |
| 865 if (!result) { |
| 866 return nullptr; |
| 867 } |
| 868 |
| 869 if (stretchedKey.isValid()) { |
| 870 ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result); |
| 871 this->onNotifyStretchCached(stretchedKey); |
| 872 } |
| 873 return result; |
| 874 } |
| 875 |
| 876 GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGr
Stretch& stretch) { |
| 877 if (this->width() < ctx->caps()->minTextureSize() || |
| 878 this->height() < ctx->caps()->minTextureSize()) |
| 879 { |
| 880 // we can't trust our ability to use HW to perform the stretch, so we re
quest |
| 881 // a raster instead, and perform the stretch on the CPU. |
| 882 SkBitmap bitmap; |
| 883 if (!this->onGetROBitmap(&bitmap)) { |
| 884 return nullptr; |
| 885 } |
| 886 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); |
| 887 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey(
)); |
| 888 } else { |
| 889 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); |
| 890 if (!unstretched) { |
| 891 return nullptr; |
| 892 } |
| 893 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); |
| 894 } |
| 895 } |
| OLD | NEW |