Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkBitmapProcShader.h" | 8 #include "SkBitmapProcShader.h" |
| 9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
| 10 #include "SkBitmapProvider.h" | 10 #include "SkBitmapProvider.h" |
| 11 #include "SkColorPriv.h" | |
| 12 #include "SkErrorInternals.h" | |
| 13 #include "SkPixelRef.h" | |
| 14 #include "SkReadBuffer.h" | |
| 15 #include "SkWriteBuffer.h" | |
| 16 | |
| 17 #if SK_SUPPORT_GPU | |
| 18 #include "SkGrPriv.h" | |
| 19 #include "effects/GrBicubicEffect.h" | |
| 20 #include "effects/GrSimpleTextureEffect.h" | |
| 21 #endif | |
| 22 | 11 |
| 23 static bool only_scale_and_translate(const SkMatrix& matrix) { | 12 static bool only_scale_and_translate(const SkMatrix& matrix) { |
| 24 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; | 13 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
| 25 return (matrix.getType() & ~mask) == 0; | 14 return (matrix.getType() & ~mask) == 0; |
| 26 } | 15 } |
| 27 | 16 |
| 28 class BitmapProcInfoContext : public SkShader::Context { | 17 class BitmapProcInfoContext : public SkShader::Context { |
| 29 public: | 18 public: |
| 30 // The info has been allocated elsewhere, but we are responsible for calling its destructor. | 19 // The info has been allocated elsewhere, but we are responsible for calling its destructor. |
| 31 BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re c, | 20 BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re c, |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 | 193 |
| 205 static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImag eInfo& srcInfo) { | 194 static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImag eInfo& srcInfo) { |
| 206 // If we get here, we can reasonably use either context, respect the caller' s preference | 195 // If we get here, we can reasonably use either context, respect the caller' s preference |
| 207 // | 196 // |
| 208 bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType; | 197 bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType; |
| 209 bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != k N32_SkColorType; | 198 bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != k N32_SkColorType; |
| 210 return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType | 199 return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType |
| 211 || needsPremul || needsSwizzle; | 200 || needsPremul || needsSwizzle; |
| 212 } | 201 } |
| 213 | 202 |
| 214 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec, const SkImageInfo& srcInfo) { | 203 size_t SkBitmapProcLegacyShader::ContextSize(const ContextRec& rec, const SkImag eInfo& srcInfo) { |
| 215 size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | 204 size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); |
| 216 size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); | 205 size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); |
| 206 size_t s = SkTMax(size0, size1); | |
| 207 return s; | |
|
scroggo
2016/09/08 13:42:24
This is effectively the same as the old code, righ
| |
| 217 return SkTMax(size0, size1); | 208 return SkTMax(size0, size1); |
| 218 } | 209 } |
| 219 | 210 |
| 220 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, | 211 SkShader::Context* SkBitmapProcLegacyShader::MakeContext(const SkShader& shader, |
| 221 TileMode tmx, TileMode tmy, | 212 TileMode tmx, TileMode tmy, |
| 222 const SkBitmapProvider& provi der, | 213 const SkBitmapProvider& provi der, |
| 223 const ContextRec& rec, void* storage) { | 214 const ContextRec& rec, void* storage) { |
| 224 SkMatrix totalInverse; | 215 SkMatrix totalInverse; |
| 225 // Do this first, so we know the matrix can be inverted. | 216 // Do this first, so we know the matrix can be inverted. |
| 226 if (!shader.computeTotalInverse(rec, &totalInverse)) { | 217 if (!shader.computeTotalInverse(rec, &totalInverse)) { |
| 227 return nullptr; | 218 return nullptr; |
| 228 } | 219 } |
| 229 | 220 |
| 230 // Decide if we can/want to use the new linear pipeline | 221 // Decide if we can/want to use the new linear pipeline |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 244 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | 235 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); |
| 245 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider , tmx, tmy, | 236 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider , tmx, tmy, |
| 246 treatmen t); | 237 treatmen t); |
| 247 if (!state->setup(totalInverse, *rec.fPaint)) { | 238 if (!state->setup(totalInverse, *rec.fPaint)) { |
| 248 state->~SkBitmapProcState(); | 239 state->~SkBitmapProcState(); |
| 249 return nullptr; | 240 return nullptr; |
| 250 } | 241 } |
| 251 return new (storage) BitmapProcShaderContext(shader, rec, state); | 242 return new (storage) BitmapProcShaderContext(shader, rec, state); |
| 252 } | 243 } |
| 253 } | 244 } |
| 254 | |
| 255 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo id* storage) const { | |
| 256 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, | |
| 257 SkBitmapProvider(fRawBitmap), rec, storage); | |
| 258 } | |
| 259 | |
| 260 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 261 | |
| 262 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo de tmy, | |
| 263 const SkMatrix* localMatrix) | |
| 264 : INHERITED(localMatrix) { | |
| 265 fRawBitmap = src; | |
| 266 fTileModeX = (uint8_t)tmx; | |
| 267 fTileModeY = (uint8_t)tmy; | |
| 268 } | |
| 269 | |
| 270 bool SkBitmapProcShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode xy[]) const { | |
| 271 if (texture) { | |
| 272 *texture = fRawBitmap; | |
| 273 } | |
| 274 if (texM) { | |
| 275 *texM = this->getLocalMatrix(); | |
| 276 } | |
| 277 if (xy) { | |
| 278 xy[0] = (TileMode)fTileModeX; | |
| 279 xy[1] = (TileMode)fTileModeY; | |
| 280 } | |
| 281 return true; | |
| 282 } | |
| 283 | |
| 284 sk_sp<SkFlattenable> SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) { | |
| 285 SkMatrix lm; | |
| 286 buffer.readMatrix(&lm); | |
| 287 SkBitmap bm; | |
| 288 if (!buffer.readBitmap(&bm)) { | |
| 289 return nullptr; | |
| 290 } | |
| 291 bm.setImmutable(); | |
| 292 TileMode mx = (TileMode)buffer.readUInt(); | |
| 293 TileMode my = (TileMode)buffer.readUInt(); | |
| 294 return SkShader::MakeBitmapShader(bm, mx, my, &lm); | |
| 295 } | |
| 296 | |
| 297 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { | |
| 298 buffer.writeMatrix(this->getLocalMatrix()); | |
| 299 buffer.writeBitmap(fRawBitmap); | |
| 300 buffer.writeUInt(fTileModeX); | |
| 301 buffer.writeUInt(fTileModeY); | |
| 302 } | |
| 303 | |
| 304 bool SkBitmapProcShader::isOpaque() const { | |
| 305 return fRawBitmap.isOpaque(); | |
| 306 } | |
| 307 | |
| 308 bool SkBitmapProcShader::BitmapIsTooBig(const SkBitmap& bm) { | |
| 309 static const int kMaxSize = 65535; | |
| 310 | |
| 311 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
| 312 } | |
| 313 | |
| 314 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 315 | |
| 316 #include "SkUnPreMultiply.h" | |
| 317 #include "SkColorShader.h" | |
| 318 #include "SkEmptyShader.h" | |
| 319 | |
| 320 // returns true and set color if the bitmap can be drawn as a single color | |
| 321 // (for efficiency) | |
| 322 static bool can_use_color_shader(const SkBitmap& bm, SkColor* color) { | |
| 323 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
| 324 // HWUI does not support color shaders (see b/22390304) | |
| 325 return false; | |
| 326 #endif | |
| 327 | |
| 328 if (1 != bm.width() || 1 != bm.height()) { | |
| 329 return false; | |
| 330 } | |
| 331 | |
| 332 SkAutoLockPixels alp(bm); | |
| 333 if (!bm.readyToDraw()) { | |
| 334 return false; | |
| 335 } | |
| 336 | |
| 337 switch (bm.colorType()) { | |
| 338 case kN32_SkColorType: | |
| 339 *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0)); | |
| 340 return true; | |
| 341 case kRGB_565_SkColorType: | |
| 342 *color = SkPixel16ToColor(*bm.getAddr16(0, 0)); | |
| 343 return true; | |
| 344 case kIndex_8_SkColorType: | |
| 345 *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0)); | |
| 346 return true; | |
| 347 default: // just skip the other configs for now | |
| 348 break; | |
| 349 } | |
| 350 return false; | |
| 351 } | |
| 352 | |
| 353 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
| 354 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
| 355 // communicates between its matrix-proc and its sampler-proc. Until we can | |
| 356 // widen that, we have to reject bitmaps that are larger. | |
| 357 // | |
| 358 static const int kMaxSize = 65535; | |
| 359 | |
| 360 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
| 361 } | |
| 362 | |
| 363 sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode tmx, | |
| 364 SkShader::TileMode tmy, const SkMatrix* local Matrix, | |
| 365 SkTBlitterAllocator* allocator) { | |
| 366 SkShader* shader; | |
| 367 SkColor color; | |
| 368 if (src.isNull() || bitmap_is_too_big(src)) { | |
| 369 if (nullptr == allocator) { | |
| 370 shader = new SkEmptyShader; | |
| 371 } else { | |
| 372 shader = allocator->createT<SkEmptyShader>(); | |
| 373 } | |
| 374 } else if (can_use_color_shader(src, &color)) { | |
| 375 if (nullptr == allocator) { | |
| 376 shader = new SkColorShader(color); | |
| 377 } else { | |
| 378 shader = allocator->createT<SkColorShader>(color); | |
| 379 } | |
| 380 } else { | |
| 381 if (nullptr == allocator) { | |
| 382 shader = new SkBitmapProcShader(src, tmx, tmy, localMatrix); | |
| 383 } else { | |
| 384 shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, local Matrix); | |
| 385 } | |
| 386 } | |
| 387 return sk_sp<SkShader>(shader); | |
| 388 } | |
| 389 | |
| 390 /////////////////////////////////////////////////////////////////////////////// | |
| 391 | |
| 392 #ifndef SK_IGNORE_TO_STRING | |
| 393 void SkBitmapProcShader::toString(SkString* str) const { | |
| 394 static const char* gTileModeName[SkShader::kTileModeCount] = { | |
| 395 "clamp", "repeat", "mirror" | |
| 396 }; | |
| 397 | |
| 398 str->append("BitmapShader: ("); | |
| 399 | |
| 400 str->appendf("(%s, %s)", | |
| 401 gTileModeName[fTileModeX], | |
| 402 gTileModeName[fTileModeY]); | |
| 403 | |
| 404 str->append(" "); | |
| 405 fRawBitmap.toString(str); | |
| 406 | |
| 407 this->INHERITED::toString(str); | |
| 408 | |
| 409 str->append(")"); | |
| 410 } | |
| 411 #endif | |
| 412 | |
| 413 /////////////////////////////////////////////////////////////////////////////// | |
| 414 | |
| 415 #if SK_SUPPORT_GPU | |
| 416 | |
| 417 #include "GrTextureAccess.h" | |
| 418 #include "SkGr.h" | |
| 419 #include "effects/GrSimpleTextureEffect.h" | |
| 420 | |
| 421 sk_sp<GrFragmentProcessor> SkBitmapProcShader::asFragmentProcessor(const AsFPArg s& args) const { | |
| 422 SkMatrix matrix; | |
| 423 matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); | |
| 424 | |
| 425 SkMatrix lmInverse; | |
| 426 if (!this->getLocalMatrix().invert(&lmInverse)) { | |
| 427 return nullptr; | |
| 428 } | |
| 429 if (args.fLocalMatrix) { | |
| 430 SkMatrix inv; | |
| 431 if (!args.fLocalMatrix->invert(&inv)) { | |
| 432 return nullptr; | |
| 433 } | |
| 434 lmInverse.postConcat(inv); | |
| 435 } | |
| 436 matrix.preConcat(lmInverse); | |
| 437 | |
| 438 SkShader::TileMode tm[] = { | |
| 439 (TileMode)fTileModeX, | |
| 440 (TileMode)fTileModeY, | |
| 441 }; | |
| 442 | |
| 443 // Must set wrap and filter on the sampler before requesting a texture. In t wo places below | |
| 444 // we check the matrix scale factors to determine how to interpret the filte r quality setting. | |
| 445 // This completely ignores the complexity of the drawVertices case where exp licit local coords | |
| 446 // are provided by the caller. | |
| 447 bool doBicubic; | |
| 448 GrTextureParams::FilterMode textureFilterMode = | |
| 449 GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatr ix, | |
| 450 this->getLocalMatrix(), &doBicubic); | |
| 451 GrTextureParams params(tm, textureFilterMode); | |
| 452 SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(args.fContext, fRaw Bitmap, params, | |
| 453 args.fGammaTreatmen t)); | |
| 454 | |
| 455 if (!texture) { | |
| 456 SkErrorInternals::SetError( kInternalError_SkError, | |
| 457 "Couldn't convert bitmap to texture."); | |
| 458 return nullptr; | |
| 459 } | |
| 460 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fRawBitma p.colorSpace(), | |
| 461 args.fDst ColorSpace); | |
| 462 sk_sp<GrFragmentProcessor> inner; | |
| 463 if (doBicubic) { | |
| 464 inner = GrBicubicEffect::Make(texture, std::move(colorSpaceXform), matri x, tm); | |
| 465 } else { | |
| 466 inner = GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, params); | |
| 467 } | |
| 468 | |
| 469 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { | |
| 470 return GrFragmentProcessor::MulOutputByInputUnpremulColor(std::move(inne r)); | |
| 471 } | |
| 472 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); | |
| 473 } | |
| 474 | |
| 475 #endif | |
| OLD | NEW |