1 /* 2 * Copyright 2010 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkGr.h" 9 10 #include "GrXferProcessor.h" 11 #include "SkColorFilter.h" 12 #include "SkConfig8888.h" 13 #include "SkData.h" 14 #include "SkErrorInternals.h" 15 #include "SkGrPixelRef.h" 16 #include "SkMessageBus.h" 17 #include "SkPixelRef.h" 18 #include "SkResourceCache.h" 19 #include "SkTextureCompressor.h" 20 #include "SkYUVPlanesCache.h" 21 #include "effects/GrDitherEffect.h" 22 #include "effects/GrPorterDuffXferProcessor.h" 23 #include "effects/GrYUVtoRGBEffect.h" 24 25 #ifndef SK_IGNORE_ETC1_SUPPORT 26 # include "ktx.h" 27 # include "etc1.h" 28 #endif 29 30 /* Fill out buffer with the compressed format Ganesh expects from a colortable 31 based bitmap. [palette (colortable) + indices]. 32 33 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others 34 we could detect that the colortable.count is <= 16, and then repack the 35 indices as nibbles to save RAM, but it would take more time (i.e. a lot 36 slower than memcpy), so skipping that for now. 37 38 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big 39 as the colortable.count says it is. 40 */ 41 static void build_index8_data(void* buffer, const SkBitmap& bitmap) { 42 SkASSERT(kIndex_8_SkColorType == bitmap.colorType()); 43 44 SkAutoLockPixels alp(bitmap); 45 if (!bitmap.readyToDraw()) { 46 SkDEBUGFAIL("bitmap not ready to draw!"); 47 return; 48 } 49 50 SkColorTable* ctable = bitmap.getColorTable(); 51 char* dst = (char*)buffer; 52 53 const int count = ctable->count(); 54 55 SkDstPixelInfo dstPI; 56 dstPI.fColorType = kRGBA_8888_SkColorType; 57 dstPI.fAlphaType = kPremul_SkAlphaType; 58 dstPI.fPixels = buffer; 59 dstPI.fRowBytes = count * sizeof(SkPMColor); 60 61 SkSrcPixelInfo srcPI; 62 srcPI.fColorType = kN32_SkColorType; 63 srcPI.fAlphaType = kPremul_SkAlphaType; 64 srcPI.fPixels = ctable->readColors(); 65 srcPI.fRowBytes = count * sizeof(SkPMColor); 66 67 srcPI.convertPixelsTo(&dstPI, count, 1); 68 69 // always skip a full 256 number of entries, even if we memcpy'd fewer 70 dst += 256 * sizeof(GrColor); 71 72 if ((unsigned)bitmap.width() == bitmap.rowBytes()) { 73 memcpy(dst, bitmap.getPixels(), bitmap.getSize()); 74 } else { 75 // need to trim off the extra bytes per row 76 size_t width = bitmap.width(); 77 size_t rowBytes = bitmap.rowBytes(); 78 const char* src = (const char*)bitmap.getPixels(); 79 for (int y = 0; y < bitmap.height(); y++) { 80 memcpy(dst, src, width); 81 src += rowBytes; 82 dst += width; 83 } 84 } 85 } 86 87 //////////////////////////////////////////////////////////////////////////////// 88 89 enum Stretch { 90 kNo_Stretch, 91 kBilerp_Stretch, 92 kNearest_Stretch 93 }; 94 95 static Stretch get_stretch_type(const GrContext* ctx, int width, int height, 96 const GrTextureParams* params) { 97 if (params && params->isTiled()) { 98 if (!ctx->npotTextureTileSupport() && (!SkIsPow2(width) || !SkIsPow2(height))) { 99 switch(params->filterMode()) { 100 case GrTextureParams::kNone_FilterMode: 101 return kNearest_Stretch; 102 case GrTextureParams::kBilerp_FilterMode: 103 case GrTextureParams::kMipMap_FilterMode: 104 return kBilerp_Stretch; 105 } 106 } 107 } 108 return kNo_Stretch; 109 } 110 111 static bool make_stretched_key(const GrUniqueKey& origKey, Stretch stretch, 112 GrUniqueKey* stretchedKey) { 113 if (origKey.isValid() && kNo_Stretch != stretch) { 114 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 115 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 1); 116 builder[0] = stretch; 117 builder.finish(); 118 return true; 119 } 120 SkASSERT(!stretchedKey->isValid()); 121 return false; 122 } 123 124 static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) { 125 // Our id includes the offset, width, and height so that bitmaps created by extractSubset() 126 // are unique. 127 uint32_t genID = bitmap.getGenerationID(); 128 SkIPoint origin = bitmap.pixelRefOrigin(); 129 uint32_t width = SkToU16(bitmap.width()); 130 uint32_t height = SkToU16(bitmap.height()); 131 132 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 133 GrUniqueKey::Builder builder(key, kDomain, 4); 134 builder[0] = genID; 135 builder[1] = origin.fX; 136 builder[2] = origin.fY; 137 builder[3] = width | (height << 16); 138 } 139 140 static void make_bitmap_keys(const SkBitmap& bitmap, 141 Stretch stretch, 142 GrUniqueKey* key, 143 GrUniqueKey* stretchedKey) { 144 make_unstretched_key(bitmap, key); 145 if (kNo_Stretch != stretch) { 146 make_stretched_key(*key, stretch, stretchedKey); 147 } 148 } 149 150 static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) { 151 desc->fFlags = kNone_GrSurfaceFlags; 152 desc->fWidth = bitmap.width(); 153 desc->fHeight = bitmap.height(); 154 desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); 155 desc->fSampleCnt = 0; 156 } 157 158 namespace { 159 160 // When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key. 161 class BitmapInvalidator : public SkPixelRef::GenIDChangeListener { 162 public: 163 explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {} 164 private: 165 GrUniqueKeyInvalidatedMessage fMsg; 166 167 void onChange() override { 168 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); 169 } 170 }; 171 172 } // namespace 173 174 175 static GrTexture* create_texture_for_bmp(GrContext* ctx, 176 const GrUniqueKey& optionalKey, 177 GrSurfaceDesc desc, 178 SkPixelRef* pixelRefForInvalidationNotification, 179 const void* pixels, 180 size_t rowBytes) { 181 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes); 182 if (result && optionalKey.isValid()) { 183 BitmapInvalidator* listener = SkNEW_ARGS(BitmapInvalidator, (optionalKey)); 184 pixelRefForInvalidationNotification->addGenIDChangeListener(listener); 185 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result); 186 } 187 return result; 188 } 189 190 // creates a new texture that is the input texture scaled up to the next power of two in 191 // width or height. If optionalKey is valid it will be set on the new texture. stretch 192 // controls whether the scaling is done using nearest or bilerp filtering. 193 GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch, 194 SkPixelRef* pixelRef, 195 const GrUniqueKey& optionalKey) { 196 SkASSERT(kNo_Stretch != stretch); 197 198 GrContext* context = inputTexture->getContext(); 199 SkASSERT(context); 200 201 // Either it's a cache miss or the original wasn't cached to begin with. 202 GrSurfaceDesc rtDesc = inputTexture->desc(); 203 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; 204 rtDesc.fWidth = GrNextPow2(rtDesc.fWidth); 205 rtDesc.fHeight = GrNextPow2(rtDesc.fHeight); 206 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig); 207 208 // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise, 209 // fail. 210 if (!context->isConfigRenderable(rtDesc.fConfig, false)) { 211 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) { 212 if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 213 rtDesc.fConfig = kAlpha_8_GrPixelConfig; 214 } else if (context->isConfigRenderable(kSkia8888_GrPixelConfig, false)) { 215 rtDesc.fConfig = kSkia8888_GrPixelConfig; 216 } else { 217 return NULL; 218 } 219 } else if (kRGB_GrColorComponentFlags == 220 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) { 221 if (context->isConfigRenderable(kSkia8888_GrPixelConfig, false)) { 222 rtDesc.fConfig = kSkia8888_GrPixelConfig; 223 } else { 224 return NULL; 225 } 226 } else { 227 return NULL; 228 } 229 } 230 231 GrTexture* stretched = create_texture_for_bmp(context, optionalKey, rtDesc, pixelRef, NULL, 0); 232 233 if (!stretched) { 234 return NULL; 235 } 236 GrPaint paint; 237 238 // If filtering is not desired then we want to ensure all texels in the resampled image are 239 // copies of texels from the original. 240 GrTextureParams params(SkShader::kClamp_TileMode, 241 kBilerp_Stretch == stretch ? GrTextureParams::kBilerp_FilterMode : 242 GrTextureParams::kNone_FilterMode); 243 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); 244 245 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight)); 246 SkRect localRect = SkRect::MakeWH(1.f, 1.f); 247 248 context->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOpen(), paint, 249 SkMatrix::I(), rect, localRect); 250 251 return stretched; 252 } 253 254 #ifndef SK_IGNORE_ETC1_SUPPORT 255 static GrTexture *load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey, 256 const SkBitmap &bm, GrSurfaceDesc desc) { 257 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); 258 259 // Is this even encoded data? 260 if (NULL == data) { 261 return NULL; 262 } 263 264 // Is this a valid PKM encoded data? 265 const uint8_t *bytes = data->bytes(); 266 if (etc1_pkm_is_valid(bytes)) { 267 uint32_t encodedWidth = etc1_pkm_get_width(bytes); 268 uint32_t encodedHeight = etc1_pkm_get_height(bytes); 269 270 // Does the data match the dimensions of the bitmap? If not, 271 // then we don't know how to scale the image to match it... 272 if (encodedWidth != static_cast<uint32_t>(bm.width()) || 273 encodedHeight != static_cast<uint32_t>(bm.height())) { 274 return NULL; 275 } 276 277 // Everything seems good... skip ahead to the data. 278 bytes += ETC_PKM_HEADER_SIZE; 279 desc.fConfig = kETC1_GrPixelConfig; 280 } else if (SkKTXFile::is_ktx(bytes)) { 281 SkKTXFile ktx(data); 282 283 // Is it actually an ETC1 texture? 284 if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { 285 return NULL; 286 } 287 288 // Does the data match the dimensions of the bitmap? If not, 289 // then we don't know how to scale the image to match it... 290 if (ktx.width() != bm.width() || ktx.height() != bm.height()) { 291 return NULL; 292 } 293 294 bytes = ktx.pixelData(); 295 desc.fConfig = kETC1_GrPixelConfig; 296 } else { 297 return NULL; 298 } 299 300 return create_texture_for_bmp(ctx, optionalKey, desc, bm.pixelRef(), bytes, 0); 301 } 302 #endif // SK_IGNORE_ETC1_SUPPORT 303 304 static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey, 305 const SkBitmap& bm, const GrSurfaceDesc& desc) { 306 // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding 307 SkPixelRef* pixelRef = bm.pixelRef(); 308 if ((NULL == pixelRef) || 309 (pixelRef->info().width() != bm.info().width()) || 310 (pixelRef->info().height() != bm.info().height())) { 311 return NULL; 312 } 313 314 const bool useCache = optionalKey.isValid(); 315 SkYUVPlanesCache::Info yuvInfo; 316 SkAutoTUnref<SkCachedData> cachedData; 317 SkAutoMalloc storage; 318 if (useCache) { 319 cachedData.reset(SkYUVPlanesCache::FindAndRef(pixelRef->getGenerationID(), &yuvInfo)); 320 } 321 322 void* planes[3]; 323 if (cachedData.get()) { 324 planes[0] = (void*)cachedData->data(); 325 planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0]; 326 planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1]; 327 } else { 328 // Fetch yuv plane sizes for memory allocation. Here, width and height can be 329 // rounded up to JPEG block size and be larger than the image's width and height. 330 if (!pixelRef->getYUV8Planes(yuvInfo.fSize, NULL, NULL, NULL)) { 331 return NULL; 332 } 333 334 // Allocate the memory for YUV 335 size_t totalSize(0); 336 for (int i = 0; i < 3; ++i) { 337 yuvInfo.fRowBytes[i] = yuvInfo.fSize[i].fWidth; 338 yuvInfo.fSizeInMemory[i] = yuvInfo.fRowBytes[i] * yuvInfo.fSize[i].fHeight; 339 totalSize += yuvInfo.fSizeInMemory[i]; 340 } 341 if (useCache) { 342 cachedData.reset(SkResourceCache::NewCachedData(totalSize)); 343 planes[0] = cachedData->writable_data(); 344 } else { 345 storage.reset(totalSize); 346 planes[0] = storage.get(); 347 } 348 planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0]; 349 planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1]; 350 351 // Get the YUV planes and update plane sizes to actual image size 352 if (!pixelRef->getYUV8Planes(yuvInfo.fSize, planes, yuvInfo.fRowBytes, 353 &yuvInfo.fColorSpace)) { 354 return NULL; 355 } 356 357 if (useCache) { 358 // Decoding is done, cache the resulting YUV planes 359 SkYUVPlanesCache::Add(pixelRef->getGenerationID(), cachedData, &yuvInfo); 360 } 361 } 362 363 GrSurfaceDesc yuvDesc; 364 yuvDesc.fConfig = kAlpha_8_GrPixelConfig; 365 SkAutoTUnref<GrTexture> yuvTextures[3]; 366 for (int i = 0; i < 3; ++i) { 367 yuvDesc.fWidth = yuvInfo.fSize[i].fWidth; 368 yuvDesc.fHeight = yuvInfo.fSize[i].fHeight; 369 bool needsExactTexture = 370 (yuvDesc.fWidth != yuvInfo.fSize[0].fWidth) || 371 (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight); 372 yuvTextures[i].reset(ctx->textureProvider()->refScratchTexture(yuvDesc, 373 needsExactTexture ? GrTextureProvider::kExact_ScratchTexMatch : 374 GrTextureProvider::kApprox_ScratchTexMatch)); 375 if (!yuvTextures[i] || 376 !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight, 377 yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) { 378 return NULL; 379 } 380 } 381 382 GrSurfaceDesc rtDesc = desc; 383 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; 384 385 GrTexture* result = create_texture_for_bmp(ctx, optionalKey, rtDesc, pixelRef, NULL, 0); 386 if (!result) { 387 return NULL; 388 } 389 390 GrRenderTarget* renderTarget = result->asRenderTarget(); 391 SkASSERT(renderTarget); 392 393 SkAutoTUnref<GrFragmentProcessor> 394 yuvToRgbProcessor(GrYUVtoRGBEffect::Create(yuvTextures[0], yuvTextures[1], yuvTextures[2], 395 yuvInfo.fSize, yuvInfo.fColorSpace)); 396 GrPaint paint; 397 paint.addColorProcessor(yuvToRgbProcessor); 398 SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth), 399 SkIntToScalar(yuvInfo.fSize[0].fHeight)); 400 401 ctx->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r); 402 403 return result; 404 } 405 406 static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx, 407 const SkBitmap& origBitmap, 408 const GrUniqueKey& optionalKey) { 409 SkBitmap tmpBitmap; 410 411 const SkBitmap* bitmap = &origBitmap; 412 413 GrSurfaceDesc desc; 414 generate_bitmap_texture_desc(*bitmap, &desc); 415 416 if (kIndex_8_SkColorType == bitmap->colorType()) { 417 if (ctx->isConfigTexturable(kIndex_8_GrPixelConfig)) { 418 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig, 419 bitmap->width(), bitmap->height()); 420 SkAutoMalloc storage(imageSize); 421 build_index8_data(storage.get(), origBitmap); 422 423 // our compressed data will be trimmed, so pass width() for its 424 // "rowBytes", since they are the same now. 425 return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(), 426 storage.get(), bitmap->width()); 427 } else { 428 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType); 429 // now bitmap points to our temp, which has been promoted to 32bits 430 bitmap = &tmpBitmap; 431 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info()); 432 } 433 } 434 435 // Is this an ETC1 encoded texture? 436 #ifndef SK_IGNORE_ETC1_SUPPORT 437 // Make sure that the underlying device supports ETC1 textures before we go ahead 438 // and check the data. 439 else if (ctx->isConfigTexturable(kETC1_GrPixelConfig) 440 // If the bitmap had compressed data and was then uncompressed, it'll still return 441 // compressed data on 'refEncodedData' and upload it. Probably not good, since if 442 // the bitmap has available pixels, then they might not be what the decompressed 443 // data is. 444 && !(bitmap->readyToDraw())) { 445 GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc); 446 if (texture) { 447 return texture; 448 } 449 } 450 #endif // SK_IGNORE_ETC1_SUPPORT 451 452 GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc); 453 if (texture) { 454 return texture; 455 } 456 457 SkAutoLockPixels alp(*bitmap); 458 if (!bitmap->readyToDraw()) { 459 return NULL; 460 } 461 462 return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(), 463 bitmap->getPixels(), bitmap->rowBytes()); 464 } 465 466 static GrTexture* create_bitmap_texture(GrContext* ctx, 467 const SkBitmap& bmp, 468 Stretch stretch, 469 const GrUniqueKey& unstretchedKey, 470 const GrUniqueKey& stretchedKey) { 471 if (kNo_Stretch != stretch) { 472 SkAutoTUnref<GrTexture> unstretched; 473 // Check if we have the unstretched version in the cache, if not create it. 474 if (unstretchedKey.isValid()) { 475 unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey)); 476 } 477 if (!unstretched) { 478 unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey)); 479 if (!unstretched) { 480 return NULL; 481 } 482 } 483 GrTexture* stretched = stretch_texture_to_next_pot(unstretched, stretch, bmp.pixelRef(), 484 stretchedKey); 485 return stretched; 486 } 487 488 return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey); 489 490 } 491 492 bool GrIsBitmapInCache(const GrContext* ctx, 493 const SkBitmap& bitmap, 494 const GrTextureParams* params) { 495 Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params); 496 497 // Handle the case where the bitmap is explicitly texture backed. 498 GrTexture* texture = bitmap.getTexture(); 499 if (texture) { 500 if (kNo_Stretch == stretch) { 501 return true; 502 } 503 // No keys for volatile bitmaps. 504 if (bitmap.isVolatile()) { 505 return false; 506 } 507 const GrUniqueKey& key = texture->getUniqueKey(); 508 if (!key.isValid()) { 509 return false; 510 } 511 GrUniqueKey stretchedKey; 512 make_stretched_key(key, stretch, &stretchedKey); 513 return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); 514 } 515 516 // We don't cache volatile bitmaps 517 if (bitmap.isVolatile()) { 518 return false; 519 } 520 521 GrUniqueKey key, stretchedKey; 522 make_bitmap_keys(bitmap, stretch, &key, &stretchedKey); 523 return ctx->textureProvider()->existsTextureWithUniqueKey( 524 (kNo_Stretch == stretch) ? key : stretchedKey); 525 } 526 527 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, 528 const SkBitmap& bitmap, 529 const GrTextureParams* params) { 530 531 Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params); 532 533 GrTexture* result = bitmap.getTexture(); 534 if (result) { 535 if (kNo_Stretch == stretch) { 536 return SkRef(result); 537 } 538 GrUniqueKey stretchedKey; 539 // Don't create a key for the resized version if the bmp is volatile. 540 if (!bitmap.isVolatile()) { 541 const GrUniqueKey& key = result->getUniqueKey(); 542 if (key.isValid()) { 543 make_stretched_key(key, stretch, &stretchedKey); 544 GrTexture* stretched = 545 ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey); 546 if (stretched) { 547 return stretched; 548 } 549 } 550 } 551 return stretch_texture_to_next_pot(result, stretch, bitmap.pixelRef(), stretchedKey); 552 } 553 554 GrUniqueKey key, resizedKey; 555 556 if (!bitmap.isVolatile()) { 557 // If the bitmap isn't changing try to find a cached copy first. 558 make_bitmap_keys(bitmap, stretch, &key, &resizedKey); 559 560 result = ctx->textureProvider()->findAndRefTextureByUniqueKey( 561 resizedKey.isValid() ? resizedKey : key); 562 if (result) { 563 return result; 564 } 565 } 566 567 result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey); 568 if (result) { 569 return result; 570 } 571 572 SkErrorInternals::SetError( kInternalError_SkError, 573 "---- failed to create texture for cache [%d %d]\n", 574 bitmap.width(), bitmap.height()); 575 576 return NULL; 577 } 578 /////////////////////////////////////////////////////////////////////////////// 579 580 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass 581 // alpha info, that will be considered. 582 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) { 583 switch (ct) { 584 case kUnknown_SkColorType: 585 return kUnknown_GrPixelConfig; 586 case kAlpha_8_SkColorType: 587 return kAlpha_8_GrPixelConfig; 588 case kRGB_565_SkColorType: 589 return kRGB_565_GrPixelConfig; 590 case kARGB_4444_SkColorType: 591 return kRGBA_4444_GrPixelConfig; 592 case kRGBA_8888_SkColorType: 593 // if (kSRGB_SkColorProfileType == pt) { 594 // return kSRGBA_8888_GrPixelConfig; 595 // } 596 return kRGBA_8888_GrPixelConfig; 597 case kBGRA_8888_SkColorType: 598 return kBGRA_8888_GrPixelConfig; 599 case kIndex_8_SkColorType: 600 return kIndex_8_GrPixelConfig; 601 case kGray_8_SkColorType: 602 return kAlpha_8_GrPixelConfig; // TODO: gray8 support on gpu 603 } 604 SkASSERT(0); // shouldn't get here 605 return kUnknown_GrPixelConfig; 606 } 607 608 bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut, 609 SkColorProfileType* ptOut) { 610 SkColorType ct; 611 SkColorProfileType pt = kLinear_SkColorProfileType; 612 switch (config) { 613 case kAlpha_8_GrPixelConfig: 614 ct = kAlpha_8_SkColorType; 615 break; 616 case kIndex_8_GrPixelConfig: 617 ct = kIndex_8_SkColorType; 618 break; 619 case kRGB_565_GrPixelConfig: 620 ct = kRGB_565_SkColorType; 621 break; 622 case kRGBA_4444_GrPixelConfig: 623 ct = kARGB_4444_SkColorType; 624 break; 625 case kRGBA_8888_GrPixelConfig: 626 ct = kRGBA_8888_SkColorType; 627 break; 628 case kBGRA_8888_GrPixelConfig: 629 ct = kBGRA_8888_SkColorType; 630 break; 631 case kSRGBA_8888_GrPixelConfig: 632 ct = kRGBA_8888_SkColorType; 633 pt = kSRGB_SkColorProfileType; 634 break; 635 default: 636 return false; 637 } 638 if (ctOut) { 639 *ctOut = ct; 640 } 641 if (ptOut) { 642 *ptOut = pt; 643 } 644 return true; 645 } 646 647 /////////////////////////////////////////////////////////////////////////////// 648 649 bool SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint, 650 GrColor paintColor, bool constantColor, GrPaint* grPaint) { 651 652 grPaint->setDither(skPaint.isDither()); 653 grPaint->setAntiAlias(skPaint.isAntiAlias()); 654 655 SkXfermode* mode = skPaint.getXfermode(); 656 GrXPFactory* xpFactory = NULL; 657 if (!SkXfermode::AsXPFactory(mode, &xpFactory)) { 658 // Fall back to src-over 659 // return false here? 660 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode); 661 } 662 SkASSERT(xpFactory); 663 grPaint->setXPFactory(xpFactory)->unref(); 664 665 //set the color of the paint to the one of the parameter 666 grPaint->setColor(paintColor); 667 668 SkColorFilter* colorFilter = skPaint.getColorFilter(); 669 if (colorFilter) { 670 // if the source color is a constant then apply the filter here once rather than per pixel 671 // in a shader. 672 if (constantColor) { 673 SkColor filtered = colorFilter->filterColor(skPaint.getColor()); 674 grPaint->setColor(SkColor2GrColor(filtered)); 675 } else { 676 SkTDArray<GrFragmentProcessor*> array; 677 // return false if failed? 678 if (colorFilter->asFragmentProcessors(context, &array)) { 679 for (int i = 0; i < array.count(); ++i) { 680 grPaint->addColorProcessor(array[i]); 681 array[i]->unref(); 682 } 683 } 684 } 685 } 686 687 #ifndef SK_IGNORE_GPU_DITHER 688 // If the dither flag is set, then we need to see if the underlying context 689 // supports it. If not, then install a dither effect. 690 if (skPaint.isDither() && grPaint->numColorStages() > 0) { 691 // What are we rendering into? 692 SkASSERT(rt); 693 694 // Suspect the dithering flag has no effect on these configs, otherwise 695 // fall back on setting the appropriate state. 696 if (GrPixelConfigIs8888(rt->config()) || 697 GrPixelConfigIs8888(rt->config())) { 698 // The dither flag is set and the target is likely 699 // not going to be dithered by the GPU. 700 SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create()); 701 if (fp.get()) { 702 grPaint->addColorProcessor(fp); 703 grPaint->setDither(false); 704 } 705 } 706 } 707 #endif 708 return true; 709 } 710 711 bool SkPaint2GrPaint(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint, 712 const SkMatrix& viewM, bool constantColor, GrPaint* grPaint) { 713 SkShader* shader = skPaint.getShader(); 714 if (NULL == shader) { 715 return SkPaint2GrPaintNoShader(context, rt, skPaint, SkColor2GrColor(skPaint.getColor()), 716 constantColor, grPaint); 717 } 718 719 GrColor paintColor = SkColor2GrColor(skPaint.getColor()); 720 721 // Start a new block here in order to preserve our context state after calling 722 // asFragmentProcessor(). Since these calls get passed back to the client, we don't really 723 // want them messing around with the context. 724 { 725 // Allow the shader to modify paintColor and also create an effect to be installed as 726 // the first color effect on the GrPaint. 727 GrFragmentProcessor* fp = NULL; 728 if (!shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp)) { 729 return false; 730 } 731 if (fp) { 732 grPaint->addColorProcessor(fp)->unref(); 733 constantColor = false; 734 } 735 } 736 737 // The grcolor is automatically set when calling asFragmentProcessor. 738 // If the shader can be seen as an effect it returns true and adds its effect to the grpaint. 739 return SkPaint2GrPaintNoShader(context, rt, skPaint, paintColor, constantColor, grPaint); 740 } 741 742 SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) { 743 #ifdef SK_DEBUG 744 const GrSurfaceDesc& desc = tex->desc(); 745 SkASSERT(w <= desc.fWidth); 746 SkASSERT(h <= desc.fHeight); 747 #endif 748 const GrPixelConfig config = tex->config(); 749 SkColorType ct; 750 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 751 if (!GrPixelConfig2ColorAndProfileType(config, &ct, NULL)) { 752 ct = kUnknown_SkColorType; 753 } 754 return SkImageInfo::Make(w, h, ct, at); 755 } 756 757 758 void GrWrapTextureInBitmap(GrTexture* src, int w, int h, bool isOpaque, SkBitmap* dst) { 759 const SkImageInfo info = GrMakeInfoFromTexture(src, w, h, isOpaque); 760 dst->setInfo(info); 761 dst->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, src)))->unref(); 762 } 763