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

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: Fix comments 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
« no previous file with comments | « src/effects/SkGpuBlurUtils.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
46 bool cropToSrcRect,
44 float sigma, 47 float sigma,
45 int radius, 48 int radius,
46 Gr1DKernelEffect::Direction direction) { 49 Gr1DKernelEffect::Direction direction) {
47 GrPaint paint; 50 GrPaint paint;
51 paint.reset();
52 float cropRect[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
53 if (cropToSrcRect) {
54 if (direction == Gr1DKernelEffect::kX_Direction) {
55 cropRect[0] = SkScalarToFloat(srcRect.left()) / texture->width();
56 cropRect[1] = SkScalarToFloat(srcRect.right()) / texture->width();
57 } else {
58 cropRect[2] = SkScalarToFloat(srcRect.top()) / texture->height();
59 cropRect[3] = SkScalarToFloat(srcRect.bottom()) / texture->height();
60 }
61 }
48 62
49 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture, 63 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture,
50 direction , 64 direction ,
51 radius, 65 radius,
52 sigma)); 66 sigma,
67 cropToSrc Rect,
68 cropRect) );
53 paint.addColorEffect(conv); 69 paint.addColorEffect(conv);
54 context->drawRect(paint, rect); 70 context->drawRectToRect(paint, dstRect, srcRect);
55 } 71 }
56 72
57 GrTexture* GaussianBlur(GrContext* context, 73 GrTexture* GaussianBlur(GrContext* context,
58 GrTexture* srcTexture, 74 GrTexture* srcTexture,
59 bool canClobberSrc, 75 bool canClobberSrc,
60 const SkRect& rect, 76 const SkRect& rect,
77 bool cropToRect,
61 float sigmaX, 78 float sigmaX,
62 float sigmaY) { 79 float sigmaY) {
63 GrAssert(NULL != context); 80 GrAssert(NULL != context);
64 81
65 GrContext::AutoRenderTarget art(context); 82 GrContext::AutoRenderTarget art(context);
66 83
67 GrContext::AutoMatrix am; 84 GrContext::AutoMatrix am;
68 am.setIdentity(context); 85 am.setIdentity(context);
69 86
70 SkIRect clearRect; 87 SkIRect clearRect;
71 int scaleFactorX, radiusX; 88 int scaleFactorX, radiusX;
72 int scaleFactorY, radiusY; 89 int scaleFactorY, radiusY;
73 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX); 90 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
74 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY); 91 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
75 92
76 SkRect srcRect(rect); 93 SkRect srcRect(rect);
77 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); 94 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
78 srcRect.roundOut(); 95 srcRect.roundOut();
79 scale_rect(&srcRect, static_cast<float>(scaleFactorX), 96 scale_rect(&srcRect, static_cast<float>(scaleFactorX),
80 static_cast<float>(scaleFactorY)); 97 static_cast<float>(scaleFactorY));
81 98
82 GrContext::AutoClip acs(context, srcRect); 99 GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.hei ght()));
83 100
84 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() || 101 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
85 kRGBA_8888_GrPixelConfig == srcTexture->config() || 102 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
86 kAlpha_8_GrPixelConfig == srcTexture->config()); 103 kAlpha_8_GrPixelConfig == srcTexture->config());
87 104
88 GrTextureDesc desc; 105 GrTextureDesc desc;
89 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 106 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
90 desc.fWidth = SkScalarFloorToInt(srcRect.width()); 107 desc.fWidth = SkScalarFloorToInt(srcRect.width());
91 desc.fHeight = SkScalarFloorToInt(srcRect.height()); 108 desc.fHeight = SkScalarFloorToInt(srcRect.height());
92 desc.fConfig = srcTexture->config(); 109 desc.fConfig = srcTexture->config();
93 110
94 GrAutoScratchTexture temp1, temp2; 111 GrAutoScratchTexture temp1, temp2;
95 GrTexture* dstTexture = temp1.set(context, desc); 112 GrTexture* dstTexture = temp1.set(context, desc);
96 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c); 113 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c);
97 if (NULL == dstTexture || NULL == tempTexture) { 114 if (NULL == dstTexture || NULL == tempTexture) {
98 return NULL; 115 return NULL;
99 } 116 }
100 117
101 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { 118 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
102 GrPaint paint; 119 GrPaint paint;
103 SkMatrix matrix; 120 SkMatrix matrix;
104 matrix.setIDiv(srcTexture->width(), srcTexture->height()); 121 matrix.setIDiv(srcTexture->width(), srcTexture->height());
105 context->setRenderTarget(dstTexture->asRenderTarget()); 122 context->setRenderTarget(dstTexture->asRenderTarget());
106 SkRect dstRect(srcRect); 123 SkRect dstRect(srcRect);
124 if (cropToRect && i == 1) {
125 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
126 SkRect domain;
127 matrix.mapRect(&domain, rect);
128 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
129 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
130 SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
131 srcTexture,
132 matrix,
133 domain,
134 GrTextureDomainEffect::kDecal_WrapMode,
135 true));
136 paint.addColorEffect(effect);
137 } else {
138 GrTextureParams params(SkShader::kClamp_TileMode, true);
139 paint.addColorTextureEffect(srcTexture, matrix, params);
140 }
107 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, 141 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
108 i < scaleFactorY ? 0.5f : 1.0f); 142 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); 143 context->drawRectToRect(paint, dstRect, srcRect);
112 srcRect = dstRect; 144 srcRect = dstRect;
113 srcTexture = dstTexture; 145 srcTexture = dstTexture;
114 SkTSwap(dstTexture, tempTexture); 146 SkTSwap(dstTexture, tempTexture);
115 } 147 }
116 148
117 SkIRect srcIRect; 149 SkIRect srcIRect;
118 srcRect.roundOut(&srcIRect); 150 srcRect.roundOut(&srcIRect);
119 151
120 if (sigmaX > 0.0f) { 152 if (sigmaX > 0.0f) {
121 if (scaleFactorX > 1) { 153 if (scaleFactorX > 1) {
122 // Clear out a radius to the right of the srcRect to prevent the 154 // Clear out a radius to the right of the srcRect to prevent the
123 // X convolution from reading garbage. 155 // X convolution from reading garbage.
124 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 156 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
125 radiusX, srcIRect.height()); 157 radiusX, srcIRect.height());
126 context->clear(&clearRect, 0x0); 158 context->clear(&clearRect, 0x0);
127 } 159 }
128 context->setRenderTarget(dstTexture->asRenderTarget()); 160 context->setRenderTarget(dstTexture->asRenderTarget());
129 convolve_gaussian(context, srcTexture, srcRect, sigmaX, radiusX, 161 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
130 Gr1DKernelEffect::kX_Direction); 162 convolve_gaussian(context, srcTexture, srcRect, dstRect, cropToRect,
163 sigmaX, radiusX, Gr1DKernelEffect::kX_Direction);
131 srcTexture = dstTexture; 164 srcTexture = dstTexture;
165 srcRect = dstRect;
132 SkTSwap(dstTexture, tempTexture); 166 SkTSwap(dstTexture, tempTexture);
133 } 167 }
134 168
135 if (sigmaY > 0.0f) { 169 if (sigmaY > 0.0f) {
136 if (scaleFactorY > 1 || sigmaX > 0.0f) { 170 if (scaleFactorY > 1 || sigmaX > 0.0f) {
137 // Clear out a radius below the srcRect to prevent the Y 171 // Clear out a radius below the srcRect to prevent the Y
138 // convolution from reading garbage. 172 // convolution from reading garbage.
139 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 173 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
140 srcIRect.width(), radiusY); 174 srcIRect.width(), radiusY);
141 context->clear(&clearRect, 0x0); 175 context->clear(&clearRect, 0x0);
142 } 176 }
143 177
144 context->setRenderTarget(dstTexture->asRenderTarget()); 178 context->setRenderTarget(dstTexture->asRenderTarget());
145 convolve_gaussian(context, srcTexture, srcRect, sigmaY, radiusY, 179 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
146 Gr1DKernelEffect::kY_Direction); 180 convolve_gaussian(context, srcTexture, srcRect, dstRect, cropToRect,
181 sigmaY, radiusY, Gr1DKernelEffect::kY_Direction);
147 srcTexture = dstTexture; 182 srcTexture = dstTexture;
183 srcRect = dstRect;
148 SkTSwap(dstTexture, tempTexture); 184 SkTSwap(dstTexture, tempTexture);
149 } 185 }
150 186
151 if (scaleFactorX > 1 || scaleFactorY > 1) { 187 if (scaleFactorX > 1 || scaleFactorY > 1) {
152 // Clear one pixel to the right and below, to accommodate bilinear 188 // Clear one pixel to the right and below, to accommodate bilinear
153 // upsampling. 189 // upsampling.
154 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 190 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
155 srcIRect.width() + 1, 1); 191 srcIRect.width() + 1, 1);
156 context->clear(&clearRect, 0x0); 192 context->clear(&clearRect, 0x0);
157 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 193 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
(...skipping 20 matching lines...) Expand all
178 } else if (srcTexture == temp2.texture()) { 214 } else if (srcTexture == temp2.texture()) {
179 return temp2.detach(); 215 return temp2.detach();
180 } else { 216 } else {
181 srcTexture->ref(); 217 srcTexture->ref();
182 return srcTexture; 218 return srcTexture;
183 } 219 }
184 } 220 }
185 #endif 221 #endif
186 222
187 } 223 }
OLDNEW
« no previous file with comments | « src/effects/SkGpuBlurUtils.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698