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