gfx/skia/trunk/src/gpu/effects/GrConfigConversionEffect.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2012 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "GrConfigConversionEffect.h"
michael@0 9 #include "GrContext.h"
michael@0 10 #include "GrTBackendEffectFactory.h"
michael@0 11 #include "GrSimpleTextureEffect.h"
michael@0 12 #include "gl/GrGLEffect.h"
michael@0 13 #include "SkMatrix.h"
michael@0 14
michael@0 15 class GrGLConfigConversionEffect : public GrGLEffect {
michael@0 16 public:
michael@0 17 GrGLConfigConversionEffect(const GrBackendEffectFactory& factory,
michael@0 18 const GrDrawEffect& drawEffect)
michael@0 19 : INHERITED (factory) {
michael@0 20 const GrConfigConversionEffect& effect = drawEffect.castEffect<GrConfigConversionEffect>();
michael@0 21 fSwapRedAndBlue = effect.swapsRedAndBlue();
michael@0 22 fPMConversion = effect.pmConversion();
michael@0 23 }
michael@0 24
michael@0 25 virtual void emitCode(GrGLShaderBuilder* builder,
michael@0 26 const GrDrawEffect&,
michael@0 27 EffectKey key,
michael@0 28 const char* outputColor,
michael@0 29 const char* inputColor,
michael@0 30 const TransformedCoordsArray& coords,
michael@0 31 const TextureSamplerArray& samplers) SK_OVERRIDE {
michael@0 32 builder->fsCodeAppendf("\t\t%s = ", outputColor);
michael@0 33 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
michael@0 34 builder->fsCodeAppend(";\n");
michael@0 35 if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
michael@0 36 SkASSERT(fSwapRedAndBlue);
michael@0 37 builder->fsCodeAppendf("\t%s = %s.bgra;\n", outputColor, outputColor);
michael@0 38 } else {
michael@0 39 const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
michael@0 40 switch (fPMConversion) {
michael@0 41 case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
michael@0 42 builder->fsCodeAppendf(
michael@0 43 "\t\t%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);\n",
michael@0 44 outputColor, outputColor, swiz, outputColor, outputColor);
michael@0 45 break;
michael@0 46 case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
michael@0 47 // Add a compensation(0.001) here to avoid the side effect of the floor operation.
michael@0 48 // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
michael@0 49 // is less than the integer value converted from %s.r by 1 when the %s.r is
michael@0 50 // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
michael@0 51 builder->fsCodeAppendf(
michael@0 52 "\t\t%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);\n",
michael@0 53 outputColor, outputColor, swiz, outputColor, outputColor);
michael@0 54 break;
michael@0 55 case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
michael@0 56 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",
michael@0 57 outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
michael@0 58 break;
michael@0 59 case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
michael@0 60 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",
michael@0 61 outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
michael@0 62 break;
michael@0 63 default:
michael@0 64 GrCrash("Unknown conversion op.");
michael@0 65 break;
michael@0 66 }
michael@0 67 }
michael@0 68 SkString modulate;
michael@0 69 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
michael@0 70 builder->fsCodeAppend(modulate.c_str());
michael@0 71 }
michael@0 72
michael@0 73 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
michael@0 74 const GrConfigConversionEffect& conv = drawEffect.castEffect<GrConfigConversionEffect>();
michael@0 75 return static_cast<EffectKey>(conv.swapsRedAndBlue()) | (conv.pmConversion() << 1);
michael@0 76 }
michael@0 77
michael@0 78 private:
michael@0 79 bool fSwapRedAndBlue;
michael@0 80 GrConfigConversionEffect::PMConversion fPMConversion;
michael@0 81
michael@0 82 typedef GrGLEffect INHERITED;
michael@0 83
michael@0 84 };
michael@0 85
michael@0 86 ///////////////////////////////////////////////////////////////////////////////
michael@0 87
michael@0 88 GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
michael@0 89 bool swapRedAndBlue,
michael@0 90 PMConversion pmConversion,
michael@0 91 const SkMatrix& matrix)
michael@0 92 : GrSingleTextureEffect(texture, matrix)
michael@0 93 , fSwapRedAndBlue(swapRedAndBlue)
michael@0 94 , fPMConversion(pmConversion) {
michael@0 95 SkASSERT(kRGBA_8888_GrPixelConfig == texture->config() ||
michael@0 96 kBGRA_8888_GrPixelConfig == texture->config());
michael@0 97 // Why did we pollute our texture cache instead of using a GrSingleTextureEffect?
michael@0 98 SkASSERT(swapRedAndBlue || kNone_PMConversion != pmConversion);
michael@0 99 }
michael@0 100
michael@0 101 const GrBackendEffectFactory& GrConfigConversionEffect::getFactory() const {
michael@0 102 return GrTBackendEffectFactory<GrConfigConversionEffect>::getInstance();
michael@0 103 }
michael@0 104
michael@0 105 bool GrConfigConversionEffect::onIsEqual(const GrEffect& s) const {
michael@0 106 const GrConfigConversionEffect& other = CastEffect<GrConfigConversionEffect>(s);
michael@0 107 return this->texture(0) == s.texture(0) &&
michael@0 108 other.fSwapRedAndBlue == fSwapRedAndBlue &&
michael@0 109 other.fPMConversion == fPMConversion;
michael@0 110 }
michael@0 111
michael@0 112 void GrConfigConversionEffect::getConstantColorComponents(GrColor* color,
michael@0 113 uint32_t* validFlags) const {
michael@0 114 this->updateConstantColorComponentsForModulation(color, validFlags);
michael@0 115 }
michael@0 116
michael@0 117 ///////////////////////////////////////////////////////////////////////////////
michael@0 118
michael@0 119 GR_DEFINE_EFFECT_TEST(GrConfigConversionEffect);
michael@0 120
michael@0 121 GrEffectRef* GrConfigConversionEffect::TestCreate(SkRandom* random,
michael@0 122 GrContext*,
michael@0 123 const GrDrawTargetCaps&,
michael@0 124 GrTexture* textures[]) {
michael@0 125 PMConversion pmConv = static_cast<PMConversion>(random->nextULessThan(kPMConversionCnt));
michael@0 126 bool swapRB;
michael@0 127 if (kNone_PMConversion == pmConv) {
michael@0 128 swapRB = true;
michael@0 129 } else {
michael@0 130 swapRB = random->nextBool();
michael@0 131 }
michael@0 132 AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect,
michael@0 133 (textures[GrEffectUnitTest::kSkiaPMTextureIdx],
michael@0 134 swapRB,
michael@0 135 pmConv,
michael@0 136 GrEffectUnitTest::TestMatrix(random))));
michael@0 137 return CreateEffectRef(effect);
michael@0 138 }
michael@0 139
michael@0 140 ///////////////////////////////////////////////////////////////////////////////
michael@0 141 void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context,
michael@0 142 PMConversion* pmToUPMRule,
michael@0 143 PMConversion* upmToPMRule) {
michael@0 144 *pmToUPMRule = kNone_PMConversion;
michael@0 145 *upmToPMRule = kNone_PMConversion;
michael@0 146 SkAutoTMalloc<uint32_t> data(256 * 256 * 3);
michael@0 147 uint32_t* srcData = data.get();
michael@0 148 uint32_t* firstRead = data.get() + 256 * 256;
michael@0 149 uint32_t* secondRead = data.get() + 2 * 256 * 256;
michael@0 150
michael@0 151 // Fill with every possible premultiplied A, color channel value. There will be 256-y duplicate
michael@0 152 // values in row y. We set r,g, and b to the same value since they are handled identically.
michael@0 153 for (int y = 0; y < 256; ++y) {
michael@0 154 for (int x = 0; x < 256; ++x) {
michael@0 155 uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
michael@0 156 color[3] = y;
michael@0 157 color[2] = GrMin(x, y);
michael@0 158 color[1] = GrMin(x, y);
michael@0 159 color[0] = GrMin(x, y);
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 GrTextureDesc desc;
michael@0 164 desc.fFlags = kRenderTarget_GrTextureFlagBit |
michael@0 165 kNoStencil_GrTextureFlagBit;
michael@0 166 desc.fWidth = 256;
michael@0 167 desc.fHeight = 256;
michael@0 168 desc.fConfig = kRGBA_8888_GrPixelConfig;
michael@0 169
michael@0 170 SkAutoTUnref<GrTexture> readTex(context->createUncachedTexture(desc, NULL, 0));
michael@0 171 if (!readTex.get()) {
michael@0 172 return;
michael@0 173 }
michael@0 174 SkAutoTUnref<GrTexture> tempTex(context->createUncachedTexture(desc, NULL, 0));
michael@0 175 if (!tempTex.get()) {
michael@0 176 return;
michael@0 177 }
michael@0 178 desc.fFlags = kNone_GrTextureFlags;
michael@0 179 SkAutoTUnref<GrTexture> dataTex(context->createUncachedTexture(desc, data, 0));
michael@0 180 if (!dataTex.get()) {
michael@0 181 return;
michael@0 182 }
michael@0 183
michael@0 184 static const PMConversion kConversionRules[][2] = {
michael@0 185 {kDivByAlpha_RoundDown_PMConversion, kMulByAlpha_RoundUp_PMConversion},
michael@0 186 {kDivByAlpha_RoundUp_PMConversion, kMulByAlpha_RoundDown_PMConversion},
michael@0 187 };
michael@0 188
michael@0 189 GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
michael@0 190
michael@0 191 bool failed = true;
michael@0 192
michael@0 193 for (size_t i = 0; i < GR_ARRAY_COUNT(kConversionRules) && failed; ++i) {
michael@0 194 *pmToUPMRule = kConversionRules[i][0];
michael@0 195 *upmToPMRule = kConversionRules[i][1];
michael@0 196
michael@0 197 static const SkRect kDstRect = SkRect::MakeWH(SkIntToScalar(256), SkIntToScalar(256));
michael@0 198 static const SkRect kSrcRect = SkRect::MakeWH(SK_Scalar1, SK_Scalar1);
michael@0 199 // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
michael@0 200 // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
michael@0 201 // We then verify that two reads produced the same values.
michael@0 202
michael@0 203 AutoEffectUnref pmToUPM1(SkNEW_ARGS(GrConfigConversionEffect, (dataTex,
michael@0 204 false,
michael@0 205 *pmToUPMRule,
michael@0 206 SkMatrix::I())));
michael@0 207 AutoEffectUnref upmToPM(SkNEW_ARGS(GrConfigConversionEffect, (readTex,
michael@0 208 false,
michael@0 209 *upmToPMRule,
michael@0 210 SkMatrix::I())));
michael@0 211 AutoEffectUnref pmToUPM2(SkNEW_ARGS(GrConfigConversionEffect, (tempTex,
michael@0 212 false,
michael@0 213 *pmToUPMRule,
michael@0 214 SkMatrix::I())));
michael@0 215
michael@0 216 SkAutoTUnref<GrEffectRef> pmToUPMEffect1(CreateEffectRef(pmToUPM1));
michael@0 217 SkAutoTUnref<GrEffectRef> upmToPMEffect(CreateEffectRef(upmToPM));
michael@0 218 SkAutoTUnref<GrEffectRef> pmToUPMEffect2(CreateEffectRef(pmToUPM2));
michael@0 219
michael@0 220 context->setRenderTarget(readTex->asRenderTarget());
michael@0 221 GrPaint paint1;
michael@0 222 paint1.addColorEffect(pmToUPMEffect1);
michael@0 223 context->drawRectToRect(paint1, kDstRect, kSrcRect);
michael@0 224
michael@0 225 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead);
michael@0 226
michael@0 227 context->setRenderTarget(tempTex->asRenderTarget());
michael@0 228 GrPaint paint2;
michael@0 229 paint2.addColorEffect(upmToPMEffect);
michael@0 230 context->drawRectToRect(paint2, kDstRect, kSrcRect);
michael@0 231 context->setRenderTarget(readTex->asRenderTarget());
michael@0 232
michael@0 233 GrPaint paint3;
michael@0 234 paint3.addColorEffect(pmToUPMEffect2);
michael@0 235 context->drawRectToRect(paint3, kDstRect, kSrcRect);
michael@0 236
michael@0 237 readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, secondRead);
michael@0 238
michael@0 239 failed = false;
michael@0 240 for (int y = 0; y < 256 && !failed; ++y) {
michael@0 241 for (int x = 0; x <= y; ++x) {
michael@0 242 if (firstRead[256 * y + x] != secondRead[256 * y + x]) {
michael@0 243 failed = true;
michael@0 244 break;
michael@0 245 }
michael@0 246 }
michael@0 247 }
michael@0 248 }
michael@0 249 if (failed) {
michael@0 250 *pmToUPMRule = kNone_PMConversion;
michael@0 251 *upmToPMRule = kNone_PMConversion;
michael@0 252 }
michael@0 253 }
michael@0 254
michael@0 255 const GrEffectRef* GrConfigConversionEffect::Create(GrTexture* texture,
michael@0 256 bool swapRedAndBlue,
michael@0 257 PMConversion pmConversion,
michael@0 258 const SkMatrix& matrix) {
michael@0 259 if (!swapRedAndBlue && kNone_PMConversion == pmConversion) {
michael@0 260 // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
michael@0 261 // then we may pollute our texture cache with redundant shaders. So in the case that no
michael@0 262 // conversions were requested we instead return a GrSimpleTextureEffect.
michael@0 263 return GrSimpleTextureEffect::Create(texture, matrix);
michael@0 264 } else {
michael@0 265 if (kRGBA_8888_GrPixelConfig != texture->config() &&
michael@0 266 kBGRA_8888_GrPixelConfig != texture->config() &&
michael@0 267 kNone_PMConversion != pmConversion) {
michael@0 268 // The PM conversions assume colors are 0..255
michael@0 269 return NULL;
michael@0 270 }
michael@0 271 AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect, (texture,
michael@0 272 swapRedAndBlue,
michael@0 273 pmConversion,
michael@0 274 matrix)));
michael@0 275 return CreateEffectRef(effect);
michael@0 276 }
michael@0 277 }

mercurial