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#include "SkColorFilter.h" 10#include "SkConfig8888.h" 11#include "SkData.h" 12#include "SkMessageBus.h" 13#include "SkPixelRef.h" 14#include "GrResourceCache.h" 15#include "GrGpu.h" 16#include "effects/GrDitherEffect.h" 17#include "GrDrawTargetCaps.h" 18 19#ifndef SK_IGNORE_ETC1_SUPPORT 20# include "ktx.h" 21# include "etc1.h" 22#endif 23 24/* Fill out buffer with the compressed format Ganesh expects from a colortable 25 based bitmap. [palette (colortable) + indices]. 26 27 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others 28 we could detect that the colortable.count is <= 16, and then repack the 29 indices as nibbles to save RAM, but it would take more time (i.e. a lot 30 slower than memcpy), so skipping that for now. 31 32 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big 33 as the colortable.count says it is. 34 */ 35static void build_compressed_data(void* buffer, const SkBitmap& bitmap) { 36 SkASSERT(kIndex_8_SkColorType == bitmap.colorType()); 37 38 SkAutoLockPixels alp(bitmap); 39 if (!bitmap.readyToDraw()) { 40 SkDEBUGFAIL("bitmap not ready to draw!"); 41 return; 42 } 43 44 SkColorTable* ctable = bitmap.getColorTable(); 45 char* dst = (char*)buffer; 46 47 const int count = ctable->count(); 48 49 SkDstPixelInfo dstPI; 50 dstPI.fColorType = kRGBA_8888_SkColorType; 51 dstPI.fAlphaType = kPremul_SkAlphaType; 52 dstPI.fPixels = buffer; 53 dstPI.fRowBytes = count * sizeof(SkPMColor); 54 55 SkSrcPixelInfo srcPI; 56 srcPI.fColorType = kN32_SkColorType; 57 srcPI.fAlphaType = kPremul_SkAlphaType; 58 srcPI.fPixels = ctable->lockColors(); 59 srcPI.fRowBytes = count * sizeof(SkPMColor); 60 61 srcPI.convertPixelsTo(&dstPI, count, 1); 62 63 ctable->unlockColors(); 64 65 // always skip a full 256 number of entries, even if we memcpy'd fewer 66 dst += kGrColorTableSize; 67 68 if ((unsigned)bitmap.width() == bitmap.rowBytes()) { 69 memcpy(dst, bitmap.getPixels(), bitmap.getSize()); 70 } else { 71 // need to trim off the extra bytes per row 72 size_t width = bitmap.width(); 73 size_t rowBytes = bitmap.rowBytes(); 74 const char* src = (const char*)bitmap.getPixels(); 75 for (int y = 0; y < bitmap.height(); y++) { 76 memcpy(dst, src, width); 77 src += rowBytes; 78 dst += width; 79 } 80 } 81} 82 83//////////////////////////////////////////////////////////////////////////////// 84 85static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) { 86 // Our id includes the offset, width, and height so that bitmaps created by extractSubset() 87 // are unique. 88 uint32_t genID = bitmap.getGenerationID(); 89 SkIPoint origin = bitmap.pixelRefOrigin(); 90 int16_t width = SkToS16(bitmap.width()); 91 int16_t height = SkToS16(bitmap.height()); 92 93 GrCacheID::Key key; 94 memcpy(key.fData8 + 0, &genID, 4); 95 memcpy(key.fData8 + 4, &origin.fX, 4); 96 memcpy(key.fData8 + 8, &origin.fY, 4); 97 memcpy(key.fData8 + 12, &width, 2); 98 memcpy(key.fData8 + 14, &height, 2); 99 static const size_t kKeyDataSize = 16; 100 memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize); 101 GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize); 102 static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain(); 103 id->reset(gBitmapTextureDomain, key); 104} 105 106static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrTextureDesc* desc) { 107 desc->fFlags = kNone_GrTextureFlags; 108 desc->fWidth = bitmap.width(); 109 desc->fHeight = bitmap.height(); 110 desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); 111 desc->fSampleCnt = 0; 112} 113 114namespace { 115 116// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key. 117class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener { 118public: 119 explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {} 120private: 121 GrResourceKey fKey; 122 123 virtual void onChange() SK_OVERRIDE { 124 const GrResourceInvalidatedMessage message = { fKey }; 125 SkMessageBus<GrResourceInvalidatedMessage>::Post(message); 126 } 127}; 128 129} // namespace 130 131static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) { 132 SkASSERT(NULL != pixelRef); 133 pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key))); 134} 135 136#ifndef SK_IGNORE_ETC1_SUPPORT 137static GrTexture *load_etc1_texture(GrContext* ctx, 138 const GrTextureParams* params, 139 const SkBitmap &bm, GrTextureDesc desc) { 140 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); 141 142 // Is this even encoded data? 143 if (NULL == data) { 144 return NULL; 145 } 146 147 // Is this a valid PKM encoded data? 148 const uint8_t *bytes = data->bytes(); 149 if (etc1_pkm_is_valid(bytes)) { 150 uint32_t encodedWidth = etc1_pkm_get_width(bytes); 151 uint32_t encodedHeight = etc1_pkm_get_height(bytes); 152 153 // Does the data match the dimensions of the bitmap? If not, 154 // then we don't know how to scale the image to match it... 155 if (encodedWidth != static_cast<uint32_t>(bm.width()) || 156 encodedHeight != static_cast<uint32_t>(bm.height())) { 157 return NULL; 158 } 159 160 // Everything seems good... skip ahead to the data. 161 bytes += ETC_PKM_HEADER_SIZE; 162 desc.fConfig = kETC1_GrPixelConfig; 163 } else if (SkKTXFile::is_ktx(bytes)) { 164 SkKTXFile ktx(data); 165 166 // Is it actually an ETC1 texture? 167 if (!ktx.isETC1()) { 168 return NULL; 169 } 170 171 // Does the data match the dimensions of the bitmap? If not, 172 // then we don't know how to scale the image to match it... 173 if (ktx.width() != bm.width() || ktx.height() != bm.height()) { 174 return NULL; 175 } 176 177 bytes = ktx.pixelData(); 178 desc.fConfig = kETC1_GrPixelConfig; 179 } else { 180 return NULL; 181 } 182 183 // This texture is likely to be used again so leave it in the cache 184 GrCacheID cacheID; 185 generate_bitmap_cache_id(bm, &cacheID); 186 187 GrResourceKey key; 188 GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key); 189 if (NULL != result) { 190 add_genID_listener(key, bm.pixelRef()); 191 } 192 return result; 193} 194#endif // SK_IGNORE_ETC1_SUPPORT 195 196static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, 197 bool cache, 198 const GrTextureParams* params, 199 const SkBitmap& origBitmap) { 200 SkBitmap tmpBitmap; 201 202 const SkBitmap* bitmap = &origBitmap; 203 204 GrTextureDesc desc; 205 generate_bitmap_texture_desc(*bitmap, &desc); 206 207 if (kIndex_8_SkColorType == bitmap->colorType()) { 208 // build_compressed_data doesn't do npot->pot expansion 209 // and paletted textures can't be sub-updated 210 if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) { 211 size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize; 212 SkAutoMalloc storage(imagesize); 213 214 build_compressed_data(storage.get(), origBitmap); 215 216 // our compressed data will be trimmed, so pass width() for its 217 // "rowBytes", since they are the same now. 218 219 if (cache) { 220 GrCacheID cacheID; 221 generate_bitmap_cache_id(origBitmap, &cacheID); 222 223 GrResourceKey key; 224 GrTexture* result = ctx->createTexture(params, desc, cacheID, 225 storage.get(), bitmap->width(), &key); 226 if (NULL != result) { 227 add_genID_listener(key, origBitmap.pixelRef()); 228 } 229 return result; 230 } else { 231 GrTexture* result = ctx->lockAndRefScratchTexture(desc, 232 GrContext::kExact_ScratchTexMatch); 233 result->writePixels(0, 0, bitmap->width(), 234 bitmap->height(), desc.fConfig, 235 storage.get()); 236 return result; 237 } 238 } else { 239 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType); 240 // now bitmap points to our temp, which has been promoted to 32bits 241 bitmap = &tmpBitmap; 242 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info()); 243 } 244 } 245 246 // Is this an ETC1 encoded texture? 247#ifndef SK_IGNORE_ETC1_SUPPORT 248 else if ( 249 // We do not support scratch ETC1 textures, hence they should all be at least 250 // trying to go to the cache. 251 cache 252 // Make sure that the underlying device supports ETC1 textures before we go ahead 253 // and check the data. 254 && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig) 255 // If the bitmap had compressed data and was then uncompressed, it'll still return 256 // compressed data on 'refEncodedData' and upload it. Probably not good, since if 257 // the bitmap has available pixels, then they might not be what the decompressed 258 // data is. 259 && !(bitmap->readyToDraw())) { 260 GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc); 261 if (NULL != texture) { 262 return texture; 263 } 264 } 265#endif // SK_IGNORE_ETC1_SUPPORT 266 267 SkAutoLockPixels alp(*bitmap); 268 if (!bitmap->readyToDraw()) { 269 return NULL; 270 } 271 if (cache) { 272 // This texture is likely to be used again so leave it in the cache 273 GrCacheID cacheID; 274 generate_bitmap_cache_id(origBitmap, &cacheID); 275 276 GrResourceKey key; 277 GrTexture* result = ctx->createTexture(params, desc, cacheID, 278 bitmap->getPixels(), bitmap->rowBytes(), &key); 279 if (NULL != result) { 280 add_genID_listener(key, origBitmap.pixelRef()); 281 } 282 return result; 283 } else { 284 // This texture is unlikely to be used again (in its present form) so 285 // just use a scratch texture. This will remove the texture from the 286 // cache so no one else can find it. Additionally, once unlocked, the 287 // scratch texture will go to the end of the list for purging so will 288 // likely be available for this volatile bitmap the next time around. 289 GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch); 290 result->writePixels(0, 0, 291 bitmap->width(), bitmap->height(), 292 desc.fConfig, 293 bitmap->getPixels(), 294 bitmap->rowBytes()); 295 return result; 296 } 297} 298 299bool GrIsBitmapInCache(const GrContext* ctx, 300 const SkBitmap& bitmap, 301 const GrTextureParams* params) { 302 GrCacheID cacheID; 303 generate_bitmap_cache_id(bitmap, &cacheID); 304 305 GrTextureDesc desc; 306 generate_bitmap_texture_desc(bitmap, &desc); 307 return ctx->isTextureInCache(desc, cacheID, params); 308} 309 310GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx, 311 const SkBitmap& bitmap, 312 const GrTextureParams* params) { 313 GrTexture* result = NULL; 314 315 bool cache = !bitmap.isVolatile(); 316 317 if (cache) { 318 // If the bitmap isn't changing try to find a cached copy first. 319 320 GrCacheID cacheID; 321 generate_bitmap_cache_id(bitmap, &cacheID); 322 323 GrTextureDesc desc; 324 generate_bitmap_texture_desc(bitmap, &desc); 325 326 result = ctx->findAndRefTexture(desc, cacheID, params); 327 } 328 if (NULL == result) { 329 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); 330 } 331 if (NULL == result) { 332 GrPrintf("---- failed to create texture for cache [%d %d]\n", 333 bitmap.width(), bitmap.height()); 334 } 335 return result; 336} 337 338void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) { 339 SkASSERT(NULL != texture->getContext()); 340 341 texture->getContext()->unlockScratchTexture(texture); 342 texture->unref(); 343} 344 345/////////////////////////////////////////////////////////////////////////////// 346 347#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 348GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) { 349 switch (config) { 350 case SkBitmap::kA8_Config: 351 return kAlpha_8_GrPixelConfig; 352 case SkBitmap::kIndex8_Config: 353 return kIndex_8_GrPixelConfig; 354 case SkBitmap::kRGB_565_Config: 355 return kRGB_565_GrPixelConfig; 356 case SkBitmap::kARGB_4444_Config: 357 return kRGBA_4444_GrPixelConfig; 358 case SkBitmap::kARGB_8888_Config: 359 return kSkia8888_GrPixelConfig; 360 default: 361 // kNo_Config, kA1_Config missing 362 return kUnknown_GrPixelConfig; 363 } 364} 365#endif 366 367// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass 368// alpha info, that will be considered. 369GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) { 370 switch (ct) { 371 case kUnknown_SkColorType: 372 return kUnknown_GrPixelConfig; 373 case kAlpha_8_SkColorType: 374 return kAlpha_8_GrPixelConfig; 375 case kRGB_565_SkColorType: 376 return kRGB_565_GrPixelConfig; 377 case kARGB_4444_SkColorType: 378 return kRGBA_4444_GrPixelConfig; 379 case kRGBA_8888_SkColorType: 380 return kRGBA_8888_GrPixelConfig; 381 case kBGRA_8888_SkColorType: 382 return kBGRA_8888_GrPixelConfig; 383 case kIndex_8_SkColorType: 384 return kIndex_8_GrPixelConfig; 385 } 386 SkASSERT(0); // shouldn't get here 387 return kUnknown_GrPixelConfig; 388} 389 390bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) { 391 SkColorType ct; 392 switch (config) { 393 case kAlpha_8_GrPixelConfig: 394 ct = kAlpha_8_SkColorType; 395 break; 396 case kIndex_8_GrPixelConfig: 397 ct = kIndex_8_SkColorType; 398 break; 399 case kRGB_565_GrPixelConfig: 400 ct = kRGB_565_SkColorType; 401 break; 402 case kRGBA_4444_GrPixelConfig: 403 ct = kARGB_4444_SkColorType; 404 break; 405 case kRGBA_8888_GrPixelConfig: 406 ct = kRGBA_8888_SkColorType; 407 break; 408 case kBGRA_8888_GrPixelConfig: 409 ct = kBGRA_8888_SkColorType; 410 break; 411 default: 412 return false; 413 } 414 if (ctOut) { 415 *ctOut = ct; 416 } 417 return true; 418} 419 420/////////////////////////////////////////////////////////////////////////////// 421 422void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor grColor, 423 bool constantColor, GrPaint* grPaint) { 424 425 grPaint->setDither(skPaint.isDither()); 426 grPaint->setAntiAlias(skPaint.isAntiAlias()); 427 428 SkXfermode::Coeff sm; 429 SkXfermode::Coeff dm; 430 431 SkXfermode* mode = skPaint.getXfermode(); 432 GrEffectRef* xferEffect = NULL; 433 if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) { 434 if (NULL != xferEffect) { 435 grPaint->addColorEffect(xferEffect)->unref(); 436 sm = SkXfermode::kOne_Coeff; 437 dm = SkXfermode::kZero_Coeff; 438 } 439 } else { 440 //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) 441 // Fall back to src-over 442 sm = SkXfermode::kOne_Coeff; 443 dm = SkXfermode::kISA_Coeff; 444 } 445 grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm)); 446 447 //set the color of the paint to the one of the parameter 448 grPaint->setColor(grColor); 449 450 SkColorFilter* colorFilter = skPaint.getColorFilter(); 451 if (NULL != colorFilter) { 452 // if the source color is a constant then apply the filter here once rather than per pixel 453 // in a shader. 454 if (constantColor) { 455 SkColor filtered = colorFilter->filterColor(skPaint.getColor()); 456 grPaint->setColor(SkColor2GrColor(filtered)); 457 } else { 458 SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(context)); 459 if (NULL != effect.get()) { 460 grPaint->addColorEffect(effect); 461 } 462 } 463 } 464 465#ifndef SK_IGNORE_GPU_DITHER 466 // If the dither flag is set, then we need to see if the underlying context 467 // supports it. If not, then install a dither effect. 468 if (skPaint.isDither() && grPaint->numColorStages() > 0) { 469 // What are we rendering into? 470 const GrRenderTarget *target = context->getRenderTarget(); 471 SkASSERT(NULL != target); 472 473 // Suspect the dithering flag has no effect on these configs, otherwise 474 // fall back on setting the appropriate state. 475 if (target->config() == kRGBA_8888_GrPixelConfig || 476 target->config() == kBGRA_8888_GrPixelConfig) { 477 // The dither flag is set and the target is likely 478 // not going to be dithered by the GPU. 479 SkAutoTUnref<GrEffectRef> effect(GrDitherEffect::Create()); 480 if (NULL != effect.get()) { 481 grPaint->addColorEffect(effect); 482 grPaint->setDither(false); 483 } 484 } 485 } 486#endif 487} 488 489/** 490 * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrContext::AutoMatrix 491 * likes to set the new matrix in its constructor because it is usually necessary to simulataneously 492 * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint, however. 493 */ 494class AutoMatrix { 495public: 496 AutoMatrix(GrContext* context) { 497 fMatrix = context->getMatrix(); 498 fContext = context; 499 } 500 ~AutoMatrix() { 501 SkASSERT(NULL != fContext); 502 fContext->setMatrix(fMatrix); 503 } 504private: 505 GrContext* fContext; 506 SkMatrix fMatrix; 507}; 508 509void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint, 510 bool constantColor, GrPaint* grPaint) { 511 SkShader* shader = skPaint.getShader(); 512 if (NULL == shader) { 513 SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()), 514 constantColor, grPaint); 515 return; 516 } 517 518 // SkShader::asNewEffect() may do offscreen rendering. Save off the current RT, clip, and 519 // matrix. We don't reset the matrix on the context because SkShader::asNewEffect may use 520 // GrContext::getMatrix() to know the transformation from local coords to device space. 521 GrColor grColor = SkColor2GrColor(skPaint.getColor()); 522 523 // Start a new block here in order to preserve our context state after calling 524 // asNewEffect(). Since these calls get passed back to the client, we don't really 525 // want them messing around with the context. 526 { 527 GrContext::AutoRenderTarget art(context, NULL); 528 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip); 529 AutoMatrix am(context); 530 531 // setup the shader as the first color effect on the paint 532 // the default grColor is the paint's color 533 GrEffectRef* grEffect = NULL; 534 if (shader->asNewEffect(context, skPaint, NULL, &grColor, &grEffect) && NULL != grEffect) { 535 SkAutoTUnref<GrEffectRef> effect(grEffect); 536 grPaint->addColorEffect(effect); 537 constantColor = false; 538 } 539 } 540 541 // The grcolor is automatically set when calling asneweffect. 542 // If the shader can be seen as an effect it returns true and adds its effect to the grpaint. 543 SkPaint2GrPaintNoShader(context, skPaint, grColor, constantColor, grPaint); 544} 545