• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkImageShader(const SkImage * img,TileMode tmx,TileMode tmy,const SkMatrix * matrix)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 
CreateProc(SkReadBuffer & buffer)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 
flatten(SkWriteBuffer & buffer) const34 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 
isOpaque() const41 bool SkImageShader::isOpaque() const {
42     return fImage->isOpaque();
43 }
44 
contextSize(const ContextRec &) const45 size_t SkImageShader::contextSize(const ContextRec&) const {
46     return SkBitmapProcShader::ContextSize();
47 }
48 
onCreateContext(const ContextRec & rec,void * storage) const49 SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const {
50     return SkBitmapProcShader::MakeContext(*this, fTileModeX, fTileModeY,
51                                            SkBitmapProvider(fImage), rec, storage);
52 }
53 
Create(const SkImage * image,TileMode tx,TileMode ty,const SkMatrix * localMatrix)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
toString(SkString * str) const63 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 
asFragmentProcessor(GrContext * context,const SkMatrix & viewM,const SkMatrix * localMatrix,SkFilterQuality filterQuality) const86 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