1/*
2    Copyright 2011 Google Inc.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8         http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17#ifndef GrPaint_DEFINED
18#define GrPaint_DEFINED
19
20#include "GrTexture.h"
21#include "GrColor.h"
22#include "GrSamplerState.h"
23
24#include "SkXfermode.h"
25
26/**
27 * The paint describes how pixels are colored when the context draws to
28 * them. TODO: Make this a "real" class with getters and setters, default
29 * values, and documentation.
30 */
31class GrPaint {
32public:
33    enum {
34        kMaxTextures = 1,
35        kMaxMasks    = 1,
36    };
37
38    // All the paint fields are public except textures/samplers
39    GrBlendCoeff                fSrcBlendCoeff;
40    GrBlendCoeff                fDstBlendCoeff;
41    bool                        fAntiAlias;
42    bool                        fDither;
43
44    GrColor                     fColor;
45
46    GrColor                     fColorFilterColor;
47    SkXfermode::Mode            fColorFilterXfermode;
48
49    void setTexture(int i, GrTexture* texture) {
50        GrAssert((unsigned)i < kMaxTextures);
51        GrSafeRef(texture);
52        GrSafeUnref(fTextures[i]);
53        fTextures[i] = texture;
54    }
55
56    GrTexture* getTexture(int i) const {
57        GrAssert((unsigned)i < kMaxTextures);
58        return fTextures[i];
59    }
60
61    GrSamplerState* getTextureSampler(int i) {
62        GrAssert((unsigned)i < kMaxTextures);
63        return fTextureSamplers + i;
64    }
65
66    const GrSamplerState* getTextureSampler(int i) const {
67        GrAssert((unsigned)i < kMaxTextures);
68        return fTextureSamplers + i;
69    }
70
71    // The mask can be alpha-only or per channel. It is applied
72    // after the colorfilter
73    void setMask(int i, GrTexture* mask) {
74        GrAssert((unsigned)i < kMaxMasks);
75        GrSafeRef(mask);
76        GrSafeUnref(fMaskTextures[i]);
77        fMaskTextures[i] = mask;
78    }
79
80    GrTexture* getMask(int i) const {
81        GrAssert((unsigned)i < kMaxMasks);
82        return fMaskTextures[i];
83    }
84
85    // mask's sampler matrix is always applied to the positions
86    // (i.e. no explicit texture coordinates)
87    GrSamplerState* getMaskSampler(int i) {
88        GrAssert((unsigned)i < kMaxMasks);
89        return fMaskSamplers + i;
90    }
91
92    const GrSamplerState* getMaskSampler(int i) const {
93        GrAssert((unsigned)i < kMaxMasks);
94        return fMaskSamplers + i;
95    }
96
97    // pre-concats sampler matrices for non-NULL textures and masks
98    void preConcatActiveSamplerMatrices(const GrMatrix& matrix) {
99        for (int i = 0; i < kMaxTextures; ++i) {
100            fTextureSamplers[i].preConcatMatrix(matrix);
101        }
102        for (int i = 0; i < kMaxMasks; ++i) {
103            fMaskSamplers[i].preConcatMatrix(matrix);
104        }
105    }
106
107    // uninitialized
108    GrPaint() {
109        for (int i = 0; i < kMaxTextures; ++i) {
110            fTextures[i] = NULL;
111        }
112        for (int i = 0; i < kMaxMasks; ++i) {
113            fMaskTextures[i] = NULL;
114        }
115    }
116
117    GrPaint(const GrPaint& paint) {
118        fSrcBlendCoeff = paint.fSrcBlendCoeff;
119        fDstBlendCoeff = paint.fDstBlendCoeff;
120        fAntiAlias = paint.fAntiAlias;
121        fDither = paint.fDither;
122
123        fColor = paint.fColor;
124
125        fColorFilterColor = paint.fColorFilterColor;
126        fColorFilterXfermode = paint.fColorFilterXfermode;
127
128        for (int i = 0; i < kMaxTextures; ++i) {
129            fTextureSamplers[i] = paint.fTextureSamplers[i];
130            fTextures[i] = paint.fTextures[i];
131            GrSafeRef(fTextures[i]);
132        }
133        for (int i = 0; i < kMaxMasks; ++i) {
134            fMaskSamplers[i] = paint.fMaskSamplers[i];
135            fMaskTextures[i] = paint.fMaskTextures[i];
136            GrSafeRef(fMaskTextures[i]);
137        }
138    }
139
140    ~GrPaint() {
141        for (int i = 0; i < kMaxTextures; ++i) {
142            GrSafeUnref(fTextures[i]);
143        }
144        for (int i = 0; i < kMaxMasks; ++i) {
145            GrSafeUnref(fMaskTextures[i]);
146        }
147    }
148
149    // sets paint to src-over, solid white, no texture, no mask
150    void reset() {
151        this->resetBlend();
152        this->resetOptions();
153        this->resetColor();
154        this->resetTextures();
155        this->resetColorFilter();
156        this->resetMasks();
157    }
158
159    void resetColorFilter() {
160        fColorFilterXfermode = SkXfermode::kDst_Mode;
161        fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
162    }
163
164    bool hasTexture() const {
165        return 0 != this->getActiveTextureStageMask();
166    }
167
168    bool hasMask() const {
169        return 0 != this->getActiveMaskStageMask();
170    }
171
172    bool hasTextureOrMask() const {
173        return this->hasTexture() || this->hasMask();
174    }
175
176    // helpers for GrContext, GrTextContext
177    int getActiveTextureStageMask() const {
178        int mask = 0;
179        for (int i = 0; i < kMaxTextures; ++i) {
180            if (NULL != fTextures[i]) {
181                mask |= 1 << (i + kFirstTextureStage);
182            }
183        }
184        return mask;
185    }
186
187    int getActiveMaskStageMask() const {
188        int mask = 0;
189        for (int i = 0; i < kMaxMasks; ++i) {
190            if (NULL != fMaskTextures[i]) {
191                mask |= 1 << (i + kFirstMaskStage);
192            }
193        }
194        return mask;
195    }
196
197    int getActiveStageMask() const {
198        return this->getActiveTextureStageMask() |
199                this->getActiveMaskStageMask();
200    }
201
202    // internal use
203    // GrPaint's textures and masks map to the first N stages
204    // of GrDrawTarget in that order (textures followed by masks)
205    enum {
206        kFirstTextureStage = 0,
207        kFirstMaskStage = kMaxTextures,
208        kTotalStages = kMaxTextures + kMaxMasks,
209    };
210
211private:
212
213    GrSamplerState              fTextureSamplers[kMaxTextures];
214    GrSamplerState              fMaskSamplers[kMaxMasks];
215
216    GrTexture*      fTextures[kMaxTextures];
217    GrTexture*      fMaskTextures[kMaxMasks];
218
219    void resetBlend() {
220        fSrcBlendCoeff = kOne_BlendCoeff;
221        fDstBlendCoeff = kZero_BlendCoeff;
222    }
223
224    void resetOptions() {
225        fAntiAlias = false;
226        fDither = false;
227    }
228
229    void resetColor() {
230        fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
231    }
232
233    void resetTextures() {
234        for (int i = 0; i < kMaxTextures; ++i) {
235            this->setTexture(i, NULL);
236            fTextureSamplers[i].setClampNoFilter();
237        }
238    }
239
240    void resetMasks() {
241        for (int i = 0; i < kMaxMasks; ++i) {
242            this->setMask(i, NULL);
243            fMaskSamplers[i].setClampNoFilter();
244        }
245    }
246};
247
248#endif
249