Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: src/effects/SkGpuBlurUtils.cpp

Issue 19775006: Implement crop rect for SkImageFilter (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Revert more unnecessary changes Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkGpuBlurUtils.h" 8 #include "SkGpuBlurUtils.h"
9 9
10 #include "SkRect.h" 10 #include "SkRect.h"
11 11
12 #if SK_SUPPORT_GPU 12 #if SK_SUPPORT_GPU
13 #include "effects/GrConvolutionEffect.h" 13 #include "effects/GrConvolutionEffect.h"
14 #include "effects/GrTextureDomainEffect.h"
14 #include "GrContext.h" 15 #include "GrContext.h"
15 #endif 16 #endif
16 17
17 namespace SkGpuBlurUtils { 18 namespace SkGpuBlurUtils {
18 19
19 #if SK_SUPPORT_GPU 20 #if SK_SUPPORT_GPU
20 21
21 #define MAX_BLUR_SIGMA 4.0f 22 #define MAX_BLUR_SIGMA 4.0f
22 23
23 static void scale_rect(SkRect* rect, float xScale, float yScale) { 24 static void scale_rect(SkRect* rect, float xScale, float yScale) {
24 rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale)); 25 rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
25 rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale)); 26 rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
26 rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale)); 27 rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
27 rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale)); 28 rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
28 } 29 }
29 30
30 static float adjust_sigma(float sigma, int *scaleFactor, int *radius) { 31 static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
31 *scaleFactor = 1; 32 *scaleFactor = 1;
32 while (sigma > MAX_BLUR_SIGMA) { 33 while (sigma > MAX_BLUR_SIGMA) {
33 *scaleFactor *= 2; 34 *scaleFactor *= 2;
34 sigma *= 0.5f; 35 sigma *= 0.5f;
35 } 36 }
36 *radius = static_cast<int>(ceilf(sigma * 3.0f)); 37 *radius = static_cast<int>(ceilf(sigma * 3.0f));
37 GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius); 38 GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
38 return sigma; 39 return sigma;
39 } 40 }
40 41
41 static void convolve_gaussian(GrContext* context, 42 static void convolve_gaussian(GrContext* context,
42 GrTexture* texture, 43 GrTexture* texture,
43 const SkRect& rect, 44 const SkRect& srcRect,
45 const SkRect& dstRect,
44 float sigma, 46 float sigma,
45 int radius, 47 int radius,
46 Gr1DKernelEffect::Direction direction) { 48 Gr1DKernelEffect::Direction direction) {
47 GrPaint paint; 49 GrPaint paint;
50 paint.reset();
51 float cropRect[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
52 if (direction == Gr1DKernelEffect::kX_Direction) {
53 cropRect[0] = SkScalarToFloat(srcRect.left()) / texture->width();
54 cropRect[1] = SkScalarToFloat(srcRect.right()) / texture->width();
55 } else {
56 cropRect[2] = SkScalarToFloat(srcRect.top()) / texture->height();
57 cropRect[3] = SkScalarToFloat(srcRect.bottom()) / texture->height();
58 }
48 59
49 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture, 60 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture,
50 direction , 61 direction ,
51 radius, 62 radius,
52 sigma)); 63 sigma,
64 cropRect) );
53 paint.addColorEffect(conv); 65 paint.addColorEffect(conv);
54 context->drawRect(paint, rect); 66 context->drawRectToRect(paint, dstRect, srcRect);
55 } 67 }
56 68
57 GrTexture* GaussianBlur(GrContext* context, 69 GrTexture* GaussianBlur(GrContext* context,
58 GrTexture* srcTexture, 70 GrTexture* srcTexture,
59 bool canClobberSrc, 71 bool canClobberSrc,
60 const SkRect& rect, 72 const SkRect& rect,
61 float sigmaX, 73 float sigmaX,
62 float sigmaY) { 74 float sigmaY) {
63 GrAssert(NULL != context); 75 GrAssert(NULL != context);
64 76
65 GrContext::AutoRenderTarget art(context); 77 GrContext::AutoRenderTarget art(context);
66 78
67 GrContext::AutoMatrix am; 79 GrContext::AutoMatrix am;
68 am.setIdentity(context); 80 am.setIdentity(context);
69 81
70 SkIRect clearRect; 82 SkIRect clearRect;
71 int scaleFactorX, radiusX; 83 int scaleFactorX, radiusX;
72 int scaleFactorY, radiusY; 84 int scaleFactorY, radiusY;
73 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX); 85 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
74 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY); 86 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
75 87
76 SkRect srcRect(rect); 88 SkRect srcRect(rect);
77 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); 89 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
78 srcRect.roundOut(); 90 srcRect.roundOut();
79 scale_rect(&srcRect, static_cast<float>(scaleFactorX), 91 scale_rect(&srcRect, static_cast<float>(scaleFactorX),
80 static_cast<float>(scaleFactorY)); 92 static_cast<float>(scaleFactorY));
81 93
82 GrContext::AutoClip acs(context, srcRect); 94 GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.hei ght()));
83 95
84 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() || 96 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
85 kRGBA_8888_GrPixelConfig == srcTexture->config() || 97 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
86 kAlpha_8_GrPixelConfig == srcTexture->config()); 98 kAlpha_8_GrPixelConfig == srcTexture->config());
87 99
88 GrTextureDesc desc; 100 GrTextureDesc desc;
89 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 101 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
90 desc.fWidth = SkScalarFloorToInt(srcRect.width()); 102 desc.fWidth = SkScalarFloorToInt(srcRect.width());
91 desc.fHeight = SkScalarFloorToInt(srcRect.height()); 103 desc.fHeight = SkScalarFloorToInt(srcRect.height());
92 desc.fConfig = srcTexture->config(); 104 desc.fConfig = srcTexture->config();
93 105
94 GrAutoScratchTexture temp1, temp2; 106 GrAutoScratchTexture temp1, temp2;
95 GrTexture* dstTexture = temp1.set(context, desc); 107 GrTexture* dstTexture = temp1.set(context, desc);
96 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c); 108 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c);
97 if (NULL == dstTexture || NULL == tempTexture) { 109 if (NULL == dstTexture || NULL == tempTexture) {
98 return NULL; 110 return NULL;
99 } 111 }
100 112
101 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { 113 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
102 GrPaint paint; 114 GrPaint paint;
103 SkMatrix matrix; 115 SkMatrix matrix;
104 matrix.setIDiv(srcTexture->width(), srcTexture->height()); 116 matrix.setIDiv(srcTexture->width(), srcTexture->height());
105 context->setRenderTarget(dstTexture->asRenderTarget()); 117 context->setRenderTarget(dstTexture->asRenderTarget());
106 SkRect dstRect(srcRect); 118 SkRect dstRect(srcRect);
119 if (i == 1) {
120 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
121 SkRect domain;
122 matrix.mapRect(&domain, rect);
123 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
124 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
125 SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
126 srcTexture,
127 matrix,
128 domain,
129 GrTextureDomainEffect::kDecal_WrapMode,
130 true));
131 paint.addColorEffect(effect);
132 } else {
133 GrTextureParams params(SkShader::kClamp_TileMode, true);
134 paint.addColorTextureEffect(srcTexture, matrix, params);
135 }
107 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, 136 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
108 i < scaleFactorY ? 0.5f : 1.0f); 137 i < scaleFactorY ? 0.5f : 1.0f);
109 GrTextureParams params(SkShader::kClamp_TileMode, true);
110 paint.addColorTextureEffect(srcTexture, matrix, params);
111 context->drawRectToRect(paint, dstRect, srcRect); 138 context->drawRectToRect(paint, dstRect, srcRect);
112 srcRect = dstRect; 139 srcRect = dstRect;
113 srcTexture = dstTexture; 140 srcTexture = dstTexture;
114 SkTSwap(dstTexture, tempTexture); 141 SkTSwap(dstTexture, tempTexture);
115 } 142 }
116 143
117 SkIRect srcIRect; 144 SkIRect srcIRect;
118 srcRect.roundOut(&srcIRect); 145 srcRect.roundOut(&srcIRect);
119 146
120 if (sigmaX > 0.0f) { 147 if (sigmaX > 0.0f) {
121 if (scaleFactorX > 1) { 148 if (scaleFactorX > 1) {
122 // Clear out a radius to the right of the srcRect to prevent the 149 // Clear out a radius to the right of the srcRect to prevent the
123 // X convolution from reading garbage. 150 // X convolution from reading garbage.
124 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 151 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
125 radiusX, srcIRect.height()); 152 radiusX, srcIRect.height());
126 context->clear(&clearRect, 0x0); 153 context->clear(&clearRect, 0x0);
127 } 154 }
128 context->setRenderTarget(dstTexture->asRenderTarget()); 155 context->setRenderTarget(dstTexture->asRenderTarget());
129 convolve_gaussian(context, srcTexture, srcRect, sigmaX, radiusX, 156 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
157 convolve_gaussian(context, srcTexture, srcRect, dstRect, sigmaX, radiusX ,
130 Gr1DKernelEffect::kX_Direction); 158 Gr1DKernelEffect::kX_Direction);
131 srcTexture = dstTexture; 159 srcTexture = dstTexture;
160 srcRect = dstRect;
132 SkTSwap(dstTexture, tempTexture); 161 SkTSwap(dstTexture, tempTexture);
133 } 162 }
134 163
135 if (sigmaY > 0.0f) { 164 if (sigmaY > 0.0f) {
136 if (scaleFactorY > 1 || sigmaX > 0.0f) { 165 if (scaleFactorY > 1 || sigmaX > 0.0f) {
137 // Clear out a radius below the srcRect to prevent the Y 166 // Clear out a radius below the srcRect to prevent the Y
138 // convolution from reading garbage. 167 // convolution from reading garbage.
139 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 168 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
140 srcIRect.width(), radiusY); 169 srcIRect.width(), radiusY);
141 context->clear(&clearRect, 0x0); 170 context->clear(&clearRect, 0x0);
142 } 171 }
143 172
144 context->setRenderTarget(dstTexture->asRenderTarget()); 173 context->setRenderTarget(dstTexture->asRenderTarget());
145 convolve_gaussian(context, srcTexture, srcRect, sigmaY, radiusY, 174 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
175 convolve_gaussian(context, srcTexture, srcRect, dstRect, sigmaY, radiusY ,
146 Gr1DKernelEffect::kY_Direction); 176 Gr1DKernelEffect::kY_Direction);
147 srcTexture = dstTexture; 177 srcTexture = dstTexture;
178 srcRect = dstRect;
148 SkTSwap(dstTexture, tempTexture); 179 SkTSwap(dstTexture, tempTexture);
149 } 180 }
150 181
151 if (scaleFactorX > 1 || scaleFactorY > 1) { 182 if (scaleFactorX > 1 || scaleFactorY > 1) {
152 // Clear one pixel to the right and below, to accommodate bilinear 183 // Clear one pixel to the right and below, to accommodate bilinear
153 // upsampling. 184 // upsampling.
154 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 185 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
155 srcIRect.width() + 1, 1); 186 srcIRect.width() + 1, 1);
156 context->clear(&clearRect, 0x0); 187 context->clear(&clearRect, 0x0);
157 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 188 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
(...skipping 20 matching lines...) Expand all
178 } else if (srcTexture == temp2.texture()) { 209 } else if (srcTexture == temp2.texture()) {
179 return temp2.detach(); 210 return temp2.detach();
180 } else { 211 } else {
181 srcTexture->ref(); 212 srcTexture->ref();
182 return srcTexture; 213 return srcTexture;
183 } 214 }
184 } 215 }
185 #endif 216 #endif
186 217
187 } 218 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698