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 #ifndef GrTextureMaker_DEFINED
9 #define GrTextureMaker_DEFINED
10 
11 #include "GrTextureParams.h"
12 #include "GrResourceKey.h"
13 #include "GrTexture.h"
14 #include "SkTLazy.h"
15 
16 class GrContext;
17 class GrTextureParams;
18 class GrUniqueKey;
19 class SkBitmap;
20 
21 /**
22  * Different GPUs and API extensions have different requirements with respect to what texture
23  * sampling parameters may be used with textures of various types. This class facilitates making
24  * texture compatible with a given GrTextureParams. There are two immediate subclasses defined
25  * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
26  * SkImage). It supports subsetting the original texture. The other is for use cases where the
27  * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
28  */
29 class GrTextureProducer : public SkNoncopyable {
30 public:
31     struct CopyParams {
32         GrTextureParams::FilterMode fFilter;
33         int                         fWidth;
34         int                         fHeight;
35     };
36 
37     enum FilterConstraint {
38         kYes_FilterConstraint,
39         kNo_FilterConstraint,
40     };
41 
42     /**
43      * Helper for creating a fragment processor to sample the texture with a given filtering mode.
44      * It attempts to avoid making texture copies or using domains whenever possible.
45      *
46      * @param textureMatrix                    Matrix used to access the texture. It is applied to
47      *                                         the local coords. The post-transformed coords should
48      *                                         be in texel units (rather than normalized) with
49      *                                         respect to this Producer's bounds (width()/height()).
50      * @param constraintRect                   A rect that represents the area of the texture to be
51      *                                         sampled. It must be contained in the Producer's bounds
52      *                                         as defined by width()/height().
53      * @param filterConstriant                 Indicates whether filtering is limited to
54      *                                         constraintRect.
55      * @param coordsLimitedToConstraintRect    Is it known that textureMatrix*localCoords is bound
56      *                                         by the portion of the texture indicated by
57      *                                         constraintRect (without consideration of filter
58      *                                         width, just the raw coords).
59      * @param filterOrNullForBicubic           If non-null indicates the filter mode. If null means
60      *                                         use bicubic filtering.
61      **/
62     virtual sk_sp<GrFragmentProcessor> createFragmentProcessor(
63                                     const SkMatrix& textureMatrix,
64                                     const SkRect& constraintRect,
65                                     FilterConstraint filterConstraint,
66                                     bool coordsLimitedToConstraintRect,
67                                     const GrTextureParams::FilterMode* filterOrNullForBicubic,
68                                     SkColorSpace* dstColorSpace,
69                                     SkSourceGammaTreatment) = 0;
70 
~GrTextureProducer()71     virtual ~GrTextureProducer() {}
72 
width()73     int width() const { return fWidth; }
height()74     int height() const { return fHeight; }
isAlphaOnly()75     bool isAlphaOnly() const { return fIsAlphaOnly; }
76     virtual SkAlphaType alphaType() const = 0;
77     virtual SkColorSpace* getColorSpace() = 0;
78 
79 protected:
GrTextureProducer(int width,int height,bool isAlphaOnly)80     GrTextureProducer(int width, int height, bool isAlphaOnly)
81         : fWidth(width)
82         , fHeight(height)
83         , fIsAlphaOnly(isAlphaOnly) {}
84 
85     /** Helper for creating a key for a copy from an original key. */
MakeCopyKeyFromOrigKey(const GrUniqueKey & origKey,const CopyParams & copyParams,GrUniqueKey * copyKey)86     static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
87                                        const CopyParams& copyParams,
88                                        GrUniqueKey* copyKey) {
89         SkASSERT(!copyKey->isValid());
90         if (origKey.isValid()) {
91             static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
92             GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
93             builder[0] = copyParams.fFilter;
94             builder[1] = copyParams.fWidth;
95             builder[2] = copyParams.fHeight;
96         }
97     }
98 
99     /**
100     *  If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
101     *  return a key that identifies its original content + the CopyParms parameter. If the producer
102     *  does not want to cache the stretched version (e.g. the producer is volatile), this should
103     *  simply return without initializing the copyKey.
104     */
105     virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
106 
107     /**
108     *  If a stretched version of the texture is generated, it may be cached (assuming that
109     *  makeCopyKey() returns true). In that case, the maker is notified in case it
110     *  wants to note that for when the maker is destroyed.
111     */
112     virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
113 
114 private:
115     const int   fWidth;
116     const int   fHeight;
117     const bool  fIsAlphaOnly;
118 
119     typedef SkNoncopyable INHERITED;
120 };
121 
122 /**
123  * Base class for sources that start out as textures. Optionally allows for a content area subrect.
124  * The intent is not to use content area for subrect rendering. Rather, the pixels outside the
125  * content area have undefined values and shouldn't be read *regardless* of filtering mode or
126  * the SkCanvas::SrcRectConstraint used for subrect draws.
127  */
128 class GrTextureAdjuster : public GrTextureProducer {
129 public:
130     /** Makes the subset of the texture safe to use with the given texture parameters.
131         outOffset will be the top-left corner of the subset if a copy is not made. Otherwise,
132         the copy will be tight to the contents and outOffset will be (0, 0). If the copy's size
133         does not match subset's dimensions then the contents are scaled to fit the copy.*/
134     GrTexture* refTextureSafeForParams(const GrTextureParams&, SkSourceGammaTreatment,
135                                        SkIPoint* outOffset);
136 
137     sk_sp<GrFragmentProcessor> createFragmentProcessor(
138                                 const SkMatrix& textureMatrix,
139                                 const SkRect& constraintRect,
140                                 FilterConstraint,
141                                 bool coordsLimitedToConstraintRect,
142                                 const GrTextureParams::FilterMode* filterOrNullForBicubic,
143                                 SkColorSpace* dstColorSpace,
144                                 SkSourceGammaTreatment) override;
145 
146     // We do not ref the texture nor the colorspace, so the caller must keep them in scope while
147     // this Adjuster is alive.
148     GrTextureAdjuster(GrTexture*, SkAlphaType, const SkIRect& area, uint32_t uniqueID,
149                       SkColorSpace*);
150 
151 protected:
alphaType()152     SkAlphaType alphaType() const override { return fAlphaType; }
153     SkColorSpace* getColorSpace() override;
154     void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) override;
155     void didCacheCopy(const GrUniqueKey& copyKey) override;
156 
originalTexture()157     GrTexture* originalTexture() const { return fOriginal; }
158 
159     /** Returns the content area or null for the whole original texture */
contentAreaOrNull()160     const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); }
161 
162 private:
163     SkTLazy<SkIRect>    fContentArea;
164     GrTexture*          fOriginal;
165     SkAlphaType         fAlphaType;
166     SkColorSpace*       fColorSpace;
167     uint32_t            fUniqueID;
168 
169     GrTexture* refCopy(const CopyParams &copyParams);
170 
171     typedef GrTextureProducer INHERITED;
172 };
173 
174 /**
175  * Base class for sources that start out as something other than a texture (encoded image,
176  * picture, ...).
177  */
178 class GrTextureMaker : public GrTextureProducer {
179 public:
180     /** Returns a texture that is safe for use with the params. If the size of the returned texture
181         does not match width()/height() then the contents of the original must be scaled to fit
182         the texture. */
183     GrTexture* refTextureForParams(const GrTextureParams&, SkSourceGammaTreatment);
184 
185     sk_sp<GrFragmentProcessor> createFragmentProcessor(
186                                 const SkMatrix& textureMatrix,
187                                 const SkRect& constraintRect,
188                                 FilterConstraint filterConstraint,
189                                 bool coordsLimitedToConstraintRect,
190                                 const GrTextureParams::FilterMode* filterOrNullForBicubic,
191                                 SkColorSpace* dstColorSpace,
192                                 SkSourceGammaTreatment) override;
193 
194 protected:
GrTextureMaker(GrContext * context,int width,int height,bool isAlphaOnly)195     GrTextureMaker(GrContext* context, int width, int height, bool isAlphaOnly)
196         : INHERITED(width, height, isAlphaOnly)
197         , fContext(context) {}
198 
199     /**
200      *  Return the maker's "original" texture. It is the responsibility of the maker to handle any
201      *  caching of the original if desired.
202      */
203     virtual GrTexture* refOriginalTexture(bool willBeMipped, SkSourceGammaTreatment) = 0;
204 
205     /**
206      *  Return a new (uncached) texture that is the stretch of the maker's original.
207      *
208      *  The base-class handles general logic for this, and only needs access to the following
209      *  method:
210      *  - refOriginalTexture()
211      *
212      *  Subclass may override this if they can handle creating the texture more directly than
213      *  by copying.
214      */
215     virtual GrTexture* generateTextureForParams(const CopyParams&, bool willBeMipped,
216                                                 SkSourceGammaTreatment);
217 
context()218     GrContext* context() const { return fContext; }
219 
220 private:
221     GrContext*  fContext;
222 
223     typedef GrTextureProducer INHERITED;
224 };
225 
226 #endif
227