Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright 2015 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 "SkBitmapProcShader.h"
      9 #include "SkBitmapProvider.h"
     10 #include "SkImage_Base.h"
     11 #include "SkImageShader.h"
     12 #include "SkReadBuffer.h"
     13 #include "SkWriteBuffer.h"
     14 
     15 SkImageShader::SkImageShader(const SkImage* img, TileMode tmx, TileMode tmy, const SkMatrix* matrix)
     16     : INHERITED(matrix)
     17     , fImage(SkRef(img))
     18     , fTileModeX(tmx)
     19     , fTileModeY(tmy)
     20 {}
     21 
     22 SkFlattenable* SkImageShader::CreateProc(SkReadBuffer& buffer) {
     23     const TileMode tx = (TileMode)buffer.readUInt();
     24     const TileMode ty = (TileMode)buffer.readUInt();
     25     SkMatrix matrix;
     26     buffer.readMatrix(&matrix);
     27     SkAutoTUnref<SkImage> img(buffer.readImage());
     28     if (!img) {
     29         return nullptr;
     30     }
     31     return new SkImageShader(img, tx, ty, &matrix);
     32 }
     33 
     34 void SkImageShader::flatten(SkWriteBuffer& buffer) const {
     35     buffer.writeUInt(fTileModeX);
     36     buffer.writeUInt(fTileModeY);
     37     buffer.writeMatrix(this->getLocalMatrix());
     38     buffer.writeImage(fImage);
     39 }
     40 
     41 bool SkImageShader::isOpaque() const {
     42     return fImage->isOpaque();
     43 }
     44 
     45 size_t SkImageShader::contextSize(const ContextRec&) const {
     46     return SkBitmapProcShader::ContextSize();
     47 }
     48 
     49 SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const {
     50     return SkBitmapProcShader::MakeContext(*this, fTileModeX, fTileModeY,
     51                                            SkBitmapProvider(fImage), rec, storage);
     52 }
     53 
     54 SkShader* SkImageShader::Create(const SkImage* image, TileMode tx, TileMode ty,
     55                                 const SkMatrix* localMatrix) {
     56     if (!image) {
     57         return nullptr;
     58     }
     59     return new SkImageShader(image, tx, ty, localMatrix);
     60 }
     61 
     62 #ifndef SK_IGNORE_TO_STRING
     63 void SkImageShader::toString(SkString* str) const {
     64     const char* gTileModeName[SkShader::kTileModeCount] = {
     65         "clamp", "repeat", "mirror"
     66     };
     67 
     68     str->appendf("ImageShader: ((%s %s) ", gTileModeName[fTileModeX], gTileModeName[fTileModeY]);
     69     fImage->toString(str);
     70     this->INHERITED::toString(str);
     71     str->append(")");
     72 }
     73 #endif
     74 
     75 ///////////////////////////////////////////////////////////////////////////////////////////////////
     76 
     77 #if SK_SUPPORT_GPU
     78 
     79 #include "GrTextureAccess.h"
     80 #include "SkGr.h"
     81 #include "SkGrPriv.h"
     82 #include "effects/GrSimpleTextureEffect.h"
     83 #include "effects/GrBicubicEffect.h"
     84 #include "effects/GrSimpleTextureEffect.h"
     85 
     86 const GrFragmentProcessor* SkImageShader::asFragmentProcessor(GrContext* context,
     87                                                               const SkMatrix& viewM,
     88                                                               const SkMatrix* localMatrix,
     89                                                               SkFilterQuality filterQuality) const {
     90     SkMatrix matrix;
     91     matrix.setIDiv(fImage->width(), fImage->height());
     92 
     93     SkMatrix lmInverse;
     94     if (!this->getLocalMatrix().invert(&lmInverse)) {
     95         return nullptr;
     96     }
     97     if (localMatrix) {
     98         SkMatrix inv;
     99         if (!localMatrix->invert(&inv)) {
    100             return nullptr;
    101         }
    102         lmInverse.postConcat(inv);
    103     }
    104     matrix.preConcat(lmInverse);
    105 
    106     SkShader::TileMode tm[] = { fTileModeX, fTileModeY };
    107 
    108     // Must set wrap and filter on the sampler before requesting a texture. In two places below
    109     // we check the matrix scale factors to determine how to interpret the filter quality setting.
    110     // This completely ignores the complexity of the drawVertices case where explicit local coords
    111     // are provided by the caller.
    112     bool doBicubic;
    113     GrTextureParams::FilterMode textureFilterMode =
    114     GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(), &doBicubic);
    115     GrTextureParams params(tm, textureFilterMode);
    116     SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(context, params));
    117     if (!texture) {
    118         return nullptr;
    119     }
    120 
    121     SkAutoTUnref<const GrFragmentProcessor> inner;
    122     if (doBicubic) {
    123         inner.reset(GrBicubicEffect::Create(texture, matrix, tm));
    124     } else {
    125         inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params));
    126     }
    127 
    128     if (GrPixelConfigIsAlphaOnly(texture->config())) {
    129         return SkRef(inner.get());
    130     }
    131     return GrFragmentProcessor::MulOutputByInputAlpha(inner);
    132 }
    133 
    134 #endif
    135