gfx/skia/trunk/src/effects/SkGpuBlurUtils.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 2013 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 "SkGpuBlurUtils.h"
michael@0 9
michael@0 10 #include "SkRect.h"
michael@0 11
michael@0 12 #if SK_SUPPORT_GPU
michael@0 13 #include "effects/GrConvolutionEffect.h"
michael@0 14 #include "effects/GrTextureDomain.h"
michael@0 15 #include "GrContext.h"
michael@0 16 #endif
michael@0 17
michael@0 18 namespace SkGpuBlurUtils {
michael@0 19
michael@0 20 #if SK_SUPPORT_GPU
michael@0 21
michael@0 22 #define MAX_BLUR_SIGMA 4.0f
michael@0 23
michael@0 24 static void scale_rect(SkRect* rect, float xScale, float yScale) {
michael@0 25 rect->fLeft = SkScalarMul(rect->fLeft, xScale);
michael@0 26 rect->fTop = SkScalarMul(rect->fTop, yScale);
michael@0 27 rect->fRight = SkScalarMul(rect->fRight, xScale);
michael@0 28 rect->fBottom = SkScalarMul(rect->fBottom, yScale);
michael@0 29 }
michael@0 30
michael@0 31 static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
michael@0 32 *scaleFactor = 1;
michael@0 33 while (sigma > MAX_BLUR_SIGMA) {
michael@0 34 *scaleFactor *= 2;
michael@0 35 sigma *= 0.5f;
michael@0 36 }
michael@0 37 *radius = static_cast<int>(ceilf(sigma * 3.0f));
michael@0 38 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
michael@0 39 return sigma;
michael@0 40 }
michael@0 41
michael@0 42 static void convolve_gaussian_pass(GrContext* context,
michael@0 43 const SkRect& srcRect,
michael@0 44 const SkRect& dstRect,
michael@0 45 GrTexture* texture,
michael@0 46 Gr1DKernelEffect::Direction direction,
michael@0 47 int radius,
michael@0 48 float sigma,
michael@0 49 bool useBounds,
michael@0 50 float bounds[2]) {
michael@0 51 GrPaint paint;
michael@0 52 paint.reset();
michael@0 53 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(
michael@0 54 texture, direction, radius, sigma, useBounds, bounds));
michael@0 55 paint.reset();
michael@0 56 paint.addColorEffect(conv);
michael@0 57 context->drawRectToRect(paint, dstRect, srcRect);
michael@0 58 }
michael@0 59
michael@0 60 static void convolve_gaussian(GrContext* context,
michael@0 61 const SkRect& srcRect,
michael@0 62 const SkRect& dstRect,
michael@0 63 GrTexture* texture,
michael@0 64 Gr1DKernelEffect::Direction direction,
michael@0 65 int radius,
michael@0 66 float sigma,
michael@0 67 bool cropToSrcRect) {
michael@0 68 float bounds[2] = { 0.0f, 1.0f };
michael@0 69 if (!cropToSrcRect) {
michael@0 70 convolve_gaussian_pass(context, srcRect, dstRect, texture,
michael@0 71 direction, radius, sigma, false, bounds);
michael@0 72 return;
michael@0 73 }
michael@0 74 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
michael@0 75 SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
michael@0 76 SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
michael@0 77 SkScalar size;
michael@0 78 SkScalar rad = SkIntToScalar(radius);
michael@0 79 if (direction == Gr1DKernelEffect::kX_Direction) {
michael@0 80 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
michael@0 81 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
michael@0 82 size = srcRect.width();
michael@0 83 lowerSrcRect.fRight = srcRect.left() + rad;
michael@0 84 lowerDstRect.fRight = dstRect.left() + rad;
michael@0 85 upperSrcRect.fLeft = srcRect.right() - rad;
michael@0 86 upperDstRect.fLeft = dstRect.right() - rad;
michael@0 87 middleSrcRect.inset(rad, 0);
michael@0 88 middleDstRect.inset(rad, 0);
michael@0 89 } else {
michael@0 90 bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
michael@0 91 bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
michael@0 92 size = srcRect.height();
michael@0 93 lowerSrcRect.fBottom = srcRect.top() + rad;
michael@0 94 lowerDstRect.fBottom = dstRect.top() + rad;
michael@0 95 upperSrcRect.fTop = srcRect.bottom() - rad;
michael@0 96 upperDstRect.fTop = dstRect.bottom() - rad;
michael@0 97 middleSrcRect.inset(0, rad);
michael@0 98 middleDstRect.inset(0, rad);
michael@0 99 }
michael@0 100 if (radius >= size * SK_ScalarHalf) {
michael@0 101 // Blur radius covers srcRect; use bounds over entire draw
michael@0 102 convolve_gaussian_pass(context, srcRect, dstRect, texture,
michael@0 103 direction, radius, sigma, true, bounds);
michael@0 104 } else {
michael@0 105 // Draw upper and lower margins with bounds; middle without.
michael@0 106 convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture,
michael@0 107 direction, radius, sigma, true, bounds);
michael@0 108 convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture,
michael@0 109 direction, radius, sigma, true, bounds);
michael@0 110 convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture,
michael@0 111 direction, radius, sigma, false, bounds);
michael@0 112 }
michael@0 113 }
michael@0 114
michael@0 115 GrTexture* GaussianBlur(GrContext* context,
michael@0 116 GrTexture* srcTexture,
michael@0 117 bool canClobberSrc,
michael@0 118 const SkRect& rect,
michael@0 119 bool cropToRect,
michael@0 120 float sigmaX,
michael@0 121 float sigmaY) {
michael@0 122 SkASSERT(NULL != context);
michael@0 123
michael@0 124 GrContext::AutoRenderTarget art(context);
michael@0 125
michael@0 126 GrContext::AutoMatrix am;
michael@0 127 am.setIdentity(context);
michael@0 128
michael@0 129 SkIRect clearRect;
michael@0 130 int scaleFactorX, radiusX;
michael@0 131 int scaleFactorY, radiusY;
michael@0 132 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
michael@0 133 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
michael@0 134
michael@0 135 SkRect srcRect(rect);
michael@0 136 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
michael@0 137 srcRect.roundOut();
michael@0 138 scale_rect(&srcRect, static_cast<float>(scaleFactorX),
michael@0 139 static_cast<float>(scaleFactorY));
michael@0 140
michael@0 141 GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));
michael@0 142
michael@0 143 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
michael@0 144 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
michael@0 145 kAlpha_8_GrPixelConfig == srcTexture->config());
michael@0 146
michael@0 147 GrTextureDesc desc;
michael@0 148 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
michael@0 149 desc.fWidth = SkScalarFloorToInt(srcRect.width());
michael@0 150 desc.fHeight = SkScalarFloorToInt(srcRect.height());
michael@0 151 desc.fConfig = srcTexture->config();
michael@0 152
michael@0 153 GrAutoScratchTexture temp1, temp2;
michael@0 154 GrTexture* dstTexture = temp1.set(context, desc);
michael@0 155 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
michael@0 156 if (NULL == dstTexture || NULL == tempTexture) {
michael@0 157 return NULL;
michael@0 158 }
michael@0 159
michael@0 160 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
michael@0 161 GrPaint paint;
michael@0 162 SkMatrix matrix;
michael@0 163 matrix.setIDiv(srcTexture->width(), srcTexture->height());
michael@0 164 context->setRenderTarget(dstTexture->asRenderTarget());
michael@0 165 SkRect dstRect(srcRect);
michael@0 166 if (cropToRect && i == 1) {
michael@0 167 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
michael@0 168 SkRect domain;
michael@0 169 matrix.mapRect(&domain, rect);
michael@0 170 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
michael@0 171 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
michael@0 172 SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
michael@0 173 srcTexture,
michael@0 174 matrix,
michael@0 175 domain,
michael@0 176 GrTextureDomain::kDecal_Mode,
michael@0 177 GrTextureParams::kBilerp_FilterMode));
michael@0 178 paint.addColorEffect(effect);
michael@0 179 } else {
michael@0 180 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
michael@0 181 paint.addColorTextureEffect(srcTexture, matrix, params);
michael@0 182 }
michael@0 183 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
michael@0 184 i < scaleFactorY ? 0.5f : 1.0f);
michael@0 185 context->drawRectToRect(paint, dstRect, srcRect);
michael@0 186 srcRect = dstRect;
michael@0 187 srcTexture = dstTexture;
michael@0 188 SkTSwap(dstTexture, tempTexture);
michael@0 189 }
michael@0 190
michael@0 191 SkIRect srcIRect;
michael@0 192 srcRect.roundOut(&srcIRect);
michael@0 193
michael@0 194 if (sigmaX > 0.0f) {
michael@0 195 if (scaleFactorX > 1) {
michael@0 196 // Clear out a radius to the right of the srcRect to prevent the
michael@0 197 // X convolution from reading garbage.
michael@0 198 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
michael@0 199 radiusX, srcIRect.height());
michael@0 200 context->clear(&clearRect, 0x0, false);
michael@0 201 }
michael@0 202 context->setRenderTarget(dstTexture->asRenderTarget());
michael@0 203 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
michael@0 204 convolve_gaussian(context, srcRect, dstRect, srcTexture,
michael@0 205 Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
michael@0 206 srcTexture = dstTexture;
michael@0 207 srcRect = dstRect;
michael@0 208 SkTSwap(dstTexture, tempTexture);
michael@0 209 }
michael@0 210
michael@0 211 if (sigmaY > 0.0f) {
michael@0 212 if (scaleFactorY > 1 || sigmaX > 0.0f) {
michael@0 213 // Clear out a radius below the srcRect to prevent the Y
michael@0 214 // convolution from reading garbage.
michael@0 215 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
michael@0 216 srcIRect.width(), radiusY);
michael@0 217 context->clear(&clearRect, 0x0, false);
michael@0 218 }
michael@0 219
michael@0 220 context->setRenderTarget(dstTexture->asRenderTarget());
michael@0 221 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
michael@0 222 convolve_gaussian(context, srcRect, dstRect, srcTexture,
michael@0 223 Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
michael@0 224 srcTexture = dstTexture;
michael@0 225 srcRect = dstRect;
michael@0 226 SkTSwap(dstTexture, tempTexture);
michael@0 227 }
michael@0 228
michael@0 229 if (scaleFactorX > 1 || scaleFactorY > 1) {
michael@0 230 // Clear one pixel to the right and below, to accommodate bilinear
michael@0 231 // upsampling.
michael@0 232 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
michael@0 233 srcIRect.width() + 1, 1);
michael@0 234 context->clear(&clearRect, 0x0, false);
michael@0 235 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
michael@0 236 1, srcIRect.height());
michael@0 237 context->clear(&clearRect, 0x0, false);
michael@0 238 SkMatrix matrix;
michael@0 239 matrix.setIDiv(srcTexture->width(), srcTexture->height());
michael@0 240 context->setRenderTarget(dstTexture->asRenderTarget());
michael@0 241
michael@0 242 GrPaint paint;
michael@0 243 // FIXME: this should be mitchell, not bilinear.
michael@0 244 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
michael@0 245 paint.addColorTextureEffect(srcTexture, matrix, params);
michael@0 246
michael@0 247 SkRect dstRect(srcRect);
michael@0 248 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
michael@0 249 context->drawRectToRect(paint, dstRect, srcRect);
michael@0 250 srcRect = dstRect;
michael@0 251 srcTexture = dstTexture;
michael@0 252 SkTSwap(dstTexture, tempTexture);
michael@0 253 }
michael@0 254 if (srcTexture == temp1.texture()) {
michael@0 255 return temp1.detach();
michael@0 256 } else if (srcTexture == temp2.texture()) {
michael@0 257 return temp2.detach();
michael@0 258 } else {
michael@0 259 srcTexture->ref();
michael@0 260 return srcTexture;
michael@0 261 }
michael@0 262 }
michael@0 263 #endif
michael@0 264
michael@0 265 }

mercurial