blob: d73ed2543c493a0dd8590be0a09530cc6140a186 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkImageInfo.h"
12#include "include/gpu/GrSamplerState.h"
13#include "include/private/GrResourceKey.h"
14#include "include/private/SkNoncopyable.h"
Brian Salomone7499c72019-06-24 12:12:36 -040015#include "src/gpu/GrColorSpaceInfo.h"
Brian Osmane8e54582016-11-28 10:06:27 -050016
Brian Salomon2bbdcc42017-09-07 12:36:34 -040017class GrFragmentProcessor;
Robert Phillips9338c602019-02-19 12:52:29 -050018class GrRecordingContext;
Brian Osmane8e54582016-11-28 10:06:27 -050019class GrTexture;
Robert Phillipsb66b42f2017-03-14 08:53:02 -040020class GrTextureProxy;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040021class SkColorSpace;
22class SkMatrix;
23struct SkRect;
Brian Osmane8e54582016-11-28 10:06:27 -050024
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
Brian Salomon2bbdcc42017-09-07 12:36:34 -040028 * texture compatible with a given GrSamplerState. There are two immediate subclasses defined
Brian Osmane8e54582016-11-28 10:06:27 -050029 * 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 */
33class GrTextureProducer : public SkNoncopyable {
34public:
35 struct CopyParams {
Brian Salomon2bbdcc42017-09-07 12:36:34 -040036 GrSamplerState::Filter fFilter;
37 int fWidth;
38 int fHeight;
Brian Osmane8e54582016-11-28 10:06:27 -050039 };
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 **/
Brian Salomonaff329b2017-08-11 09:40:37 -040066 virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
67 const SkMatrix& textureMatrix,
68 const SkRect& constraintRect,
69 FilterConstraint filterConstraint,
70 bool coordsLimitedToConstraintRect,
Brian Osman05c8f462018-10-22 17:13:36 -040071 const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -050072
Brian Salomon2a943df2018-05-04 13:43:19 -040073 /**
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).
Brian Salomon2a943df2018-05-04 13:43:19 -040085 */
86 sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
Brian Salomon2a943df2018-05-04 13:43:19 -040087 SkScalar scaleAdjust[2]);
88
Michael Ludwigddeed372019-02-20 16:50:10 -050089 sk_sp<GrTextureProxy> refTextureProxyForParams(
90 const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]);
Brian Salomon2a943df2018-05-04 13:43:19 -040091
Greg Daniel5f4b09d2018-06-12 16:39:59 -040092 /**
Brian Osmane7fd8c32018-10-19 13:30:39 -040093 * 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.
Greg Daniel5f4b09d2018-06-12 16:39:59 -040096 */
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.
Brian Osman6064e1c2018-10-19 14:27:54 -0400101 sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400102
Brian Osmane8e54582016-11-28 10:06:27 -0500103 virtual ~GrTextureProducer() {}
104
105 int width() const { return fWidth; }
106 int height() const { return fHeight; }
Brian Salomond6287472019-06-24 15:50:07 -0400107 GrColorType colorType() const { return fColorSpaceInfo.colorType(); }
Brian Salomone7499c72019-06-24 12:12:36 -0400108 SkAlphaType alphaType() const { return fColorSpaceInfo.alphaType(); }
109 SkColorSpace* colorSpace() const { return fColorSpaceInfo.colorSpace(); }
110 bool isAlphaOnly() const { return GrPixelConfigIsAlphaOnly(fColorSpaceInfo.config()); }
Michael Ludwigddeed372019-02-20 16:50:10 -0500111 bool domainNeedsDecal() const { return fDomainNeedsDecal; }
Michael Ludwiga6a84002019-04-12 15:03:02 -0400112 // If the "texture" samples multiple images that have different resolutions (e.g. YUV420)
113 virtual bool hasMixedResolutions() const { return false; }
Brian Osmane8e54582016-11-28 10:06:27 -0500114
115protected:
Robert Phillips51e7ca32017-03-27 10:14:08 -0400116 friend class GrTextureProducer_TestAccess;
117
Brian Salomone7499c72019-06-24 12:12:36 -0400118 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) {}
Brian Osmane8e54582016-11-28 10:06:27 -0500125
126 /** Helper for creating a key for a copy from an original key. */
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);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400134 builder[0] = static_cast<uint32_t>(copyParams.fFilter);
Brian Osmane8e54582016-11-28 10:06:27 -0500135 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
Brian Osman61624f02016-12-09 14:51:59 -0500145 * depends on the destination color space, then that information should also be incorporated
146 * in the key.
Brian Osmane8e54582016-11-28 10:06:27 -0500147 */
Brian Osmanb3f38302018-09-07 15:24:44 -0400148 virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -0500149
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 */
Brian Salomon238069b2018-07-11 15:58:57 -0400155 virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -0500156
157 enum DomainMode {
158 kNoDomain_DomainMode,
159 kDomain_DomainMode,
160 kTightCopy_DomainMode
161 };
162
Robert Phillips9338c602019-02-19 12:52:29 -0500163 // This can draw to accomplish the copy, thus the recording context is needed
Brian Salomond6287472019-06-24 15:50:07 -0400164 static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*,
165 sk_sp<GrTextureProxy> inputProxy,
166 GrColorType,
Greg Danielc77085d2017-11-01 16:38:48 -0400167 const CopyParams& copyParams,
Greg Daniele1da1d92017-10-06 15:59:27 -0400168 bool dstWillRequireMipMaps);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400169
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400170 static DomainMode DetermineDomainMode(const SkRect& constraintRect,
171 FilterConstraint filterConstraint,
172 bool coordsLimitedToConstraintRect,
173 GrTextureProxy*,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400174 const GrSamplerState::Filter* filterModeOrNullForBicubic,
175 SkRect* domainRect);
Robert Phillips51e7ca32017-03-27 10:14:08 -0400176
Michael Ludwigddeed372019-02-20 16:50:10 -0500177 std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter(
Brian Salomonaff329b2017-08-11 09:40:37 -0400178 sk_sp<GrTextureProxy> proxy,
Brian Salomonaff329b2017-08-11 09:40:37 -0400179 const SkMatrix& textureMatrix,
180 DomainMode,
181 const SkRect& domain,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400182 const GrSamplerState::Filter* filterOrNullForBicubic);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400183
Robert Phillips9338c602019-02-19 12:52:29 -0500184 GrRecordingContext* context() const { return fContext; }
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400185
Brian Osmane8e54582016-11-28 10:06:27 -0500186private:
Brian Salomon2a943df2018-05-04 13:43:19 -0400187 virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400188 bool willBeMipped,
Brian Salomon2a943df2018-05-04 13:43:19 -0400189 SkScalar scaleAdjust[2]) = 0;
190
Robert Phillips9338c602019-02-19 12:52:29 -0500191 GrRecordingContext* fContext;
Brian Salomone7499c72019-06-24 12:12:36 -0400192 const int fWidth;
193 const int fHeight;
194 const GrColorSpaceInfo fColorSpaceInfo;
Michael Ludwigddeed372019-02-20 16:50:10 -0500195 // If true, any domain effect uses kDecal instead of kClamp, and sampler filter uses
196 // kClampToBorder instead of kClamp.
197 const bool fDomainNeedsDecal;
Brian Osmane8e54582016-11-28 10:06:27 -0500198
199 typedef SkNoncopyable INHERITED;
200};
201
202#endif