blob: 467948dfa65a88116a74f35b45439d18b8d6b21e [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"
Brian Osmane8e54582016-11-28 10:06:27 -050014
Brian Salomon2bbdcc42017-09-07 12:36:34 -040015class GrContext;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040016class GrFragmentProcessor;
Brian Osmane8e54582016-11-28 10:06:27 -050017class GrTexture;
Robert Phillipsb66b42f2017-03-14 08:53:02 -040018class GrTextureProxy;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040019class SkColorSpace;
20class SkMatrix;
21struct SkRect;
Brian Osmane8e54582016-11-28 10:06:27 -050022
23/**
24 * Different GPUs and API extensions have different requirements with respect to what texture
25 * sampling parameters may be used with textures of various types. This class facilitates making
Brian Salomon2bbdcc42017-09-07 12:36:34 -040026 * texture compatible with a given GrSamplerState. There are two immediate subclasses defined
Brian Osmane8e54582016-11-28 10:06:27 -050027 * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
28 * SkImage). It supports subsetting the original texture. The other is for use cases where the
29 * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
30 */
31class GrTextureProducer : public SkNoncopyable {
32public:
33 struct CopyParams {
Brian Salomon2bbdcc42017-09-07 12:36:34 -040034 GrSamplerState::Filter fFilter;
35 int fWidth;
36 int fHeight;
Brian Osmane8e54582016-11-28 10:06:27 -050037 };
38
39 enum FilterConstraint {
40 kYes_FilterConstraint,
41 kNo_FilterConstraint,
42 };
43
44 /**
45 * Helper for creating a fragment processor to sample the texture with a given filtering mode.
46 * It attempts to avoid making texture copies or using domains whenever possible.
47 *
48 * @param textureMatrix Matrix used to access the texture. It is applied to
49 * the local coords. The post-transformed coords should
50 * be in texel units (rather than normalized) with
51 * respect to this Producer's bounds (width()/height()).
52 * @param constraintRect A rect that represents the area of the texture to be
53 * sampled. It must be contained in the Producer's
54 * bounds as defined by width()/height().
55 * @param filterConstriant Indicates whether filtering is limited to
56 * constraintRect.
57 * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
58 * by the portion of the texture indicated by
59 * constraintRect (without consideration of filter
60 * width, just the raw coords).
61 * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
62 * use bicubic filtering.
63 **/
Brian Salomonaff329b2017-08-11 09:40:37 -040064 virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
65 const SkMatrix& textureMatrix,
66 const SkRect& constraintRect,
67 FilterConstraint filterConstraint,
68 bool coordsLimitedToConstraintRect,
Brian Salomon2bbdcc42017-09-07 12:36:34 -040069 const GrSamplerState::Filter* filterOrNullForBicubic,
Brian Salomonaff329b2017-08-11 09:40:37 -040070 SkColorSpace* dstColorSpace) = 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).
84 *
85 * Places the color space of the texture in (*proxyColorSpace).
86 */
87 sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
88 SkColorSpace* dstColorSpace,
89 sk_sp<SkColorSpace>* proxyColorSpace,
90 SkScalar scaleAdjust[2]);
91
92 sk_sp<GrTextureProxy> refTextureProxyForParams(GrSamplerState::Filter filter,
93 SkColorSpace* dstColorSpace,
94 sk_sp<SkColorSpace>* proxyColorSpace,
95 SkScalar scaleAdjust[2]) {
96 return this->refTextureProxyForParams(
97 GrSamplerState(GrSamplerState::WrapMode::kClamp, filter), dstColorSpace,
98 proxyColorSpace, scaleAdjust);
99 }
100
Brian Osmane8e54582016-11-28 10:06:27 -0500101 virtual ~GrTextureProducer() {}
102
103 int width() const { return fWidth; }
104 int height() const { return fHeight; }
105 bool isAlphaOnly() const { return fIsAlphaOnly; }
106 virtual SkAlphaType alphaType() const = 0;
107
108protected:
Robert Phillips51e7ca32017-03-27 10:14:08 -0400109 friend class GrTextureProducer_TestAccess;
110
Brian Osmane8e54582016-11-28 10:06:27 -0500111 GrTextureProducer(int width, int height, bool isAlphaOnly)
112 : fWidth(width)
113 , fHeight(height)
114 , fIsAlphaOnly(isAlphaOnly) {}
115
116 /** Helper for creating a key for a copy from an original key. */
117 static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
118 const CopyParams& copyParams,
119 GrUniqueKey* copyKey) {
120 SkASSERT(!copyKey->isValid());
121 if (origKey.isValid()) {
122 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
123 GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400124 builder[0] = static_cast<uint32_t>(copyParams.fFilter);
Brian Osmane8e54582016-11-28 10:06:27 -0500125 builder[1] = copyParams.fWidth;
126 builder[2] = copyParams.fHeight;
127 }
128 }
129
130 /**
131 * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
132 * return a key that identifies its original content + the CopyParms parameter. If the producer
133 * does not want to cache the stretched version (e.g. the producer is volatile), this should
134 * simply return without initializing the copyKey. If the texture generated by this producer
Brian Osman61624f02016-12-09 14:51:59 -0500135 * depends on the destination color space, then that information should also be incorporated
136 * in the key.
Brian Osmane8e54582016-11-28 10:06:27 -0500137 */
138 virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey,
Brian Osman61624f02016-12-09 14:51:59 -0500139 SkColorSpace* dstColorSpace) = 0;
Brian Osmane8e54582016-11-28 10:06:27 -0500140
141 /**
142 * If a stretched version of the texture is generated, it may be cached (assuming that
143 * makeCopyKey() returns true). In that case, the maker is notified in case it
144 * wants to note that for when the maker is destroyed.
145 */
146 virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
147
148
149 enum DomainMode {
150 kNoDomain_DomainMode,
151 kDomain_DomainMode,
152 kTightCopy_DomainMode
153 };
154
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400155 static sk_sp<GrTextureProxy> CopyOnGpu(GrContext*, sk_sp<GrTextureProxy> inputProxy,
Greg Danielc77085d2017-11-01 16:38:48 -0400156 const CopyParams& copyParams,
Greg Daniele1da1d92017-10-06 15:59:27 -0400157 bool dstWillRequireMipMaps);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400158
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400159 static DomainMode DetermineDomainMode(const SkRect& constraintRect,
160 FilterConstraint filterConstraint,
161 bool coordsLimitedToConstraintRect,
162 GrTextureProxy*,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400163 const GrSamplerState::Filter* filterModeOrNullForBicubic,
164 SkRect* domainRect);
Robert Phillips51e7ca32017-03-27 10:14:08 -0400165
Brian Salomonaff329b2017-08-11 09:40:37 -0400166 static std::unique_ptr<GrFragmentProcessor> CreateFragmentProcessorForDomainAndFilter(
167 sk_sp<GrTextureProxy> proxy,
Brian Salomonaff329b2017-08-11 09:40:37 -0400168 const SkMatrix& textureMatrix,
169 DomainMode,
170 const SkRect& domain,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400171 const GrSamplerState::Filter* filterOrNullForBicubic);
Robert Phillipsb66b42f2017-03-14 08:53:02 -0400172
Brian Osmane8e54582016-11-28 10:06:27 -0500173private:
Brian Salomon2a943df2018-05-04 13:43:19 -0400174 virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
175 SkColorSpace* dstColorSpace,
176 sk_sp<SkColorSpace>* proxyColorSpace,
177 SkScalar scaleAdjust[2]) = 0;
178
Brian Osmane8e54582016-11-28 10:06:27 -0500179 const int fWidth;
180 const int fHeight;
181 const bool fIsAlphaOnly;
182
183 typedef SkNoncopyable INHERITED;
184};
185
186#endif