Home | History | Annotate | Download | only in shaders
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkLocalMatrixShader.h"
      9 #include "SkTLazy.h"
     10 
     11 #if SK_SUPPORT_GPU
     12 #include "GrFragmentProcessor.h"
     13 #endif
     14 
     15 #if SK_SUPPORT_GPU
     16 std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(
     17         const GrFPArgs& args) const {
     18     return as_SB(fProxyShader)->asFragmentProcessor(
     19         GrFPArgs::WithPreLocalMatrix(args, this->getLocalMatrix()));
     20 }
     21 #endif
     22 
     23 sk_sp<SkFlattenable> SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) {
     24     SkMatrix lm;
     25     buffer.readMatrix(&lm);
     26     auto baseShader(buffer.readShader());
     27     if (!baseShader) {
     28         return nullptr;
     29     }
     30     return baseShader->makeWithLocalMatrix(lm);
     31 }
     32 
     33 void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const {
     34     buffer.writeMatrix(this->getLocalMatrix());
     35     buffer.writeFlattenable(fProxyShader.get());
     36 }
     37 
     38 #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
     39 SkShaderBase::Context* SkLocalMatrixShader::onMakeContext(
     40     const ContextRec& rec, SkArenaAlloc* alloc) const
     41 {
     42     SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix());
     43     if (rec.fLocalMatrix) {
     44         lm.writable()->preConcat(*rec.fLocalMatrix);
     45     }
     46 
     47     ContextRec newRec(rec);
     48     newRec.fLocalMatrix = lm;
     49 
     50     return as_SB(fProxyShader)->makeContext(newRec, alloc);
     51 }
     52 #endif
     53 
     54 SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const {
     55     SkMatrix imageMatrix;
     56     SkImage* image = fProxyShader->isAImage(&imageMatrix, mode);
     57     if (image && outMatrix) {
     58         // Local matrix must be applied first so it is on the right side of the concat.
     59         *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix());
     60     }
     61 
     62     return image;
     63 }
     64 
     65 bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const {
     66     SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix());
     67     if (rec.fLocalM) {
     68         lm.writable()->preConcat(*rec.fLocalM);
     69     }
     70 
     71     StageRec newRec = rec;
     72     newRec.fLocalM = lm;
     73     return as_SB(fProxyShader)->appendStages(newRec);
     74 }
     75 
     76 sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const {
     77     if (localMatrix.isIdentity()) {
     78         return sk_ref_sp(const_cast<SkShader*>(this));
     79     }
     80 
     81     const SkMatrix* lm = &localMatrix;
     82 
     83     sk_sp<SkShader> baseShader;
     84     SkMatrix otherLocalMatrix;
     85     sk_sp<SkShader> proxy(as_SB(this)->makeAsALocalMatrixShader(&otherLocalMatrix));
     86     if (proxy) {
     87         otherLocalMatrix.preConcat(localMatrix);
     88         lm = &otherLocalMatrix;
     89         baseShader = proxy;
     90     } else {
     91         baseShader = sk_ref_sp(const_cast<SkShader*>(this));
     92     }
     93 
     94     return sk_make_sp<SkLocalMatrixShader>(std::move(baseShader), *lm);
     95 }
     96