blob: 4eb2f2d750b25aab02f03b32caae5f52ccb3199d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.com27847de2011-02-22 20:59:41 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
bsalomon@google.com27847de2011-02-22 20:59:41 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.com27847de2011-02-22 20:59:41 +000010#ifndef GrPaint_DEFINED
11#define GrPaint_DEFINED
12
13#include "GrTexture.h"
14#include "GrColor.h"
15#include "GrSamplerState.h"
16
Scroggo97c88c22011-05-11 14:05:25 +000017#include "SkXfermode.h"
18
bsalomon@google.com27847de2011-02-22 20:59:41 +000019/**
20 * The paint describes how pixels are colored when the context draws to
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000021 * them. TODO: Make this a "real" class with getters and setters, default
22 * values, and documentation.
bsalomon@google.com27847de2011-02-22 20:59:41 +000023 */
24class GrPaint {
25public:
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000026 enum {
twiz@google.com58071162012-07-18 21:41:50 +000027 kMaxTextures = 2,
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000028 kMaxMasks = 1,
29 };
bsalomon@google.com27847de2011-02-22 20:59:41 +000030
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000031 // All the paint fields are public except textures/samplers
bsalomon@google.com27847de2011-02-22 20:59:41 +000032 GrBlendCoeff fSrcBlendCoeff;
33 GrBlendCoeff fDstBlendCoeff;
34 bool fAntiAlias;
35 bool fDither;
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +000036 bool fColorMatrixEnabled;
bsalomon@google.com27847de2011-02-22 20:59:41 +000037
38 GrColor fColor;
bsalomon@google.comdd1be602012-01-18 20:34:00 +000039 uint8_t fCoverage;
bsalomon@google.com27847de2011-02-22 20:59:41 +000040
Scroggo97c88c22011-05-11 14:05:25 +000041 GrColor fColorFilterColor;
42 SkXfermode::Mode fColorFilterXfermode;
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +000043 float fColorMatrix[20];
Scroggo97c88c22011-05-11 14:05:25 +000044
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000045 void setTexture(int i, GrTexture* texture) {
46 GrAssert((unsigned)i < kMaxTextures);
bsalomon@google.com27847de2011-02-22 20:59:41 +000047 GrSafeRef(texture);
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000048 GrSafeUnref(fTextures[i]);
49 fTextures[i] = texture;
bsalomon@google.com27847de2011-02-22 20:59:41 +000050 }
51
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000052 GrTexture* getTexture(int i) const {
53 GrAssert((unsigned)i < kMaxTextures);
54 return fTextures[i];
55 }
56
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000057 GrSamplerState* textureSampler(int i) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000058 GrAssert((unsigned)i < kMaxTextures);
59 return fTextureSamplers + i;
60 }
61
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000062 const GrSamplerState& getTextureSampler(int i) const {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000063 GrAssert((unsigned)i < kMaxTextures);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000064 return fTextureSamplers[i];
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000065 }
66
tomhudson@google.comf13f5882012-06-25 17:27:28 +000067 bool isTextureStageEnabled(int i) const {
68 GrAssert((unsigned)i < kMaxTextures);
69 return (NULL != fTextures[i]) ||
70 (NULL != fTextureSamplers[i].getCustomStage());
71 }
72
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000073 // The mask can be alpha-only or per channel. It is applied
74 // after the colorfilter
75 void setMask(int i, GrTexture* mask) {
76 GrAssert((unsigned)i < kMaxMasks);
77 GrSafeRef(mask);
78 GrSafeUnref(fMaskTextures[i]);
79 fMaskTextures[i] = mask;
80 }
81
82 GrTexture* getMask(int i) const {
83 GrAssert((unsigned)i < kMaxMasks);
84 return fMaskTextures[i];
85 }
86
87 // mask's sampler matrix is always applied to the positions
88 // (i.e. no explicit texture coordinates)
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000089 GrSamplerState* maskSampler(int i) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000090 GrAssert((unsigned)i < kMaxMasks);
91 return fMaskSamplers + i;
92 }
93
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000094 const GrSamplerState& getMaskSampler(int i) const {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000095 GrAssert((unsigned)i < kMaxMasks);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000096 return fMaskSamplers[i];
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000097 }
98
tomhudson@google.comf13f5882012-06-25 17:27:28 +000099 bool isMaskStageEnabled(int i) const {
100 GrAssert((unsigned)i < kMaxTextures);
101 return (NULL != fMaskTextures[i]) ||
102 (NULL != fMaskSamplers[i].getCustomStage());
103 }
104
bsalomon@google.come3d32162012-07-20 13:37:06 +0000105 bool hasMask() const {
106 for (int i = 0; i < kMaxMasks; ++i) {
107 if (this->isMaskStageEnabled(i)) {
108 return true;
109 }
110 }
111 return false;
112 }
113
114 bool hasTexture() const {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000115 for (int i = 0; i < kMaxTextures; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000116 if (this->isTextureStageEnabled(i)) {
117 return true;
118 }
119 }
120 return false;
121 }
122
123 bool hasTextureOrMask() const { return this->hasTexture() || this->hasMask(); }
124
125 /**
126 * Preconcats the matrix of all samplers in the mask with the inverse of a
127 * matrix. If the matrix inverse cannot be computed (and there is at least
128 * one enabled stage) then false is returned.
129 */
130 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
131 GrMatrix inv;
132 bool computed = false;
133 for (int i = 0; i < kMaxTextures; ++i) {
134 if (this->isTextureStageEnabled(i)) {
135 if (!computed && !matrix.invert(&inv)) {
136 return false;
137 } else {
138 computed = true;
139 }
140 fTextureSamplers[i].preConcatMatrix(inv);
141 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000142 }
143 for (int i = 0; i < kMaxMasks; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000144 if (this->isMaskStageEnabled(i)) {
145 if (!computed && !matrix.invert(&inv)) {
146 return false;
147 } else {
148 computed = true;
149 }
150 fMaskSamplers[i].preConcatMatrix(inv);
151 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000152 }
bsalomon@google.come3d32162012-07-20 13:37:06 +0000153 return true;
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000154 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000155
156 // uninitialized
157 GrPaint() {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000158 for (int i = 0; i < kMaxTextures; ++i) {
159 fTextures[i] = NULL;
160 }
161 for (int i = 0; i < kMaxMasks; ++i) {
162 fMaskTextures[i] = NULL;
163 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000164 }
165
166 GrPaint(const GrPaint& paint) {
bsalomon@google.com27c9b6d2011-09-12 14:30:27 +0000167 for (int i = 0; i < kMaxTextures; ++i) {
168 fTextures[i] = NULL;
169 }
170 for (int i = 0; i < kMaxMasks; ++i) {
171 fMaskTextures[i] = NULL;
172 }
173 *this = paint;
174 }
175
176 GrPaint& operator=(const GrPaint& paint) {
bsalomon@google.com27847de2011-02-22 20:59:41 +0000177 fSrcBlendCoeff = paint.fSrcBlendCoeff;
178 fDstBlendCoeff = paint.fDstBlendCoeff;
179 fAntiAlias = paint.fAntiAlias;
180 fDither = paint.fDither;
181
182 fColor = paint.fColor;
bsalomon@google.comdd1be602012-01-18 20:34:00 +0000183 fCoverage = paint.fCoverage;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000184
Scroggo97c88c22011-05-11 14:05:25 +0000185 fColorFilterColor = paint.fColorFilterColor;
186 fColorFilterXfermode = paint.fColorFilterXfermode;
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000187 fColorMatrixEnabled = paint.fColorMatrixEnabled;
bsalomon@google.comdddf6f62012-03-16 17:50:37 +0000188 if (fColorMatrixEnabled) {
189 memcpy(fColorMatrix, paint.fColorMatrix, sizeof(fColorMatrix));
190 }
191
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000192 for (int i = 0; i < kMaxTextures; ++i) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000193 GrSafeAssign(fTextures[i], paint.fTextures[i]);
194 if (paint.isTextureStageEnabled(i)) {
bsalomon@google.comdddf6f62012-03-16 17:50:37 +0000195 fTextureSamplers[i] = paint.fTextureSamplers[i];
bsalomon@google.comdddf6f62012-03-16 17:50:37 +0000196 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000197 }
198 for (int i = 0; i < kMaxMasks; ++i) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000199 GrSafeAssign(fMaskTextures[i], paint.fMaskTextures[i]);
200 if (paint.isMaskStageEnabled(i)) {
bsalomon@google.comdddf6f62012-03-16 17:50:37 +0000201 fMaskSamplers[i] = paint.fMaskSamplers[i];
bsalomon@google.comdddf6f62012-03-16 17:50:37 +0000202 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000203 }
bsalomon@google.com27c9b6d2011-09-12 14:30:27 +0000204 return *this;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000205 }
206
207 ~GrPaint() {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000208 for (int i = 0; i < kMaxTextures; ++i) {
209 GrSafeUnref(fTextures[i]);
210 }
211 for (int i = 0; i < kMaxMasks; ++i) {
212 GrSafeUnref(fMaskTextures[i]);
213 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000214 }
215
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000216 // sets paint to src-over, solid white, no texture, no mask
bsalomon@google.com27847de2011-02-22 20:59:41 +0000217 void reset() {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000218 this->resetBlend();
219 this->resetOptions();
220 this->resetColor();
bsalomon@google.comdd1be602012-01-18 20:34:00 +0000221 this->resetCoverage();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000222 this->resetTextures();
223 this->resetColorFilter();
224 this->resetMasks();
Scroggo97c88c22011-05-11 14:05:25 +0000225 }
226
227 void resetColorFilter() {
228 fColorFilterXfermode = SkXfermode::kDst_Mode;
229 fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000230 fColorMatrixEnabled = false;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000231 }
232
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000233 // internal use
234 // GrPaint's textures and masks map to the first N stages
235 // of GrDrawTarget in that order (textures followed by masks)
236 enum {
237 kFirstTextureStage = 0,
238 kFirstMaskStage = kMaxTextures,
239 kTotalStages = kMaxTextures + kMaxMasks,
240 };
241
bsalomon@google.com27847de2011-02-22 20:59:41 +0000242private:
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000243
244 GrSamplerState fTextureSamplers[kMaxTextures];
245 GrSamplerState fMaskSamplers[kMaxMasks];
246
247 GrTexture* fTextures[kMaxTextures];
248 GrTexture* fMaskTextures[kMaxMasks];
bsalomon@google.com27847de2011-02-22 20:59:41 +0000249
250 void resetBlend() {
bsalomon@google.com47059542012-06-06 20:51:20 +0000251 fSrcBlendCoeff = kOne_GrBlendCoeff;
252 fDstBlendCoeff = kZero_GrBlendCoeff;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000253 }
254
255 void resetOptions() {
256 fAntiAlias = false;
257 fDither = false;
258 }
259
260 void resetColor() {
261 fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
262 }
263
bsalomon@google.comdd1be602012-01-18 20:34:00 +0000264 void resetCoverage() {
265 fCoverage = 0xff;
266 }
267
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000268 void resetTextures() {
269 for (int i = 0; i < kMaxTextures; ++i) {
270 this->setTexture(i, NULL);
bsalomon@google.com97912912011-12-06 16:30:36 +0000271 fTextureSamplers[i].reset();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000272 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000273 }
274
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000275 void resetMasks() {
276 for (int i = 0; i < kMaxMasks; ++i) {
277 this->setMask(i, NULL);
bsalomon@google.com97912912011-12-06 16:30:36 +0000278 fMaskSamplers[i].reset();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000279 }
280 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000281};
282
283#endif