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