summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/gpu/GrTextureProducer.h
blob: d124bf7328e414e3c1f48d8ec832541c4c61b687 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrTextureProducer_DEFINED
#define GrTextureProducer_DEFINED

#include "include/core/SkImageInfo.h"
#include "include/private/GrResourceKey.h"
#include "include/private/SkNoncopyable.h"
#include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrSamplerState.h"

class GrFragmentProcessor;
class GrRecordingContext;
class GrTexture;
class GrTextureProxy;
class SkColorSpace;
class SkMatrix;
struct SkRect;

/**
 * Different GPUs and API extensions have different requirements with respect to what texture
 * sampling parameters may be used with textures of various types. This class facilitates making
 * texture compatible with a given GrSamplerState. There are two immediate subclasses defined
 * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
 * SkImage). It supports subsetting the original texture. The other is for use cases where the
 * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
 */
class GrTextureProducer : public SkNoncopyable {
public:
    struct CopyParams {
        GrSamplerState::Filter fFilter;
        int fWidth;
        int fHeight;
    };

    enum FilterConstraint {
        kYes_FilterConstraint,
        kNo_FilterConstraint,
    };

    /**
     * Helper for creating a fragment processor to sample the texture with a given filtering mode.
     * It attempts to avoid making texture copies or using domains whenever possible.
     *
     * @param textureMatrix                    Matrix used to access the texture. It is applied to
     *                                         the local coords. The post-transformed coords should
     *                                         be in texel units (rather than normalized) with
     *                                         respect to this Producer's bounds (width()/height()).
     * @param constraintRect                   A rect that represents the area of the texture to be
     *                                         sampled. It must be contained in the Producer's
     *                                         bounds as defined by width()/height().
     * @param filterConstriant                 Indicates whether filtering is limited to
     *                                         constraintRect.
     * @param coordsLimitedToConstraintRect    Is it known that textureMatrix*localCoords is bound
     *                                         by the portion of the texture indicated by
     *                                         constraintRect (without consideration of filter
     *                                         width, just the raw coords).
     * @param filterOrNullForBicubic           If non-null indicates the filter mode. If null means
     *                                         use bicubic filtering.
     **/
    virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
            const SkMatrix& textureMatrix,
            const SkRect& constraintRect,
            FilterConstraint filterConstraint,
            bool coordsLimitedToConstraintRect,
            const GrSamplerState::Filter* filterOrNullForBicubic) = 0;

    /**
     *  Returns a texture that is safe for use with the params.
     *
     * If the size of the returned texture does not match width()/height() then the contents of the
     * original may have been scaled to fit the texture or the original may have been copied into
     * a subrect of the copy. 'scaleAdjust' must be  applied to the normalized texture coordinates
     * in order to correct for the latter case.
     *
     * If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the
     * proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird
     * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling
     * this method. (TODO: Fix this and make this function always initialize scaleAdjust).
     */
    sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
                                                   SkScalar scaleAdjust[2]);

    sk_sp<GrTextureProxy> refTextureProxyForParams(
            const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]);

    /**
     * Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
     * allocated mip map levels. This can be a performance win if future draws with the texture
     * require mip maps.
     */
    // TODO: Once we remove support for npot textures, we should add a flag for must support repeat
    // wrap mode. To support that flag now would require us to support scaleAdjust array like in
    // refTextureProxyForParams, however the current public API that uses this call does not expose
    // that array.
    sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);

    virtual ~GrTextureProducer() {}

    int width() const { return fWidth; }
    int height() const { return fHeight; }
    const GrColorInfo& colorInfo() const { return fColorInfo; }
    GrColorType colorType() const { return fColorInfo.colorType(); }
    SkAlphaType alphaType() const { return fColorInfo.alphaType(); }
    SkColorSpace* colorSpace() const { return fColorInfo.colorSpace(); }
    bool isAlphaOnly() const { return GrColorTypeIsAlphaOnly(fColorInfo.colorType()); }
    bool domainNeedsDecal() const { return fDomainNeedsDecal; }
    // If the "texture" samples multiple images that have different resolutions (e.g. YUV420)
    virtual bool hasMixedResolutions() const { return false; }

protected:
    friend class GrTextureProducer_TestAccess;

    GrTextureProducer(GrRecordingContext* context, int width, int height,
                      const GrColorInfo& colorInfo, bool domainNeedsDecal)
            : fContext(context)
            , fWidth(width)
            , fHeight(height)
            , fColorInfo(colorInfo)
            , fDomainNeedsDecal(domainNeedsDecal) {}

    /** Helper for creating a key for a copy from an original key. */
    static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
                                       const CopyParams& copyParams,
                                       GrUniqueKey* copyKey) {
        SkASSERT(!copyKey->isValid());
        if (origKey.isValid()) {
            static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
            GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
            builder[0] = static_cast<uint32_t>(copyParams.fFilter);
            builder[1] = copyParams.fWidth;
            builder[2] = copyParams.fHeight;
        }
    }

    /**
    *  If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
    *  return a key that identifies its original content + the CopyParms parameter. If the producer
    *  does not want to cache the stretched version (e.g. the producer is volatile), this should
    *  simply return without initializing the copyKey. If the texture generated by this producer
    *  depends on the destination color space, then that information should also be incorporated
    *  in the key.
    */
    virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;

    /**
    *  If a stretched version of the texture is generated, it may be cached (assuming that
    *  makeCopyKey() returns true). In that case, the maker is notified in case it
    *  wants to note that for when the maker is destroyed.
    */
    virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;

    enum DomainMode {
        kNoDomain_DomainMode,
        kDomain_DomainMode,
        kTightCopy_DomainMode
    };

    // This can draw to accomplish the copy, thus the recording context is needed
    static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*,
                                           sk_sp<GrTextureProxy> inputProxy,
                                           GrColorType,
                                           const CopyParams& copyParams,
                                           bool dstWillRequireMipMaps);

    static DomainMode DetermineDomainMode(const SkRect& constraintRect,
                                          FilterConstraint filterConstraint,
                                          bool coordsLimitedToConstraintRect,
                                          GrTextureProxy*,
                                          const GrSamplerState::Filter* filterModeOrNullForBicubic,
                                          SkRect* domainRect);

    std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter(
            sk_sp<GrTextureProxy> proxy,
            const SkMatrix& textureMatrix,
            DomainMode,
            const SkRect& domain,
            const GrSamplerState::Filter* filterOrNullForBicubic);

    GrRecordingContext* context() const { return fContext; }

private:
    virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
                                                             bool willBeMipped,
                                                             SkScalar scaleAdjust[2]) = 0;

    GrRecordingContext* fContext;
    const int fWidth;
    const int fHeight;
    const GrColorInfo fColorInfo;
    // If true, any domain effect uses kDecal instead of kClamp, and sampler filter uses
    // kClampToBorder instead of kClamp.
    const bool  fDomainNeedsDecal;

    typedef SkNoncopyable INHERITED;
};

#endif