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

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

Issue 1151283004: Split drawing functionality out of GrContext and into new GrDrawContext (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix no-GPU builds Created 5 years, 7 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
« no previous file with comments | « src/effects/SkDisplacementMapEffect.cpp ('k') | src/effects/SkLightingImageFilter.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/GrMatrixConvolutionEffect.h" 14 #include "effects/GrMatrixConvolutionEffect.h"
15 #include "GrContext.h" 15 #include "GrContext.h"
16 #include "GrDrawContext.h"
16 #endif 17 #endif
17 18
18 namespace SkGpuBlurUtils { 19 namespace SkGpuBlurUtils {
19 20
20 #if SK_SUPPORT_GPU 21 #if SK_SUPPORT_GPU
21 22
22 #define MAX_BLUR_SIGMA 4.0f 23 #define MAX_BLUR_SIGMA 4.0f
23 24
24 static void scale_rect(SkRect* rect, float xScale, float yScale) { 25 static void scale_rect(SkRect* rect, float xScale, float yScale) {
25 rect->fLeft = SkScalarMul(rect->fLeft, xScale); 26 rect->fLeft = SkScalarMul(rect->fLeft, xScale);
(...skipping 10 matching lines...) Expand all
36 if (*scaleFactor > maxTextureSize) { 37 if (*scaleFactor > maxTextureSize) {
37 *scaleFactor = maxTextureSize; 38 *scaleFactor = maxTextureSize;
38 sigma = MAX_BLUR_SIGMA; 39 sigma = MAX_BLUR_SIGMA;
39 } 40 }
40 } 41 }
41 *radius = static_cast<int>(ceilf(sigma * 3.0f)); 42 *radius = static_cast<int>(ceilf(sigma * 3.0f));
42 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius); 43 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
43 return sigma; 44 return sigma;
44 } 45 }
45 46
46 static void convolve_gaussian_1d(GrContext* context, 47 static void convolve_gaussian_1d(GrDrawContext* drawContext,
47 GrRenderTarget* rt, 48 GrRenderTarget* rt,
48 const GrClip& clip, 49 const GrClip& clip,
49 const SkRect& srcRect, 50 const SkRect& srcRect,
50 const SkRect& dstRect, 51 const SkRect& dstRect,
51 GrTexture* texture, 52 GrTexture* texture,
52 Gr1DKernelEffect::Direction direction, 53 Gr1DKernelEffect::Direction direction,
53 int radius, 54 int radius,
54 float sigma, 55 float sigma,
55 bool useBounds, 56 bool useBounds,
56 float bounds[2]) { 57 float bounds[2]) {
57 GrPaint paint; 58 GrPaint paint;
58 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian( 59 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
59 texture, direction, radius, sigma, useBounds, bounds)); 60 texture, direction, radius, sigma, useBounds, bounds));
60 paint.addColorProcessor(conv); 61 paint.addColorProcessor(conv);
61 context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRec t); 62 drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, sr cRect);
62 } 63 }
63 64
64 static void convolve_gaussian_2d(GrContext* context, 65 static void convolve_gaussian_2d(GrDrawContext* drawContext,
65 GrRenderTarget* rt, 66 GrRenderTarget* rt,
66 const GrClip& clip, 67 const GrClip& clip,
67 const SkRect& srcRect, 68 const SkRect& srcRect,
68 const SkRect& dstRect, 69 const SkRect& dstRect,
69 GrTexture* texture, 70 GrTexture* texture,
70 int radiusX, 71 int radiusX,
71 int radiusY, 72 int radiusY,
72 SkScalar sigmaX, 73 SkScalar sigmaX,
73 SkScalar sigmaY, 74 SkScalar sigmaY,
74 bool useBounds, 75 bool useBounds,
75 SkIRect bounds) { 76 SkIRect bounds) {
76 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); 77 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
77 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); 78 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
78 GrPaint paint; 79 GrPaint paint;
79 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus sian( 80 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus sian(
80 texture, bounds, size, 1.0, 0.0, kernelOffset, 81 texture, bounds, size, 1.0, 0.0, kernelOffset,
81 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_ Mode, 82 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_ Mode,
82 true, sigmaX, sigmaY)); 83 true, sigmaX, sigmaY));
83 paint.addColorProcessor(conv); 84 paint.addColorProcessor(conv);
84 context->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRec t); 85 drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, sr cRect);
85 } 86 }
86 87
87 static void convolve_gaussian(GrContext* context, 88 static void convolve_gaussian(GrDrawContext* drawContext,
88 GrRenderTarget* rt, 89 GrRenderTarget* rt,
89 const GrClip& clip, 90 const GrClip& clip,
90 const SkRect& srcRect, 91 const SkRect& srcRect,
91 const SkRect& dstRect, 92 const SkRect& dstRect,
92 GrTexture* texture, 93 GrTexture* texture,
93 Gr1DKernelEffect::Direction direction, 94 Gr1DKernelEffect::Direction direction,
94 int radius, 95 int radius,
95 float sigma, 96 float sigma,
96 bool cropToSrcRect) { 97 bool cropToSrcRect) {
97 float bounds[2] = { 0.0f, 1.0f }; 98 float bounds[2] = { 0.0f, 1.0f };
98 if (!cropToSrcRect) { 99 if (!cropToSrcRect) {
99 convolve_gaussian_1d(context, rt, clip, srcRect, dstRect, texture, 100 convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
100 direction, radius, sigma, false, bounds); 101 direction, radius, sigma, false, bounds);
101 return; 102 return;
102 } 103 }
103 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect; 104 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
104 SkRect middleSrcRect = srcRect, middleDstRect = dstRect; 105 SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
105 SkRect upperSrcRect = srcRect, upperDstRect = dstRect; 106 SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
106 SkScalar size; 107 SkScalar size;
107 SkScalar rad = SkIntToScalar(radius); 108 SkScalar rad = SkIntToScalar(radius);
108 if (direction == Gr1DKernelEffect::kX_Direction) { 109 if (direction == Gr1DKernelEffect::kX_Direction) {
109 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width(); 110 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
(...skipping 11 matching lines...) Expand all
121 size = srcRect.height(); 122 size = srcRect.height();
122 lowerSrcRect.fBottom = srcRect.top() + rad; 123 lowerSrcRect.fBottom = srcRect.top() + rad;
123 lowerDstRect.fBottom = dstRect.top() + rad; 124 lowerDstRect.fBottom = dstRect.top() + rad;
124 upperSrcRect.fTop = srcRect.bottom() - rad; 125 upperSrcRect.fTop = srcRect.bottom() - rad;
125 upperDstRect.fTop = dstRect.bottom() - rad; 126 upperDstRect.fTop = dstRect.bottom() - rad;
126 middleSrcRect.inset(0, rad); 127 middleSrcRect.inset(0, rad);
127 middleDstRect.inset(0, rad); 128 middleDstRect.inset(0, rad);
128 } 129 }
129 if (radius >= size * SK_ScalarHalf) { 130 if (radius >= size * SK_ScalarHalf) {
130 // Blur radius covers srcRect; use bounds over entire draw 131 // Blur radius covers srcRect; use bounds over entire draw
131 convolve_gaussian_1d(context, rt, clip, srcRect, dstRect, texture, 132 convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
132 direction, radius, sigma, true, bounds); 133 direction, radius, sigma, true, bounds);
133 } else { 134 } else {
134 // Draw upper and lower margins with bounds; middle without. 135 // Draw upper and lower margins with bounds; middle without.
135 convolve_gaussian_1d(context, rt, clip, lowerSrcRect, lowerDstRect, text ure, 136 convolve_gaussian_1d(drawContext, rt, clip, lowerSrcRect, lowerDstRect, texture,
136 direction, radius, sigma, true, bounds); 137 direction, radius, sigma, true, bounds);
137 convolve_gaussian_1d(context, rt, clip, upperSrcRect, upperDstRect, text ure, 138 convolve_gaussian_1d(drawContext, rt, clip, upperSrcRect, upperDstRect, texture,
138 direction, radius, sigma, true, bounds); 139 direction, radius, sigma, true, bounds);
139 convolve_gaussian_1d(context, rt, clip, middleSrcRect, middleDstRect, te xture, 140 convolve_gaussian_1d(drawContext, rt, clip, middleSrcRect, middleDstRect , texture,
140 direction, radius, sigma, false, bounds); 141 direction, radius, sigma, false, bounds);
141 } 142 }
142 } 143 }
143 144
144 GrTexture* GaussianBlur(GrContext* context, 145 GrTexture* GaussianBlur(GrContext* context,
145 GrTexture* srcTexture, 146 GrTexture* srcTexture,
146 bool canClobberSrc, 147 bool canClobberSrc,
147 const SkRect& rect, 148 const SkRect& rect,
148 bool cropToRect, 149 bool cropToRect,
149 float sigmaX, 150 float sigmaX,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } else { 189 } else {
189 temp2.reset(context->textureProvider()->refScratchTexture( 190 temp2.reset(context->textureProvider()->refScratchTexture(
190 desc, GrTextureProvider::kApprox_ScratchTexMatch)); 191 desc, GrTextureProvider::kApprox_ScratchTexMatch));
191 tempTexture = temp2.get(); 192 tempTexture = temp2.get();
192 } 193 }
193 194
194 if (NULL == dstTexture || NULL == tempTexture) { 195 if (NULL == dstTexture || NULL == tempTexture) {
195 return NULL; 196 return NULL;
196 } 197 }
197 198
199 GrDrawContext* drawContext = context->drawContext();
200 if (!drawContext) {
201 return NULL;
202 }
203
198 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { 204 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
199 GrPaint paint; 205 GrPaint paint;
200 SkMatrix matrix; 206 SkMatrix matrix;
201 matrix.setIDiv(srcTexture->width(), srcTexture->height()); 207 matrix.setIDiv(srcTexture->width(), srcTexture->height());
202 SkRect dstRect(srcRect); 208 SkRect dstRect(srcRect);
203 if (cropToRect && i == 1) { 209 if (cropToRect && i == 1) {
204 dstRect.offset(-dstRect.fLeft, -dstRect.fTop); 210 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
205 SkRect domain; 211 SkRect domain;
206 matrix.mapRect(&domain, rect); 212 matrix.mapRect(&domain, rect);
207 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f, 213 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
208 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f); 214 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
209 SkAutoTUnref<GrFragmentProcessor> fp( GrTextureDomainEffect::Creat e( 215 SkAutoTUnref<GrFragmentProcessor> fp( GrTextureDomainEffect::Creat e(
210 srcTexture, 216 srcTexture,
211 matrix, 217 matrix,
212 domain, 218 domain,
213 GrTextureDomain::kDecal_Mode, 219 GrTextureDomain::kDecal_Mode,
214 GrTextureParams::kBilerp_FilterMode)); 220 GrTextureParams::kBilerp_FilterMode));
215 paint.addColorProcessor(fp); 221 paint.addColorProcessor(fp);
216 } else { 222 } else {
217 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k Bilerp_FilterMode); 223 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k Bilerp_FilterMode);
218 paint.addColorTextureProcessor(srcTexture, matrix, params); 224 paint.addColorTextureProcessor(srcTexture, matrix, params);
219 } 225 }
220 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, 226 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
221 i < scaleFactorY ? 0.5f : 1.0f); 227 i < scaleFactorY ? 0.5f : 1.0f);
222 context->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint, SkMatrix::I(), 228 drawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, pai nt, SkMatrix::I(),
223 dstRect, srcRect); 229 dstRect, srcRect);
224 srcRect = dstRect; 230 srcRect = dstRect;
225 srcTexture = dstTexture; 231 srcTexture = dstTexture;
226 SkTSwap(dstTexture, tempTexture); 232 SkTSwap(dstTexture, tempTexture);
227 } 233 }
228 234
229 const SkIRect srcIRect = srcRect.roundOut(); 235 const SkIRect srcIRect = srcRect.roundOut();
230 236
231 // For really small blurs(Certainly no wider than 5x5 on desktop gpus) it is faster to just 237 // For really small blurs(Certainly no wider than 5x5 on desktop gpus) it is faster to just
232 // launch a single non separable kernel vs two launches 238 // launch a single non separable kernel vs two launches
233 if (sigmaX > 0.0f && sigmaY > 0 && 239 if (sigmaX > 0.0f && sigmaY > 0 &&
234 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { 240 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
235 // We shouldn't be scaling because this is a small size blur 241 // We shouldn't be scaling because this is a small size blur
236 SkASSERT((scaleFactorX == scaleFactorY) == 1); 242 SkASSERT((scaleFactorX == scaleFactorY) == 1);
237 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 243 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
238 convolve_gaussian_2d(context, dstTexture->asRenderTarget(), clip, srcRec t, dstRect, 244 convolve_gaussian_2d(drawContext, dstTexture->asRenderTarget(), clip, sr cRect, dstRect,
239 srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropT oRect, srcIRect); 245 srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropT oRect, srcIRect);
240 srcTexture = dstTexture; 246 srcTexture = dstTexture;
241 srcRect = dstRect; 247 srcRect = dstRect;
242 SkTSwap(dstTexture, tempTexture); 248 SkTSwap(dstTexture, tempTexture);
243 249
244 } else { 250 } else {
245 if (sigmaX > 0.0f) { 251 if (sigmaX > 0.0f) {
246 if (scaleFactorX > 1) { 252 if (scaleFactorX > 1) {
247 // Clear out a radius to the right of the srcRect to prevent the 253 // Clear out a radius to the right of the srcRect to prevent the
248 // X convolution from reading garbage. 254 // X convolution from reading garbage.
249 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 255 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
250 radiusX, srcIRect.height()); 256 radiusX, srcIRect.height());
251 context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarge t()); 257 drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0 , false);
252 } 258 }
253 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 259 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
254 convolve_gaussian(context, dstTexture->asRenderTarget(), clip, srcRe ct, dstRect, 260 convolve_gaussian(drawContext, dstTexture->asRenderTarget(), clip, s rcRect, dstRect,
255 srcTexture, Gr1DKernelEffect::kX_Direction, radius X, sigmaX, 261 srcTexture, Gr1DKernelEffect::kX_Direction, radius X, sigmaX,
256 cropToRect); 262 cropToRect);
257 srcTexture = dstTexture; 263 srcTexture = dstTexture;
258 srcRect = dstRect; 264 srcRect = dstRect;
259 SkTSwap(dstTexture, tempTexture); 265 SkTSwap(dstTexture, tempTexture);
260 } 266 }
261 267
262 if (sigmaY > 0.0f) { 268 if (sigmaY > 0.0f) {
263 if (scaleFactorY > 1 || sigmaX > 0.0f) { 269 if (scaleFactorY > 1 || sigmaX > 0.0f) {
264 // Clear out a radius below the srcRect to prevent the Y 270 // Clear out a radius below the srcRect to prevent the Y
265 // convolution from reading garbage. 271 // convolution from reading garbage.
266 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 272 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
267 srcIRect.width(), radiusY); 273 srcIRect.width(), radiusY);
268 context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarge t()); 274 drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0 , false);
269 } 275 }
270 276
271 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 277 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
272 convolve_gaussian(context, dstTexture->asRenderTarget(), clip, srcRe ct, 278 convolve_gaussian(drawContext, dstTexture->asRenderTarget(), clip, s rcRect,
273 dstRect, srcTexture, Gr1DKernelEffect::kY_Directio n, radiusY, sigmaY, 279 dstRect, srcTexture, Gr1DKernelEffect::kY_Directio n, radiusY, sigmaY,
274 cropToRect); 280 cropToRect);
275 srcTexture = dstTexture; 281 srcTexture = dstTexture;
276 srcRect = dstRect; 282 srcRect = dstRect;
277 SkTSwap(dstTexture, tempTexture); 283 SkTSwap(dstTexture, tempTexture);
278 } 284 }
279 } 285 }
280 286
281 if (scaleFactorX > 1 || scaleFactorY > 1) { 287 if (scaleFactorX > 1 || scaleFactorY > 1) {
282 // Clear one pixel to the right and below, to accommodate bilinear 288 // Clear one pixel to the right and below, to accommodate bilinear
283 // upsampling. 289 // upsampling.
284 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 290 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
285 srcIRect.width() + 1, 1); 291 srcIRect.width() + 1, 1);
286 context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget()); 292 drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false) ;
287 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 293 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
288 1, srcIRect.height()); 294 1, srcIRect.height());
289 context->clear(&clearRect, 0x0, false, srcTexture->asRenderTarget()); 295 drawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false) ;
290 SkMatrix matrix; 296 SkMatrix matrix;
291 matrix.setIDiv(srcTexture->width(), srcTexture->height()); 297 matrix.setIDiv(srcTexture->width(), srcTexture->height());
292 298
293 GrPaint paint; 299 GrPaint paint;
294 // FIXME: this should be mitchell, not bilinear. 300 // FIXME: this should be mitchell, not bilinear.
295 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile rp_FilterMode); 301 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile rp_FilterMode);
296 paint.addColorTextureProcessor(srcTexture, matrix, params); 302 paint.addColorTextureProcessor(srcTexture, matrix, params);
297 303
298 SkRect dstRect(srcRect); 304 SkRect dstRect(srcRect);
299 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); 305 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
300 context->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint, 306 drawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, pai nt,
301 SkMatrix::I(), dstRect, srcRect); 307 SkMatrix::I(), dstRect, srcRect);
302 srcRect = dstRect; 308 srcRect = dstRect;
303 srcTexture = dstTexture; 309 srcTexture = dstTexture;
304 SkTSwap(dstTexture, tempTexture); 310 SkTSwap(dstTexture, tempTexture);
305 } 311 }
306 return SkRef(srcTexture); 312 return SkRef(srcTexture);
307 } 313 }
308 #endif 314 #endif
309 315
310 } 316 }
OLDNEW
« no previous file with comments | « src/effects/SkDisplacementMapEffect.cpp ('k') | src/effects/SkLightingImageFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698