blob: bdb58597eb3de1017b00ba82ea51632b54133cae [file] [log] [blame]
Brian Osmane8e54582016-11-28 10:06:27 -05001/*
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
Brian Osmane8e54582016-11-28 10:06:27 -050011#include "GrResourceKey.h"
Brian Salomon2bbdcc42017-09-07 12:36:34 -040012#include "GrSamplerState.h"
13#include "SkImageInfo.h"
Ben Wagnerd5148e32018-07-16 17:44:06 -040014#include "SkNoncopyable.h"
Brian Osmane8e54582016-11-28 10:06:27 -050015
Brian Salomon2bbdcc42017-09-07 12:36:34 -040016class GrFragmentProcessor;
Robert Phillips9338c602019-02-19 12:52:29 -050017class GrRecordingContext;
Brian Osmane8e54582016-11-28 10:06:27 -050018class GrTexture;
Robert Phillipsb66b42f2017-03-14 08:53:02 -040019class GrTextureProxy;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040020class SkColorSpace;
21class SkMatrix;
22struct SkRect;
Brian Osmane8e54582016-11-28 10:06:27 -050023
24/**
25 * Different GPUs and API extensions have different requirements with respect to what texture
26 * sampling parameters may be used with textures of various types. This class facilitates making
Brian Salomon2bbdcc42017-09-07 12:36:34 -040027 * texture compatible with a given GrSamplerState. There are two immediate subclasses defined
Brian Osmane8e54582016-11-28 10:06:27 -050028 * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
29 * SkImage). It supports subsetting the original texture. The other is for use cases where the
30 * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
31 */
32class GrTextureProducer : public SkNoncopyable {
33public:
34 struct CopyParams {
Brian Salomon2bbdcc42017-09-07 12:36:34 -040035 GrSamplerState::Filter fFilter;
36 int fWidth;
37 int fHeight;
Brian Osmane8e54582016-11-28 10:06:27 -050038 };
39
40 enum FilterConstraint {
41 kYes_FilterConstraint,
42 kNo_FilterConstraint,
43 };
44
45 /**
46 * Helper for creating a fragment processor to sample the texture with a given filtering mode.
47 * It attempts to avoid making texture copies or using domains whenever possible.
48 *
49 * @param textureMatrix Matrix used to access the texture. It is applied to
50 * the local coords. The post-transformed coords should
51 * be in texel units (rather than normalized) with
52 * respect to this Producer's bounds (width()/height()).
53 * @param constraintRect A rect that represents the area of the texture to be
54 * sampled. It must be contained in the Producer's
55 * bounds as defined by width()/height().
56 * @param filterConstriant Indicates whether filtering is limited to
57 * constraintRect.
58 * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
59 * by the portion of the texture indicated by
60 * constraintRect (without consideration of filter
61 * width, just the raw coords).
62 * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
63 * use bicubic filtering.
64 **/
Brian Salomonaff329b2017-08-11 09:40:37 -040065 virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
66 const SkMatrix& textureMatrix,
67 const SkRect& constraintRect,
68 FilterConstraint filterConstraint,
69 bool coordsLimitedToConstraintRect,
Brian Osman05c8f462018-10-22 17:13:36 -040070 const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -050071
Brian Salomon2a943df2018-05-04 13:43:19 -040072 /**
73 * Returns a texture that is safe for use with the params.
74 *
75 * If the size of the returned texture does not match width()/height() then the contents of the
76 * original may have been scaled to fit the texture or the original may have been copied into
77 * a subrect of the copy. 'scaleAdjust' must be applied to the normalized texture coordinates
78 * in order to correct for the latter case.
79 *
80 * If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the
81 * proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird
82 * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling
83 * this method. (TODO: Fix this and make this function always initialize scaleAdjust).
Brian Salomon2a943df2018-05-04 13:43:19 -040084 */
85 sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
Brian Salomon2a943df2018-05-04 13:43:19 -040086 SkScalar scaleAdjust[2]);
87
Michael Ludwigddeed372019-02-20 16:50:10 -050088 sk_sp<GrTextureProxy> refTextureProxyForParams(
89 const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]);
Brian Salomon2a943df2018-05-04 13:43:19 -040090
Greg Daniel5f4b09d2018-06-12 16:39:59 -040091 /**
Brian Osmane7fd8c32018-10-19 13:30:39 -040092 * Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
93 * allocated mip map levels. This can be a performance win if future draws with the texture
94 * require mip maps.
Greg Daniel5f4b09d2018-06-12 16:39:59 -040095 */
96 // TODO: Once we remove support for npot textures, we should add a flag for must support repeat
97 // wrap mode. To support that flag now would require us to support scaleAdjust array like in
98 // refTextureProxyForParams, however the current public API that uses this call does not expose
99 // that array.
Brian Osman6064e1c2018-10-19 14:27:54 -0400100 sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400101
Brian Osmane8e54582016-11-28 10:06:27 -0500102 virtual ~GrTextureProducer() {}
103
104 int width() const { return fWidth; }
105 int height() const { return fHeight; }
106 bool isAlphaOnly() const { return fIsAlphaOnly; }
Michael Ludwigddeed372019-02-20 16:50:10 -0500107 bool domainNeedsDecal() const { return fDomainNeedsDecal; }
Brian Osmane8e54582016-11-28 10:06:27 -0500108 virtual SkAlphaType alphaType() const = 0;
Brian Osman6064e1c2018-10-19 14:27:54 -0400109 virtual SkColorSpace* colorSpace() const = 0;
Michael Ludwiga6a84002019-04-12 15:03:02 -0400110 // If the "texture" samples multiple images that have different resolutions (e.g. YUV420)
111 virtual bool hasMixedResolutions() const { return false; }
Brian Osmane8e54582016-11-28 10:06:27 -0500112
113protected:
Robert Phillips51e7ca32017-03-27 10:14:08 -0400114 friend class GrTextureProducer_TestAccess;
115
Michael Ludwigddeed372019-02-20 16:50:10 -0500116 GrTextureProducer(GrRecordingContext* context, int width, int height, bool isAlphaOnly,
117 bool domainNeedsDecal)
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400118 : fContext(context)
119 , fWidth(width)
Brian Osmane8e54582016-11-28 10:06:27 -0500120 , fHeight(height)
Michael Ludwigddeed372019-02-20 16:50:10 -0500121 , fIsAlphaOnly(isAlphaOnly)
122 , fDomainNeedsDecal(domainNeedsDecal) {}
Brian Osmane8e54582016-11-28 10:06:27 -0500123
124 /** Helper for creating a key for a copy from an original key. */
125 static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
126 const CopyParams& copyParams,
127 GrUniqueKey* copyKey) {
128 SkASSERT(!copyKey->isValid());
129 if (origKey.isValid()) {
130 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
131 GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400132 builder[0] = static_cast<uint32_t>(copyParams.fFilter);
Brian Osmane8e54582016-11-28 10:06:27 -0500133 builder[1] = copyParams.fWidth;
134 builder[2] = copyParams.fHeight;
135 }
136 }
137
138 /**
139 * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
140 * return a key that identifies its original content + the CopyParms parameter. If the producer
141 * does not want to cache the stretched version (e.g. the producer is volatile), this should
142 * simply return without initializing the copyKey. If the texture generated by this producer
Brian Osman61624f02016-12-09 14:51:59 -0500143 * depends on the destination color space, then that information should also be incorporated
144 * in the key.
Brian Osmane8e54582016-11-28 10:06:27 -0500145 */
Brian Osmanb3f38302018-09-07 15:24:44 -0400146 virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -0500147
148 /**
149 * If a stretched version of the texture is generated, it may be cached (assuming that
150 * makeCopyKey() returns true). In that case, the maker is notified in case it
151 * wants to note that for when the maker is destroyed.
152 */
Brian Salomon238069b2018-07-11 15:58:57 -0400153 virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -0500154
155 enum DomainMode {
156 kNoDomain_DomainMode,
157 kDomain_DomainMode,
158 kTightCopy_DomainMode
159 };
160
Robert Phillips9338c602019-02-19 12:52:29 -0500161 // This can draw to accomplish the copy, thus the recording context is needed
162 static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*, sk_sp<GrTextureProxy> inputProxy,
Greg Danielc77085d2017-11-01 16:38:48 -0400163 const CopyParams& copyParams,
Greg Daniele1da1d92017-10-06 15:59:27 -0400164 bool dstWillRequireMipMaps);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400165
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400166 static DomainMode DetermineDomainMode(const SkRect& constraintRect,
167 FilterConstraint filterConstraint,
168 bool coordsLimitedToConstraintRect,
169 GrTextureProxy*,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400170 const GrSamplerState::Filter* filterModeOrNullForBicubic,
171 SkRect* domainRect);
Robert Phillips51e7ca32017-03-27 10:14:08 -0400172
Michael Ludwigddeed372019-02-20 16:50:10 -0500173 std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter(
Brian Salomonaff329b2017-08-11 09:40:37 -0400174 sk_sp<GrTextureProxy> proxy,
Brian Salomonaff329b2017-08-11 09:40:37 -0400175 const SkMatrix& textureMatrix,
176 DomainMode,
177 const SkRect& domain,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400178 const GrSamplerState::Filter* filterOrNullForBicubic);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400179
Robert Phillips9338c602019-02-19 12:52:29 -0500180 GrRecordingContext* context() const { return fContext; }
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400181
Brian Osmane8e54582016-11-28 10:06:27 -0500182private:
Brian Salomon2a943df2018-05-04 13:43:19 -0400183 virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400184 bool willBeMipped,
Brian Salomon2a943df2018-05-04 13:43:19 -0400185 SkScalar scaleAdjust[2]) = 0;
186
Robert Phillips9338c602019-02-19 12:52:29 -0500187 GrRecordingContext* fContext;
188 const int fWidth;
189 const int fHeight;
190 const bool fIsAlphaOnly;
Michael Ludwigddeed372019-02-20 16:50:10 -0500191 // If true, any domain effect uses kDecal instead of kClamp, and sampler filter uses
192 // kClampToBorder instead of kClamp.
193 const bool fDomainNeedsDecal;
Brian Osmane8e54582016-11-28 10:06:27 -0500194
195 typedef SkNoncopyable INHERITED;
196};
197
198#endif