1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkArenaAlloc.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAtomics.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmapProcShader.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorShader.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXformer.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkEmptyShader.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMallocPixelRef.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPicture.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureShader.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPM4fPriv.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRasterPipeline.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScalar.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkShaderBase.h"
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTLazy.h"
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWriteBuffer.h"
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../jumper/SkJumper.h"
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrFragmentProcessor.h"
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define SK_TRACK_SHADER_LIFETIME
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_TRACK_SHADER_LIFETIME
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int32_t gShaderCounter;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic inline void inc_shader_counter() {
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_TRACK_SHADER_LIFETIME
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t prev = sk_atomic_inc(&gShaderCounter);
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("+++ shader counter %d\n", prev + 1);
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic inline void dec_shader_counter() {
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_TRACK_SHADER_LIFETIME
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t prev = sk_atomic_dec(&gShaderCounter);
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("--- shader counter %d\n", prev - 1);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::SkShaderBase(const SkMatrix* localMatrix)
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    : fLocalMatrix(localMatrix ? *localMatrix : SkMatrix::I()) {
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    inc_shader_counter();
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Pre-cache so future calls to fLocalMatrix.getType() are threadsafe.
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void)fLocalMatrix.getType();
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::~SkShaderBase() {
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    dec_shader_counter();
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkShaderBase::flatten(SkWriteBuffer& buffer) const {
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->INHERITED::flatten(buffer);
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasLocalM = !fLocalMatrix.isIdentity();
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeBool(hasLocalM);
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (hasLocalM) {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        buffer.writeMatrix(fLocalMatrix);
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       const SkMatrix* outerLocalMatrix,
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       SkMatrix* totalInverse) const {
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix total = SkMatrix::Concat(ctm, fLocalMatrix);
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (outerLocalMatrix) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        total.preConcat(*outerLocalMatrix);
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return total.invert(totalInverse);
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkColor storage;
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (nullptr == colorPtr) {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        colorPtr = &storage;
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this->onAsLuminanceColor(colorPtr)) {
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *colorPtr = SkColorSetA(*colorPtr, 0xFF);   // we only return opaque
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::Context* SkShaderBase::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ? this->onMakeContext(rec, alloc)
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : nullptr;
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::Context* SkShaderBase::makeBurstPipelineContext(const ContextRec& rec,
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                              SkArenaAlloc* alloc) const {
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(rec.fPreferredDstType == ContextRec::kPM4f_DstType);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Always use vanilla stages for perspective.
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (rec.fMatrix->hasPerspective() || fLocalMatrix.hasPerspective()) {
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ? this->onMakeBurstPipelineContext(rec, alloc)
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : nullptr;
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec)
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    : fShader(shader), fCTM(*rec.fMatrix)
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We should never use a context for RP-only shaders.
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!shader.isRasterPipelineOnly(*rec.fMatrix));
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // ... or for perspective.
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!rec.fMatrix->hasPerspective());
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!rec.fLocalMatrix || !rec.fLocalMatrix->hasPerspective());
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Because the context parameters must be valid at this point, we know that the matrix is
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // invertible.
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &fTotalInverse));
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fPaintAlpha = rec.fPaint->getAlpha();
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShaderBase::Context::~Context() {}
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkShaderBase::Context::shadeSpan4f(int x, int y, SkPM4f dst[], int count) {
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int N = 128;
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPMColor tmp[N];
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (count > 0) {
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int n = SkTMin(count, N);
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->shadeSpan(x, y, tmp, n);
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < n; ++i) {
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            dst[i] = SkPM4f::FromPMColor(tmp[i]);
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dst += n;
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        x += n;
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        count -= n;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkMatrix& SkShader::getLocalMatrix() const {
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return as_SB(this)->getLocalMatrix();
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkShader::isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return  as_SB(this)->onIsABitmap(outTexture, outMatrix, xy);
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkImage* SkShader::isAImage(SkMatrix* localMatrix, TileMode xy[2]) const {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return as_SB(this)->onIsAImage(localMatrix, xy);
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return kNone_GradientType;
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrFragmentProcessor> SkShaderBase::asFragmentProcessor(const GrFPArgs&) const {
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr;
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkShader::makeAsALocalMatrixShader(SkMatrix*) const {
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr;
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkShader::MakeEmptyShader() { return sk_make_sp<SkEmptyShader>(); }
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkShader::MakeColorShader(SkColor color) { return sk_make_sp<SkColorShader>(color); }
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkShader::MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const SkMatrix* localMatrix) {
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (localMatrix && !localMatrix->invert(nullptr)) {
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkMakeBitmapShader(src, tmx, tmy, localMatrix, kIfMutable_SkCopyPixelsMode);
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkShader::MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy,
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            const SkMatrix* localMatrix, const SkRect* tile) {
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (localMatrix && !localMatrix->invert(nullptr)) {
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkPictureShader::Make(std::move(src), tmx, tmy, localMatrix, tile);
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkShaderBase::toString(SkString* str) const {
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!fLocalMatrix.isIdentity()) {
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str->append(" ");
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLocalMatrix.toString(str);
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkShaderBase::appendStages(const StageRec& rec) const {
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->onAppendStages(rec);
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkShaderBase::onAppendStages(const StageRec& rec) const {
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // SkShader::Context::shadeSpan4f() handles the paint opacity internally,
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // but SkRasterPipelineBlitter applies it as a separate stage.
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We skip the internal shadeSpan4f() step by forcing the paint opaque.
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTCopyOnFirstWrite<SkPaint> opaquePaint(rec.fPaint);
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (rec.fPaint.getAlpha() != SK_AlphaOPAQUE) {
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        opaquePaint.writable()->setAlpha(SK_AlphaOPAQUE);
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ContextRec cr(*opaquePaint, rec.fCTM, rec.fLocalM, ContextRec::kPM4f_DstType, rec.fDstCS);
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct CallbackCtx : SkJumper_CallbackCtx {
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkShader> shader;
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Context*        ctx;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto cb = rec.fAlloc->make<CallbackCtx>();
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    cb->shader = rec.fDstCS ? SkColorSpaceXformer::Make(sk_ref_sp(rec.fDstCS))->apply(this)
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            : sk_ref_sp((SkShader*)this);
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    cb->ctx = as_SB(cb->shader)->makeContext(cr, rec.fAlloc);
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    cb->fn  = [](SkJumper_CallbackCtx* self, int active_pixels) {
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto c = (CallbackCtx*)self;
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int x = (int)c->rgba[0],
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        y = (int)c->rgba[1];
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        c->ctx->shadeSpan4f(x,y, (SkPM4f*)c->rgba, active_pixels);
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (cb->ctx) {
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rec.fPipeline->append_seed_shader();
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rec.fPipeline->append(SkRasterPipeline::callback, cb);
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkShader::MakeEmptyShader();
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkEmptyShader.h"
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkEmptyShader::toString(SkString* str) const {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->append("SkEmptyShader: (");
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->INHERITED::toString(str);
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->append(")");
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
259