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.

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

mercurial