bool SkComposeShader::onAppendStages(const StageRec& rec) const { struct Storage { float fRGBA[4 * SkJumper_kMaxStride]; float fAlpha; }; auto storage = rec.fAlloc->make<Storage>(); if (!as_SB(fSrc)->appendStages(rec)) { return false; } // This outputs r,g,b,a, which we'll need later when we apply the mode, but we save it off now // since fShaderB will overwrite them. rec.fPipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA); if (!as_SB(fDst)->appendStages(rec)) { return false; } // We now have our logical 'dst' in r,g,b,a, but we need it in dr,dg,db,da for the mode/lerp // so we have to shuttle them. If we had a stage the would load_into_dst, then we could // reverse the two shader invocations, and avoid this move... rec.fPipeline->append(SkRasterPipeline::move_src_dst); rec.fPipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA); if (!this->isJustLerp()) { SkBlendMode_AppendStages(fMode, rec.fPipeline); } if (!this->isJustMode()) { rec.fPipeline->append(SkRasterPipeline::lerp_1_float, &fLerpT); } 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; }
void SkRasterPipelineBlitter::append_blend(SkRasterPipeline* p) const { SkAssertResult(SkBlendMode_AppendStages(fBlend, p)); }