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"
10ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips#include "GrDrawContext.h"
11605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
1268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com#include "GrSimpleTextureEffect.h"
13eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkMatrix.h"
1464c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h"
152d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h"
16a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1764c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLConfigConversionEffect : public GrGLSLFragmentProcessor {
18a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.compublic:
199cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips    void emitCode(EmitArgs& args) override {
206c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        const GrConfigConversionEffect& cce = args.fFp.cast<GrConfigConversionEffect>();
216c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        const GrSwizzle& swizzle = cce.swizzle();
226c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        GrConfigConversionEffect::PMConversion pmConversion = cce.pmConversion();
236c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon
24cecc91c4446c9c2f9b95736e206bfd1d507a75a9changjun.yang        // Using highp for GLES here in order to avoid some precision issues on specific GPUs.
250d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
26cecc91c4446c9c2f9b95736e206bfd1d507a75a9changjun.yang        SkString tmpDecl;
27a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel        tmpVar.appendDecl(args.fGLSLCaps, &tmpDecl);
28cecc91c4446c9c2f9b95736e206bfd1d507a75a9changjun.yang
298528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
3030ba436f04e61d4505fb854d5fc56079636e0788joshualitt
314ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf("%s;", tmpDecl.c_str());
3230ba436f04e61d4505fb854d5fc56079636e0788joshualitt
334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf("%s = ", tmpVar.c_str());
344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
357c157a988845fb00f9024d6db6dda142c3458033wangyix                                       args.fCoords[0].getType());
364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppend(";");
37cecc91c4446c9c2f9b95736e206bfd1d507a75a9changjun.yang
386c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        if (GrConfigConversionEffect::kNone_PMConversion == pmConversion) {
396c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon            SkASSERT(GrSwizzle::RGBA() != swizzle);
406c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon            fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
416c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                                     swizzle.c_str());
42a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        } else {
436c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon            switch (pmConversion) {
44a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
454ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf(
466c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        "%s = vec4(ceil(%s.rgb * %s.a * 255.0) / 255.0, %s.a);",
476c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());
48a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
49a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
50b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // Add a compensation(0.001) here to avoid the side effect of the floor operation.
51b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
52b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // is less than the integer value converted from  %s.r by 1 when the %s.r is
53b4e200ec6bafd2a2ebbc5c73a954136acd4b587dcommit-bot@chromium.org                    // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf(
556c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        "%s = vec4(floor(%s.rgb * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
566c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());
576c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon
58a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
59a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf(
616c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
626c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
636c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str());
64a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
65a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
664ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf(
676c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
686c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
696c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                        tmpVar.c_str());
70a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
712af1b188aa186936a78696e00170167204d9a666robertphillips@google.com                default:
7288cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org                    SkFAIL("Unknown conversion op.");
732af1b188aa186936a78696e00170167204d9a666robertphillips@google.com                    break;
74a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
756c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon            fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
766c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                                     swizzle.c_str());
77a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
78f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        SkString modulate;
797c157a988845fb00f9024d6db6dda142c3458033wangyix        GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
804ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppend(modulate.c_str());
81a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
82a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
83cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&,
84b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
856c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        const GrConfigConversionEffect& cce = processor.cast<GrConfigConversionEffect>();
866c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        uint32_t key = (cce.swizzle().asKey()) | (cce.pmConversion() << 16);
8763e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon        b->add32(key);
88a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
89a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
90a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comprivate:
9164c4728c70001ed074fecf5c4e083781987b12e9egdaniel    typedef GrGLSLFragmentProcessor INHERITED;
92a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
93a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com};
94a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
95a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
96a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
974a339529612a43871d021877e58698e067d6c4cdbsalomonGrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
986c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                                                   const GrSwizzle& swizzle,
99b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com                                                   PMConversion pmConversion,
100b1456d70100d309c852906fafab006fae63de53ebsalomon@google.com                                                   const SkMatrix& matrix)
1014a339529612a43871d021877e58698e067d6c4cdbsalomon    : INHERITED(texture, matrix)
1026c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    , fSwizzle(swizzle)
103a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    , fPMConversion(pmConversion) {
104eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    this->initClassID<GrConfigConversionEffect>();
105445fc43b9d59b53845254065feb905732cdde110bsalomon    // We expect to get here with non-BGRA/RGBA only if we're doing not doing a premul/unpremul
106445fc43b9d59b53845254065feb905732cdde110bsalomon    // conversion.
107445fc43b9d59b53845254065feb905732cdde110bsalomon    SkASSERT((kRGBA_8888_GrPixelConfig == texture->config() ||
108445fc43b9d59b53845254065feb905732cdde110bsalomon              kBGRA_8888_GrPixelConfig == texture->config()) ||
109445fc43b9d59b53845254065feb905732cdde110bsalomon              kNone_PMConversion == pmConversion);
110a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Why did we pollute our texture cache instead of using a GrSingleTextureEffect?
1116c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    SkASSERT(swizzle != GrSwizzle::RGBA() || kNone_PMConversion != pmConversion);
112a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
113a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1140e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrConfigConversionEffect::onIsEqual(const GrFragmentProcessor& s) const {
11549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrConfigConversionEffect& other = s.cast<GrConfigConversionEffect>();
1166c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    return other.fSwizzle == fSwizzle &&
11768b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com           other.fPMConversion == fPMConversion;
11868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com}
11968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
120605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrConfigConversionEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
1211a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    this->updateInvariantOutputForModulation(inout);
122a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
123a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
124a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
125a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
126b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConfigConversionEffect);
127a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
128c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* GrConfigConversionEffect::TestCreate(GrProcessorTestData* d) {
1290067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    PMConversion pmConv = static_cast<PMConversion>(d->fRandom->nextULessThan(kPMConversionCnt));
1306c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    GrSwizzle swizzle;
1316c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    do {
1326c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        swizzle = GrSwizzle::CreateRandom(d->fRandom);
1336c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    } while (pmConv == kNone_PMConversion && swizzle == GrSwizzle::RGBA());
1344a339529612a43871d021877e58698e067d6c4cdbsalomon    return new GrConfigConversionEffect(d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx],
1356c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                                        swizzle, pmConv, GrTest::TestMatrix(d->fRandom));
136a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
137a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
138a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
139eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
14057d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrConfigConversionEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
14157d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                                     GrProcessorKeyBuilder* b) const {
142eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLConfigConversionEffect::GenKey(*this, caps, b);
143eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
144eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
14557d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrConfigConversionEffect::onCreateGLSLInstance() const {
1466c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    return new GrGLConfigConversionEffect();
147eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
148eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
149e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips
150e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips
151a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context,
152a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                                              PMConversion* pmToUPMRule,
153a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                                              PMConversion* upmToPMRule) {
154a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *pmToUPMRule = kNone_PMConversion;
155a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *upmToPMRule = kNone_PMConversion;
156a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTMalloc<uint32_t> data(256 * 256 * 3);
157a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* srcData = data.get();
158a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* firstRead = data.get() + 256 * 256;
159a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    uint32_t* secondRead = data.get() + 2 * 256 * 256;
160a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
161a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Fill with every possible premultiplied A, color channel value. There will be 256-y duplicate
162a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // values in row y. We set r,g, and b to the same value since they are handled identically.
163a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    for (int y = 0; y < 256; ++y) {
164a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        for (int x = 0; x < 256; ++x) {
165a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
166a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            color[3] = y;
167972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[2] = SkTMin(x, y);
168972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[1] = SkTMin(x, y);
169972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            color[0] = SkTMin(x, y);
170a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
171a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
172a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
173f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc desc;
1746bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    desc.fFlags = kRenderTarget_GrSurfaceFlag;
175a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fWidth = 256;
176a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fHeight = 256;
177a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fConfig = kRGBA_8888_GrPixelConfig;
178a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1795ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    SkAutoTUnref<GrTexture> readTex(context->textureProvider()->createTexture(
1805ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        desc, SkBudgeted::kYes, nullptr, 0));
181a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!readTex.get()) {
182a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
183a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1845ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    SkAutoTUnref<GrTexture> tempTex(context->textureProvider()->createTexture(
1855ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        desc, SkBudgeted::kYes, nullptr, 0));
186a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!tempTex.get()) {
187a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
188a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
189f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    desc.fFlags = kNone_GrSurfaceFlags;
1905ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    SkAutoTUnref<GrTexture> dataTex(context->textureProvider()->createTexture(
1915ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        desc, SkBudgeted::kYes, data, 0));
192a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!dataTex.get()) {
193a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return;
194a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
195a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
196a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    static const PMConversion kConversionRules[][2] = {
197a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        {kDivByAlpha_RoundDown_PMConversion, kMulByAlpha_RoundUp_PMConversion},
198a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        {kDivByAlpha_RoundUp_PMConversion, kMulByAlpha_RoundDown_PMConversion},
199a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    };
200a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
201a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool failed = true;
202a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
203972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) {
204a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *pmToUPMRule = kConversionRules[i][0];
205a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *upmToPMRule = kConversionRules[i][1];
206a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
207fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        static const SkRect kDstRect = SkRect::MakeWH(SkIntToScalar(256), SkIntToScalar(256));
208fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        static const SkRect kSrcRect = SkRect::MakeWH(SK_Scalar1, SK_Scalar1);
209a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
210a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
211a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // We then verify that two reads produced the same values.
212a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
2135f10b5c1b5744106312e24835d235b72fdba5802joshualitt        GrPaint paint1;
2145f10b5c1b5744106312e24835d235b72fdba5802joshualitt        GrPaint paint2;
2155f10b5c1b5744106312e24835d235b72fdba5802joshualitt        GrPaint paint3;
216385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        SkAutoTUnref<GrFragmentProcessor> pmToUPM1(new GrConfigConversionEffect(
2176c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                dataTex, GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
218385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        SkAutoTUnref<GrFragmentProcessor> upmToPM(new GrConfigConversionEffect(
2196c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                readTex, GrSwizzle::RGBA(), *upmToPMRule, SkMatrix::I()));
220385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        SkAutoTUnref<GrFragmentProcessor> pmToUPM2(new GrConfigConversionEffect(
2216c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                tempTex, GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
222a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
223ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon        paint1.addColorFragmentProcessor(pmToUPM1);
224c4b72720e75313079212e69e46a5ef7c474b2305egdaniel        paint1.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
225ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
226ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
22777a2e52c7d5c77de73ecab5fec79072ee4460706robertphillips        SkAutoTUnref<GrDrawContext> readDrawContext(
22877a2e52c7d5c77de73ecab5fec79072ee4460706robertphillips                                    context->drawContext(readTex->asRenderTarget()));
229ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        if (!readDrawContext) {
230ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            failed = true;
231ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            break;
232ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        }
233ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
234a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon        readDrawContext->fillRectToRect(GrClip::WideOpen(),
235a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        paint1,
236a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        SkMatrix::I(),
237a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kDstRect,
238a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kSrcRect);
239a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
240a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead);
241a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
242ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon        paint2.addColorFragmentProcessor(upmToPM);
243c4b72720e75313079212e69e46a5ef7c474b2305egdaniel        paint2.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
244ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
24577a2e52c7d5c77de73ecab5fec79072ee4460706robertphillips        SkAutoTUnref<GrDrawContext> tempDrawContext(
24677a2e52c7d5c77de73ecab5fec79072ee4460706robertphillips                                    context->drawContext(tempTex->asRenderTarget()));
247ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        if (!tempDrawContext) {
248ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            failed = true;
249ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            break;
250ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        }
251a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon        tempDrawContext->fillRectToRect(GrClip::WideOpen(),
252a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        paint2,
253a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        SkMatrix::I(),
254a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kDstRect,
255a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kSrcRect);
25642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
257ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon        paint3.addColorFragmentProcessor(pmToUPM2);
258c4b72720e75313079212e69e46a5ef7c474b2305egdaniel        paint3.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
259ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
2602e1e51f04985f7c258b96f0decc190456f5dd74drobertphillips        readDrawContext.reset(context->drawContext(readTex->asRenderTarget()));
261ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        if (!readDrawContext) {
262ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            failed = true;
263ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips            break;
264ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips        }
265ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips
266a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon        readDrawContext->fillRectToRect(GrClip::WideOpen(),
267a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        paint3,
268a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        SkMatrix::I(),
269a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kDstRect,
270a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon                                        kSrcRect);
271a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
272a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead);
273a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
274a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        failed = false;
275a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        for (int y = 0; y < 256 && !failed; ++y) {
276a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            for (int x = 0; x <= y; ++x) {
277a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                if (firstRead[256 * y + x] != secondRead[256 * y + x]) {
278a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    failed = true;
279a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    break;
280a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
281a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
282a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
283a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
284a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (failed) {
285a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *pmToUPMRule = kNone_PMConversion;
286a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        *upmToPMRule = kNone_PMConversion;
287a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
288a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
289a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
2904a339529612a43871d021877e58698e067d6c4cdbsalomonconst GrFragmentProcessor* GrConfigConversionEffect::Create(GrTexture* texture,
2916c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon                                                            const GrSwizzle& swizzle,
2925f10b5c1b5744106312e24835d235b72fdba5802joshualitt                                                            PMConversion pmConversion,
2935f10b5c1b5744106312e24835d235b72fdba5802joshualitt                                                            const SkMatrix& matrix) {
2946c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon    if (swizzle == GrSwizzle::RGBA() && kNone_PMConversion == pmConversion) {
295adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
296a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // then we may pollute our texture cache with redundant shaders. So in the case that no
297adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        // conversions were requested we instead return a GrSimpleTextureEffect.
2984a339529612a43871d021877e58698e067d6c4cdbsalomon        return GrSimpleTextureEffect::Create(texture, matrix);
299a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
300a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (kRGBA_8888_GrPixelConfig != texture->config() &&
301a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            kBGRA_8888_GrPixelConfig != texture->config() &&
302a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            kNone_PMConversion != pmConversion) {
303a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // The PM conversions assume colors are 0..255
30496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
305a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
3066c9cd55f00beeba3ded3f28bcbdd6ef030c4dac7bsalomon        return new GrConfigConversionEffect(texture, swizzle, pmConversion, matrix);
307a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
308a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
309