• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 GrTextureProducer_DEFINED
9 #define GrTextureProducer_DEFINED
10 
11 #include "include/core/SkImageInfo.h"
12 #include "include/private/GrResourceKey.h"
13 #include "include/private/SkNoncopyable.h"
14 #include "src/gpu/GrColorSpaceInfo.h"
15 #include "src/gpu/GrSamplerState.h"
16 
17 class GrFragmentProcessor;
18 class GrRecordingContext;
19 class GrTexture;
20 class GrTextureProxy;
21 class SkColorSpace;
22 class SkMatrix;
23 struct SkRect;
24 
25 /**
26  * Different GPUs and API extensions have different requirements with respect to what texture
27  * sampling parameters may be used with textures of various types. This class facilitates making
28  * texture compatible with a given GrSamplerState. There are two immediate subclasses defined
29  * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
30  * SkImage). It supports subsetting the original texture. The other is for use cases where the
31  * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
32  */
33 class GrTextureProducer : public SkNoncopyable {
34 public:
35     struct CopyParams {
36         GrSamplerState::Filter fFilter;
37         int fWidth;
38         int fHeight;
39     };
40 
41     enum FilterConstraint {
42         kYes_FilterConstraint,
43         kNo_FilterConstraint,
44     };
45 
46     /**
47      * Helper for creating a fragment processor to sample the texture with a given filtering mode.
48      * It attempts to avoid making texture copies or using domains whenever possible.
49      *
50      * @param textureMatrix                    Matrix used to access the texture. It is applied to
51      *                                         the local coords. The post-transformed coords should
52      *                                         be in texel units (rather than normalized) with
53      *                                         respect to this Producer's bounds (width()/height()).
54      * @param constraintRect                   A rect that represents the area of the texture to be
55      *                                         sampled. It must be contained in the Producer's
56      *                                         bounds as defined by width()/height().
57      * @param filterConstriant                 Indicates whether filtering is limited to
58      *                                         constraintRect.
59      * @param coordsLimitedToConstraintRect    Is it known that textureMatrix*localCoords is bound
60      *                                         by the portion of the texture indicated by
61      *                                         constraintRect (without consideration of filter
62      *                                         width, just the raw coords).
63      * @param filterOrNullForBicubic           If non-null indicates the filter mode. If null means
64      *                                         use bicubic filtering.
65      **/
66     virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
67             const SkMatrix& textureMatrix,
68             const SkRect& constraintRect,
69             FilterConstraint filterConstraint,
70             bool coordsLimitedToConstraintRect,
71             const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
72 
73     /**
74      *  Returns a texture that is safe for use with the params.
75      *
76      * If the size of the returned texture does not match width()/height() then the contents of the
77      * original may have been scaled to fit the texture or the original may have been copied into
78      * a subrect of the copy. 'scaleAdjust' must be  applied to the normalized texture coordinates
79      * in order to correct for the latter case.
80      *
81      * If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the
82      * proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird
83      * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling
84      * this method. (TODO: Fix this and make this function always initialize scaleAdjust).
85      */
86     sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
87                                                    SkScalar scaleAdjust[2]);
88 
89     sk_sp<GrTextureProxy> refTextureProxyForParams(
90             const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]);
91 
92     /**
93      * Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
94      * allocated mip map levels. This can be a performance win if future draws with the texture
95      * require mip maps.
96      */
97     // TODO: Once we remove support for npot textures, we should add a flag for must support repeat
98     // wrap mode. To support that flag now would require us to support scaleAdjust array like in
99     // refTextureProxyForParams, however the current public API that uses this call does not expose
100     // that array.
101     sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);
102 
~GrTextureProducer()103     virtual ~GrTextureProducer() {}
104 
width()105     int width() const { return fWidth; }
height()106     int height() const { return fHeight; }
colorType()107     GrColorType colorType() const { return fColorSpaceInfo.colorType(); }
alphaType()108     SkAlphaType alphaType() const { return fColorSpaceInfo.alphaType(); }
colorSpace()109     SkColorSpace* colorSpace() const { return fColorSpaceInfo.colorSpace(); }
isAlphaOnly()110     bool isAlphaOnly() const { return GrColorTypeIsAlphaOnly(fColorSpaceInfo.colorType()); }
domainNeedsDecal()111     bool domainNeedsDecal() const { return fDomainNeedsDecal; }
112     // If the "texture" samples multiple images that have different resolutions (e.g. YUV420)
hasMixedResolutions()113     virtual bool hasMixedResolutions() const { return false; }
114 
115 protected:
116     friend class GrTextureProducer_TestAccess;
117 
GrTextureProducer(GrRecordingContext * context,int width,int height,const GrColorSpaceInfo & csInfo,bool domainNeedsDecal)118     GrTextureProducer(GrRecordingContext* context, int width, int height,
119                       const GrColorSpaceInfo& csInfo, bool domainNeedsDecal)
120             : fContext(context)
121             , fWidth(width)
122             , fHeight(height)
123             , fColorSpaceInfo(csInfo)
124             , fDomainNeedsDecal(domainNeedsDecal) {}
125 
126     /** Helper for creating a key for a copy from an original key. */
MakeCopyKeyFromOrigKey(const GrUniqueKey & origKey,const CopyParams & copyParams,GrUniqueKey * copyKey)127     static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
128                                        const CopyParams& copyParams,
129                                        GrUniqueKey* copyKey) {
130         SkASSERT(!copyKey->isValid());
131         if (origKey.isValid()) {
132             static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
133             GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
134             builder[0] = static_cast<uint32_t>(copyParams.fFilter);
135             builder[1] = copyParams.fWidth;
136             builder[2] = copyParams.fHeight;
137         }
138     }
139 
140     /**
141     *  If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
142     *  return a key that identifies its original content + the CopyParms parameter. If the producer
143     *  does not want to cache the stretched version (e.g. the producer is volatile), this should
144     *  simply return without initializing the copyKey. If the texture generated by this producer
145     *  depends on the destination color space, then that information should also be incorporated
146     *  in the key.
147     */
148     virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
149 
150     /**
151     *  If a stretched version of the texture is generated, it may be cached (assuming that
152     *  makeCopyKey() returns true). In that case, the maker is notified in case it
153     *  wants to note that for when the maker is destroyed.
154     */
155     virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;
156 
157     enum DomainMode {
158         kNoDomain_DomainMode,
159         kDomain_DomainMode,
160         kTightCopy_DomainMode
161     };
162 
163     // This can draw to accomplish the copy, thus the recording context is needed
164     static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*,
165                                            sk_sp<GrTextureProxy> inputProxy,
166                                            GrColorType,
167                                            const CopyParams& copyParams,
168                                            bool dstWillRequireMipMaps);
169 
170     static DomainMode DetermineDomainMode(const SkRect& constraintRect,
171                                           FilterConstraint filterConstraint,
172                                           bool coordsLimitedToConstraintRect,
173                                           GrTextureProxy*,
174                                           const GrSamplerState::Filter* filterModeOrNullForBicubic,
175                                           SkRect* domainRect);
176 
177     std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter(
178             sk_sp<GrTextureProxy> proxy,
179             const SkMatrix& textureMatrix,
180             DomainMode,
181             const SkRect& domain,
182             const GrSamplerState::Filter* filterOrNullForBicubic);
183 
context()184     GrRecordingContext* context() const { return fContext; }
185 
186 private:
187     virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
188                                                              bool willBeMipped,
189                                                              SkScalar scaleAdjust[2]) = 0;
190 
191     GrRecordingContext* fContext;
192     const int fWidth;
193     const int fHeight;
194     const GrColorSpaceInfo fColorSpaceInfo;
195     // If true, any domain effect uses kDecal instead of kClamp, and sampler filter uses
196     // kClampToBorder instead of kClamp.
197     const bool  fDomainNeedsDecal;
198 
199     typedef SkNoncopyable INHERITED;
200 };
201 
202 #endif
203