diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 229 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.h | 26 | ||||
-rw-r--r-- | src/core/SkColorFilterShader.cpp | 138 | ||||
-rw-r--r-- | src/core/SkColorFilterShader.h | 60 | ||||
-rw-r--r-- | src/core/SkColorShader.cpp | 339 | ||||
-rw-r--r-- | src/core/SkColorShader.h | 142 | ||||
-rw-r--r-- | src/core/SkComposeShader.cpp | 311 | ||||
-rw-r--r-- | src/core/SkComposeShader.h | 88 | ||||
-rw-r--r-- | src/core/SkEmptyShader.h | 41 | ||||
-rw-r--r-- | src/core/SkLightingShader.cpp | 488 | ||||
-rw-r--r-- | src/core/SkLightingShader.h | 39 | ||||
-rw-r--r-- | src/core/SkLocalMatrixShader.cpp | 110 | ||||
-rw-r--r-- | src/core/SkLocalMatrixShader.h | 75 | ||||
-rw-r--r-- | src/core/SkPictureShader.cpp | 364 | ||||
-rw-r--r-- | src/core/SkPictureShader.h | 79 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 305 | ||||
-rw-r--r-- | src/core/SkShaderBase.h | 303 |
17 files changed, 0 insertions, 3137 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp deleted file mode 100644 index e52982354d..0000000000 --- a/src/core/SkBitmapProcShader.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBitmapProcShader.h" - -#include "SkArenaAlloc.h" -#include "SkBitmapProcState.h" -#include "SkBitmapProvider.h" -#include "SkXfermodePriv.h" - -static bool only_scale_and_translate(const SkMatrix& matrix) { - unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; - return (matrix.getType() & ~mask) == 0; -} - -class BitmapProcInfoContext : public SkShaderBase::Context { -public: - // The info has been allocated elsewhere, but we are responsible for calling its destructor. - BitmapProcInfoContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, - SkBitmapProcInfo* info) - : INHERITED(shader, rec) - , fInfo(info) - { - fFlags = 0; - if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { - fFlags |= SkShaderBase::kOpaqueAlpha_Flag; - } - - if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) { - fFlags |= SkShaderBase::kConstInY32_Flag; - } - } - - uint32_t getFlags() const override { return fFlags; } - -private: - SkBitmapProcInfo* fInfo; - uint32_t fFlags; - - typedef SkShaderBase::Context INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class BitmapProcShaderContext : public BitmapProcInfoContext { -public: - BitmapProcShaderContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, - SkBitmapProcState* state) - : INHERITED(shader, rec, state) - , fState(state) - {} - - void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { - const SkBitmapProcState& state = *fState; - if (state.getShaderProc32()) { - state.getShaderProc32()(&state, x, y, dstC, count); - return; - } - - const int BUF_MAX = 128; - uint32_t buffer[BUF_MAX]; - SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); - SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); - const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); - - SkASSERT(state.fPixmap.addr()); - - for (;;) { - int n = SkTMin(count, max); - SkASSERT(n > 0 && n < BUF_MAX*2); - mproc(state, buffer, n, x, y); - sproc(state, buffer, n, dstC); - - if ((count -= n) == 0) { - break; - } - SkASSERT(count > 0); - x += n; - dstC += n; - } - } - - ShadeProc asAShadeProc(void** ctx) override { - if (fState->getShaderProc32()) { - *ctx = fState; - return (ShadeProc)fState->getShaderProc32(); - } - return nullptr; - } - -private: - SkBitmapProcState* fState; - - typedef BitmapProcInfoContext INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -#include "SkLinearBitmapPipeline.h" -#include "SkPM4f.h" - -class LinearPipelineContext : public BitmapProcInfoContext { -public: - LinearPipelineContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, - SkBitmapProcInfo* info, SkArenaAlloc* alloc) - : INHERITED(shader, rec, info), fAllocator{alloc} - { - // Save things off in case we need to build a blitter pipeline. - fSrcPixmap = info->fPixmap; - fAlpha = SkColorGetA(info->fPaintColor) / 255.0f; - fFilterQuality = info->fFilterQuality; - fMatrixTypeMask = info->fRealInvMatrix.getType(); - - fShaderPipeline = alloc->make<SkLinearBitmapPipeline>( - info->fRealInvMatrix, info->fFilterQuality, - info->fTileModeX, info->fTileModeY, - info->fPaintColor, - info->fPixmap, - fAllocator); - - // To implement the old shadeSpan entry-point, we need to efficiently convert our native - // floats into SkPMColor. The SkXfermode::D32Procs do exactly that. - // - fSrcModeProc = SkXfermode::GetD32Proc(SkBlendMode::kSrc, 0); - } - - void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override { - fShaderPipeline->shadeSpan4f(x, y, dstC, count); - } - - void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { - const int N = 128; - SkPM4f tmp[N]; - - while (count > 0) { - const int n = SkTMin(count, N); - fShaderPipeline->shadeSpan4f(x, y, tmp, n); - fSrcModeProc(SkBlendMode::kSrc, dstC, tmp, n, nullptr); - dstC += n; - x += n; - count -= n; - } - } - - bool onChooseBlitProcs(const SkImageInfo& dstInfo, BlitState* state) override { - if ((fBlitterPipeline = SkLinearBitmapPipeline::ClonePipelineForBlitting( - *fShaderPipeline, - fMatrixTypeMask, - fFilterQuality, fSrcPixmap, - fAlpha, state->fMode, dstInfo, fAllocator))) - { - state->fStorage[0] = fBlitterPipeline; - state->fBlitBW = &LinearPipelineContext::ForwardToPipeline; - - return true; - } - - return false; - } - - static void ForwardToPipeline(BlitState* state, int x, int y, const SkPixmap& dst, int count) { - SkLinearBitmapPipeline* pipeline = static_cast<SkLinearBitmapPipeline*>(state->fStorage[0]); - void* addr = dst.writable_addr32(x, y); - pipeline->blitSpan(x, y, addr, count); - } - -private: - // Store the allocator from the context creation incase we are asked to build a blitter. - SkArenaAlloc* fAllocator; - SkLinearBitmapPipeline* fShaderPipeline; - SkLinearBitmapPipeline* fBlitterPipeline; - SkXfermode::D32Proc fSrcModeProc; - SkPixmap fSrcPixmap; - float fAlpha; - SkMatrix::TypeMask fMatrixTypeMask; - SkFilterQuality fFilterQuality; - - typedef BitmapProcInfoContext INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -static bool choose_linear_pipeline(const SkShaderBase::ContextRec& rec, const SkImageInfo& srcInfo) { - // If we get here, we can reasonably use either context, respect the caller's preference - // - bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType; - bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != kN32_SkColorType; - return SkShaderBase::ContextRec::kPM4f_DstType == rec.fPreferredDstType - || needsPremul || needsSwizzle; -} - -size_t SkBitmapProcLegacyShader::ContextSize(const ContextRec& rec, const SkImageInfo& srcInfo) { - size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); - size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); - size_t s = SkTMax(size0, size1); - return s; -} - -SkShaderBase::Context* SkBitmapProcLegacyShader::MakeContext( - const SkShaderBase& shader, TileMode tmx, TileMode tmy, - const SkBitmapProvider& provider, const ContextRec& rec, SkArenaAlloc* alloc) -{ - SkMatrix totalInverse; - // Do this first, so we know the matrix can be inverted. - if (!shader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &totalInverse)) { - return nullptr; - } - - // Decide if we can/want to use the new linear pipeline - bool useLinearPipeline = choose_linear_pipeline(rec, provider.info()); - - if (useLinearPipeline) { - SkBitmapProcInfo* info = alloc->make<SkBitmapProcInfo>(provider, tmx, tmy); - if (!info->init(totalInverse, *rec.fPaint)) { - return nullptr; - } - - return alloc->make<LinearPipelineContext>(shader, rec, info, alloc); - } else { - SkBitmapProcState* state = alloc->make<SkBitmapProcState>(provider, tmx, tmy); - if (!state->setup(totalInverse, *rec.fPaint)) { - return nullptr; - } - return alloc->make<BitmapProcShaderContext>(shader, rec, state); - } -} diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h deleted file mode 100644 index 2a2599cb1d..0000000000 --- a/src/core/SkBitmapProcShader.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ -#ifndef SkBitmapProcShader_DEFINED -#define SkBitmapProcShader_DEFINED - -#include "SkImagePriv.h" -#include "SkShaderBase.h" - -class SkBitmapProvider; - -class SkBitmapProcLegacyShader : public SkShaderBase { -private: - friend class SkImageShader; - - static size_t ContextSize(const ContextRec&, const SkImageInfo& srcInfo); - static Context* MakeContext(const SkShaderBase&, TileMode tmx, TileMode tmy, - const SkBitmapProvider&, const ContextRec&, SkArenaAlloc* alloc); - - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkColorFilterShader.cpp b/src/core/SkColorFilterShader.cpp deleted file mode 100644 index 4798422dfa..0000000000 --- a/src/core/SkColorFilterShader.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkArenaAlloc.h" -#include "SkColorFilterShader.h" -#include "SkColorSpaceXformer.h" -#include "SkReadBuffer.h" -#include "SkWriteBuffer.h" -#include "SkShader.h" -#include "SkString.h" - -#if SK_SUPPORT_GPU -#include "GrFragmentProcessor.h" -#endif - -SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader, sk_sp<SkColorFilter> filter) - : fShader(std::move(shader)) - , fFilter(std::move(filter)) -{ - SkASSERT(fShader); - SkASSERT(fFilter); -} - -sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) { - auto shader = buffer.readShader(); - auto filter = buffer.readColorFilter(); - if (!shader || !filter) { - return nullptr; - } - return sk_make_sp<SkColorFilterShader>(shader, filter); -} - -void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeFlattenable(fShader.get()); - buffer.writeFlattenable(fFilter.get()); -} - -uint32_t SkColorFilterShader::FilterShaderContext::getFlags() const { - const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader); - - uint32_t shaderF = fShaderContext->getFlags(); - uint32_t filterF = filterShader.fFilter->getFlags(); - - // If the filter does not support a given feature, but sure to clear the corresponding flag - // in the shader flags. - // - if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) { - shaderF &= ~kOpaqueAlpha_Flag; - } - return shaderF; -} - -SkShaderBase::Context* SkColorFilterShader::onMakeContext(const ContextRec& rec, - SkArenaAlloc* alloc) const { - auto* shaderContext = as_SB(fShader)->makeContext(rec, alloc); - if (nullptr == shaderContext) { - return nullptr; - } - return alloc->make<FilterShaderContext>(*this, shaderContext, rec); -} - -sk_sp<SkShader> SkColorFilterShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const { - return xformer->apply(fShader.get())->makeWithColorFilter(xformer->apply(fFilter.get())); -} - -SkColorFilterShader::FilterShaderContext::FilterShaderContext( - const SkColorFilterShader& filterShader, - SkShaderBase::Context* shaderContext, - const ContextRec& rec) - : INHERITED(filterShader, rec) - , fShaderContext(shaderContext) -{} - -void SkColorFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[], - int count) { - const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader); - - fShaderContext->shadeSpan(x, y, result, count); - filterShader.fFilter->filterSpan(result, count, result); -} - -void SkColorFilterShader::FilterShaderContext::shadeSpan4f(int x, int y, SkPM4f result[], - int count) { - const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader); - - fShaderContext->shadeSpan4f(x, y, result, count); - filterShader.fFilter->filterSpan4f(result, count, result); -} - -#if SK_SUPPORT_GPU -///////////////////////////////////////////////////////////////////// - -sk_sp<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor(const AsFPArgs& args) const { - - sk_sp<GrFragmentProcessor> fp1(as_SB(fShader)->asFragmentProcessor(args)); - if (!fp1) { - return nullptr; - } - - sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(args.fContext, - args.fDstColorSpace)); - if (!fp2) { - return fp1; - } - - sk_sp<GrFragmentProcessor> fpSeries[] = { std::move(fp1), std::move(fp2) }; - return GrFragmentProcessor::RunInSeries(fpSeries, 2); -} -#endif - -#ifndef SK_IGNORE_TO_STRING -void SkColorFilterShader::toString(SkString* str) const { - str->append("SkColorFilterShader: ("); - - str->append("Shader: "); - as_SB(fShader)->toString(str); - str->append(" Filter: "); - // TODO: add "fFilter->toString(str);" once SkColorFilter::toString is added - - this->INHERITED::toString(str); - - str->append(")"); -} -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -sk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const { - SkShader* base = const_cast<SkShader*>(this); - if (!filter) { - return sk_ref_sp(base); - } - return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), filter); -} diff --git a/src/core/SkColorFilterShader.h b/src/core/SkColorFilterShader.h deleted file mode 100644 index 7f4202158a..0000000000 --- a/src/core/SkColorFilterShader.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkColorFilterShader_DEFINED -#define SkColorFilterShader_DEFINED - -#include "SkColorFilter.h" -#include "SkShaderBase.h" - -class SkArenaAlloc; - -class SkColorFilterShader : public SkShaderBase { -public: - SkColorFilterShader(sk_sp<SkShader> shader, sk_sp<SkColorFilter> filter); - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - class FilterShaderContext : public Context { - public: - // Takes ownership of shaderContext and calls its destructor. - FilterShaderContext(const SkColorFilterShader&, SkShaderBase::Context*, const ContextRec&); - - uint32_t getFlags() const override; - - void shadeSpan(int x, int y, SkPMColor[], int count) override; - void shadeSpan4f(int x, int y, SkPM4f[], int count) override; - - void set3DMask(const SkMask* mask) override { - // forward to our proxy - fShaderContext->set3DMask(mask); - } - - private: - SkShaderBase::Context* fShaderContext; - - typedef Context INHERITED; - }; - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterShader) - -protected: - void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc* alloc) const override; - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; - -private: - sk_sp<SkShader> fShader; - sk_sp<SkColorFilter> fFilter; - - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp deleted file mode 100644 index 32b2c54d71..0000000000 --- a/src/core/SkColorShader.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkArenaAlloc.h" -#include "SkColorShader.h" -#include "SkColorSpace.h" -#include "SkPM4fPriv.h" -#include "SkRasterPipeline.h" -#include "SkReadBuffer.h" -#include "SkUtils.h" - -SkColorShader::SkColorShader(SkColor c) : fColor(c) {} - -bool SkColorShader::isOpaque() const { - return SkColorGetA(fColor) == 255; -} - -sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) { - return sk_make_sp<SkColorShader>(buffer.readColor()); -} - -void SkColorShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeColor(fColor); -} - -uint32_t SkColorShader::ColorShaderContext::getFlags() const { - return fFlags; -} - -SkShaderBase::Context* SkColorShader::onMakeContext(const ContextRec& rec, - SkArenaAlloc* alloc) const { - return alloc->make<ColorShaderContext>(*this, rec); -} - -SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, - const ContextRec& rec) - : INHERITED(shader, rec) -{ - SkColor color = shader.fColor; - unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); - - unsigned r = SkColorGetR(color); - unsigned g = SkColorGetG(color); - unsigned b = SkColorGetB(color); - - if (a != 255) { - r = SkMulDiv255Round(r, a); - g = SkMulDiv255Round(g, a); - b = SkMulDiv255Round(b, a); - } - fPMColor = SkPackARGB32(a, r, g, b); - - SkColor4f c4 = SkColor4f::FromColor(shader.fColor); - c4.fA *= rec.fPaint->getAlpha() / 255.0f; - fPM4f = c4.premul(); - - fFlags = kConstInY32_Flag; - if (255 == a) { - fFlags |= kOpaqueAlpha_Flag; - } -} - -void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { - sk_memset32(span, fPMColor, count); -} - -void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { - memset(alpha, SkGetPackedA32(fPMColor), count); -} - -void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) { - for (int i = 0; i < count; ++i) { - span[i] = fPM4f; - } -} - -SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { - if (info) { - if (info->fColors && info->fColorCount >= 1) { - info->fColors[0] = fColor; - } - info->fColorCount = 1; - info->fTileMode = SkShader::kRepeat_TileMode; - } - return kColor_GradientType; -} - -#if SK_SUPPORT_GPU - -#include "SkGr.h" -#include "effects/GrConstColorProcessor.h" -sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const { - GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace); - return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode); -} - -#endif - -#ifndef SK_IGNORE_TO_STRING -void SkColorShader::toString(SkString* str) const { - str->append("SkColorShader: ("); - - str->append("Color: "); - str->appendHex(fColor); - - this->INHERITED::toString(str); - - str->append(")"); -} -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -static unsigned unit_to_byte(float unit) { - SkASSERT(unit >= 0 && unit <= 1); - return (unsigned)(unit * 255 + 0.5); -} - -static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) { - return SkColorSetARGB(unit_to_byte(unit.fA), unit_to_byte(unit.fR), - unit_to_byte(unit.fG), unit_to_byte(unit.fB)); -} - -SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space) - : fColorSpace(std::move(space)) - , fColor4(color) - , fCachedByteColor(unit_to_skcolor(color.pin(), space.get())) -{} - -sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) { - SkColor4f color; - buffer.readColor4f(&color); - if (buffer.readBool()) { - // TODO how do we unflatten colorspaces - } - return SkShader::MakeColorShader(color, nullptr); -} - -void SkColor4Shader::flatten(SkWriteBuffer& buffer) const { - buffer.writeColor4f(fColor4); - buffer.writeBool(false); // TODO how do we flatten colorspaces? -} - -uint32_t SkColor4Shader::Color4Context::getFlags() const { - return fFlags; -} - -SkShaderBase::Context* SkColor4Shader::onMakeContext(const ContextRec& rec, - SkArenaAlloc* alloc) const { - return alloc->make<Color4Context>(*this, rec); -} - -SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader, - const ContextRec& rec) -: INHERITED(shader, rec) -{ - SkColor color = shader.fCachedByteColor; - unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); - - unsigned r = SkColorGetR(color); - unsigned g = SkColorGetG(color); - unsigned b = SkColorGetB(color); - - if (a != 255) { - r = SkMulDiv255Round(r, a); - g = SkMulDiv255Round(g, a); - b = SkMulDiv255Round(b, a); - } - fPMColor = SkPackARGB32(a, r, g, b); - - SkColor4f c4 = shader.fColor4; - c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f); - fPM4f = c4.premul(); - - fFlags = kConstInY32_Flag; - if (255 == a) { - fFlags |= kOpaqueAlpha_Flag; - } -} - -void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) { - sk_memset32(span, fPMColor, count); -} - -void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { - memset(alpha, SkGetPackedA32(fPMColor), count); -} - -void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) { - for (int i = 0; i < count; ++i) { - span[i] = fPM4f; - } -} - -// TODO: do we need an updated version of this method for color4+colorspace? -SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const { - if (info) { - if (info->fColors && info->fColorCount >= 1) { - info->fColors[0] = fCachedByteColor; - } - info->fColorCount = 1; - info->fTileMode = SkShader::kRepeat_TileMode; - } - return kColor_GradientType; -} - -#if SK_SUPPORT_GPU - -#include "SkGr.h" -#include "effects/GrConstColorProcessor.h" -#include "GrColorSpaceXform.h" -sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const { - sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(), - args.fDstColorSpace); - GrColor4f color = GrColor4f::FromSkColor4f(fColor4); - if (colorSpaceXform) { - color = colorSpaceXform->apply(color); - } - return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode); -} - -#endif - -#ifndef SK_IGNORE_TO_STRING -void SkColor4Shader::toString(SkString* str) const { - str->append("SkColor4Shader: ("); - - str->append("RGBA:"); - for (int i = 0; i < 4; ++i) { - str->appendf(" %g", fColor4.vec()[i]); - } - str->append(" )"); -} -#endif - -sk_sp<SkShader> SkColor4Shader::onMakeColorSpace(SkColorSpaceXformer* xformer) const { - return SkShader::MakeColorShader(xformer->apply(fCachedByteColor)); -} - -sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) { - if (!SkScalarsAreFinite(color.vec(), 4)) { - return nullptr; - } - return sk_make_sp<SkColor4Shader>(color, std::move(space)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -static void D32_BlitBW(SkShaderBase::Context::BlitState* state, int x, int y, const SkPixmap& dst, - int count) { - SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0]; - const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; - proc(state->fMode, dst.writable_addr32(x, y), src, count, nullptr); -} - -static void D32_BlitAA(SkShaderBase::Context::BlitState* state, int x, int y, const SkPixmap& dst, - int count, const SkAlpha aa[]) { - SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0]; - const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; - proc(state->fMode, dst.writable_addr32(x, y), src, count, aa); -} - -static void F16_BlitBW(SkShaderBase::Context::BlitState* state, int x, int y, const SkPixmap& dst, - int count) { - SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0]; - const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; - proc(state->fMode, dst.writable_addr64(x, y), src, count, nullptr); -} - -static void F16_BlitAA(SkShaderBase::Context::BlitState* state, int x, int y, const SkPixmap& dst, - int count, const SkAlpha aa[]) { - SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0]; - const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; - proc(state->fMode, dst.writable_addr64(x, y), src, count, aa); -} - -static bool choose_blitprocs(const SkPM4f* pm4, const SkImageInfo& info, - SkShaderBase::Context::BlitState* state) { - uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag; - if (pm4->a() == 1) { - flags |= SkXfermode::kSrcIsOpaque_D32Flag; - } - switch (info.colorType()) { - case kN32_SkColorType: - if (info.gammaCloseToSRGB()) { - flags |= SkXfermode::kDstIsSRGB_D32Flag; - } - state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fMode, flags); - state->fStorage[1] = (void*)pm4; - state->fBlitBW = D32_BlitBW; - state->fBlitAA = D32_BlitAA; - return true; - case kRGBA_F16_SkColorType: - state->fStorage[0] = (void*)SkXfermode::GetF16Proc(state->fMode, flags); - state->fStorage[1] = (void*)pm4; - state->fBlitBW = F16_BlitBW; - state->fBlitAA = F16_BlitAA; - return true; - default: - return false; - } -} - -bool SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& info, - BlitState* state) { - return choose_blitprocs(&fPM4f, info, state); -} - -bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) { - return choose_blitprocs(&fPM4f, info, state); -} - -bool SkColorShader::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dst, - SkArenaAlloc* scratch, - const SkMatrix&, - const SkPaint&, - const SkMatrix*) const { - auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst)); - p->append(SkRasterPipeline::constant_color, color); - return true; -} - -bool SkColor4Shader::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dst, - SkArenaAlloc* scratch, - const SkMatrix&, - const SkPaint&, - const SkMatrix*) const { - auto color = scratch->make<SkPM4f>(to_colorspace(fColor4, fColorSpace.get(), dst).premul()); - p->append(SkRasterPipeline::constant_color, color); - return true; -} diff --git a/src/core/SkColorShader.h b/src/core/SkColorShader.h deleted file mode 100644 index 9af83c1163..0000000000 --- a/src/core/SkColorShader.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2007 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. - */ - -#ifndef SkColorShader_DEFINED -#define SkColorShader_DEFINED - -#include "SkColorSpaceXformer.h" -#include "SkShaderBase.h" -#include "SkPM4f.h" - -/** \class SkColorShader - A Shader that represents a single color. In general, this effect can be - accomplished by just using the color field on the paint, but if an - actual shader object is needed, this provides that feature. -*/ -class SK_API SkColorShader : public SkShaderBase { -public: - /** Create a ColorShader that ignores the color in the paint, and uses the - specified color. Note: like all shaders, at draw time the paint's alpha - will be respected, and is applied to the specified color. - */ - explicit SkColorShader(SkColor c); - - bool isOpaque() const override; - bool isConstant() const override { return true; } - - class ColorShaderContext : public Context { - public: - ColorShaderContext(const SkColorShader& shader, const ContextRec&); - - uint32_t getFlags() const override; - void shadeSpan(int x, int y, SkPMColor span[], int count) override; - void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) override; - void shadeSpan4f(int x, int y, SkPM4f[], int count) override; - - protected: - bool onChooseBlitProcs(const SkImageInfo&, BlitState*) override; - - private: - SkPM4f fPM4f; - SkPMColor fPMColor; - uint32_t fFlags; - - typedef Context INHERITED; - }; - - GradientType asAGradient(GradientInfo* info) const override; - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorShader) - -protected: - SkColorShader(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override; - - bool onAsLuminanceColor(SkColor* lum) const override { - *lum = fColor; - return true; - } - - bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, - const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override; - - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { - return SkShader::MakeColorShader(xformer->apply(fColor)); - } - -private: - SkColor fColor; - - typedef SkShaderBase INHERITED; -}; - -class SkColor4Shader : public SkShaderBase { -public: - SkColor4Shader(const SkColor4f&, sk_sp<SkColorSpace>); - - bool isOpaque() const override { - return SkColorGetA(fCachedByteColor) == 255; - } - bool isConstant() const override { return true; } - - class Color4Context : public Context { - public: - Color4Context(const SkColor4Shader& shader, const ContextRec&); - - uint32_t getFlags() const override; - void shadeSpan(int x, int y, SkPMColor span[], int count) override; - void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) override; - void shadeSpan4f(int x, int y, SkPM4f[], int count) override; - - protected: - bool onChooseBlitProcs(const SkImageInfo&, BlitState*) override; - - private: - SkPM4f fPM4f; - SkPMColor fPMColor; - uint32_t fFlags; - - typedef Context INHERITED; - }; - - GradientType asAGradient(GradientInfo* info) const override; - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorShader) - -protected: - SkColor4Shader(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; - bool onAsLuminanceColor(SkColor* lum) const override { - *lum = fCachedByteColor; - return true; - } - bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, - const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override; - - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; - -private: - sk_sp<SkColorSpace> fColorSpace; - const SkColor4f fColor4; - const SkColor fCachedByteColor; - - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp deleted file mode 100644 index 7735494291..0000000000 --- a/src/core/SkComposeShader.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * 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 "SkArenaAlloc.h" -#include "SkBlendModePriv.h" -#include "SkComposeShader.h" -#include "SkColorFilter.h" -#include "SkColorPriv.h" -#include "SkColorShader.h" -#include "SkRasterPipeline.h" -#include "SkReadBuffer.h" -#include "SkWriteBuffer.h" -#include "SkString.h" -#include "../jumper/SkJumper.h" - -sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, - SkBlendMode mode) { - if (!src || !dst) { - return nullptr; - } - if (SkBlendMode::kSrc == mode) { - return src; - } - if (SkBlendMode::kDst == mode) { - return dst; - } - return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode)); -} - -/////////////////////////////////////////////////////////////////////////////// - -class SkAutoAlphaRestore { -public: - SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { - fAlpha = paint->getAlpha(); - fPaint = paint; - paint->setAlpha(newAlpha); - } - - ~SkAutoAlphaRestore() { - fPaint->setAlpha(fAlpha); - } -private: - SkPaint* fPaint; - uint8_t fAlpha; -}; -#define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) - -sk_sp<SkFlattenable> SkComposeShader::CreateProc(SkReadBuffer& buffer) { - sk_sp<SkShader> shaderA(buffer.readShader()); - sk_sp<SkShader> shaderB(buffer.readShader()); - SkBlendMode mode; - if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode2_Version)) { - sk_sp<SkXfermode> xfer = buffer.readXfermode(); - mode = xfer ? xfer->blend() : SkBlendMode::kSrcOver; - } else { - mode = (SkBlendMode)buffer.read32(); - } - if (!shaderA || !shaderB) { - return nullptr; - } - return sk_make_sp<SkComposeShader>(std::move(shaderA), std::move(shaderB), mode); -} - -void SkComposeShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeFlattenable(fShaderA.get()); - buffer.writeFlattenable(fShaderB.get()); - buffer.write32((int)fMode); -} - -SkShaderBase::Context* SkComposeShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ - // we preconcat our localMatrix (if any) with the device matrix - // before calling our sub-shaders - SkMatrix tmpM; - tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); - - // Our sub-shaders need to see opaque, so by combining them we don't double-alphatize the - // result. ComposeShader itself will respect the alpha, and post-apply it after calling the - // sub-shaders. - SkPaint opaquePaint(*rec.fPaint); - opaquePaint.setAlpha(0xFF); - - ContextRec newRec(rec); - newRec.fMatrix = &tmpM; - newRec.fPaint = &opaquePaint; - - SkShaderBase::Context* contextA = as_SB(fShaderA)->makeContext(newRec, alloc); - SkShaderBase::Context* contextB = as_SB(fShaderB)->makeContext(newRec, alloc); - if (!contextA || !contextB) { - return nullptr; - } - - return alloc->make<ComposeShaderContext>(*this, rec, contextA, contextB); -} - -sk_sp<SkShader> SkComposeShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const { - return SkShader::MakeComposeShader(xformer->apply(fShaderA.get()), - xformer->apply(fShaderB.get()), fMode); -} - -SkComposeShader::ComposeShaderContext::ComposeShaderContext( - const SkComposeShader& shader, const ContextRec& rec, - SkShaderBase::Context* contextA, SkShaderBase::Context* contextB) - : INHERITED(shader, rec) - , fShaderContextA(contextA) - , fShaderContextB(contextB) {} - -bool SkComposeShader::asACompose(ComposeRec* rec) const { - if (rec) { - rec->fShaderA = fShaderA.get(); - rec->fShaderB = fShaderB.get(); - rec->fBlendMode = fMode; - } - return true; -} - -bool SkComposeShader::isRasterPipelineOnly() const { - return as_SB(fShaderA)->isRasterPipelineOnly() || as_SB(fShaderB)->isRasterPipelineOnly(); -} - -bool SkComposeShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, - SkArenaAlloc* alloc, const SkMatrix& ctm, - const SkPaint& paint, const SkMatrix* localM) const { - struct Storage { - float fXY[4 * SkJumper_kMaxStride]; - float fRGBA[4 * SkJumper_kMaxStride]; - float fAlpha; - }; - auto storage = alloc->make<Storage>(); - - // We need to save off device x,y (inputs to shader), since after calling fShaderA they - // will be smashed, and I'll need them again for fShaderB. store_rgba saves off 4 registers - // even though we only need to save r,g. - pipeline->append(SkRasterPipeline::store_rgba, storage->fXY); - if (!as_SB(fShaderB)->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) { // SRC - 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. - pipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA); - // Now we restore the device x,y for the next shader - pipeline->append(SkRasterPipeline::load_rgba, storage->fXY); - if (!as_SB(fShaderA)->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) { // DST - 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 - // 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... - pipeline->append(SkRasterPipeline::move_src_dst); - pipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA); - - // Idea: should time this, and see if it helps to have custom versions of the overflow modes - // that do their own clamping, avoiding the overhead of an extra stage. - SkBlendMode_AppendStages(fMode, pipeline); - if (SkBlendMode_CanOverflow(fMode)) { - pipeline->append(SkRasterPipeline::clamp_a); - } - return true; -} - -// larger is better (fewer times we have to loop), but we shouldn't -// take up too much stack-space (each element is 4 bytes) -#define TMP_COLOR_COUNT 64 - -void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { - auto* shaderContextA = fShaderContextA; - auto* shaderContextB = fShaderContextB; - SkBlendMode mode = static_cast<const SkComposeShader&>(fShader).fMode; - unsigned scale = SkAlpha255To256(this->getPaintAlpha()); - - SkPMColor tmp[TMP_COLOR_COUNT]; - - SkXfermode* xfer = SkXfermode::Peek(mode); - if (nullptr == xfer) { // implied SRC_OVER - // TODO: when we have a good test-case, should use SkBlitRow::Proc32 - // for these loops - do { - int n = count; - if (n > TMP_COLOR_COUNT) { - n = TMP_COLOR_COUNT; - } - - shaderContextA->shadeSpan(x, y, result, n); - shaderContextB->shadeSpan(x, y, tmp, n); - - if (256 == scale) { - for (int i = 0; i < n; i++) { - result[i] = SkPMSrcOver(tmp[i], result[i]); - } - } else { - for (int i = 0; i < n; i++) { - result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), - scale); - } - } - - result += n; - x += n; - count -= n; - } while (count > 0); - } else { // use mode for the composition - do { - int n = count; - if (n > TMP_COLOR_COUNT) { - n = TMP_COLOR_COUNT; - } - - shaderContextA->shadeSpan(x, y, result, n); - shaderContextB->shadeSpan(x, y, tmp, n); - xfer->xfer32(result, tmp, n, nullptr); - - if (256 != scale) { - for (int i = 0; i < n; i++) { - result[i] = SkAlphaMulQ(result[i], scale); - } - } - - result += n; - x += n; - count -= n; - } while (count > 0); - } -} - -void SkComposeShader::ComposeShaderContext::shadeSpan4f(int x, int y, SkPM4f result[], int count) { - auto* shaderContextA = fShaderContextA; - auto* shaderContextB = fShaderContextB; - SkBlendMode mode = static_cast<const SkComposeShader&>(fShader).fMode; - unsigned alpha = this->getPaintAlpha(); - Sk4f scale(alpha * (1.0f / 255)); - - SkPM4f tmp[TMP_COLOR_COUNT]; - - SkXfermodeProc4f xfer = SkXfermode::GetProc4f(mode); - do { - int n = SkTMin(count, TMP_COLOR_COUNT); - - shaderContextA->shadeSpan4f(x, y, result, n); - shaderContextB->shadeSpan4f(x, y, tmp, n); - if (255 == alpha) { - for (int i = 0; i < n; ++i) { - result[i] = xfer(tmp[i], result[i]); - } - } else { - for (int i = 0; i < n; ++i) { - (xfer(tmp[i], result[i]).to4f() * scale).store(result + i); - } - } - result += n; - x += n; - count -= n; - } while (count > 0); -} - -#if SK_SUPPORT_GPU - -#include "effects/GrConstColorProcessor.h" -#include "effects/GrXfermodeFragmentProcessor.h" - -///////////////////////////////////////////////////////////////////// - -sk_sp<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(const AsFPArgs& args) const { - switch (fMode) { - case SkBlendMode::kClear: - return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(), - GrConstColorProcessor::kIgnore_InputMode); - break; - case SkBlendMode::kSrc: - return as_SB(fShaderB)->asFragmentProcessor(args); - break; - case SkBlendMode::kDst: - return as_SB(fShaderA)->asFragmentProcessor(args); - break; - default: - sk_sp<GrFragmentProcessor> fpA(as_SB(fShaderA)->asFragmentProcessor(args)); - if (!fpA) { - return nullptr; - } - sk_sp<GrFragmentProcessor> fpB(as_SB(fShaderB)->asFragmentProcessor(args)); - if (!fpB) { - return nullptr; - } - return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), - std::move(fpA), fMode); - } -} -#endif - -#ifndef SK_IGNORE_TO_STRING -void SkComposeShader::toString(SkString* str) const { - str->append("SkComposeShader: ("); - - str->append("ShaderA: "); - as_SB(fShaderA)->toString(str); - str->append(" ShaderB: "); - as_SB(fShaderB)->toString(str); - if (SkBlendMode::kSrcOver != fMode) { - str->appendf(" Xfermode: %s", SkXfermode::ModeName(fMode)); - } - - this->INHERITED::toString(str); - - str->append(")"); -} -#endif diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h deleted file mode 100644 index 8592f3a8ae..0000000000 --- a/src/core/SkComposeShader.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ - -#ifndef SkComposeShader_DEFINED -#define SkComposeShader_DEFINED - -#include "SkShaderBase.h" -#include "SkBlendMode.h" - -class SkColorSpacXformer; - -/////////////////////////////////////////////////////////////////////////////////////////// - -/** \class SkComposeShader - This subclass of shader returns the composition of two other shaders, combined by - a xfermode. -*/ -class SK_API SkComposeShader : public SkShaderBase { -public: - /** Create a new compose shader, given shaders A, B, and a combining xfermode mode. - When the xfermode is called, it will be given the result from shader A as its - "dst", and the result from shader B as its "src". - mode->xfer32(sA_result, sB_result, ...) - @param shaderA The colors from this shader are seen as the "dst" by the xfermode - @param shaderB The colors from this shader are seen as the "src" by the xfermode - @param mode The xfermode that combines the colors from the two shaders. If mode - is null, then SRC_OVER is assumed. - */ - SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, SkBlendMode mode) - : fShaderA(std::move(sA)) - , fShaderB(std::move(sB)) - , fMode(mode) - {} - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - class ComposeShaderContext : public Context { - public: - // When this object gets destroyed, it will call contextA and contextB's destructor - // but it will NOT free the memory. - ComposeShaderContext(const SkComposeShader&, const ContextRec&, - SkShaderBase::Context* contextA, SkShaderBase::Context* contextB); - - void shadeSpan(int x, int y, SkPMColor[], int count) override; - void shadeSpan4f(int x, int y, SkPM4f[], int count) override; - - private: - SkShaderBase::Context* fShaderContextA; - SkShaderBase::Context* fShaderContextB; - - typedef Context INHERITED; - }; - -#ifdef SK_DEBUG - SkShader* getShaderA() { return fShaderA.get(); } - SkShader* getShaderB() { return fShaderB.get(); } -#endif - - bool asACompose(ComposeRec* rec) const override; - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader) - -protected: - SkComposeShader(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; - bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*, - const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override; - - bool isRasterPipelineOnly() const final; - -private: - sk_sp<SkShader> fShaderA; - sk_sp<SkShader> fShaderB; - SkBlendMode fMode; - - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkEmptyShader.h b/src/core/SkEmptyShader.h deleted file mode 100644 index c1bcfe0957..0000000000 --- a/src/core/SkEmptyShader.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkEmptyShader_DEFINED -#define SkEmptyShader_DEFINED - -#include "SkShaderBase.h" - -// TODO: move this to private, as there is a public factory on SkShader - -/** - * \class SkEmptyShader - * A Shader that always draws nothing. Its createContext always returns nullptr. - */ -class SK_API SkEmptyShader : public SkShaderBase { -public: - SkEmptyShader() {} - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader) - -protected: - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override { - return nullptr; - } - - void flatten(SkWriteBuffer& buffer) const override { - // Do nothing. - // We just don't want to fall through to SkShader::flatten(), - // which will write data we don't care to serialize or decode. - } - -private: - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp deleted file mode 100644 index cdfa528e1e..0000000000 --- a/src/core/SkLightingShader.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkArenaAlloc.h" -#include "SkBitmapProcShader.h" -#include "SkBitmapProcState.h" -#include "SkColor.h" -#include "SkColorSpaceXformer.h" -#include "SkEmptyShader.h" -#include "SkLightingShader.h" -#include "SkMathPriv.h" -#include "SkNormalSource.h" -#include "SkPoint3.h" -#include "SkReadBuffer.h" -#include "SkShaderBase.h" -#include "SkWriteBuffer.h" - -//////////////////////////////////////////////////////////////////////////// - -/* - SkLightingShader TODOs: - support different light types - support multiple lights - fix non-opaque diffuse textures - - To Test: - A8 diffuse textures - down & upsampled draws -*/ - - - -/** \class SkLightingShaderImpl - This subclass of shader applies lighting. -*/ -class SkLightingShaderImpl : public SkShaderBase { -public: - /** Create a new lighting shader that uses the provided normal map and - lights to light the diffuse bitmap. - @param diffuseShader the shader that provides the diffuse colors - @param normalSource the source of normals for lighting computation - @param lights the lights applied to the geometry - */ - SkLightingShaderImpl(sk_sp<SkShader> diffuseShader, - sk_sp<SkNormalSource> normalSource, - sk_sp<SkLights> lights) - : fDiffuseShader(std::move(diffuseShader)) - , fNormalSource(std::move(normalSource)) - , fLights(std::move(lights)) {} - - bool isOpaque() const override; - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - class LightingShaderContext : public Context { - public: - // The context takes ownership of the context and provider. It will call their destructors - // and then indirectly free their memory by calling free() on heapAllocated - LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, - SkShaderBase::Context* diffuseContext, SkNormalSource::Provider*, - void* heapAllocated); - - void shadeSpan(int x, int y, SkPMColor[], int count) override; - - uint32_t getFlags() const override { return fFlags; } - - private: - SkShaderBase::Context* fDiffuseContext; - SkNormalSource::Provider* fNormalProvider; - SkColor fPaintColor; - uint32_t fFlags; - - typedef Context INHERITED; - }; - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) - -protected: - void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; - -private: - sk_sp<SkShader> fDiffuseShader; - sk_sp<SkNormalSource> fNormalSource; - sk_sp<SkLights> fLights; - - friend class SkLightingShader; - - typedef SkShaderBase INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////// - -#if SK_SUPPORT_GPU - -#include "GrCoordTransform.h" -#include "GrFragmentProcessor.h" -#include "glsl/GrGLSLFragmentProcessor.h" -#include "glsl/GrGLSLFragmentShaderBuilder.h" -#include "glsl/GrGLSLProgramDataManager.h" -#include "glsl/GrGLSLUniformHandler.h" -#include "SkGr.h" - -// This FP expects a premul'd color input for its diffuse color. Premul'ing of the paint's color is -// handled by the asFragmentProcessor() factory, but shaders providing diffuse color must output it -// premul'd. -class LightingFP : public GrFragmentProcessor { -public: - LightingFP(sk_sp<GrFragmentProcessor> normalFP, sk_sp<SkLights> lights) - : INHERITED(kPreservesOpaqueInput_OptimizationFlag) { - // fuse all ambient lights into a single one - fAmbientColor = lights->ambientLightColor(); - for (int i = 0; i < lights->numLights(); ++i) { - if (SkLights::Light::kDirectional_LightType == lights->light(i).type()) { - fDirectionalLights.push_back(lights->light(i)); - // TODO get the handle to the shadow map if there is one - } else { - SkDEBUGFAIL("Unimplemented Light Type passed to LightingFP"); - } - } - - this->registerChildProcessor(std::move(normalFP)); - this->initClassID<LightingFP>(); - } - - class GLSLLightingFP : public GrGLSLFragmentProcessor { - public: - GLSLLightingFP() { - fAmbientColor.fX = 0.0f; - } - - void emitCode(EmitArgs& args) override { - - GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; - GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; - const LightingFP& lightingFP = args.fFp.cast<LightingFP>(); - - const char *lightDirsUniName = nullptr; - const char *lightColorsUniName = nullptr; - if (lightingFP.fDirectionalLights.count() != 0) { - fLightDirsUni = uniformHandler->addUniformArray( - kFragment_GrShaderFlag, - kVec3f_GrSLType, - kDefault_GrSLPrecision, - "LightDir", - lightingFP.fDirectionalLights.count(), - &lightDirsUniName); - fLightColorsUni = uniformHandler->addUniformArray( - kFragment_GrShaderFlag, - kVec3f_GrSLType, - kDefault_GrSLPrecision, - "LightColor", - lightingFP.fDirectionalLights.count(), - &lightColorsUniName); - } - - const char* ambientColorUniName = nullptr; - fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, - kVec3f_GrSLType, kDefault_GrSLPrecision, - "AmbientColor", &ambientColorUniName); - - fragBuilder->codeAppendf("vec4 diffuseColor = %s;", args.fInputColor); - - SkString dstNormalName("dstNormal"); - this->emitChild(0, &dstNormalName, args); - - fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_str()); - - fragBuilder->codeAppend( "vec3 result = vec3(0.0);"); - - // diffuse light - if (lightingFP.fDirectionalLights.count() != 0) { - fragBuilder->codeAppendf("for (int i = 0; i < %d; i++) {", - lightingFP.fDirectionalLights.count()); - // TODO: modulate the contribution from each light based on the shadow map - fragBuilder->codeAppendf(" float NdotL = clamp(dot(normal, %s[i]), 0.0, 1.0);", - lightDirsUniName); - fragBuilder->codeAppendf(" result += %s[i]*diffuseColor.rgb*NdotL;", - lightColorsUniName); - fragBuilder->codeAppend("}"); - } - - // ambient light - fragBuilder->codeAppendf("result += %s * diffuseColor.rgb;", ambientColorUniName); - - // Clamping to alpha (equivalent to an unpremul'd clamp to 1.0) - fragBuilder->codeAppendf("%s = vec4(clamp(result.rgb, 0.0, diffuseColor.a), " - "diffuseColor.a);", args.fOutputColor); - } - - static void GenKey(const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) { - const LightingFP& lightingFP = proc.cast<LightingFP>(); - b->add32(lightingFP.fDirectionalLights.count()); - } - - protected: - void onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& proc) override { - const LightingFP& lightingFP = proc.cast<LightingFP>(); - - const SkTArray<SkLights::Light>& directionalLights = lightingFP.directionalLights(); - if (directionalLights != fDirectionalLights) { - SkTArray<SkColor3f> lightDirs(directionalLights.count()); - SkTArray<SkVector3> lightColors(directionalLights.count()); - for (const SkLights::Light& light : directionalLights) { - lightDirs.push_back(light.dir()); - lightColors.push_back(light.color()); - } - - pdman.set3fv(fLightDirsUni, directionalLights.count(), &(lightDirs[0].fX)); - pdman.set3fv(fLightColorsUni, directionalLights.count(), &(lightColors[0].fX)); - - fDirectionalLights = directionalLights; - } - - const SkColor3f& ambientColor = lightingFP.ambientColor(); - if (ambientColor != fAmbientColor) { - pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); - fAmbientColor = ambientColor; - } - } - - private: - SkTArray<SkLights::Light> fDirectionalLights; - GrGLSLProgramDataManager::UniformHandle fLightDirsUni; - GrGLSLProgramDataManager::UniformHandle fLightColorsUni; - - SkColor3f fAmbientColor; - GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; - }; - - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { - GLSLLightingFP::GenKey(*this, caps, b); - } - - const char* name() const override { return "LightingFP"; } - - const SkTArray<SkLights::Light>& directionalLights() const { return fDirectionalLights; } - const SkColor3f& ambientColor() const { return fAmbientColor; } - -private: - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLLightingFP; } - - bool onIsEqual(const GrFragmentProcessor& proc) const override { - const LightingFP& lightingFP = proc.cast<LightingFP>(); - return fDirectionalLights == lightingFP.fDirectionalLights && - fAmbientColor == lightingFP.fAmbientColor; - } - - SkTArray<SkLights::Light> fDirectionalLights; - SkColor3f fAmbientColor; - - typedef GrFragmentProcessor INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////// - -sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor(const AsFPArgs& args) const { - sk_sp<GrFragmentProcessor> normalFP(fNormalSource->asFragmentProcessor(args)); - if (!normalFP) { - return nullptr; - } - - if (fDiffuseShader) { - sk_sp<GrFragmentProcessor> fpPipeline[] = { - as_SB(fDiffuseShader)->asFragmentProcessor(args), - sk_make_sp<LightingFP>(std::move(normalFP), fLights) - }; - if(!fpPipeline[0]) { - return nullptr; - } - - sk_sp<GrFragmentProcessor> innerLightFP = GrFragmentProcessor::RunInSeries(fpPipeline, 2); - // FP is wrapped because paint's alpha needs to be applied to output - return GrFragmentProcessor::MulOutputByInputAlpha(std::move(innerLightFP)); - } else { - // FP is wrapped because paint comes in unpremul'd to fragment shader, but LightingFP - // expects premul'd color. - return GrFragmentProcessor::PremulInput(sk_make_sp<LightingFP>(std::move(normalFP), - fLights)); - } -} - -#endif - -//////////////////////////////////////////////////////////////////////////// - -bool SkLightingShaderImpl::isOpaque() const { - return (fDiffuseShader ? fDiffuseShader->isOpaque() : false); -} - -SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( - const SkLightingShaderImpl& shader, const ContextRec& rec, - SkShaderBase::Context* diffuseContext, SkNormalSource::Provider* normalProvider, - void* heapAllocated) - : INHERITED(shader, rec) - , fDiffuseContext(diffuseContext) - , fNormalProvider(normalProvider) { - bool isOpaque = shader.isOpaque(); - - // update fFlags - uint32_t flags = 0; - if (isOpaque && (255 == this->getPaintAlpha())) { - flags |= kOpaqueAlpha_Flag; - } - - fPaintColor = rec.fPaint->getColor(); - fFlags = flags; -} - -static inline SkPMColor convert(SkColor3f color, U8CPU a) { - if (color.fX <= 0.0f) { - color.fX = 0.0f; - } else if (color.fX >= 255.0f) { - color.fX = 255.0f; - } - - if (color.fY <= 0.0f) { - color.fY = 0.0f; - } else if (color.fY >= 255.0f) { - color.fY = 255.0f; - } - - if (color.fZ <= 0.0f) { - color.fZ = 0.0f; - } else if (color.fZ >= 255.0f) { - color.fZ = 255.0f; - } - - return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ); -} - -// larger is better (fewer times we have to loop), but we shouldn't -// take up too much stack-space (each one here costs 16 bytes) -#define BUFFER_MAX 16 -void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, - SkPMColor result[], int count) { - const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShaderImpl&>(fShader); - - SkPMColor diffuse[BUFFER_MAX]; - SkPoint3 normals[BUFFER_MAX]; - - SkColor diffColor = fPaintColor; - - do { - int n = SkTMin(count, BUFFER_MAX); - - fNormalProvider->fillScanLine(x, y, normals, n); - - if (fDiffuseContext) { - fDiffuseContext->shadeSpan(x, y, diffuse, n); - } - - for (int i = 0; i < n; ++i) { - if (fDiffuseContext) { - diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); - } - - SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); - - // Adding ambient light - accum.fX += lightShader.fLights->ambientLightColor().fX * SkColorGetR(diffColor); - accum.fY += lightShader.fLights->ambientLightColor().fY * SkColorGetG(diffColor); - accum.fZ += lightShader.fLights->ambientLightColor().fZ * SkColorGetB(diffColor); - - // This is all done in linear unpremul color space (each component 0..255.0f though) - for (int l = 0; l < lightShader.fLights->numLights(); ++l) { - const SkLights::Light& light = lightShader.fLights->light(l); - - SkScalar illuminanceScalingFactor = 1.0f; - - if (SkLights::Light::kDirectional_LightType == light.type()) { - illuminanceScalingFactor = normals[i].dot(light.dir()); - if (illuminanceScalingFactor < 0.0f) { - illuminanceScalingFactor = 0.0f; - } - } - - accum.fX += light.color().fX * SkColorGetR(diffColor) * illuminanceScalingFactor; - accum.fY += light.color().fY * SkColorGetG(diffColor) * illuminanceScalingFactor; - accum.fZ += light.color().fZ * SkColorGetB(diffColor) * illuminanceScalingFactor; - } - - // convert() premultiplies the accumulate color with alpha - result[i] = convert(accum, SkColorGetA(diffColor)); - } - - result += n; - x += n; - count -= n; - } while (count > 0); -} - -//////////////////////////////////////////////////////////////////////////// - -#ifndef SK_IGNORE_TO_STRING -void SkLightingShaderImpl::toString(SkString* str) const { - str->appendf("LightingShader: ()"); -} -#endif - -sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { - - // Discarding SkShader flattenable params - bool hasLocalMatrix = buf.readBool(); - SkAssertResult(!hasLocalMatrix); - - sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf); - - sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); - - bool hasDiffuse = buf.readBool(); - sk_sp<SkShader> diffuseShader = nullptr; - if (hasDiffuse) { - diffuseShader = buf.readFlattenable<SkShaderBase>(); - } - - return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource), - std::move(lights)); -} - -void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { - this->INHERITED::flatten(buf); - - fLights->flatten(buf); - - buf.writeFlattenable(fNormalSource.get()); - buf.writeBool(fDiffuseShader); - if (fDiffuseShader) { - buf.writeFlattenable(fDiffuseShader.get()); - } -} - -SkShaderBase::Context* SkLightingShaderImpl::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ - SkShaderBase::Context *diffuseContext = nullptr; - if (fDiffuseShader) { - diffuseContext = as_SB(fDiffuseShader)->makeContext(rec, alloc); - if (!diffuseContext) { - return nullptr; - } - } - - SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, alloc); - if (!normalProvider) { - return nullptr; - } - - return alloc->make<LightingShaderContext>(*this, rec, diffuseContext, normalProvider, nullptr); -} - -sk_sp<SkShader> SkLightingShaderImpl::onMakeColorSpace(SkColorSpaceXformer* xformer) const { - sk_sp<SkShader> xformedDiffuseShader = - fDiffuseShader ? xformer->apply(fDiffuseShader.get()) : nullptr; - return SkLightingShader::Make(std::move(xformedDiffuseShader), fNormalSource, - fLights->makeColorSpace(xformer)); -} - -/////////////////////////////////////////////////////////////////////////////// - -sk_sp<SkShader> SkLightingShader::Make(sk_sp<SkShader> diffuseShader, - sk_sp<SkNormalSource> normalSource, - sk_sp<SkLights> lights) { - SkASSERT(lights); - if (!normalSource) { - normalSource = SkNormalSource::MakeFlat(); - } - - return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource), - std::move(lights)); -} - -/////////////////////////////////////////////////////////////////////////////// - -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END - -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkLightingShader.h b/src/core/SkLightingShader.h deleted file mode 100644 index aa90710aa4..0000000000 --- a/src/core/SkLightingShader.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkLightingShader_DEFINED -#define SkLightingShader_DEFINED - -#include "SkLights.h" -#include "SkShader.h" - -class SkBitmap; -class SkMatrix; -class SkNormalSource; - -class SK_API SkLightingShader { -public: - /** Returns a shader that lights the shape, colored by the diffuseShader, using the - normals from normalSource, with the set of lights provided. - - @param diffuseShader the shader that provides the colors. If nullptr, uses the paint's - color. - @param normalSource the source for the shape's normals. If nullptr, assumes straight - up normals (<0,0,1>). - @param lights the lights applied to the normals - - The lighting equation is currently: - result = (LightColor * dot(Normal, LightDir) + AmbientColor) * DiffuseColor - - */ - static sk_sp<SkShader> Make(sk_sp<SkShader> diffuseShader, sk_sp<SkNormalSource> normalSource, - sk_sp<SkLights> lights); - - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() -}; - -#endif diff --git a/src/core/SkLocalMatrixShader.cpp b/src/core/SkLocalMatrixShader.cpp deleted file mode 100644 index e21e4a84b7..0000000000 --- a/src/core/SkLocalMatrixShader.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkLocalMatrixShader.h" - -#if SK_SUPPORT_GPU -#include "GrFragmentProcessor.h" -#endif - -#if SK_SUPPORT_GPU -sk_sp<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(const AsFPArgs& args) const { - SkMatrix tmp = this->getLocalMatrix(); - if (args.fLocalMatrix) { - tmp.preConcat(*args.fLocalMatrix); - } - return as_SB(fProxyShader)->asFragmentProcessor(AsFPArgs( - args.fContext, args.fViewMatrix, &tmp, args.fFilterQuality, args.fDstColorSpace)); -} -#endif - -sk_sp<SkFlattenable> SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) { - SkMatrix lm; - buffer.readMatrix(&lm); - auto baseShader(buffer.readShader()); - if (!baseShader) { - return nullptr; - } - return baseShader->makeWithLocalMatrix(lm); -} - -void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeMatrix(this->getLocalMatrix()); - buffer.writeFlattenable(fProxyShader.get()); -} - -SkShaderBase::Context* SkLocalMatrixShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ - ContextRec newRec(rec); - SkMatrix tmp; - if (rec.fLocalMatrix) { - tmp.setConcat(*rec.fLocalMatrix, this->getLocalMatrix()); - newRec.fLocalMatrix = &tmp; - } else { - newRec.fLocalMatrix = &this->getLocalMatrix(); - } - return as_SB(fProxyShader)->makeContext(newRec, alloc); -} - -SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const { - SkMatrix imageMatrix; - SkImage* image = fProxyShader->isAImage(&imageMatrix, mode); - if (image && outMatrix) { - // Local matrix must be applied first so it is on the right side of the concat. - *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix()); - } - - return image; -} - -bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dst, - SkArenaAlloc* scratch, - const SkMatrix& ctm, - const SkPaint& paint, - const SkMatrix* localM) const { - SkMatrix tmp; - if (localM) { - tmp.setConcat(*localM, this->getLocalMatrix()); - } - return as_SB(fProxyShader)->appendStages(p, dst, scratch, ctm, paint, - localM ? &tmp : &this->getLocalMatrix()); -} - -#ifndef SK_IGNORE_TO_STRING -void SkLocalMatrixShader::toString(SkString* str) const { - str->append("SkLocalMatrixShader: ("); - - as_SB(fProxyShader)->toString(str); - - this->INHERITED::toString(str); - - str->append(")"); -} -#endif - -sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const { - if (localMatrix.isIdentity()) { - return sk_ref_sp(const_cast<SkShader*>(this)); - } - - const SkMatrix* lm = &localMatrix; - - sk_sp<SkShader> baseShader; - SkMatrix otherLocalMatrix; - sk_sp<SkShader> proxy(as_SB(this)->makeAsALocalMatrixShader(&otherLocalMatrix)); - if (proxy) { - otherLocalMatrix.preConcat(localMatrix); - lm = &otherLocalMatrix; - baseShader = proxy; - } else { - baseShader = sk_ref_sp(const_cast<SkShader*>(this)); - } - - return sk_make_sp<SkLocalMatrixShader>(std::move(baseShader), *lm); -} diff --git a/src/core/SkLocalMatrixShader.h b/src/core/SkLocalMatrixShader.h deleted file mode 100644 index 4572e9fe2e..0000000000 --- a/src/core/SkLocalMatrixShader.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkLocalMatrixShader_DEFINED -#define SkLocalMatrixShader_DEFINED - -#include "SkShaderBase.h" -#include "SkReadBuffer.h" -#include "SkWriteBuffer.h" - -class GrFragmentProcessor; -class SkArenaAlloc; -class SkColorSpaceXformer; - -class SkLocalMatrixShader : public SkShaderBase { -public: - SkLocalMatrixShader(sk_sp<SkShader> proxy, const SkMatrix& localMatrix) - : INHERITED(&localMatrix) - , fProxyShader(std::move(proxy)) - {} - - GradientType asAGradient(GradientInfo* info) const override { - return fProxyShader->asAGradient(info); - } - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - - sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const override { - if (localMatrix) { - *localMatrix = this->getLocalMatrix(); - } - return fProxyShader; - } - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixShader) - -protected: - void flatten(SkWriteBuffer&) const override; - - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; - - SkImage* onIsAImage(SkMatrix* matrix, TileMode* mode) const override; - - bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, - const SkMatrix&, const SkPaint&, const SkMatrix*) const override; - - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { - return as_SB(fProxyShader)->makeColorSpace(xformer)->makeWithLocalMatrix( - this->getLocalMatrix()); - } - -#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP - bool onIsABitmap(SkBitmap* bitmap, SkMatrix* matrix, TileMode* mode) const override { - return fProxyShader->isABitmap(bitmap, matrix, mode); - } -#endif - - bool isRasterPipelineOnly() const final { - return as_SB(fProxyShader)->isRasterPipelineOnly(); - } - -private: - sk_sp<SkShader> fProxyShader; - - typedef SkShaderBase INHERITED; -}; - -#endif diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp deleted file mode 100644 index d6ee941251..0000000000 --- a/src/core/SkPictureShader.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkPictureShader.h" - -#include "SkArenaAlloc.h" -#include "SkBitmap.h" -#include "SkBitmapProcShader.h" -#include "SkCanvas.h" -#include "SkColorSpaceXformCanvas.h" -#include "SkImage.h" -#include "SkImageShader.h" -#include "SkMatrixUtils.h" -#include "SkPicture.h" -#include "SkPictureImageGenerator.h" -#include "SkReadBuffer.h" -#include "SkResourceCache.h" - -#if SK_SUPPORT_GPU -#include "GrContext.h" -#include "GrCaps.h" -#include "GrFragmentProcessor.h" -#endif - -namespace { -static unsigned gBitmapSkaderKeyNamespaceLabel; - -struct BitmapShaderKey : public SkResourceCache::Key { -public: - BitmapShaderKey(sk_sp<SkColorSpace> colorSpace, - uint32_t pictureID, - const SkRect& tile, - SkShader::TileMode tmx, - SkShader::TileMode tmy, - const SkSize& scale, - const SkMatrix& localMatrix, - SkTransferFunctionBehavior blendBehavior) - : fColorSpace(std::move(colorSpace)) - , fPictureID(pictureID) - , fTile(tile) - , fTmx(tmx) - , fTmy(tmy) - , fScale(scale) - , fBlendBehavior(blendBehavior) { - - for (int i = 0; i < 9; ++i) { - fLocalMatrixStorage[i] = localMatrix[i]; - } - - static const size_t keySize = sizeof(fColorSpace) + - sizeof(fPictureID) + - sizeof(fTile) + - sizeof(fTmx) + sizeof(fTmy) + - sizeof(fScale) + - sizeof(fLocalMatrixStorage) + - sizeof(fBlendBehavior); - // This better be packed. - SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - (uint32_t*)&fColorSpace) == keySize); - this->init(&gBitmapSkaderKeyNamespaceLabel, 0, keySize); - } - -private: - sk_sp<SkColorSpace> fColorSpace; - uint32_t fPictureID; - SkRect fTile; - SkShader::TileMode fTmx, fTmy; - SkSize fScale; - SkScalar fLocalMatrixStorage[9]; - SkTransferFunctionBehavior fBlendBehavior; - - SkDEBUGCODE(uint32_t fEndOfStruct;) -}; - -struct BitmapShaderRec : public SkResourceCache::Rec { - BitmapShaderRec(const BitmapShaderKey& key, SkShader* tileShader) - : fKey(key) - , fShader(SkRef(tileShader)) {} - - BitmapShaderKey fKey; - sk_sp<SkShader> fShader; - size_t fBitmapBytes; - - const Key& getKey() const override { return fKey; } - size_t bytesUsed() const override { - // Just the record overhead -- the actual pixels are accounted by SkImageCacherator. - return sizeof(fKey) + sizeof(SkImageShader); - } - const char* getCategory() const override { return "bitmap-shader"; } - SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; } - - static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader) { - const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec); - sk_sp<SkShader>* result = reinterpret_cast<sk_sp<SkShader>*>(contextShader); - - *result = rec.fShader; - - // The bitmap shader is backed by an image generator, thus it can always re-generate its - // pixels if discarded. - return true; - } -}; - -} // namespace - -SkPictureShader::SkPictureShader(sk_sp<SkPicture> picture, TileMode tmx, TileMode tmy, - const SkMatrix* localMatrix, const SkRect* tile, - sk_sp<SkColorSpace> colorSpace) - : INHERITED(localMatrix) - , fPicture(std::move(picture)) - , fTile(tile ? *tile : fPicture->cullRect()) - , fTmx(tmx) - , fTmy(tmy) - , fColorSpace(std::move(colorSpace)) -{} - -sk_sp<SkShader> SkPictureShader::Make(sk_sp<SkPicture> picture, TileMode tmx, TileMode tmy, - const SkMatrix* localMatrix, const SkRect* tile) { - if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) { - return SkShader::MakeEmptyShader(); - } - return sk_sp<SkShader>(new SkPictureShader(std::move(picture), tmx, tmy, localMatrix, tile, - nullptr)); -} - -sk_sp<SkFlattenable> SkPictureShader::CreateProc(SkReadBuffer& buffer) { - SkMatrix lm; - buffer.readMatrix(&lm); - TileMode mx = (TileMode)buffer.read32(); - TileMode my = (TileMode)buffer.read32(); - SkRect tile; - buffer.readRect(&tile); - - sk_sp<SkPicture> picture; - - if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) { - if (buffer.isVersionLT(SkReadBuffer::kPictureShaderHasPictureBool_Version)) { - // Older code blindly serialized pictures. We don't trust them. - buffer.validate(false); - return nullptr; - } - // Newer code won't serialize pictures in disallow-cross-process-picture mode. - // Assert that they didn't serialize anything except a false here. - buffer.validate(!buffer.readBool()); - } else { - // Old code always serialized the picture. New code writes a 'true' first if it did. - if (buffer.isVersionLT(SkReadBuffer::kPictureShaderHasPictureBool_Version) || - buffer.readBool()) { - picture = SkPicture::MakeFromBuffer(buffer); - } - } - return SkPictureShader::Make(picture, mx, my, &lm, &tile); -} - -void SkPictureShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeMatrix(this->getLocalMatrix()); - buffer.write32(fTmx); - buffer.write32(fTmy); - buffer.writeRect(fTile); - - // The deserialization code won't trust that our serialized picture is safe to deserialize. - // So write a 'false' telling it that we're not serializing a picture. - if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) { - buffer.writeBool(false); - } else { - buffer.writeBool(true); - fPicture->flatten(buffer); - } -} - -sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, const SkMatrix* localM, - SkColorSpace* dstColorSpace, - const int maxTextureSize) const { - SkASSERT(fPicture && !fPicture->cullRect().isEmpty()); - - SkMatrix m; - m.setConcat(viewMatrix, this->getLocalMatrix()); - if (localM) { - m.preConcat(*localM); - } - - // Use a rotation-invariant scale - SkPoint scale; - // - // TODO: replace this with decomposeScale() -- but beware LayoutTest rebaselines! - // - if (!SkDecomposeUpper2x2(m, nullptr, &scale, nullptr)) { - // Decomposition failed, use an approximation. - scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()), - SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY())); - } - SkSize scaledSize = SkSize::Make(SkScalarAbs(scale.x() * fTile.width()), - SkScalarAbs(scale.y() * fTile.height())); - - // Clamp the tile size to about 4M pixels - static const SkScalar kMaxTileArea = 2048 * 2048; - SkScalar tileArea = scaledSize.width() * scaledSize.height(); - if (tileArea > kMaxTileArea) { - SkScalar clampScale = SkScalarSqrt(kMaxTileArea / tileArea); - scaledSize.set(scaledSize.width() * clampScale, - scaledSize.height() * clampScale); - } -#if SK_SUPPORT_GPU - // Scale down the tile size if larger than maxTextureSize for GPU Path or it should fail on create texture - if (maxTextureSize) { - if (scaledSize.width() > maxTextureSize || scaledSize.height() > maxTextureSize) { - SkScalar downScale = maxTextureSize / SkMaxScalar(scaledSize.width(), scaledSize.height()); - scaledSize.set(SkScalarFloorToScalar(scaledSize.width() * downScale), - SkScalarFloorToScalar(scaledSize.height() * downScale)); - } - } -#endif - -#ifdef SK_SUPPORT_LEGACY_PICTURESHADER_ROUNDING - const SkISize tileSize = scaledSize.toRound(); -#else - const SkISize tileSize = scaledSize.toCeil(); -#endif - if (tileSize.isEmpty()) { - return SkShader::MakeEmptyShader(); - } - - // The actual scale, compensating for rounding & clamping. - const SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fTile.width(), - SkIntToScalar(tileSize.height()) / fTile.height()); - - // |fColorSpace| will only be set when using an SkColorSpaceXformCanvas to do pre-draw xforms. - // This canvas is strictly for legacy mode. A non-null |dstColorSpace| indicates that we - // should perform color correct rendering and xform at draw time. - SkASSERT(!fColorSpace || !dstColorSpace); - sk_sp<SkColorSpace> keyCS = dstColorSpace ? sk_ref_sp(dstColorSpace) : fColorSpace; - SkTransferFunctionBehavior blendBehavior = dstColorSpace ? SkTransferFunctionBehavior::kRespect - : SkTransferFunctionBehavior::kIgnore; - - sk_sp<SkShader> tileShader; - BitmapShaderKey key(std::move(keyCS), - fPicture->uniqueID(), - fTile, - fTmx, - fTmy, - tileScale, - this->getLocalMatrix(), - blendBehavior); - - if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { - SkMatrix tileMatrix; - tileMatrix.setRectToRect(fTile, SkRect::MakeIWH(tileSize.width(), tileSize.height()), - SkMatrix::kFill_ScaleToFit); - - sk_sp<SkImage> tileImage = SkImage::MakeFromGenerator( - SkPictureImageGenerator::Make(tileSize, fPicture, &tileMatrix, nullptr, - SkImage::BitDepth::kU8, sk_ref_sp(dstColorSpace))); - if (!tileImage) { - return nullptr; - } - - if (fColorSpace) { - tileImage = tileImage->makeColorSpace(fColorSpace, SkTransferFunctionBehavior::kIgnore); - } - - SkMatrix shaderMatrix = this->getLocalMatrix(); - shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); - tileShader = tileImage->makeShader(fTmx, fTmy, &shaderMatrix); - - SkResourceCache::Add(new BitmapShaderRec(key, tileShader.get())); - } - - return tileShader; -} - -bool SkPictureShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, - const SkMatrix& ctm, const SkPaint& paint, - const SkMatrix* localMatrix) const { - // Keep bitmapShader alive by using alloc instead of stack memory - auto& bitmapShader = *alloc->make<sk_sp<SkShader>>(); - bitmapShader = this->refBitmapShader(ctm, localMatrix, cs); - return bitmapShader && as_SB(bitmapShader)->appendStages(p, cs, alloc, ctm, paint); -} - -///////////////////////////////////////////////////////////////////////////////////////// -SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) -const { - sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix, - rec.fDstColorSpace)); - if (!bitmapShader) { - return nullptr; - } - - PictureShaderContext* ctx = - alloc->make<PictureShaderContext>(*this, rec, std::move(bitmapShader), alloc); - if (nullptr == ctx->fBitmapShaderContext) { - ctx = nullptr; - } - return ctx; -} - -sk_sp<SkShader> SkPictureShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const { - return sk_sp<SkPictureShader>(new SkPictureShader(fPicture, fTmx, fTmy, &this->getLocalMatrix(), - &fTile, xformer->dst())); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -SkPictureShader::PictureShaderContext::PictureShaderContext( - const SkPictureShader& shader, const ContextRec& rec, sk_sp<SkShader> bitmapShader, - SkArenaAlloc* alloc) - : INHERITED(shader, rec) - , fBitmapShader(std::move(bitmapShader)) -{ - fBitmapShaderContext = as_SB(fBitmapShader)->makeContext(rec, alloc); - //if fBitmapShaderContext is null, we are invalid -} - -uint32_t SkPictureShader::PictureShaderContext::getFlags() const { - SkASSERT(fBitmapShaderContext); - return fBitmapShaderContext->getFlags(); -} - -SkShaderBase::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) { - SkASSERT(fBitmapShaderContext); - return fBitmapShaderContext->asAShadeProc(ctx); -} - -void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { - SkASSERT(fBitmapShaderContext); - fBitmapShaderContext->shadeSpan(x, y, dstC, count); -} - -#ifndef SK_IGNORE_TO_STRING -void SkPictureShader::toString(SkString* str) const { - static const char* gTileModeName[SkShader::kTileModeCount] = { - "clamp", "repeat", "mirror" - }; - - str->appendf("PictureShader: [%f:%f:%f:%f] ", - fPicture->cullRect().fLeft, - fPicture->cullRect().fTop, - fPicture->cullRect().fRight, - fPicture->cullRect().fBottom); - - str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); - - this->INHERITED::toString(str); -} -#endif - -#if SK_SUPPORT_GPU -sk_sp<GrFragmentProcessor> SkPictureShader::asFragmentProcessor(const AsFPArgs& args) const { - int maxTextureSize = 0; - if (args.fContext) { - maxTextureSize = args.fContext->caps()->maxTextureSize(); - } - sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix, - args.fDstColorSpace, maxTextureSize)); - if (!bitmapShader) { - return nullptr; - } - return as_SB(bitmapShader)->asFragmentProcessor(SkShaderBase::AsFPArgs( - args.fContext, args.fViewMatrix, nullptr, args.fFilterQuality, args.fDstColorSpace)); -} -#endif diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h deleted file mode 100644 index f7a509f181..0000000000 --- a/src/core/SkPictureShader.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkPictureShader_DEFINED -#define SkPictureShader_DEFINED - -#include "SkShaderBase.h" - -class SkArenaAlloc; -class SkBitmap; -class SkPicture; - -/* - * An SkPictureShader can be used to draw SkPicture-based patterns. - * - * The SkPicture is first rendered into a tile, which is then used to shade the area according - * to specified tiling rules. - */ -class SkPictureShader : public SkShaderBase { -public: - static sk_sp<SkShader> Make(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, - const SkRect*); - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureShader) - -#if SK_SUPPORT_GPU - sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; -#endif - -protected: - SkPictureShader(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, - const SkMatrix&, const SkPaint&, const SkMatrix*) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; - sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; - -private: - SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*, - sk_sp<SkColorSpace>); - - sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix, - SkColorSpace* dstColorSpace, - const int maxTextureSize = 0) const; - - sk_sp<SkPicture> fPicture; - SkRect fTile; - TileMode fTmx, fTmy; - - class PictureShaderContext : public Context { - public: - PictureShaderContext( - const SkPictureShader&, const ContextRec&, sk_sp<SkShader> bitmapShader, SkArenaAlloc*); - - uint32_t getFlags() const override; - - ShadeProc asAShadeProc(void** ctx) override; - void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; - - sk_sp<SkShader> fBitmapShader; - SkShaderBase::Context* fBitmapShaderContext; - void* fBitmapShaderContextStorage; - - typedef Context INHERITED; - }; - - // Should never be set by a public constructor. This is only used when onMakeColorSpace() - // forces a deferred color space xform. - sk_sp<SkColorSpace> fColorSpace; - - typedef SkShaderBase INHERITED; -}; - -#endif // SkPictureShader_DEFINED diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp deleted file mode 100644 index d04fbfe4df..0000000000 --- a/src/core/SkShader.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 "SkArenaAlloc.h" -#include "SkAtomics.h" -#include "SkBitmapProcShader.h" -#include "SkColorShader.h" -#include "SkEmptyShader.h" -#include "SkMallocPixelRef.h" -#include "SkPaint.h" -#include "SkPicture.h" -#include "SkPictureShader.h" -#include "SkPM4fPriv.h" -#include "SkRasterPipeline.h" -#include "SkReadBuffer.h" -#include "SkScalar.h" -#include "SkShaderBase.h" -#include "SkTLazy.h" -#include "SkWriteBuffer.h" -#include "../jumper/SkJumper.h" - -#if SK_SUPPORT_GPU -#include "GrFragmentProcessor.h" -#endif - -//#define SK_TRACK_SHADER_LIFETIME - -#ifdef SK_TRACK_SHADER_LIFETIME - static int32_t gShaderCounter; -#endif - -static inline void inc_shader_counter() { -#ifdef SK_TRACK_SHADER_LIFETIME - int32_t prev = sk_atomic_inc(&gShaderCounter); - SkDebugf("+++ shader counter %d\n", prev + 1); -#endif -} -static inline void dec_shader_counter() { -#ifdef SK_TRACK_SHADER_LIFETIME - int32_t prev = sk_atomic_dec(&gShaderCounter); - SkDebugf("--- shader counter %d\n", prev - 1); -#endif -} - -SkShaderBase::SkShaderBase(const SkMatrix* localMatrix) - : fLocalMatrix(localMatrix ? *localMatrix : SkMatrix::I()) { - inc_shader_counter(); - // Pre-cache so future calls to fLocalMatrix.getType() are threadsafe. - (void)fLocalMatrix.getType(); -} - -SkShaderBase::~SkShaderBase() { - dec_shader_counter(); -} - -void SkShaderBase::flatten(SkWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - bool hasLocalM = !fLocalMatrix.isIdentity(); - buffer.writeBool(hasLocalM); - if (hasLocalM) { - buffer.writeMatrix(fLocalMatrix); - } -} - -bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm, - const SkMatrix* outerLocalMatrix, - SkMatrix* totalInverse) const { - SkMatrix total = SkMatrix::Concat(ctm, fLocalMatrix); - if (outerLocalMatrix) { - total.preConcat(*outerLocalMatrix); - } - - return total.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 { - if (!this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)) { - return nullptr; - } - return this->onMakeContext(rec, alloc); -} - -SkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec) - : fShader(shader), fCTM(*rec.fMatrix) -{ - // We should never use a context for RP-only shaders. - SkASSERT(!shader.isRasterPipelineOnly()); - - // 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)); - fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); - - fPaintAlpha = rec.fPaint->getAlpha(); -} - -SkShaderBase::Context::~Context() {} - -SkShaderBase::Context::ShadeProc SkShaderBase::Context::asAShadeProc(void** ctx) { - return nullptr; -} - -void SkShaderBase::Context::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { - const int N = 128; - SkPMColor tmp[N]; - while (count > 0) { - int n = SkTMin(count, N); - this->shadeSpan(x, y, tmp, n); - for (int i = 0; i < n; ++i) { - dst[i] = SkPM4f::FromPMColor(tmp[i]); - } - dst += n; - x += n; - count -= n; - } -} - -#include "SkColorPriv.h" - -#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space -#define kTempColorCount (kTempColorQuadCount << 2) - -#ifdef SK_CPU_BENDIAN - #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) -#else - #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) -#endif - -void SkShaderBase::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { - SkASSERT(count > 0); - - SkPMColor colors[kTempColorCount]; - - while ((count -= kTempColorCount) >= 0) { - this->shadeSpan(x, y, colors, kTempColorCount); - x += kTempColorCount; - - const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); - int quads = kTempColorQuadCount; - do { - U8CPU a0 = srcA[0]; - U8CPU a1 = srcA[4]; - U8CPU a2 = srcA[8]; - U8CPU a3 = srcA[12]; - srcA += 4*4; - *alpha++ = SkToU8(a0); - *alpha++ = SkToU8(a1); - *alpha++ = SkToU8(a2); - *alpha++ = SkToU8(a3); - } while (--quads != 0); - } - SkASSERT(count < 0); - SkASSERT(count + kTempColorCount >= 0); - if (count += kTempColorCount) { - this->shadeSpan(x, y, colors, count); - - const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); - do { - *alpha++ = *srcA; - srcA += 4; - } while (--count != 0); - } -#if 0 - do { - int n = count; - if (n > kTempColorCount) - n = kTempColorCount; - SkASSERT(n > 0); - - this->shadeSpan(x, y, colors, n); - x += n; - count -= n; - - const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); - do { - *alpha++ = *srcA; - srcA += 4; - } while (--n != 0); - } while (count > 0); -#endif -} - -SkShaderBase::Context::MatrixClass SkShaderBase::Context::ComputeMatrixClass(const SkMatrix& mat) { - MatrixClass mc = kLinear_MatrixClass; - - if (mat.hasPerspective()) { - if (mat.isFixedStepInX()) { - mc = kFixedStepInX_MatrixClass; - } else { - mc = kPerspective_MatrixClass; - } - } - return mc; -} - -////////////////////////////////////////////////////////////////////////////// - -const SkMatrix& SkShader::getLocalMatrix() const { - return as_SB(this)->getLocalMatrix(); -} - -#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP -bool SkShader::isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const { - return as_SB(this)->onIsABitmap(outTexture, outMatrix, xy); -} -#endif - -SkImage* SkShader::isAImage(SkMatrix* localMatrix, TileMode xy[2]) const { - return as_SB(this)->onIsAImage(localMatrix, xy); -} - -SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { - return kNone_GradientType; -} - -#if SK_SUPPORT_GPU -sk_sp<GrFragmentProcessor> SkShaderBase::asFragmentProcessor(const AsFPArgs&) const { - return nullptr; -} -#endif - -sk_sp<SkShader> SkShader::makeAsALocalMatrixShader(SkMatrix*) const { - return nullptr; -} - -sk_sp<SkShader> SkShader::MakeEmptyShader() { return sk_make_sp<SkEmptyShader>(); } - -sk_sp<SkShader> SkShader::MakeColorShader(SkColor color) { return sk_make_sp<SkColorShader>(color); } - -sk_sp<SkShader> SkShader::MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, - const SkMatrix* localMatrix) { - if (localMatrix && !localMatrix->invert(nullptr)) { - return nullptr; - } - return SkMakeBitmapShader(src, tmx, tmy, localMatrix, kIfMutable_SkCopyPixelsMode); -} - -sk_sp<SkShader> SkShader::MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy, - const SkMatrix* localMatrix, const SkRect* tile) { - if (localMatrix && !localMatrix->invert(nullptr)) { - return nullptr; - } - return SkPictureShader::Make(std::move(src), tmx, tmy, localMatrix, tile); -} - -#ifndef SK_IGNORE_TO_STRING -void SkShaderBase::toString(SkString* str) const { - if (!fLocalMatrix.isIdentity()) { - str->append(" "); - fLocalMatrix.toString(str); - } -} -#endif - -bool SkShaderBase::appendStages(SkRasterPipeline* p, - SkColorSpace* dstCS, - SkArenaAlloc* alloc, - const SkMatrix& ctm, - const SkPaint& paint, - const SkMatrix* localM) const { - return this->onAppendStages(p, dstCS, alloc, ctm, paint, localM); -} - -bool SkShaderBase::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dstCS, - SkArenaAlloc* alloc, - const SkMatrix& ctm, - const SkPaint& paint, - const SkMatrix* localM) const { - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) { - return SkShader::MakeEmptyShader(); -} - -#ifndef SK_IGNORE_TO_STRING -#include "SkEmptyShader.h" - -void SkEmptyShader::toString(SkString* str) const { - str->append("SkEmptyShader: ("); - - this->INHERITED::toString(str); - - str->append(")"); -} -#endif diff --git a/src/core/SkShaderBase.h b/src/core/SkShaderBase.h deleted file mode 100644 index 895fc6cf05..0000000000 --- a/src/core/SkShaderBase.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkShaderBase_DEFINED -#define SkShaderBase_DEFINED - -#include "SkFilterQuality.h" -#include "SkMatrix.h" -#include "SkShader.h" - -class GrContext; -class GrFragmentProcessor; -class SkArenaAlloc; -class SkColorSpace; -class SkColorSpaceXformer; -class SkImage; -struct SkImageInfo; -class SkPaint; -class SkRasterPipeline; - -class SkShaderBase : public SkShader { -public: - SkShaderBase(const SkMatrix* localMatrix = nullptr); - - ~SkShaderBase() override; - - /** - * Returns true if the shader is guaranteed to produce only a single color. - * Subclasses can override this to allow loop-hoisting optimization. - */ - virtual bool isConstant() const { return false; } - - const SkMatrix& getLocalMatrix() const { return fLocalMatrix; } - - enum Flags { - //!< set if all of the colors will be opaque - kOpaqueAlpha_Flag = 1 << 0, - - /** set if the spans only vary in X (const in Y). - e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient - that varies from left-to-right. This flag specifies this for - shadeSpan(). - */ - kConstInY32_Flag = 1 << 1, - - /** hint for the blitter that 4f is the preferred shading mode. - */ - kPrefers4f_Flag = 1 << 2, - }; - - /** - * ContextRec acts as a parameter bundle for creating Contexts. - */ - struct ContextRec { - enum DstType { - kPMColor_DstType, // clients prefer shading into PMColor dest - kPM4f_DstType, // clients prefer shading into PM4f dest - }; - - ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM, - DstType dstType, SkColorSpace* dstColorSpace) - : fPaint(&paint) - , fMatrix(&matrix) - , fLocalMatrix(localM) - , fPreferredDstType(dstType) - , fDstColorSpace(dstColorSpace) {} - - const SkPaint* fPaint; // the current paint associated with the draw - const SkMatrix* fMatrix; // the current matrix in the canvas - const SkMatrix* fLocalMatrix; // optional local matrix - const DstType fPreferredDstType; // the "natural" client dest type - SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any) - }; - - class Context : public ::SkNoncopyable { - public: - Context(const SkShaderBase& shader, const ContextRec&); - - virtual ~Context(); - - /** - * Called sometimes before drawing with this shader. Return the type of - * alpha your shader will return. The default implementation returns 0. - * Your subclass should override if it can (even sometimes) report a - * non-zero value, since that will enable various blitters to perform - * faster. - */ - virtual uint32_t getFlags() const { return 0; } - - /** - * Called for each span of the object being drawn. Your subclass should - * set the appropriate colors (with premultiplied alpha) that correspond - * to the specified device coordinates. - */ - virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; - - virtual void shadeSpan4f(int x, int y, SkPM4f[], int count); - - struct BlitState; - typedef void (*BlitBW)(BlitState*, - int x, int y, const SkPixmap&, int count); - typedef void (*BlitAA)(BlitState*, - int x, int y, const SkPixmap&, int count, const SkAlpha[]); - - struct BlitState { - // inputs - Context* fCtx; - SkBlendMode fMode; - - // outputs - enum { N = 2 }; - void* fStorage[N]; - BlitBW fBlitBW; - BlitAA fBlitAA; - }; - - // Returns true if one or more of the blitprocs are set in the BlitState - bool chooseBlitProcs(const SkImageInfo& info, BlitState* state) { - state->fBlitBW = nullptr; - state->fBlitAA = nullptr; - if (this->onChooseBlitProcs(info, state)) { - SkASSERT(state->fBlitBW || state->fBlitAA); - return true; - } - return false; - } - - /** - * The const void* ctx is only const because all the implementations are const. - * This can be changed to non-const if a new shade proc needs to change the ctx. - */ - typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count); - virtual ShadeProc asAShadeProc(void** ctx); - - /** - * Similar to shadeSpan, but only returns the alpha-channel for a span. - * The default implementation calls shadeSpan() and then extracts the alpha - * values from the returned colors. - */ - virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); - - // Notification from blitter::blitMask in case we need to see the non-alpha channels - virtual void set3DMask(const SkMask*) {} - - protected: - // Reference to shader, so we don't have to dupe information. - const SkShaderBase& fShader; - - enum MatrixClass { - kLinear_MatrixClass, // no perspective - kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each - // scanline - kPerspective_MatrixClass // slow perspective, need to mappoints each pixel - }; - static MatrixClass ComputeMatrixClass(const SkMatrix&); - - uint8_t getPaintAlpha() const { return fPaintAlpha; } - const SkMatrix& getTotalInverse() const { return fTotalInverse; } - MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } - const SkMatrix& getCTM() const { return fCTM; } - - virtual bool onChooseBlitProcs(const SkImageInfo&, BlitState*) { return false; } - - private: - SkMatrix fCTM; - SkMatrix fTotalInverse; - uint8_t fPaintAlpha; - uint8_t fTotalInverseClass; - - typedef SkNoncopyable INHERITED; - }; - - /** - * Make a context using the memory provided by the arena. - * - * @return pointer to context or nullptr if can't be created - */ - Context* makeContext(const ContextRec&, SkArenaAlloc*) const; - -#if SK_SUPPORT_GPU - struct AsFPArgs { - AsFPArgs() {} - AsFPArgs(GrContext* context, - const SkMatrix* viewMatrix, - const SkMatrix* localMatrix, - SkFilterQuality filterQuality, - SkColorSpace* dstColorSpace) - : fContext(context) - , fViewMatrix(viewMatrix) - , fLocalMatrix(localMatrix) - , fFilterQuality(filterQuality) - , fDstColorSpace(dstColorSpace) {} - - GrContext* fContext; - const SkMatrix* fViewMatrix; - const SkMatrix* fLocalMatrix; - SkFilterQuality fFilterQuality; - SkColorSpace* fDstColorSpace; - }; - - /** - * Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is - * returned if there is no GPU implementation. - * - * The GPU device does not call SkShader::createContext(), instead we pass the view matrix, - * local matrix, and filter quality directly. - * - * The GrContext may be used by the to create textures that are required by the returned - * processor. - * - * The returned GrFragmentProcessor should expect an unpremultiplied input color and - * produce a premultiplied output. - */ - virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const; -#endif - - /** - * If the shader can represent its "average" luminance in a single color, return true and - * if color is not NULL, return that color. If it cannot, return false and ignore the color - * parameter. - * - * Note: if this returns true, the returned color will always be opaque, as only the RGB - * components are used to compute luminance. - */ - bool asLuminanceColor(SkColor*) const; - - /** - * Returns a shader transformed into a new color space via the |xformer|. - */ - sk_sp<SkShader> makeColorSpace(SkColorSpaceXformer* xformer) const { - return this->onMakeColorSpace(xformer); - } - - virtual bool isRasterPipelineOnly() const { return false; } - - bool appendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*, - const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM=nullptr) const; - - bool computeTotalInverse(const SkMatrix& ctm, - const SkMatrix* outerLocalMatrix, - SkMatrix* totalInverse) const; - -#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP - virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const { - return false; - } -#endif - - virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const { - return nullptr; - } - - SK_TO_STRING_VIRT() - - SK_DEFINE_FLATTENABLE_TYPE(SkShaderBase) - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() - -protected: - void flatten(SkWriteBuffer&) const override; - - /** - * Specialize creating a SkShader context using the supplied allocator. - * @return pointer to context owned by the arena allocator. - */ - virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const { - return nullptr; - } - - virtual bool onAsLuminanceColor(SkColor*) const { - return false; - } - - virtual sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer*) const { - return sk_ref_sp(const_cast<SkShaderBase*>(this)); - } - - virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*, - const SkMatrix&, const SkPaint&, const SkMatrix* localM) const; - -private: - // This is essentially const, but not officially so it can be modified in constructors. - SkMatrix fLocalMatrix; - - typedef SkShader INHERITED; -}; - -inline SkShaderBase* as_SB(SkShader* shader) { - return static_cast<SkShaderBase*>(shader); -} - -inline const SkShaderBase* as_SB(const SkShader* shader) { - return static_cast<const SkShaderBase*>(shader); -} - -inline const SkShaderBase* as_SB(const sk_sp<SkShader>& shader) { - return static_cast<SkShaderBase*>(shader.get()); -} - -#endif // SkShaderBase_DEFINED |