OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrConfigConversionEffect.h" | 8 #include "GrConfigConversionEffect.h" |
9 #include "GrContext.h" | 9 #include "GrContext.h" |
10 #include "GrTBackendEffectFactory.h" | 10 #include "GrTBackendProcessorFactory.h" |
11 #include "GrSimpleTextureEffect.h" | 11 #include "GrSimpleTextureEffect.h" |
12 #include "gl/GrGLEffect.h" | 12 #include "gl/GrGLProcessor.h" |
13 #include "gl/builders/GrGLProgramBuilder.h" | 13 #include "gl/builders/GrGLProgramBuilder.h" |
14 #include "SkMatrix.h" | 14 #include "SkMatrix.h" |
15 | 15 |
16 class GrGLConfigConversionEffect : public GrGLEffect { | 16 class GrGLConfigConversionEffect : public GrGLFragmentProcessor { |
17 public: | 17 public: |
18 GrGLConfigConversionEffect(const GrBackendEffectFactory& factory, | 18 GrGLConfigConversionEffect(const GrBackendProcessorFactory& factory, |
19 const GrEffect& effect) | 19 const GrProcessor& processor) |
20 : INHERITED (factory) { | 20 : INHERITED (factory) { |
21 const GrConfigConversionEffect& configConversionEffect = effect.cast<GrC
onfigConversionEffect>(); | 21 const GrConfigConversionEffect& configConversionEffect = |
| 22 processor.cast<GrConfigConversionEffect>(); |
22 fSwapRedAndBlue = configConversionEffect.swapsRedAndBlue(); | 23 fSwapRedAndBlue = configConversionEffect.swapsRedAndBlue(); |
23 fPMConversion = configConversionEffect.pmConversion(); | 24 fPMConversion = configConversionEffect.pmConversion(); |
24 } | 25 } |
25 | 26 |
26 virtual void emitCode(GrGLProgramBuilder* builder, | 27 virtual void emitCode(GrGLProgramBuilder* builder, |
27 const GrEffect&, | 28 const GrFragmentProcessor&, |
28 const GrEffectKey& key, | 29 const GrProcessorKey& key, |
29 const char* outputColor, | 30 const char* outputColor, |
30 const char* inputColor, | 31 const char* inputColor, |
31 const TransformedCoordsArray& coords, | 32 const TransformedCoordsArray& coords, |
32 const TextureSamplerArray& samplers) SK_OVERRIDE { | 33 const TextureSamplerArray& samplers) SK_OVERRIDE { |
33 // Using highp for GLES here in order to avoid some precision issues on
specific GPUs. | 34 // Using highp for GLES here in order to avoid some precision issues on
specific GPUs. |
34 GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, GrGLShaderVar::kHig
h_Precision); | 35 GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, GrGLShaderVar::kHig
h_Precision); |
35 SkString tmpDecl; | 36 SkString tmpDecl; |
36 tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl); | 37 tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl); |
37 | 38 |
38 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder
(); | 39 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder
(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 SkFAIL("Unknown conversion op."); | 78 SkFAIL("Unknown conversion op."); |
78 break; | 79 break; |
79 } | 80 } |
80 fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str()); | 81 fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str()); |
81 } | 82 } |
82 SkString modulate; | 83 SkString modulate; |
83 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); | 84 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); |
84 fsBuilder->codeAppend(modulate.c_str()); | 85 fsBuilder->codeAppend(modulate.c_str()); |
85 } | 86 } |
86 | 87 |
87 static inline void GenKey(const GrEffect& effect, const GrGLCaps&, | 88 static inline void GenKey(const GrProcessor& processor, const GrGLCaps&, |
88 GrEffectKeyBuilder* b) { | 89 GrProcessorKeyBuilder* b) { |
89 const GrConfigConversionEffect& conv = effect.cast<GrConfigConversionEff
ect>(); | 90 const GrConfigConversionEffect& conv = processor.cast<GrConfigConversion
Effect>(); |
90 uint32_t key = (conv.swapsRedAndBlue() ? 0 : 1) | (conv.pmConversion() <
< 1); | 91 uint32_t key = (conv.swapsRedAndBlue() ? 0 : 1) | (conv.pmConversion() <
< 1); |
91 b->add32(key); | 92 b->add32(key); |
92 } | 93 } |
93 | 94 |
94 private: | 95 private: |
95 bool fSwapRedAndBlue; | 96 bool fSwapRedAndBlue; |
96 GrConfigConversionEffect::PMConversion fPMConversion; | 97 GrConfigConversionEffect::PMConversion fPMConversion; |
97 | 98 |
98 typedef GrGLEffect INHERITED; | 99 typedef GrGLFragmentProcessor INHERITED; |
99 | 100 |
100 }; | 101 }; |
101 | 102 |
102 /////////////////////////////////////////////////////////////////////////////// | 103 /////////////////////////////////////////////////////////////////////////////// |
103 | 104 |
104 GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture, | 105 GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture, |
105 bool swapRedAndBlue, | 106 bool swapRedAndBlue, |
106 PMConversion pmConversion, | 107 PMConversion pmConversion, |
107 const SkMatrix& matrix) | 108 const SkMatrix& matrix) |
108 : GrSingleTextureEffect(texture, matrix) | 109 : GrSingleTextureEffect(texture, matrix) |
109 , fSwapRedAndBlue(swapRedAndBlue) | 110 , fSwapRedAndBlue(swapRedAndBlue) |
110 , fPMConversion(pmConversion) { | 111 , fPMConversion(pmConversion) { |
111 SkASSERT(kRGBA_8888_GrPixelConfig == texture->config() || | 112 SkASSERT(kRGBA_8888_GrPixelConfig == texture->config() || |
112 kBGRA_8888_GrPixelConfig == texture->config()); | 113 kBGRA_8888_GrPixelConfig == texture->config()); |
113 // Why did we pollute our texture cache instead of using a GrSingleTextureEf
fect? | 114 // Why did we pollute our texture cache instead of using a GrSingleTextureEf
fect? |
114 SkASSERT(swapRedAndBlue || kNone_PMConversion != pmConversion); | 115 SkASSERT(swapRedAndBlue || kNone_PMConversion != pmConversion); |
115 } | 116 } |
116 | 117 |
117 const GrBackendEffectFactory& GrConfigConversionEffect::getFactory() const { | 118 const GrBackendFragmentProcessorFactory& GrConfigConversionEffect::getFactory()
const { |
118 return GrTBackendEffectFactory<GrConfigConversionEffect>::getInstance(); | 119 return GrTBackendFragmentProcessorFactory<GrConfigConversionEffect>::getInst
ance(); |
119 } | 120 } |
120 | 121 |
121 bool GrConfigConversionEffect::onIsEqual(const GrEffect& s) const { | 122 bool GrConfigConversionEffect::onIsEqual(const GrProcessor& s) const { |
122 const GrConfigConversionEffect& other = s.cast<GrConfigConversionEffect>(); | 123 const GrConfigConversionEffect& other = s.cast<GrConfigConversionEffect>(); |
123 return this->texture(0) == s.texture(0) && | 124 return this->texture(0) == s.texture(0) && |
124 other.fSwapRedAndBlue == fSwapRedAndBlue && | 125 other.fSwapRedAndBlue == fSwapRedAndBlue && |
125 other.fPMConversion == fPMConversion; | 126 other.fPMConversion == fPMConversion; |
126 } | 127 } |
127 | 128 |
128 void GrConfigConversionEffect::getConstantColorComponents(GrColor* color, | 129 void GrConfigConversionEffect::getConstantColorComponents(GrColor* color, |
129 uint32_t* validFlags)
const { | 130 uint32_t* validFlags)
const { |
130 this->updateConstantColorComponentsForModulation(color, validFlags); | 131 this->updateConstantColorComponentsForModulation(color, validFlags); |
131 } | 132 } |
132 | 133 |
133 /////////////////////////////////////////////////////////////////////////////// | 134 /////////////////////////////////////////////////////////////////////////////// |
134 | 135 |
135 GR_DEFINE_EFFECT_TEST(GrConfigConversionEffect); | 136 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConfigConversionEffect); |
136 | 137 |
137 GrEffect* GrConfigConversionEffect::TestCreate(SkRandom* random, | 138 GrFragmentProcessor* GrConfigConversionEffect::TestCreate(SkRandom* random, |
138 GrContext*, | 139 GrContext*, |
139 const GrDrawTargetCaps&, | 140 const GrDrawTargetCaps
&, |
140 GrTexture* textures[]) { | 141 GrTexture* textures[])
{ |
141 PMConversion pmConv = static_cast<PMConversion>(random->nextULessThan(kPMCon
versionCnt)); | 142 PMConversion pmConv = static_cast<PMConversion>(random->nextULessThan(kPMCon
versionCnt)); |
142 bool swapRB; | 143 bool swapRB; |
143 if (kNone_PMConversion == pmConv) { | 144 if (kNone_PMConversion == pmConv) { |
144 swapRB = true; | 145 swapRB = true; |
145 } else { | 146 } else { |
146 swapRB = random->nextBool(); | 147 swapRB = random->nextBool(); |
147 } | 148 } |
148 return SkNEW_ARGS(GrConfigConversionEffect, | 149 return SkNEW_ARGS(GrConfigConversionEffect, |
149 (textures[GrEffectUnitTest::kSkiaPMTexture
Idx], | 150 (textures[GrProcessorUnitTest::kSkiaPMText
ureIdx], |
150 swapRB, | 151 swapRB, |
151 pmConv, | 152 pmConv, |
152 GrEffectUnitTest::TestMatrix(random))); | 153 GrProcessorUnitTest::TestMatrix(random)))
; |
153 } | 154 } |
154 | 155 |
155 /////////////////////////////////////////////////////////////////////////////// | 156 /////////////////////////////////////////////////////////////////////////////// |
156 void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
, | 157 void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
, |
157 PMConversion* pmTo
UPMRule, | 158 PMConversion* pmTo
UPMRule, |
158 PMConversion* upmT
oPMRule) { | 159 PMConversion* upmT
oPMRule) { |
159 *pmToUPMRule = kNone_PMConversion; | 160 *pmToUPMRule = kNone_PMConversion; |
160 *upmToPMRule = kNone_PMConversion; | 161 *upmToPMRule = kNone_PMConversion; |
161 SkAutoTMalloc<uint32_t> data(256 * 256 * 3); | 162 SkAutoTMalloc<uint32_t> data(256 * 256 * 3); |
162 uint32_t* srcData = data.get(); | 163 uint32_t* srcData = data.get(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) { | 209 for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) { |
209 *pmToUPMRule = kConversionRules[i][0]; | 210 *pmToUPMRule = kConversionRules[i][0]; |
210 *upmToPMRule = kConversionRules[i][1]; | 211 *upmToPMRule = kConversionRules[i][1]; |
211 | 212 |
212 static const SkRect kDstRect = SkRect::MakeWH(SkIntToScalar(256), SkIntT
oScalar(256)); | 213 static const SkRect kDstRect = SkRect::MakeWH(SkIntToScalar(256), SkIntT
oScalar(256)); |
213 static const SkRect kSrcRect = SkRect::MakeWH(SK_Scalar1, SK_Scalar1); | 214 static const SkRect kSrcRect = SkRect::MakeWH(SK_Scalar1, SK_Scalar1); |
214 // We do a PM->UPM draw from dataTex to readTex and read the data. Then
we do a UPM->PM draw | 215 // We do a PM->UPM draw from dataTex to readTex and read the data. Then
we do a UPM->PM draw |
215 // from readTex to tempTex followed by a PM->UPM draw to readTex and fin
ally read the data. | 216 // from readTex to tempTex followed by a PM->UPM draw to readTex and fin
ally read the data. |
216 // We then verify that two reads produced the same values. | 217 // We then verify that two reads produced the same values. |
217 | 218 |
218 SkAutoTUnref<GrEffect> pmToUPM1(SkNEW_ARGS(GrConfigConversionEffect, (da
taTex, | 219 SkAutoTUnref<GrFragmentProcessor> pmToUPM1( |
219 fa
lse, | 220 SkNEW_ARGS(GrConfigConversionEffect, |
220 *p
mToUPMRule, | 221 (dataTex, false, *pmToUPMRule, SkMatrix::I()))); |
221 Sk
Matrix::I()))); | 222 SkAutoTUnref<GrFragmentProcessor> upmToPM( |
222 SkAutoTUnref<GrEffect> upmToPM(SkNEW_ARGS(GrConfigConversionEffect, (rea
dTex, | 223 SkNEW_ARGS(GrConfigConversionEffect, |
223 fal
se, | 224 (readTex, false, *upmToPMRule, SkMatrix::I()))); |
224 *up
mToPMRule, | 225 SkAutoTUnref<GrFragmentProcessor> pmToUPM2( |
225 SkM
atrix::I()))); | 226 SkNEW_ARGS(GrConfigConversionEffect, |
226 SkAutoTUnref<GrEffect> pmToUPM2(SkNEW_ARGS(GrConfigConversionEffect, (te
mpTex, | 227 (tempTex, false, *pmToUPMRule, SkMatrix::I()))); |
227 fa
lse, | |
228 *p
mToUPMRule, | |
229 Sk
Matrix::I()))); | |
230 | 228 |
231 context->setRenderTarget(readTex->asRenderTarget()); | 229 context->setRenderTarget(readTex->asRenderTarget()); |
232 GrPaint paint1; | 230 GrPaint paint1; |
233 paint1.addColorEffect(pmToUPM1); | 231 paint1.addColorProcessor(pmToUPM1); |
234 context->drawRectToRect(paint1, kDstRect, kSrcRect); | 232 context->drawRectToRect(paint1, kDstRect, kSrcRect); |
235 | 233 |
236 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead)
; | 234 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead)
; |
237 | 235 |
238 context->setRenderTarget(tempTex->asRenderTarget()); | 236 context->setRenderTarget(tempTex->asRenderTarget()); |
239 GrPaint paint2; | 237 GrPaint paint2; |
240 paint2.addColorEffect(upmToPM); | 238 paint2.addColorProcessor(upmToPM); |
241 context->drawRectToRect(paint2, kDstRect, kSrcRect); | 239 context->drawRectToRect(paint2, kDstRect, kSrcRect); |
242 context->setRenderTarget(readTex->asRenderTarget()); | 240 context->setRenderTarget(readTex->asRenderTarget()); |
243 | 241 |
244 GrPaint paint3; | 242 GrPaint paint3; |
245 paint3.addColorEffect(pmToUPM2); | 243 paint3.addColorProcessor(pmToUPM2); |
246 context->drawRectToRect(paint3, kDstRect, kSrcRect); | 244 context->drawRectToRect(paint3, kDstRect, kSrcRect); |
247 | 245 |
248 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead
); | 246 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead
); |
249 | 247 |
250 failed = false; | 248 failed = false; |
251 for (int y = 0; y < 256 && !failed; ++y) { | 249 for (int y = 0; y < 256 && !failed; ++y) { |
252 for (int x = 0; x <= y; ++x) { | 250 for (int x = 0; x <= y; ++x) { |
253 if (firstRead[256 * y + x] != secondRead[256 * y + x]) { | 251 if (firstRead[256 * y + x] != secondRead[256 * y + x]) { |
254 failed = true; | 252 failed = true; |
255 break; | 253 break; |
256 } | 254 } |
257 } | 255 } |
258 } | 256 } |
259 } | 257 } |
260 if (failed) { | 258 if (failed) { |
261 *pmToUPMRule = kNone_PMConversion; | 259 *pmToUPMRule = kNone_PMConversion; |
262 *upmToPMRule = kNone_PMConversion; | 260 *upmToPMRule = kNone_PMConversion; |
263 } | 261 } |
264 } | 262 } |
265 | 263 |
266 const GrEffect* GrConfigConversionEffect::Create(GrTexture* texture, | 264 const GrFragmentProcessor* GrConfigConversionEffect::Create(GrTexture* texture, |
267 bool swapRedAndBlue, | 265 bool swapRedAndBlue, |
268 PMConversion pmConversion, | 266 PMConversion pmConversion, |
269 const SkMatrix& matrix) { | 267 const SkMatrix& matrix) { |
270 if (!swapRedAndBlue && kNone_PMConversion == pmConversion) { | 268 if (!swapRedAndBlue && kNone_PMConversion == pmConversion) { |
271 // If we returned a GrConfigConversionEffect that was equivalent to a Gr
SimpleTextureEffect | 269 // If we returned a GrConfigConversionEffect that was equivalent to a Gr
SimpleTextureEffect |
272 // then we may pollute our texture cache with redundant shaders. So in t
he case that no | 270 // then we may pollute our texture cache with redundant shaders. So in t
he case that no |
273 // conversions were requested we instead return a GrSimpleTextureEffect. | 271 // conversions were requested we instead return a GrSimpleTextureEffect. |
274 return GrSimpleTextureEffect::Create(texture, matrix); | 272 return GrSimpleTextureEffect::Create(texture, matrix); |
275 } else { | 273 } else { |
276 if (kRGBA_8888_GrPixelConfig != texture->config() && | 274 if (kRGBA_8888_GrPixelConfig != texture->config() && |
277 kBGRA_8888_GrPixelConfig != texture->config() && | 275 kBGRA_8888_GrPixelConfig != texture->config() && |
278 kNone_PMConversion != pmConversion) { | 276 kNone_PMConversion != pmConversion) { |
279 // The PM conversions assume colors are 0..255 | 277 // The PM conversions assume colors are 0..255 |
280 return NULL; | 278 return NULL; |
281 } | 279 } |
282 return SkNEW_ARGS(GrConfigConversionEffect, (texture, | 280 return SkNEW_ARGS(GrConfigConversionEffect, (texture, |
283 swapRedAndBlue, | 281 swapRedAndBlue, |
284 pmConversion, | 282 pmConversion, |
285 matrix)); | 283 matrix)); |
286 } | 284 } |
287 } | 285 } |
OLD | NEW |