1/*
2 * Copyright 2012 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 GrTextureAccess_DEFINED
9#define GrTextureAccess_DEFINED
10
11#include "SkRefCnt.h"
12#include "SkShader.h"
13#include "SkTypes.h"
14
15class GrTexture;
16
17/**
18 * Represents the filtering and tile modes used to access a texture. It is mostly used with
19 * GrTextureAccess (defined below). Also, some of the texture cache methods require knowledge about
20 * filtering and tiling to perform a cache lookup. If it wasn't for this latter usage this would
21 * be folded into GrTextureAccess. The default is clamp tile modes and no filtering.
22 */
23class GrTextureParams {
24public:
25    GrTextureParams() {
26        this->reset();
27    }
28
29    enum FilterMode {
30        kNone_FilterMode,
31        kBilerp_FilterMode,
32        kMipMap_FilterMode
33    };
34
35    GrTextureParams(SkShader::TileMode tileXAndY, FilterMode filterMode) {
36        this->reset(tileXAndY, filterMode);
37    }
38
39    GrTextureParams(const SkShader::TileMode tileModes[2], FilterMode filterMode) {
40        this->reset(tileModes, filterMode);
41    }
42
43    GrTextureParams(const GrTextureParams& params) {
44        *this = params;
45    }
46
47    GrTextureParams& operator= (const GrTextureParams& params) {
48        fTileModes[0] = params.fTileModes[0];
49        fTileModes[1] = params.fTileModes[1];
50        fFilterMode = params.fFilterMode;
51        return *this;
52    }
53
54    void reset() {
55        this->reset(SkShader::kClamp_TileMode, kNone_FilterMode);
56    }
57
58    void reset(SkShader::TileMode tileXAndY, FilterMode filterMode) {
59        fTileModes[0] = fTileModes[1] = tileXAndY;
60        fFilterMode = filterMode;
61    }
62
63    void reset(const SkShader::TileMode tileModes[2], FilterMode filterMode) {
64        fTileModes[0] = tileModes[0];
65        fTileModes[1] = tileModes[1];
66        fFilterMode = filterMode;
67    }
68
69    void setClampNoFilter() {
70        fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
71        fFilterMode = kNone_FilterMode;
72    }
73
74    void setClamp() {
75        fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
76    }
77
78    void setFilterMode(FilterMode filterMode) { fFilterMode = filterMode; }
79
80    void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; }
81    void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; }
82    void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; }
83
84    SkShader::TileMode getTileModeX() const { return fTileModes[0]; }
85
86    SkShader::TileMode getTileModeY() const { return fTileModes[1]; }
87
88    bool isTiled() const {
89        return SkShader::kClamp_TileMode != fTileModes[0] ||
90               SkShader::kClamp_TileMode != fTileModes[1];
91    }
92
93    FilterMode filterMode() const { return fFilterMode; }
94
95    bool operator== (const GrTextureParams& other) const {
96        return fTileModes[0] == other.fTileModes[0] &&
97               fTileModes[1] == other.fTileModes[1] &&
98               fFilterMode == other.fFilterMode;
99    }
100
101    bool operator!= (const GrTextureParams& other) const { return !(*this == other); }
102
103private:
104
105    SkShader::TileMode fTileModes[2];
106    FilterMode         fFilterMode;
107};
108
109/** A class representing the swizzle access pattern for a texture. Note that if the texture is
110 *  an alpha-only texture then the alpha channel is substituted for other components. Any mangling
111 *  to handle the r,g,b->a conversions for alpha textures is automatically included in the stage
112 *  key. However, if a GrEffect uses different swizzles based on its input then it must
113 *  consider that variation in its key-generation.
114 */
115class GrTextureAccess : SkNoncopyable {
116public:
117    /**
118     * A default GrTextureAccess must have reset() called on it in a GrEffect subclass's
119     * constructor if it will be accessible via GrEffect::textureAccess().
120     */
121    GrTextureAccess();
122
123    /**
124     * Uses the default swizzle, "rgba".
125     */
126    GrTextureAccess(GrTexture*, const GrTextureParams&);
127    explicit GrTextureAccess(GrTexture*,
128                             GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
129                             SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
130
131    /**
132     * swizzle must be a string between one and four (inclusive) characters containing only 'r',
133     * 'g', 'b',  and/or 'a'.
134     */
135    GrTextureAccess(GrTexture*, const char* swizzle, const GrTextureParams&);
136    GrTextureAccess(GrTexture*,
137                    const char* swizzle,
138                    GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
139                    SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
140
141    void reset(GrTexture*, const GrTextureParams&);
142    void reset(GrTexture*,
143               GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
144               SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
145    void reset(GrTexture*, const char* swizzle, const GrTextureParams&);
146    void reset(GrTexture*,
147               const char* swizzle,
148               GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
149               SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
150
151    bool operator== (const GrTextureAccess& other) const {
152#ifdef SK_DEBUG
153        // below assumes all chars in fSwizzle are initialized even if string is < 4 chars long.
154        SkASSERT(memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1) ==
155                 strcmp(fSwizzle, other.fSwizzle));
156#endif
157        return fParams == other.fParams &&
158               (fTexture.get() == other.fTexture.get()) &&
159               (0 == memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1));
160    }
161
162    bool operator!= (const GrTextureAccess& other) const { return !(*this == other); }
163
164    GrTexture* getTexture() const { return fTexture.get(); }
165
166    /**
167     * Returns a string representing the swizzle. The string is is null-terminated.
168     */
169    const char* getSwizzle() const { return fSwizzle; }
170
171    /** Returns a mask indicating which components are referenced in the swizzle. The return
172        is a bitfield of GrColorComponentFlags. */
173    uint32_t swizzleMask() const { return fSwizzleMask; }
174
175    const GrTextureParams& getParams() const { return fParams; }
176
177private:
178    void setSwizzle(const char*);
179
180    GrTextureParams         fParams;
181    SkAutoTUnref<GrTexture> fTexture;
182    uint32_t                fSwizzleMask;
183    char                    fSwizzle[5];
184
185    typedef SkNoncopyable INHERITED;
186};
187
188#endif
189