1 /* 2 * Copyright 2016 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 "SkArenaAlloc.h" 9 #include "SkBlitter.h" 10 #include "SkBlendModePriv.h" 11 #include "SkColor.h" 12 #include "SkColorFilter.h" 13 #include "SkColorSpaceXformer.h" 14 #include "SkOpts.h" 15 #include "SkPM4f.h" 16 #include "SkPM4fPriv.h" 17 #include "SkRasterPipeline.h" 18 #include "SkShader.h" 19 #include "SkShaderBase.h" 20 #include "SkUtils.h" 21 #include "../jumper/SkJumper.h" 22 23 class SkRasterPipelineBlitter final : public SkBlitter { 24 public: 25 // This is our common entrypoint for creating the blitter once we've sorted out shaders. 26 static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkArenaAlloc*, 27 const SkRasterPipeline& shaderPipeline, 28 SkShaderBase::Context*, 29 bool is_opaque, bool is_constant); 30 31 SkRasterPipelineBlitter(SkPixmap dst, 32 SkBlendMode blend, 33 SkArenaAlloc* alloc, 34 SkShaderBase::Context* burstCtx) 35 : fDst(dst) 36 , fBlend(blend) 37 , fAlloc(alloc) 38 , fBurstCtx(burstCtx) 39 , fColorPipeline(alloc) 40 {} 41 42 void blitH (int x, int y, int w) override; 43 void blitAntiH (int x, int y, const SkAlpha[], const int16_t[]) override; 44 void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 45 void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 46 void blitMask (const SkMask&, const SkIRect& clip) override; 47 void blitRect (int x, int y, int width, int height) override; 48 void blitV (int x, int y, int height, SkAlpha alpha) override; 49 50 private: 51 void append_load_dst(SkRasterPipeline*) const; 52 void append_store (SkRasterPipeline*) const; 53 54 // If we have an burst context, use it to fill our shader buffer. 55 void burst_shade(int x, int y, int w); 56 57 SkPixmap fDst; 58 SkBlendMode fBlend; 59 SkArenaAlloc* fAlloc; 60 SkShaderBase::Context* fBurstCtx; 61 SkRasterPipeline fColorPipeline; 62 63 SkJumper_MemoryCtx fShaderOutput = {nullptr,0}, // Possibly updated each call to burst_shade(). 64 fDstPtr = {nullptr,0}, // Always points to the top-left of fDst. 65 fMaskPtr = {nullptr,0}; // Updated each call to blitMask(). 66 67 // We may be able to specialize blitH() or blitRect() into a memset. 68 bool fCanMemsetInBlitRect = false; 69 uint64_t fMemsetColor = 0; // Big enough for largest dst format, F16. 70 71 // Built lazily on first use. 72 std::function<void(size_t, size_t, size_t, size_t)> fBlitRect, 73 fBlitAntiH, 74 fBlitMaskA8, 75 fBlitMaskLCD16; 76 77 // These values are pointed to by the blit pipelines above, 78 // which allows us to adjust them from call to call. 79 float fCurrentCoverage = 0.0f; 80 float fDitherRate = 0.0f; 81 82 std::vector<SkPM4f> fShaderBuffer; 83 84 typedef SkBlitter INHERITED; 85 }; 86 87 SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, 88 const SkPaint& paint, 89 const SkMatrix& ctm, 90 SkArenaAlloc* alloc) { 91 SkColorSpace* dstCS = dst.colorSpace(); 92 SkPM4f paintColor = SkPM4f_from_SkColor(paint.getColor(), dstCS); 93 auto shader = as_SB(paint.getShader()); 94 95 SkRasterPipeline_<256> shaderPipeline; 96 if (!shader) { 97 // Having no shader makes things nice and easy... just use the paint color. 98 shaderPipeline.append_constant_color(alloc, paintColor); 99 bool is_opaque = paintColor.a() == 1.0f, 100 is_constant = true; 101 return SkRasterPipelineBlitter::Create(dst, paint, alloc, 102 shaderPipeline, nullptr, 103 is_opaque, is_constant); 104 } 105 106 bool is_opaque = shader->isOpaque() && paintColor.a() == 1.0f; 107 bool is_constant = shader->isConstant(); 108 109 // Check whether the shader prefers to run in burst mode. 110 if (auto* burstCtx = shader->makeBurstPipelineContext( 111 SkShaderBase::ContextRec(paint, ctm, nullptr, SkShaderBase::ContextRec::kPM4f_DstType, 112 dstCS), alloc)) { 113 return SkRasterPipelineBlitter::Create(dst, paint, alloc, 114 shaderPipeline, burstCtx, 115 is_opaque, is_constant); 116 } 117 118 if (shader->appendStages({&shaderPipeline, alloc, dstCS, paint, nullptr, ctm})) { 119 if (paintColor.a() != 1.0f) { 120 shaderPipeline.append(SkRasterPipeline::scale_1_float, 121 alloc->make<float>(paintColor.a())); 122 } 123 return SkRasterPipelineBlitter::Create(dst, paint, alloc, shaderPipeline, nullptr, 124 is_opaque, is_constant); 125 } 126 127 // The shader has opted out of drawing anything. 128 return alloc->make<SkNullBlitter>(); 129 } 130 131 SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, 132 const SkPaint& paint, 133 const SkRasterPipeline& shaderPipeline, 134 bool is_opaque, 135 SkArenaAlloc* alloc) { 136 bool is_constant = false; // If this were the case, it'd be better to just set a paint color. 137 return SkRasterPipelineBlitter::Create(dst, paint, alloc, shaderPipeline, nullptr, 138 is_opaque, is_constant); 139 } 140 141 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, 142 const SkPaint& paint, 143 SkArenaAlloc* alloc, 144 const SkRasterPipeline& shaderPipeline, 145 SkShaderBase::Context* burstCtx, 146 bool is_opaque, 147 bool is_constant) { 148 auto blitter = alloc->make<SkRasterPipelineBlitter>(dst, 149 paint.getBlendMode(), 150 alloc, 151 burstCtx); 152 153 // Our job in this factory is to fill out the blitter's color pipeline. 154 // This is the common front of the full blit pipelines, each constructed lazily on first use. 155 // The full blit pipelines handle reading and writing the dst, blending, coverage, dithering. 156 auto colorPipeline = &blitter->fColorPipeline; 157 158 // Let's get the shader in first. 159 if (burstCtx) { 160 colorPipeline->append(SkRasterPipeline::load_f32, &blitter->fShaderOutput); 161 } else { 162 colorPipeline->extend(shaderPipeline); 163 } 164 165 // If there's a color filter it comes next. 166 if (auto colorFilter = paint.getColorFilter()) { 167 colorFilter->appendStages(colorPipeline, dst.colorSpace(), alloc, is_opaque); 168 is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); 169 } 170 171 // Not all formats make sense to dither (think, F16). We set their dither rate 172 // to zero. We need to decide if we're going to dither now to keep is_constant accurate. 173 if (paint.isDither()) { 174 switch (dst.info().colorType()) { 175 default: blitter->fDitherRate = 0.0f; break; 176 case kARGB_4444_SkColorType: blitter->fDitherRate = 1/15.0f; break; 177 case kRGB_565_SkColorType: blitter->fDitherRate = 1/63.0f; break; 178 case kGray_8_SkColorType: 179 case kRGB_888x_SkColorType: 180 case kRGBA_8888_SkColorType: 181 case kBGRA_8888_SkColorType: blitter->fDitherRate = 1/255.0f; break; 182 case kRGB_101010x_SkColorType: 183 case kRGBA_1010102_SkColorType: blitter->fDitherRate = 1/1023.0f; break; 184 } 185 // TODO: for constant colors, we could try to measure the effect of dithering, and if 186 // it has no value (i.e. all variations result in the same 32bit color, then we 187 // could disable it (for speed, by not adding the stage). 188 } 189 is_constant = is_constant && (blitter->fDitherRate == 0.0f); 190 191 // We're logically done here. The code between here and return blitter is all optimization. 192 193 // A pipeline that's still constant here can collapse back into a constant color. 194 if (is_constant) { 195 SkPM4f constantColor; 196 SkJumper_MemoryCtx constantColorPtr = { &constantColor, 0 }; 197 colorPipeline->append(SkRasterPipeline::store_f32, &constantColorPtr); 198 colorPipeline->run(0,0,1,1); 199 colorPipeline->reset(); 200 colorPipeline->append_constant_color(alloc, constantColor); 201 202 is_opaque = constantColor.a() == 1.0f; 203 } 204 205 // We can strength-reduce SrcOver into Src when opaque. 206 if (is_opaque && blitter->fBlend == SkBlendMode::kSrcOver) { 207 blitter->fBlend = SkBlendMode::kSrc; 208 } 209 210 // When we're drawing a constant color in Src mode, we can sometimes just memset. 211 // (The previous two optimizations help find more opportunities for this one.) 212 if (is_constant && blitter->fBlend == SkBlendMode::kSrc) { 213 // Run our color pipeline all the way through to produce what we'd memset when we can. 214 // Not all blits can memset, so we need to keep colorPipeline too. 215 SkRasterPipeline_<256> p; 216 p.extend(*colorPipeline); 217 blitter->fDstPtr = SkJumper_MemoryCtx{&blitter->fMemsetColor, 0}; 218 blitter->append_store(&p); 219 p.run(0,0,1,1); 220 221 blitter->fCanMemsetInBlitRect = true; 222 } 223 224 blitter->fDstPtr = SkJumper_MemoryCtx{ 225 blitter->fDst.writable_addr(), 226 blitter->fDst.rowBytesAsPixels(), 227 }; 228 229 return blitter; 230 } 231 232 void SkRasterPipelineBlitter::append_load_dst(SkRasterPipeline* p) const { 233 const void* ctx = &fDstPtr; 234 switch (fDst.info().colorType()) { 235 default: break; 236 237 case kGray_8_SkColorType: p->append(SkRasterPipeline::load_g8_dst, ctx); break; 238 case kAlpha_8_SkColorType: p->append(SkRasterPipeline::load_a8_dst, ctx); break; 239 case kRGB_565_SkColorType: p->append(SkRasterPipeline::load_565_dst, ctx); break; 240 case kARGB_4444_SkColorType: p->append(SkRasterPipeline::load_4444_dst, ctx); break; 241 case kBGRA_8888_SkColorType: p->append(SkRasterPipeline::load_bgra_dst, ctx); break; 242 case kRGBA_8888_SkColorType: p->append(SkRasterPipeline::load_8888_dst, ctx); break; 243 case kRGBA_1010102_SkColorType: p->append(SkRasterPipeline::load_1010102_dst, ctx); break; 244 case kRGBA_F16_SkColorType: p->append(SkRasterPipeline::load_f16_dst, ctx); break; 245 246 case kRGB_888x_SkColorType: p->append(SkRasterPipeline::load_8888_dst, ctx); 247 p->append(SkRasterPipeline::force_opaque_dst ); break; 248 case kRGB_101010x_SkColorType: p->append(SkRasterPipeline::load_1010102_dst, ctx); 249 p->append(SkRasterPipeline::force_opaque_dst ); break; 250 } 251 if (fDst.info().gammaCloseToSRGB()) { 252 p->append(SkRasterPipeline::from_srgb_dst); 253 } 254 if (fDst.info().alphaType() == kUnpremul_SkAlphaType) { 255 p->append(SkRasterPipeline::premul_dst); 256 } 257 } 258 259 void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p) const { 260 if (fDst.info().alphaType() == kUnpremul_SkAlphaType) { 261 p->append(SkRasterPipeline::unpremul); 262 } 263 if (fDst.info().gammaCloseToSRGB()) { 264 p->append(SkRasterPipeline::to_srgb); 265 } 266 if (fDitherRate > 0.0f) { 267 // We dither after any sRGB transfer function to make sure our 1/255.0f is sensible 268 // over the whole range. If we did it before, 1/255.0f is too big a rate near zero. 269 p->append(SkRasterPipeline::dither, &fDitherRate); 270 } 271 272 const void* ctx = &fDstPtr; 273 switch (fDst.info().colorType()) { 274 default: break; 275 276 case kGray_8_SkColorType: p->append(SkRasterPipeline::luminance_to_alpha); 277 p->append(SkRasterPipeline::store_a8, ctx); break; 278 case kAlpha_8_SkColorType: p->append(SkRasterPipeline::store_a8, ctx); break; 279 case kRGB_565_SkColorType: p->append(SkRasterPipeline::store_565, ctx); break; 280 case kARGB_4444_SkColorType: p->append(SkRasterPipeline::store_4444, ctx); break; 281 case kBGRA_8888_SkColorType: p->append(SkRasterPipeline::store_bgra, ctx); break; 282 case kRGBA_8888_SkColorType: p->append(SkRasterPipeline::store_8888, ctx); break; 283 case kRGBA_1010102_SkColorType: p->append(SkRasterPipeline::store_1010102, ctx); break; 284 case kRGBA_F16_SkColorType: p->append(SkRasterPipeline::store_f16, ctx); break; 285 286 case kRGB_888x_SkColorType: p->append(SkRasterPipeline::force_opaque ); 287 p->append(SkRasterPipeline::store_8888, ctx); break; 288 case kRGB_101010x_SkColorType: p->append(SkRasterPipeline::force_opaque ); 289 p->append(SkRasterPipeline::store_1010102, ctx); break; 290 } 291 } 292 293 void SkRasterPipelineBlitter::burst_shade(int x, int y, int w) { 294 SkASSERT(fBurstCtx); 295 if (w > SkToInt(fShaderBuffer.size())) { 296 fShaderBuffer.resize(w); 297 } 298 fBurstCtx->shadeSpan4f(x,y, fShaderBuffer.data(), w); 299 // We'll be reading from fShaderOutput.pixels + x, so back up by x. 300 fShaderOutput = SkJumper_MemoryCtx{ fShaderBuffer.data() - x, 0 }; 301 } 302 303 void SkRasterPipelineBlitter::blitH(int x, int y, int w) { 304 this->blitRect(x,y,w,1); 305 } 306 307 void SkRasterPipelineBlitter::blitRect(int x, int y, int w, int h) { 308 if (fCanMemsetInBlitRect) { 309 for (int ylimit = y+h; y < ylimit; y++) { 310 switch (fDst.shiftPerPixel()) { 311 case 0: memset (fDst.writable_addr8 (x,y), fMemsetColor, w); break; 312 case 1: sk_memset16(fDst.writable_addr16(x,y), fMemsetColor, w); break; 313 case 2: sk_memset32(fDst.writable_addr32(x,y), fMemsetColor, w); break; 314 case 3: sk_memset64(fDst.writable_addr64(x,y), fMemsetColor, w); break; 315 default: break; 316 } 317 } 318 return; 319 } 320 321 if (!fBlitRect) { 322 SkRasterPipeline p(fAlloc); 323 p.extend(fColorPipeline); 324 if (fBlend == SkBlendMode::kSrcOver 325 && (fDst.info().colorType() == kRGBA_8888_SkColorType || 326 fDst.info().colorType() == kBGRA_8888_SkColorType) 327 && !fDst.colorSpace() 328 && fDst.info().alphaType() != kUnpremul_SkAlphaType 329 && fDitherRate == 0.0f) { 330 auto stage = fDst.info().colorType() == kRGBA_8888_SkColorType 331 ? SkRasterPipeline::srcover_rgba_8888 332 : SkRasterPipeline::srcover_bgra_8888; 333 p.append(stage, &fDstPtr); 334 } else { 335 if (fBlend != SkBlendMode::kSrc) { 336 this->append_load_dst(&p); 337 SkBlendMode_AppendStages(fBlend, &p); 338 } 339 this->append_store(&p); 340 } 341 fBlitRect = p.compile(); 342 } 343 344 if (fBurstCtx) { 345 // We can only burst shade one row at a time. 346 for (int ylimit = y+h; y < ylimit; y++) { 347 this->burst_shade(x,y,w); 348 fBlitRect(x,y, w,1); 349 } 350 } else { 351 // If not bursting we can blit the entire rect at once. 352 fBlitRect(x,y,w,h); 353 } 354 } 355 356 void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) { 357 if (!fBlitAntiH) { 358 SkRasterPipeline p(fAlloc); 359 p.extend(fColorPipeline); 360 if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/false)) { 361 p.append(SkRasterPipeline::scale_1_float, &fCurrentCoverage); 362 this->append_load_dst(&p); 363 SkBlendMode_AppendStages(fBlend, &p); 364 } else { 365 this->append_load_dst(&p); 366 SkBlendMode_AppendStages(fBlend, &p); 367 p.append(SkRasterPipeline::lerp_1_float, &fCurrentCoverage); 368 } 369 370 this->append_store(&p); 371 fBlitAntiH = p.compile(); 372 } 373 374 for (int16_t run = *runs; run > 0; run = *runs) { 375 switch (*aa) { 376 case 0x00: break; 377 case 0xff: this->blitH(x,y,run); break; 378 default: 379 fCurrentCoverage = *aa * (1/255.0f); 380 if (fBurstCtx) { 381 this->burst_shade(x,y,run); 382 } 383 fBlitAntiH(x,y,run,1); 384 } 385 x += run; 386 runs += run; 387 aa += run; 388 } 389 } 390 391 void SkRasterPipelineBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 392 SkIRect clip = {x,y, x+2,y+1}; 393 uint8_t coverage[] = { (uint8_t)a0, (uint8_t)a1 }; 394 395 SkMask mask; 396 mask.fImage = coverage; 397 mask.fBounds = clip; 398 mask.fRowBytes = 2; 399 mask.fFormat = SkMask::kA8_Format; 400 401 this->blitMask(mask, clip); 402 } 403 404 void SkRasterPipelineBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 405 SkIRect clip = {x,y, x+1,y+2}; 406 uint8_t coverage[] = { (uint8_t)a0, (uint8_t)a1 }; 407 408 SkMask mask; 409 mask.fImage = coverage; 410 mask.fBounds = clip; 411 mask.fRowBytes = 1; 412 mask.fFormat = SkMask::kA8_Format; 413 414 this->blitMask(mask, clip); 415 } 416 417 void SkRasterPipelineBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 418 SkIRect clip = {x,y, x+1,y+height}; 419 420 SkMask mask; 421 mask.fImage = α 422 mask.fBounds = clip; 423 mask.fRowBytes = 0; // so we reuse the 1 "row" for all of height 424 mask.fFormat = SkMask::kA8_Format; 425 426 this->blitMask(mask, clip); 427 } 428 429 void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 430 if (mask.fFormat == SkMask::kBW_Format) { 431 // TODO: native BW masks? 432 return INHERITED::blitMask(mask, clip); 433 } 434 435 // We'll use the first (A8) plane of any mask and ignore the other two, just like Ganesh. 436 SkMask::Format effectiveMaskFormat = mask.fFormat == SkMask::k3D_Format ? SkMask::kA8_Format 437 : mask.fFormat; 438 439 440 // Lazily build whichever pipeline we need, specialized for each mask format. 441 if (effectiveMaskFormat == SkMask::kA8_Format && !fBlitMaskA8) { 442 SkRasterPipeline p(fAlloc); 443 p.extend(fColorPipeline); 444 if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/false)) { 445 p.append(SkRasterPipeline::scale_u8, &fMaskPtr); 446 this->append_load_dst(&p); 447 SkBlendMode_AppendStages(fBlend, &p); 448 } else { 449 this->append_load_dst(&p); 450 SkBlendMode_AppendStages(fBlend, &p); 451 p.append(SkRasterPipeline::lerp_u8, &fMaskPtr); 452 } 453 this->append_store(&p); 454 fBlitMaskA8 = p.compile(); 455 } 456 if (effectiveMaskFormat == SkMask::kLCD16_Format && !fBlitMaskLCD16) { 457 SkRasterPipeline p(fAlloc); 458 p.extend(fColorPipeline); 459 if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/true)) { 460 // Somewhat unusually, scale_565 needs dst loaded first. 461 this->append_load_dst(&p); 462 p.append(SkRasterPipeline::scale_565, &fMaskPtr); 463 SkBlendMode_AppendStages(fBlend, &p); 464 } else { 465 this->append_load_dst(&p); 466 SkBlendMode_AppendStages(fBlend, &p); 467 p.append(SkRasterPipeline::lerp_565, &fMaskPtr); 468 } 469 this->append_store(&p); 470 fBlitMaskLCD16 = p.compile(); 471 } 472 473 std::function<void(size_t,size_t,size_t,size_t)>* blitter = nullptr; 474 // Update fMaskPtr to point "into" this current mask, but lined up with fDstPtr at (0,0). 475 // mask.fRowBytes is a uint32_t, which would break our addressing math on 64-bit builds. 476 size_t rowBytes = mask.fRowBytes; 477 switch (effectiveMaskFormat) { 478 case SkMask::kA8_Format: 479 fMaskPtr.stride = rowBytes; 480 fMaskPtr.pixels = (uint8_t*)(mask.fImage - mask.fBounds.left() * (size_t)1 481 - mask.fBounds.top() * rowBytes); 482 blitter = &fBlitMaskA8; 483 break; 484 case SkMask::kLCD16_Format: 485 fMaskPtr.stride = rowBytes / 2; 486 fMaskPtr.pixels = (uint16_t*)(mask.fImage - mask.fBounds.left() * (size_t)2 487 - mask.fBounds.top() * rowBytes); 488 blitter = &fBlitMaskLCD16; 489 break; 490 default: 491 return; 492 } 493 494 SkASSERT(blitter); 495 if (fBurstCtx) { 496 // We can only burst shade one row at a time. 497 int x = clip.left(); 498 for (int y = clip.top(); y < clip.bottom(); y++) { 499 this->burst_shade(x,y,clip.width()); 500 (*blitter)(x,y, clip.width(),1); 501 } 502 } else { 503 // If not bursting we can blit the entire mask at once. 504 (*blitter)(clip.left(),clip.top(), clip.width(),clip.height()); 505 } 506 } 507