1a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com/*
2a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com * Copyright 2012 Google Inc.
3a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com *
4a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
5a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com * found in the LICENSE file.
6a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com */
7a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
8a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com#include "GrConfigConversionEffect.h"
9b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com#include "GrContext.h"
102eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrTBackendEffectFactory.h"
1168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com#include "GrSimpleTextureEffect.h"
12d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com#include "gl/GrGLEffect.h"
13b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com#include "SkMatrix.h"
14a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.comclass GrGLConfigConversionEffect : public GrGLEffect {
16a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.compublic:
17396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com    GrGLConfigConversionEffect(const GrBackendEffectFactory& factory,
18c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com                               const GrDrawEffect& drawEffect)
1977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    : INHERITED (factory) {
20c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com        const GrConfigConversionEffect& effect = drawEffect.castEffect<GrConfigConversionEffect>();
21021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com        fSwapRedAndBlue = effect.swapsRedAndBlue();
22021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com        fPMConversion = effect.pmConversion();
23a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
24a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
2522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com    virtual void emitCode(GrGLShaderBuilder* builder,
26c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com                          const GrDrawEffect&,
27b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com                          EffectKey key,
2822a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const char* outputColor,
2922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const char* inputColor,
3077af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray& coords,
3122a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const TextureSamplerArray& samplers) SK_OVERRIDE {
32f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        builder->fsCodeAppendf("\t\t%s = ", outputColor);
3377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
34f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        builder->fsCodeAppend(";\n");
35a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
36f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(fSwapRedAndBlue);
37f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            builder->fsCodeAppendf("\t%s = %s.bgra;\n", outputColor, outputColor);
38a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        } else {
39a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
40a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            switch (fPMConversion) {
41a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
42f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                    builder->fsCodeAppendf(
43868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                        "\t\t%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);\n",
44868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                        outputColor, outputColor, swiz, outputColor, outputColor);
45a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
46a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
47b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // Add a compensation(0.001) here to avoid the side effect of the floor operation.
48b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
49b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // is less than the integer value converted from  %s.r by 1 when the %s.r is
50b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
51f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                    builder->fsCodeAppendf(
52b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                        "\t\t%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);\n",
53868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                        outputColor, outputColor, swiz, outputColor, outputColor);
54a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
55a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
56f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                    builder->fsCodeAppendf("\t\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);\n",
57868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                        outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
58a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
59a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
60f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                    builder->fsCodeAppendf("\t\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);\n",
61868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                        outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
62a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
632af1b188aa186936a78696e00170167204d9a666robertphillips@google.com                default:
6488cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org                    SkFAIL("Unknown conversion op.");
652af1b188aa186936a78696e00170167204d9a666robertphillips@google.com                    break;
66a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
67a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
68f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        SkString modulate;
69f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
70f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        builder->fsCodeAppend(modulate.c_str());
71a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
72a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
73c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
74c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com        const GrConfigConversionEffect& conv = drawEffect.castEffect<GrConfigConversionEffect>();
7577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        return static_cast<EffectKey>(conv.swapsRedAndBlue()) | (conv.pmConversion() << 1);
76a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
77a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
78a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comprivate:
79a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool                                    fSwapRedAndBlue;
80a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion  fPMConversion;
81a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
8222a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com    typedef GrGLEffect INHERITED;
83a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
84a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com};
85a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
86a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
87a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
88a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comGrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
89a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                                   bool swapRedAndBlue,
90b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com                                                   PMConversion pmConversion,
91b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com                                                   const SkMatrix& matrix)
92b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com    : GrSingleTextureEffect(texture, matrix)
93a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    , fSwapRedAndBlue(swapRedAndBlue)
94a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    , fPMConversion(pmConversion) {
95f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(kRGBA_8888_GrPixelConfig == texture->config() ||
96a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com             kBGRA_8888_GrPixelConfig == texture->config());
97a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Why did we pollute our texture cache instead of using a GrSingleTextureEffect?
98f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(swapRedAndBlue || kNone_PMConversion != pmConversion);
99a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
100a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
101396e61fe440590744345e0c56970b26ab464591dbsalomon@google.comconst GrBackendEffectFactory& GrConfigConversionEffect::getFactory() const {
102396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com    return GrTBackendEffectFactory<GrConfigConversionEffect>::getInstance();
103a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
104a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1058a252f79629b189a03de22cd8ff0312c5bccedd1bsalomon@google.combool GrConfigConversionEffect::onIsEqual(const GrEffect& s) const {
1066340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com    const GrConfigConversionEffect& other = CastEffect<GrConfigConversionEffect>(s);
1078a252f79629b189a03de22cd8ff0312c5bccedd1bsalomon@google.com    return this->texture(0) == s.texture(0) &&
10868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com           other.fSwapRedAndBlue == fSwapRedAndBlue &&
10968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com           other.fPMConversion == fPMConversion;
11068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com}
11168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
11268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.comvoid GrConfigConversionEffect::getConstantColorComponents(GrColor* color,
11368b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com                                                          uint32_t* validFlags) const {
11468b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    this->updateConstantColorComponentsForModulation(color, validFlags);
115a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
116a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
117a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
118a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
119f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrConfigConversionEffect);
120a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
121e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgGrEffectRef* GrConfigConversionEffect::TestCreate(SkRandom* random,
122e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com                                                  GrContext*,
123c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com                                                  const GrDrawTargetCaps&,
1240ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                                                  GrTexture* textures[]) {
125a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    PMConversion pmConv = static_cast<PMConversion>(random->nextULessThan(kPMConversionCnt));
126a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool swapRB;
127a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (kNone_PMConversion == pmConv) {
128a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        swapRB = true;
129a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
130a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        swapRB = random->nextBool();
131a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1326340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com    AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect,
1336340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                      (textures[GrEffectUnitTest::kSkiaPMTextureIdx],
1346340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                       swapRB,
1356340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                       pmConv,
1366340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                       GrEffectUnitTest::TestMatrix(random))));
137a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com    return CreateEffectRef(effect);
138a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
139a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
140a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
141a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context,
142a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                                              PMConversion* pmToUPMRule,
143a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                                              PMConversion* upmToPMRule) {
144a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *pmToUPMRule = kNone_PMConversion;
145a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *upmToPMRule = kNone_PMConversion;
146a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTMalloc<uint32_t> data(256 * 256 * 3);
147a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* srcData = data.get();
148a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* firstRead = data.get() + 256 * 256;
149a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* secondRead = data.get() + 2 * 256 * 256;
150a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
151a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Fill with every possible premultiplied A, color channel value. There will be 256-y duplicate
152a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // values in row y. We set r,g, and b to the same value since they are handled identically.
153a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    for (int y = 0; y < 256; ++y) {
154a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        for (int x = 0; x < 256; ++x) {
155a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
156a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            color[3] = y;
157972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[2] = SkTMin(x, y);
158972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[1] = SkTMin(x, y);
159972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[0] = SkTMin(x, y);
160a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
161a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
162a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
163a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrTextureDesc desc;
164a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fFlags = kRenderTarget_GrTextureFlagBit |
165a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                  kNoStencil_GrTextureFlagBit;
166a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fWidth = 256;
167a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fHeight = 256;
168a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fConfig = kRGBA_8888_GrPixelConfig;
169a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
170a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTUnref<GrTexture> readTex(context->createUncachedTexture(desc, NULL, 0));
171a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!readTex.get()) {
172a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
173a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
174a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTUnref<GrTexture> tempTex(context->createUncachedTexture(desc, NULL, 0));
175a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!tempTex.get()) {
176a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
177a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
178a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fFlags = kNone_GrTextureFlags;
179a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTUnref<GrTexture> dataTex(context->createUncachedTexture(desc, data, 0));
180a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!dataTex.get()) {
181a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
182a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
183a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
184a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    static const PMConversion kConversionRules[][2] = {
185a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        {kDivByAlpha_RoundDown_PMConversion, kMulByAlpha_RoundUp_PMConversion},
186a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        {kDivByAlpha_RoundUp_PMConversion, kMulByAlpha_RoundDown_PMConversion},
187a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    };
188a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
189a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
190a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
191a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool failed = true;
192a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
193972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) {
194a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *pmToUPMRule = kConversionRules[i][0];
195a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *upmToPMRule = kConversionRules[i][1];
196a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
197fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        static const SkRect kDstRect = SkRect::MakeWH(SkIntToScalar(256), SkIntToScalar(256));
198fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        static const SkRect kSrcRect = SkRect::MakeWH(SK_Scalar1, SK_Scalar1);
199a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
200a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
201a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // We then verify that two reads produced the same values.
202a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
2036340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        AutoEffectUnref pmToUPM1(SkNEW_ARGS(GrConfigConversionEffect, (dataTex,
2046340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       false,
2056340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       *pmToUPMRule,
2066340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       SkMatrix::I())));
2076340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        AutoEffectUnref upmToPM(SkNEW_ARGS(GrConfigConversionEffect, (readTex,
2086340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                      false,
2096340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                      *upmToPMRule,
2106340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                      SkMatrix::I())));
2116340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        AutoEffectUnref pmToUPM2(SkNEW_ARGS(GrConfigConversionEffect, (tempTex,
2126340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       false,
2136340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       *pmToUPMRule,
2146340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                       SkMatrix::I())));
2150ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
216a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com        SkAutoTUnref<GrEffectRef> pmToUPMEffect1(CreateEffectRef(pmToUPM1));
217a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com        SkAutoTUnref<GrEffectRef> upmToPMEffect(CreateEffectRef(upmToPM));
218a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com        SkAutoTUnref<GrEffectRef> pmToUPMEffect2(CreateEffectRef(pmToUPM2));
219a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
220a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        context->setRenderTarget(readTex->asRenderTarget());
22142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        GrPaint paint1;
22242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        paint1.addColorEffect(pmToUPMEffect1);
22342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        context->drawRectToRect(paint1, kDstRect, kSrcRect);
224a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
225a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead);
226a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
227a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        context->setRenderTarget(tempTex->asRenderTarget());
22842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        GrPaint paint2;
22942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        paint2.addColorEffect(upmToPMEffect);
23042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        context->drawRectToRect(paint2, kDstRect, kSrcRect);
231a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        context->setRenderTarget(readTex->asRenderTarget());
23242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
23342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        GrPaint paint3;
23442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        paint3.addColorEffect(pmToUPMEffect2);
23542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org        context->drawRectToRect(paint3, kDstRect, kSrcRect);
236a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
237a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead);
238a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
239a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        failed = false;
240a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        for (int y = 0; y < 256 && !failed; ++y) {
241a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            for (int x = 0; x <= y; ++x) {
242a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                if (firstRead[256 * y + x] != secondRead[256 * y + x]) {
243a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    failed = true;
244a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
245a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
246a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
247a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
248a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
249a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (failed) {
250a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *pmToUPMRule = kNone_PMConversion;
251a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *upmToPMRule = kNone_PMConversion;
252a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
253a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
254a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
255adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.comconst GrEffectRef* GrConfigConversionEffect::Create(GrTexture* texture,
256adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    bool swapRedAndBlue,
257adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    PMConversion pmConversion,
258adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    const SkMatrix& matrix) {
259a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!swapRedAndBlue && kNone_PMConversion == pmConversion) {
260adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
261a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // then we may pollute our texture cache with redundant shaders. So in the case that no
262adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        // conversions were requested we instead return a GrSimpleTextureEffect.
263adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return GrSimpleTextureEffect::Create(texture, matrix);
264a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
265a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (kRGBA_8888_GrPixelConfig != texture->config() &&
266a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            kBGRA_8888_GrPixelConfig != texture->config() &&
267a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            kNone_PMConversion != pmConversion) {
268a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // The PM conversions assume colors are 0..255
269adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com            return NULL;
270a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
2716340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect, (texture,
2726340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                     swapRedAndBlue,
2736340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                     pmConversion,
2746340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com                                                                     matrix)));
275adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return CreateEffectRef(effect);
276a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
277a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
278