1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8#include "SkColorPriv.h" 9#include "SkReadBuffer.h" 10#include "SkWriteBuffer.h" 11#include "SkPixelRef.h" 12#include "SkErrorInternals.h" 13#include "SkBitmapProcShader.h" 14 15#if SK_SUPPORT_GPU 16#include "effects/GrSimpleTextureEffect.h" 17#include "effects/GrBicubicEffect.h" 18#endif 19 20bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) { 21 switch (bm.colorType()) { 22 case kAlpha_8_SkColorType: 23 case kRGB_565_SkColorType: 24 case kIndex_8_SkColorType: 25 case kN32_SkColorType: 26 // if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx)) 27 return true; 28 default: 29 break; 30 } 31 return false; 32} 33 34SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 35 const SkMatrix* localMatrix) 36 : INHERITED(localMatrix) { 37 fRawBitmap = src; 38 fTileModeX = (uint8_t)tmx; 39 fTileModeY = (uint8_t)tmy; 40} 41 42#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 43SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer) : INHERITED(buffer) { 44 buffer.readBitmap(&fRawBitmap); 45 fRawBitmap.setImmutable(); 46 fTileModeX = buffer.readUInt(); 47 fTileModeY = buffer.readUInt(); 48} 49#endif 50 51SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, 52 SkMatrix* texM, 53 TileMode xy[]) const { 54 if (texture) { 55 *texture = fRawBitmap; 56 } 57 if (texM) { 58 texM->reset(); 59 } 60 if (xy) { 61 xy[0] = (TileMode)fTileModeX; 62 xy[1] = (TileMode)fTileModeY; 63 } 64 return kDefault_BitmapType; 65} 66 67SkFlattenable* SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) { 68 SkMatrix lm; 69 buffer.readMatrix(&lm); 70 SkBitmap bm; 71 if (!buffer.readBitmap(&bm)) { 72 return NULL; 73 } 74 bm.setImmutable(); 75 TileMode mx = (TileMode)buffer.readUInt(); 76 TileMode my = (TileMode)buffer.readUInt(); 77 return SkShader::CreateBitmapShader(bm, mx, my, &lm); 78} 79 80void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { 81 buffer.writeMatrix(this->getLocalMatrix()); 82 buffer.writeBitmap(fRawBitmap); 83 buffer.writeUInt(fTileModeX); 84 buffer.writeUInt(fTileModeY); 85} 86 87static bool only_scale_and_translate(const SkMatrix& matrix) { 88 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 89 return (matrix.getType() & ~mask) == 0; 90} 91 92bool SkBitmapProcShader::isOpaque() const { 93 return fRawBitmap.isOpaque(); 94} 95 96static bool valid_for_drawing(const SkBitmap& bm) { 97 if (0 == bm.width() || 0 == bm.height()) { 98 return false; // nothing to draw 99 } 100 if (NULL == bm.pixelRef()) { 101 return false; // no pixels to read 102 } 103 if (kIndex_8_SkColorType == bm.colorType()) { 104 // ugh, I have to lock-pixels to inspect the colortable 105 SkAutoLockPixels alp(bm); 106 if (!bm.getColorTable()) { 107 return false; 108 } 109 } 110 return true; 111} 112 113SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const { 114 if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) { 115 return NULL; 116 } 117 118 SkMatrix totalInverse; 119 // Do this first, so we know the matrix can be inverted. 120 if (!this->computeTotalInverse(rec, &totalInverse)) { 121 return NULL; 122 } 123 124 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); 125 SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState); 126 127 SkASSERT(state); 128 state->fTileModeX = fTileModeX; 129 state->fTileModeY = fTileModeY; 130 state->fOrigBitmap = fRawBitmap; 131 if (!state->chooseProcs(totalInverse, *rec.fPaint)) { 132 state->~SkBitmapProcState(); 133 return NULL; 134 } 135 136 return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, (*this, rec, state)); 137} 138 139size_t SkBitmapProcShader::contextSize() const { 140 // The SkBitmapProcState is stored outside of the context object, with the context holding 141 // a pointer to it. 142 return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); 143} 144 145SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext( 146 const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state) 147 : INHERITED(shader, rec) 148 , fState(state) 149{ 150 const SkBitmap& bitmap = *fState->fBitmap; 151 bool bitmapIsOpaque = bitmap.isOpaque(); 152 153 // update fFlags 154 uint32_t flags = 0; 155 if (bitmapIsOpaque && (255 == this->getPaintAlpha())) { 156 flags |= kOpaqueAlpha_Flag; 157 } 158 159 switch (bitmap.colorType()) { 160 case kRGB_565_SkColorType: 161 flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag); 162 break; 163 case kIndex_8_SkColorType: 164 case kN32_SkColorType: 165 if (bitmapIsOpaque) { 166 flags |= kHasSpan16_Flag; 167 } 168 break; 169 case kAlpha_8_SkColorType: 170 break; // never set kHasSpan16_Flag 171 default: 172 break; 173 } 174 175 if (rec.fPaint->isDither() && bitmap.colorType() != kRGB_565_SkColorType) { 176 // gradients can auto-dither in their 16bit sampler, but we don't so 177 // we clear the flag here. 178 flags &= ~kHasSpan16_Flag; 179 } 180 181 // if we're only 1-pixel high, and we don't rotate, then we can claim this 182 if (1 == bitmap.height() && 183 only_scale_and_translate(this->getTotalInverse())) { 184 flags |= kConstInY32_Flag; 185 if (flags & kHasSpan16_Flag) { 186 flags |= kConstInY16_Flag; 187 } 188 } 189 190 fFlags = flags; 191} 192 193SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() { 194 // The bitmap proc state has been created outside of the context on memory that will be freed 195 // elsewhere. Only call the destructor but leave the freeing of the memory to the caller. 196 fState->~SkBitmapProcState(); 197} 198 199#define BUF_MAX 128 200 201#define TEST_BUFFER_OVERRITEx 202 203#ifdef TEST_BUFFER_OVERRITE 204 #define TEST_BUFFER_EXTRA 32 205 #define TEST_PATTERN 0x88888888 206#else 207 #define TEST_BUFFER_EXTRA 0 208#endif 209 210void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], 211 int count) { 212 const SkBitmapProcState& state = *fState; 213 if (state.getShaderProc32()) { 214 state.getShaderProc32()(state, x, y, dstC, count); 215 return; 216 } 217 218 uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA]; 219 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); 220 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); 221 int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); 222 223 SkASSERT(state.fBitmap->getPixels()); 224 SkASSERT(state.fBitmap->pixelRef() == NULL || 225 state.fBitmap->pixelRef()->isLocked()); 226 227 for (;;) { 228 int n = count; 229 if (n > max) { 230 n = max; 231 } 232 SkASSERT(n > 0 && n < BUF_MAX*2); 233#ifdef TEST_BUFFER_OVERRITE 234 for (int i = 0; i < TEST_BUFFER_EXTRA; i++) { 235 buffer[BUF_MAX + i] = TEST_PATTERN; 236 } 237#endif 238 mproc(state, buffer, n, x, y); 239#ifdef TEST_BUFFER_OVERRITE 240 for (int j = 0; j < TEST_BUFFER_EXTRA; j++) { 241 SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN); 242 } 243#endif 244 sproc(state, buffer, n, dstC); 245 246 if ((count -= n) == 0) { 247 break; 248 } 249 SkASSERT(count > 0); 250 x += n; 251 dstC += n; 252 } 253} 254 255SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) { 256 if (fState->getShaderProc32()) { 257 *ctx = fState; 258 return (ShadeProc)fState->getShaderProc32(); 259 } 260 return NULL; 261} 262 263void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], 264 int count) { 265 const SkBitmapProcState& state = *fState; 266 if (state.getShaderProc16()) { 267 state.getShaderProc16()(state, x, y, dstC, count); 268 return; 269 } 270 271 uint32_t buffer[BUF_MAX]; 272 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); 273 SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16(); 274 int max = state.maxCountForBufferSize(sizeof(buffer)); 275 276 SkASSERT(state.fBitmap->getPixels()); 277 SkASSERT(state.fBitmap->pixelRef() == NULL || 278 state.fBitmap->pixelRef()->isLocked()); 279 280 for (;;) { 281 int n = count; 282 if (n > max) { 283 n = max; 284 } 285 mproc(state, buffer, n, x, y); 286 sproc(state, buffer, n, dstC); 287 288 if ((count -= n) == 0) { 289 break; 290 } 291 x += n; 292 dstC += n; 293 } 294} 295 296/////////////////////////////////////////////////////////////////////////////// 297 298#include "SkUnPreMultiply.h" 299#include "SkColorShader.h" 300#include "SkEmptyShader.h" 301 302// returns true and set color if the bitmap can be drawn as a single color 303// (for efficiency) 304static bool canUseColorShader(const SkBitmap& bm, SkColor* color) { 305 if (1 != bm.width() || 1 != bm.height()) { 306 return false; 307 } 308 309 SkAutoLockPixels alp(bm); 310 if (!bm.readyToDraw()) { 311 return false; 312 } 313 314 switch (bm.colorType()) { 315 case kN32_SkColorType: 316 *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0)); 317 return true; 318 case kRGB_565_SkColorType: 319 *color = SkPixel16ToColor(*bm.getAddr16(0, 0)); 320 return true; 321 case kIndex_8_SkColorType: 322 *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0)); 323 return true; 324 default: // just skip the other configs for now 325 break; 326 } 327 return false; 328} 329 330static bool bitmapIsTooBig(const SkBitmap& bm) { 331 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it 332 // communicates between its matrix-proc and its sampler-proc. Until we can 333 // widen that, we have to reject bitmaps that are larger. 334 // 335 const int maxSize = 65535; 336 337 return bm.width() > maxSize || bm.height() > maxSize; 338} 339 340SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx, 341 SkShader::TileMode tmy, const SkMatrix* localMatrix, SkTBlitterAllocator* allocator) { 342 SkShader* shader; 343 SkColor color; 344 if (src.isNull() || bitmapIsTooBig(src)) { 345 if (NULL == allocator) { 346 shader = SkNEW(SkEmptyShader); 347 } else { 348 shader = allocator->createT<SkEmptyShader>(); 349 } 350 } 351 else if (canUseColorShader(src, &color)) { 352 if (NULL == allocator) { 353 shader = SkNEW_ARGS(SkColorShader, (color)); 354 } else { 355 shader = allocator->createT<SkColorShader>(color); 356 } 357 } else { 358 if (NULL == allocator) { 359 shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy, localMatrix)); 360 } else { 361 shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix); 362 } 363 } 364 return shader; 365} 366 367/////////////////////////////////////////////////////////////////////////////// 368 369#ifndef SK_IGNORE_TO_STRING 370void SkBitmapProcShader::toString(SkString* str) const { 371 static const char* gTileModeName[SkShader::kTileModeCount] = { 372 "clamp", "repeat", "mirror" 373 }; 374 375 str->append("BitmapShader: ("); 376 377 str->appendf("(%s, %s)", 378 gTileModeName[fTileModeX], 379 gTileModeName[fTileModeY]); 380 381 str->append(" "); 382 fRawBitmap.toString(str); 383 384 this->INHERITED::toString(str); 385 386 str->append(")"); 387} 388#endif 389 390/////////////////////////////////////////////////////////////////////////////// 391 392#if SK_SUPPORT_GPU 393 394#include "GrTextureAccess.h" 395#include "effects/GrSimpleTextureEffect.h" 396#include "SkGr.h" 397 398bool SkBitmapProcShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, 399 const SkMatrix* localMatrix, GrColor* paintColor, 400 GrFragmentProcessor** fp) const { 401 SkMatrix matrix; 402 matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); 403 404 SkMatrix lmInverse; 405 if (!this->getLocalMatrix().invert(&lmInverse)) { 406 return false; 407 } 408 if (localMatrix) { 409 SkMatrix inv; 410 if (!localMatrix->invert(&inv)) { 411 return false; 412 } 413 lmInverse.postConcat(inv); 414 } 415 matrix.preConcat(lmInverse); 416 417 SkShader::TileMode tm[] = { 418 (TileMode)fTileModeX, 419 (TileMode)fTileModeY, 420 }; 421 422 // Must set wrap and filter on the sampler before requesting a texture. In two places below 423 // we check the matrix scale factors to determine how to interpret the filter quality setting. 424 // This completely ignores the complexity of the drawVertices case where explicit local coords 425 // are provided by the caller. 426 bool useBicubic = false; 427 GrTextureParams::FilterMode textureFilterMode; 428 switch(paint.getFilterLevel()) { 429 case SkPaint::kNone_FilterLevel: 430 textureFilterMode = GrTextureParams::kNone_FilterMode; 431 break; 432 case SkPaint::kLow_FilterLevel: 433 textureFilterMode = GrTextureParams::kBilerp_FilterMode; 434 break; 435 case SkPaint::kMedium_FilterLevel: { 436 SkMatrix matrix; 437 matrix.setConcat(context->getMatrix(), this->getLocalMatrix()); 438 if (matrix.getMinScale() < SK_Scalar1) { 439 textureFilterMode = GrTextureParams::kMipMap_FilterMode; 440 } else { 441 // Don't trigger MIP level generation unnecessarily. 442 textureFilterMode = GrTextureParams::kBilerp_FilterMode; 443 } 444 break; 445 } 446 case SkPaint::kHigh_FilterLevel: { 447 SkMatrix matrix; 448 matrix.setConcat(context->getMatrix(), this->getLocalMatrix()); 449 useBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode); 450 break; 451 } 452 default: 453 SkErrorInternals::SetError( kInvalidPaint_SkError, 454 "Sorry, I don't understand the filtering " 455 "mode you asked for. Falling back to " 456 "MIPMaps."); 457 textureFilterMode = GrTextureParams::kMipMap_FilterMode; 458 break; 459 460 } 461 GrTextureParams params(tm, textureFilterMode); 462 GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, ¶ms); 463 464 if (NULL == texture) { 465 SkErrorInternals::SetError( kInternalError_SkError, 466 "Couldn't convert bitmap to texture."); 467 return false; 468 } 469 470 *paintColor = (kAlpha_8_SkColorType == fRawBitmap.colorType()) ? 471 SkColor2GrColor(paint.getColor()) : 472 SkColor2GrColorJustAlpha(paint.getColor()); 473 474 if (useBicubic) { 475 *fp = GrBicubicEffect::Create(texture, matrix, tm); 476 } else { 477 *fp = GrSimpleTextureEffect::Create(texture, matrix, params); 478 } 479 GrUnlockAndUnrefCachedBitmapTexture(texture); 480 481 return true; 482} 483 484#else 485 486bool SkBitmapProcShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, 487 GrFragmentProcessor**) const { 488 SkDEBUGFAIL("Should not call in GPU-less build"); 489 return false; 490} 491 492#endif 493