SkColorFilterShader.cpp revision 06ca8ec87cf6fab57cadd043a5ac18c4154a4129
13061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed/*
23061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed * Copyright 2013 Google Inc.
33061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed *
43061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed * Use of this source code is governed by a BSD-style license that can be
53061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed * found in the LICENSE file.
63061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed */
73061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
83061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "SkColorFilterShader.h"
93061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "SkReadBuffer.h"
103061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "SkWriteBuffer.h"
113061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "SkShader.h"
123061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "SkString.h"
133061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
143061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#if SK_SUPPORT_GPU
153061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#include "GrFragmentProcessor.h"
163061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#endif
173061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
18d053ce9c54d4e5937a142278359e5a4cde18095ereedSkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader, sk_sp<SkColorFilter> filter)
19d053ce9c54d4e5937a142278359e5a4cde18095ereed    : fShader(std::move(shader))
20d053ce9c54d4e5937a142278359e5a4cde18095ereed    , fFilter(std::move(filter))
213061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed{
22d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkASSERT(fShader);
23d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkASSERT(fFilter);
243061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
253061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
2660c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) {
278a21c9fe7f5fef9e87115defef27bd7218419f28reed    auto shader = buffer.readShader();
28d053ce9c54d4e5937a142278359e5a4cde18095ereed    auto filter = buffer.readColorFilter();
29d053ce9c54d4e5937a142278359e5a4cde18095ereed    if (!shader || !filter) {
303061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed        return nullptr;
313061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
3260c9b58b3214b0154c931656e91e39b230e987d8reed    return sk_make_sp<SkColorFilterShader>(shader, filter);
333061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
343061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
353061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedvoid SkColorFilterShader::flatten(SkWriteBuffer& buffer) const {
36d053ce9c54d4e5937a142278359e5a4cde18095ereed    buffer.writeFlattenable(fShader.get());
37d053ce9c54d4e5937a142278359e5a4cde18095ereed    buffer.writeFlattenable(fFilter.get());
383061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
393061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
403061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reeduint32_t SkColorFilterShader::FilterShaderContext::getFlags() const {
413061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
423061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
433061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    uint32_t shaderF = fShaderContext->getFlags();
443061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    uint32_t filterF = filterShader.fFilter->getFlags();
453061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
463b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    // If the filter does not support a given feature, but sure to clear the corresponding flag
473b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    // in the shader flags.
483b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    //
493061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) {
503061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed        shaderF &= ~SkShader::kOpaqueAlpha_Flag;
513061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
523061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    return shaderF;
533061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
543061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
553061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedSkShader::Context* SkColorFilterShader::onCreateContext(const ContextRec& rec,
563061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed                                                        void* storage) const {
573061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext);
583061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage);
593061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    if (nullptr == shaderContext) {
603061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed        return nullptr;
613061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
623061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    return new (storage) FilterShaderContext(*this, shaderContext, rec);
633061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
643061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
65773ceda51ca120b686ba2d1aff1b6d5173143be0reedsize_t SkColorFilterShader::onContextSize(const ContextRec& rec) const {
66a0cee5f30e9254187a6bb943e6b8a9296214c353reed    return sizeof(FilterShaderContext) + fShader->contextSize(rec);
673061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
683061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
693061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedSkColorFilterShader::FilterShaderContext::FilterShaderContext(
703061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed                                                         const SkColorFilterShader& filterShader,
713061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed                                                         SkShader::Context* shaderContext,
723061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed                                                         const ContextRec& rec)
733061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    : INHERITED(filterShader, rec)
743061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    , fShaderContext(shaderContext)
753061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed{}
763061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
773061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedSkColorFilterShader::FilterShaderContext::~FilterShaderContext() {
783061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    fShaderContext->~Context();
793061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
803061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
813061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedvoid SkColorFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[],
823061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed                                                         int count) {
833061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
843061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
853061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    fShaderContext->shadeSpan(x, y, result, count);
863061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    filterShader.fFilter->filterSpan(result, count, result);
873061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
883061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
893b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reedvoid SkColorFilterShader::FilterShaderContext::shadeSpan4f(int x, int y, SkPM4f result[],
903b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed                                                          int count) {
913b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
923b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed
933b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    fShaderContext->shadeSpan4f(x, y, result, count);
943b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed    filterShader.fFilter->filterSpan4f(result, count, result);
953b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed}
963b69b82b22ba854f9a8e9f1ccb54f0d9022c0bd8reed
973061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#if SK_SUPPORT_GPU
983061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed/////////////////////////////////////////////////////////////////////
993061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
10006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor(
101982eb7f377a0c771345276558072deb2fcea0d3ebrianosman                                                     GrContext* context,
102982eb7f377a0c771345276558072deb2fcea0d3ebrianosman                                                     const SkMatrix& viewM,
103982eb7f377a0c771345276558072deb2fcea0d3ebrianosman                                                     const SkMatrix* localMatrix,
104982eb7f377a0c771345276558072deb2fcea0d3ebrianosman                                                     SkFilterQuality fq,
105982eb7f377a0c771345276558072deb2fcea0d3ebrianosman                                                     SkSourceGammaTreatment gammaTreatment) const {
1063061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
10706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    sk_sp<GrFragmentProcessor> fp1(fShader->asFragmentProcessor(context, viewM, localMatrix, fq,
10806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                                gammaTreatment));
10906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    if (!fp1) {
1103061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed        return nullptr;
1113061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
1123061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
11306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(context));
11406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    if (!fp2) {
11506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        return fp1;
1163061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
1173061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
11806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    sk_sp<GrFragmentProcessor> fpSeries[] = { std::move(fp1), std::move(fp2) };
1193061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    return GrFragmentProcessor::RunInSeries(fpSeries, 2);
1203061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
1213061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#endif
1223061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
1233061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#ifndef SK_IGNORE_TO_STRING
1243061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reedvoid SkColorFilterShader::toString(SkString* str) const {
1253061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    str->append("SkColorFilterShader: (");
1263061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
1273061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    str->append("Shader: ");
1283061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    fShader->toString(str);
1293061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    str->append(" Filter: ");
1303061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    // TODO: add "fFilter->toString(str);" once SkColorFilter::toString is added
1313061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
1323061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    this->INHERITED::toString(str);
1333061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
1343061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    str->append(")");
1353061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
1363061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed#endif
1373061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
1383061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed///////////////////////////////////////////////////////////////////////////////////////////////////
1393061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed
140d053ce9c54d4e5937a142278359e5a4cde18095ereedsk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const {
1413061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    SkShader* base = const_cast<SkShader*>(this);
1423061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    if (!filter) {
143150835e779ceb24e2b540f58958cbff2a0ab9942reed        return sk_ref_sp(base);
1443061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed    }
145d053ce9c54d4e5937a142278359e5a4cde18095ereed    return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), filter);
1463061af4a5f2b8ef00fc4a34b04cf99dfb780f1a1reed}
147