void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::kBW_Format) { // TODO: native BW masks? return INHERITED::blitMask(mask, clip); } if (mask.fFormat == SkMask::kA8_Format && fBlitMaskA8.empty()) { auto& p = fBlitMaskA8; p.extend(fShader); if (fBlend == SkBlendMode::kSrcOver) { p.append(SkRasterPipeline::scale_u8, &fMaskPtr); this->append_load_d(&p); this->append_blend(&p); } else { this->append_load_d(&p); this->append_blend(&p); p.append(SkRasterPipeline::lerp_u8, &fMaskPtr); } this->maybe_clamp(&p); this->append_store(&p); } if (mask.fFormat == SkMask::kLCD16_Format && fBlitMaskLCD16.empty()) { auto& p = fBlitMaskLCD16; p.extend(fShader); this->append_load_d(&p); this->append_blend(&p); p.append(SkRasterPipeline::lerp_565, &fMaskPtr); this->maybe_clamp(&p); this->append_store(&p); } int x = clip.left(); for (int y = clip.top(); y < clip.bottom(); y++) { fDstPtr = fDst.writable_addr(0,y); fCurrentY = y; switch (mask.fFormat) { case SkMask::kA8_Format: fMaskPtr = mask.getAddr8(x,y)-x; fBlitMaskA8.run(x,clip.width()); break; case SkMask::kLCD16_Format: fMaskPtr = mask.getAddrLCD16(x,y)-x; fBlitMaskLCD16.run(x,clip.width()); break; default: // TODO break; } } }
void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::kBW_Format) { // TODO: native BW masks? return INHERITED::blitMask(mask, clip); } int x = clip.left(); for (int y = clip.top(); y < clip.bottom(); y++) { auto dst = fDst.writable_addr(0,y); SkRasterPipeline p; p.extend(fShader); p.extend(fColorFilter); this->append_load_d(&p, dst); p.extend(fXfermode); switch (mask.fFormat) { case SkMask::kA8_Format: p.append<lerp_a8, lerp_a8_1>(mask.getAddr8(x,y)-x); break; case SkMask::kLCD16_Format: p.append<lerp_lcd16, lerp_lcd16_1>(mask.getAddrLCD16(x,y)-x); break; default: break; } this->append_store(&p, dst); p.run(x, clip.width()); } }
void SkRasterPipelineBlitter::blitH(int x, int y, int w) { auto dst = fDst.writable_addr(0,y); SkRasterPipeline p; p.extend(fShader); p.extend(fColorFilter); this->append_load_d(&p, dst); p.extend(fXfermode); this->append_store(&p, dst); p.run(x, w); }
void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) { auto dst = fDst.writable_addr(0,y); float coverage; SkRasterPipeline p; p.extend(fShader); p.extend(fColorFilter); this->append_load_d(&p, dst); p.extend(fXfermode); p.append<lerp_constant_float>(&coverage); this->append_store(&p, dst); for (int16_t run = *runs; run > 0; run = *runs) { coverage = *aa * (1/255.0f); p.run(x, run); x += run; runs += run; aa += run; } }
bool SkColorSpaceXform_A2B::onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src, int count, SkAlphaType alphaType) const { SkRasterPipeline pipeline; switch (srcFormat) { case kBGRA_8888_ColorFormat: pipeline.append(SkRasterPipeline::load_8888, &src); pipeline.append(SkRasterPipeline::swap_rb); break; case kRGBA_8888_ColorFormat: pipeline.append(SkRasterPipeline::load_8888, &src); break; case kRGBA_U16_BE_ColorFormat: pipeline.append(SkRasterPipeline::load_u16_be, &src); break; case kRGB_U16_BE_ColorFormat: pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src); break; default: SkCSXformPrintf("F16/F32 sources must be linear.\n"); return false; } pipeline.extend(fElementsPipeline); if (kPremul_SkAlphaType == alphaType) { pipeline.append(SkRasterPipeline::premul); } switch (dstFormat) { case kBGRA_8888_ColorFormat: pipeline.append(SkRasterPipeline::swap_rb); pipeline.append(SkRasterPipeline::store_8888, &dst); break; case kRGBA_8888_ColorFormat: pipeline.append(SkRasterPipeline::store_8888, &dst); break; case kRGBA_F16_ColorFormat: if (!fLinearDstGamma) { return false; } pipeline.append(SkRasterPipeline::store_f16, &dst); break; case kRGBA_F32_ColorFormat: if (!fLinearDstGamma) { return false; } pipeline.append(SkRasterPipeline::store_f32, &dst); break; case kBGR_565_ColorFormat: if (kOpaque_SkAlphaType != alphaType) { return false; } pipeline.append(SkRasterPipeline::store_565, &dst); break; default: return false; } pipeline.run(0,count); return true; }
SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, const SkPaint& paint, const SkMatrix& ctm, SkArenaAlloc* alloc) { auto blitter = alloc->make<SkRasterPipelineBlitter>( dst, paint.getBlendMode(), SkPM4f_from_SkColor(paint.getColor(), dst.colorSpace())); SkBlendMode* blend = &blitter->fBlend; SkPM4f* paintColor = &blitter->fPaintColor; SkRasterPipeline* pipeline = &blitter->fShader; SkShader* shader = paint.getShader(); SkColorFilter* colorFilter = paint.getColorFilter(); // TODO: all temporary if (!supported(dst.info()) || !SkBlendMode_AppendStages(*blend)) { return nullptr; } bool is_opaque = paintColor->a() == 1.0f, is_constant = true; if (shader) { pipeline->append(SkRasterPipeline::seed_shader, &blitter->fCurrentY); if (!shader->appendStages(pipeline, dst.colorSpace(), alloc, ctm, paint)) { return nullptr; } if (!is_opaque) { pipeline->append(SkRasterPipeline::scale_1_float, &paintColor->fVec[SkPM4f::A]); } is_opaque = is_opaque && shader->isOpaque(); is_constant = shader->isConstant(); } else { pipeline->append(SkRasterPipeline::constant_color, paintColor); } if (colorFilter) { if (!colorFilter->appendStages(pipeline, dst.colorSpace(), alloc, is_opaque)) { return nullptr; } is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); } if (is_constant) { pipeline->append(SkRasterPipeline::store_f32, &paintColor); pipeline->run(0,1); *pipeline = SkRasterPipeline(); pipeline->append(SkRasterPipeline::constant_color, paintColor); is_opaque = paintColor->a() == 1.0f; } if (is_opaque && *blend == SkBlendMode::kSrcOver) { *blend = SkBlendMode::kSrc; } if (is_constant && *blend == SkBlendMode::kSrc) { SkRasterPipeline p; p.extend(*pipeline); blitter->fDstPtr = &blitter->fMemsetColor; blitter->append_store(&p); p.run(0,1); blitter->fCanMemsetInBlitH = true; } return blitter; }