123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkMallocPixelRef.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkPicture.h"
- #include "include/core/SkScalar.h"
- #include "src/core/SkArenaAlloc.h"
- #include "src/core/SkColorSpacePriv.h"
- #include "src/core/SkColorSpaceXformSteps.h"
- #include "src/core/SkRasterPipeline.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkTLazy.h"
- #include "src/core/SkWriteBuffer.h"
- #include "src/shaders/SkBitmapProcShader.h"
- #include "src/shaders/SkColorShader.h"
- #include "src/shaders/SkEmptyShader.h"
- #include "src/shaders/SkPictureShader.h"
- #include "src/shaders/SkShaderBase.h"
- #if SK_SUPPORT_GPU
- #include "src/gpu/GrFragmentProcessor.h"
- #endif
- SkShaderBase::SkShaderBase(const SkMatrix* localMatrix)
- : fLocalMatrix(localMatrix ? *localMatrix : SkMatrix::I()) {
- // Pre-cache so future calls to fLocalMatrix.getType() are threadsafe.
- (void)fLocalMatrix.getType();
- }
- SkShaderBase::~SkShaderBase() {}
- void SkShaderBase::flatten(SkWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- bool hasLocalM = !fLocalMatrix.isIdentity();
- buffer.writeBool(hasLocalM);
- if (hasLocalM) {
- buffer.writeMatrix(fLocalMatrix);
- }
- }
- SkTCopyOnFirstWrite<SkMatrix>
- SkShaderBase::totalLocalMatrix(const SkMatrix* preLocalMatrix,
- const SkMatrix* postLocalMatrix) const {
- SkTCopyOnFirstWrite<SkMatrix> m(fLocalMatrix);
- if (preLocalMatrix) {
- m.writable()->preConcat(*preLocalMatrix);
- }
- if (postLocalMatrix) {
- m.writable()->postConcat(*postLocalMatrix);
- }
- return m;
- }
- bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
- const SkMatrix* outerLocalMatrix,
- SkMatrix* totalInverse) const {
- return SkMatrix::Concat(ctm, *this->totalLocalMatrix(outerLocalMatrix)).invert(totalInverse);
- }
- bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {
- SkColor storage;
- if (nullptr == colorPtr) {
- colorPtr = &storage;
- }
- if (this->onAsLuminanceColor(colorPtr)) {
- *colorPtr = SkColorSetA(*colorPtr, 0xFF); // we only return opaque
- return true;
- }
- return false;
- }
- SkShaderBase::Context* SkShaderBase::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
- #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
- // We always fall back to raster pipeline when perspective is present.
- if (rec.fMatrix->hasPerspective() ||
- fLocalMatrix.hasPerspective() ||
- (rec.fLocalMatrix && rec.fLocalMatrix->hasPerspective()) ||
- !this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)) {
- return nullptr;
- }
- return this->onMakeContext(rec, alloc);
- #else
- return nullptr;
- #endif
- }
- SkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec)
- : fShader(shader), fCTM(*rec.fMatrix)
- {
- // We should never use a context with perspective.
- SkASSERT(!rec.fMatrix->hasPerspective());
- SkASSERT(!rec.fLocalMatrix || !rec.fLocalMatrix->hasPerspective());
- SkASSERT(!shader.getLocalMatrix().hasPerspective());
- // Because the context parameters must be valid at this point, we know that the matrix is
- // invertible.
- SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &fTotalInverse));
- fPaintAlpha = rec.fPaint->getAlpha();
- }
- SkShaderBase::Context::~Context() {}
- bool SkShaderBase::ContextRec::isLegacyCompatible(SkColorSpace* shaderColorSpace) const {
- return !SkColorSpaceXformSteps::Required(shaderColorSpace, fDstColorSpace);
- }
- SkImage* SkShader::isAImage(SkMatrix* localMatrix, SkTileMode xy[2]) const {
- return as_SB(this)->onIsAImage(localMatrix, xy);
- }
- SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
- return kNone_GradientType;
- }
- #if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor> SkShaderBase::asFragmentProcessor(const GrFPArgs&) const {
- return nullptr;
- }
- #endif
- sk_sp<SkShader> SkShaderBase::makeAsALocalMatrixShader(SkMatrix*) const {
- return nullptr;
- }
- sk_sp<SkShader> SkShaders::Empty() { return sk_make_sp<SkEmptyShader>(); }
- sk_sp<SkShader> SkShaders::Color(SkColor color) { return sk_make_sp<SkColorShader>(color); }
- sk_sp<SkShader> SkBitmap::makeShader(SkTileMode tmx, SkTileMode tmy, const SkMatrix* lm) const {
- if (lm && !lm->invert(nullptr)) {
- return nullptr;
- }
- return SkMakeBitmapShader(*this, tmx, tmy, lm, kIfMutable_SkCopyPixelsMode);
- }
- sk_sp<SkShader> SkBitmap::makeShader(const SkMatrix* lm) const {
- return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, lm);
- }
- bool SkShaderBase::appendStages(const SkStageRec& rec) const {
- return this->onAppendStages(rec);
- }
- bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
- // SkShader::Context::shadeSpan() handles the paint opacity internally,
- // but SkRasterPipelineBlitter applies it as a separate stage.
- // We skip the internal shadeSpan() step by forcing the paint opaque.
- SkTCopyOnFirstWrite<SkPaint> opaquePaint(rec.fPaint);
- if (rec.fPaint.getAlpha() != SK_AlphaOPAQUE) {
- opaquePaint.writable()->setAlpha(SK_AlphaOPAQUE);
- }
- ContextRec cr(*opaquePaint, rec.fCTM, rec.fLocalM, rec.fDstColorType, sk_srgb_singleton());
- struct CallbackCtx : SkRasterPipeline_CallbackCtx {
- sk_sp<const SkShader> shader;
- Context* ctx;
- };
- auto cb = rec.fAlloc->make<CallbackCtx>();
- cb->shader = sk_ref_sp(this);
- cb->ctx = as_SB(this)->makeContext(cr, rec.fAlloc);
- cb->fn = [](SkRasterPipeline_CallbackCtx* self, int active_pixels) {
- auto c = (CallbackCtx*)self;
- int x = (int)c->rgba[0],
- y = (int)c->rgba[1];
- SkPMColor tmp[SkRasterPipeline_kMaxStride];
- c->ctx->shadeSpan(x,y, tmp, active_pixels);
- for (int i = 0; i < active_pixels; i++) {
- auto rgba_4f = SkPMColor4f::FromPMColor(tmp[i]);
- memcpy(c->rgba + 4*i, rgba_4f.vec(), 4*sizeof(float));
- }
- };
- if (cb->ctx) {
- rec.fPipeline->append(SkRasterPipeline::seed_shader);
- rec.fPipeline->append(SkRasterPipeline::callback, cb);
- rec.fAlloc->make<SkColorSpaceXformSteps>(sk_srgb_singleton(), kPremul_SkAlphaType,
- rec.fDstCS, kPremul_SkAlphaType)
- ->apply(rec.fPipeline, true);
- return true;
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {
- return SkShaders::Empty();
- }
|