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

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

Issue 1877343002: Switch SkMatrixConvolutionImageFilter over to new onFilterImage interface (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix return value Created 4 years, 8 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 | « include/effects/SkMatrixConvolutionImageFilter.h ('k') | tests/ImageFilterTest.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 2012 The Android Open Source Project 2 * Copyright 2012 The Android Open Source Project
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 "SkMatrixConvolutionImageFilter.h" 8 #include "SkMatrixConvolutionImageFilter.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkDevice.h"
12 #include "SkReadBuffer.h" 11 #include "SkReadBuffer.h"
12 #include "SkSpecialImage.h"
13 #include "SkSpecialSurface.h"
13 #include "SkWriteBuffer.h" 14 #include "SkWriteBuffer.h"
14 #include "SkRect.h" 15 #include "SkRect.h"
15 #include "SkUnPreMultiply.h" 16 #include "SkUnPreMultiply.h"
16 17
17 #if SK_SUPPORT_GPU 18 #if SK_SUPPORT_GPU
19 #include "GrContext.h"
20 #include "GrDrawContext.h"
18 #include "effects/GrMatrixConvolutionEffect.h" 21 #include "effects/GrMatrixConvolutionEffect.h"
19 #endif 22 #endif
20 23
21 // We need to be able to read at most SK_MaxS32 bytes, so divide that 24 // We need to be able to read at most SK_MaxS32 bytes, so divide that
22 // by the size of a scalar to know how many scalars we can read. 25 // by the size of a scalar to know how many scalars we can read.
23 static const int32_t gMaxKernelSize = SK_MaxS32 / sizeof(SkScalar); 26 static const int32_t gMaxKernelSize = SK_MaxS32 / sizeof(SkScalar);
24 27
25 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& ke rnelSize, 28 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& ke rnelSize,
26 const SkScalar* k ernel, 29 const SkScalar* k ernel,
27 SkScalar gain, 30 SkScalar gain,
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 break; 238 break;
236 case kClampToBlack_TileMode: 239 case kClampToBlack_TileMode:
237 filterPixels<ClampToBlackPixelFetcher>(src, result, rect, bounds); 240 filterPixels<ClampToBlackPixelFetcher>(src, result, rect, bounds);
238 break; 241 break;
239 } 242 }
240 } 243 }
241 244
242 // FIXME: This should be refactored to SkImageFilterUtils for 245 // FIXME: This should be refactored to SkImageFilterUtils for
243 // use by other filters. For now, we assume the input is always 246 // use by other filters. For now, we assume the input is always
244 // premultiplied and unpremultiply it 247 // premultiplied and unpremultiply it
245 static SkBitmap unpremultiplyBitmap(SkImageFilter::Proxy* proxy, const SkBitmap& src) 248 static SkBitmap unpremultiply_bitmap(const SkBitmap& src)
246 { 249 {
247 SkAutoLockPixels alp(src); 250 SkAutoLockPixels alp(src);
248 if (!src.getPixels()) { 251 if (!src.getPixels()) {
249 return SkBitmap(); 252 return SkBitmap();
250 } 253 }
251 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.heigh t())); 254
252 if (!device) { 255 const SkImageInfo info = SkImageInfo::MakeN32(src.width(), src.height(), src .alphaType());
256 SkBitmap result;
257 if (!result.tryAllocPixels(info)) {
253 return SkBitmap(); 258 return SkBitmap();
254 } 259 }
255 SkBitmap result = device->accessBitmap(false); 260 SkAutoLockPixels resultLock(result);
256 SkAutoLockPixels alp_result(result);
257 for (int y = 0; y < src.height(); ++y) { 261 for (int y = 0; y < src.height(); ++y) {
258 const uint32_t* srcRow = src.getAddr32(0, y); 262 const uint32_t* srcRow = src.getAddr32(0, y);
259 uint32_t* dstRow = result.getAddr32(0, y); 263 uint32_t* dstRow = result.getAddr32(0, y);
260 for (int x = 0; x < src.width(); ++x) { 264 for (int x = 0; x < src.width(); ++x) {
261 dstRow[x] = SkUnPreMultiply::PMColorToColor(srcRow[x]); 265 dstRow[x] = SkUnPreMultiply::PMColorToColor(srcRow[x]);
262 } 266 }
263 } 267 }
264 return result; 268 return result;
265 } 269 }
266 270
267 bool SkMatrixConvolutionImageFilter::onFilterImageDeprecated(Proxy* proxy, 271 #if SK_SUPPORT_GPU
268 const SkBitmap& sou rce, 272
269 const Context& ctx, 273 static GrTextureDomain::Mode convert_tilemodes(SkMatrixConvolutionImageFilter::T ileMode tileMode) {
270 SkBitmap* result, 274 switch (tileMode) {
271 SkIPoint* offset) c onst { 275 case SkMatrixConvolutionImageFilter::kClamp_TileMode:
272 SkBitmap src = source; 276 return GrTextureDomain::kClamp_Mode;
273 SkIPoint srcOffset = SkIPoint::Make(0, 0); 277 case SkMatrixConvolutionImageFilter::kRepeat_TileMode:
274 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) { 278 return GrTextureDomain::kRepeat_Mode;
275 return false; 279 case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode:
280 return GrTextureDomain::kDecal_Mode;
281 default:
282 SkASSERT(false);
276 } 283 }
284 return GrTextureDomain::kIgnore_Mode;
285 }
277 286
278 if (src.colorType() != kN32_SkColorType) { 287 #endif
279 return false; 288
289 sk_sp<SkSpecialImage> SkMatrixConvolutionImageFilter::onFilterImage(SkSpecialIma ge* source,
290 const Contex t& ctx,
291 SkIPoint* of fset) const {
292 SkIPoint inputOffset = SkIPoint::Make(0, 0);
293 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)) ;
294 if (!input) {
295 return nullptr;
280 } 296 }
281 297
282 SkIRect bounds; 298 SkIRect bounds;
283 if (!this->applyCropRectDeprecated(this->mapContext(ctx), proxy, src, &srcOf fset, 299 input = this->applyCropRect(this->mapContext(ctx), input.get(), &inputOffset , &bounds);
284 &bounds, &src)) { 300 if (!input) {
285 return false; 301 return nullptr;
286 } 302 }
287 303
288 if (!fConvolveAlpha && !src.isOpaque()) { 304 #if SK_SUPPORT_GPU
289 src = unpremultiplyBitmap(proxy, src); 305 // Note: if the kernel is too big, the GPU path falls back to SW
306 if (source->isTextureBacked() &&
307 fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE) {
308 GrContext* context = source->getContext();
309
310 sk_sp<GrTexture> inputTexture(input->asTextureRef(context));
311 SkASSERT(inputTexture);
312
313 offset->fX = bounds.left();
314 offset->fY = bounds.top();
315 bounds.offset(-inputOffset);
316
317 // SRGBTODO: handle sRGB here
318 sk_sp<GrFragmentProcessor> fp(GrMatrixConvolutionEffect::Create(
319 inputTextu re.get(),
320 bounds,
321 fKernelSiz e,
322 fKernel,
323 fGain,
324 fBias,
325 fKernelOff set,
326 convert_ti lemodes(fTileMode),
327 fConvolveA lpha));
328 if (!fp) {
329 return nullptr;
330 }
331
332 return DrawWithFP(context, std::move(fp), bounds, source->internal_getPr oxy());
333 }
334 #endif
335
336 SkBitmap inputBM;
337
338 if (!input->getROPixels(&inputBM)) {
339 return nullptr;
290 } 340 }
291 341
292 SkAutoLockPixels alp(src); 342 if (inputBM.colorType() != kN32_SkColorType) {
293 if (!src.getPixels()) { 343 return nullptr;
294 return false;
295 } 344 }
296 345
297 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds .height())); 346 if (!fConvolveAlpha && !inputBM.isOpaque()) {
298 if (!device) { 347 inputBM = unpremultiply_bitmap(inputBM);
299 return false;
300 } 348 }
301 *result = device->accessBitmap(false); 349
302 SkAutoLockPixels alp_result(*result); 350 SkAutoLockPixels alp(inputBM);
351 if (!inputBM.getPixels()) {
352 return nullptr;
353 }
354
355 const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height( ),
356 inputBM.alphaType());
357
358 SkBitmap dst;
359 if (!dst.tryAllocPixels(info)) {
360 return nullptr;
361 }
362
363 SkAutoLockPixels dstLock(dst);
303 364
304 offset->fX = bounds.fLeft; 365 offset->fX = bounds.fLeft;
305 offset->fY = bounds.fTop; 366 offset->fY = bounds.fTop;
306 bounds.offset(-srcOffset); 367 bounds.offset(-inputOffset);
307 SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fKernelOffset.fX, 368 SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fKernelOffset.fX,
308 bounds.top() + fKernelOffset.fY, 369 bounds.top() + fKernelOffset.fY,
309 bounds.width() - fKernelSize.fWidth + 1 , 370 bounds.width() - fKernelSize.fWidth + 1 ,
310 bounds.height() - fKernelSize.fHeight + 1); 371 bounds.height() - fKernelSize.fHeight + 1);
311 SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(), interior.top()); 372 SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(), interior.top());
312 SkIRect bottom = SkIRect::MakeLTRB(bounds.left(), interior.bottom(), 373 SkIRect bottom = SkIRect::MakeLTRB(bounds.left(), interior.bottom(),
313 bounds.right(), bounds.bottom()); 374 bounds.right(), bounds.bottom());
314 SkIRect left = SkIRect::MakeLTRB(bounds.left(), interior.top(), 375 SkIRect left = SkIRect::MakeLTRB(bounds.left(), interior.top(),
315 interior.left(), interior.bottom()); 376 interior.left(), interior.bottom());
316 SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(), 377 SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(),
317 bounds.right(), interior.bottom()); 378 bounds.right(), interior.bottom());
318 filterBorderPixels(src, result, top, bounds); 379 this->filterBorderPixels(inputBM, &dst, top, bounds);
319 filterBorderPixels(src, result, left, bounds); 380 this->filterBorderPixels(inputBM, &dst, left, bounds);
320 filterInteriorPixels(src, result, interior, bounds); 381 this->filterInteriorPixels(inputBM, &dst, interior, bounds);
321 filterBorderPixels(src, result, right, bounds); 382 this->filterBorderPixels(inputBM, &dst, right, bounds);
322 filterBorderPixels(src, result, bottom, bounds); 383 this->filterBorderPixels(inputBM, &dst, bottom, bounds);
323 return true; 384 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
385 SkIRect::MakeWH(bounds.width(), bounds .height()),
386 dst);
324 } 387 }
325 388
326 SkIRect SkMatrixConvolutionImageFilter::onFilterNodeBounds(const SkIRect& src, c onst SkMatrix& ctm, 389 SkIRect SkMatrixConvolutionImageFilter::onFilterNodeBounds(const SkIRect& src, c onst SkMatrix& ctm,
327 MapDirection directio n) const { 390 MapDirection directio n) const {
328 SkIRect dst = src; 391 SkIRect dst = src;
329 int w = fKernelSize.width() - 1, h = fKernelSize.height() - 1; 392 int w = fKernelSize.width() - 1, h = fKernelSize.height() - 1;
330 dst.fRight += w; 393 dst.fRight += w;
331 dst.fBottom += h; 394 dst.fBottom += h;
332 if (kReverse_MapDirection == direction) { 395 if (kReverse_MapDirection == direction) {
333 dst.offset(-fKernelOffset); 396 dst.offset(-fKernelOffset);
334 } else { 397 } else {
335 dst.offset(fKernelOffset - SkIPoint::Make(w, h)); 398 dst.offset(fKernelOffset - SkIPoint::Make(w, h));
336 } 399 }
337 return dst; 400 return dst;
338 } 401 }
339 402
340 bool SkMatrixConvolutionImageFilter::affectsTransparentBlack() const { 403 bool SkMatrixConvolutionImageFilter::affectsTransparentBlack() const {
341 // Because the kernel is applied in device-space, we have no idea what 404 // Because the kernel is applied in device-space, we have no idea what
342 // pixels it will affect in object-space. 405 // pixels it will affect in object-space.
343 return true; 406 return true;
344 } 407 }
345 408
346 #if SK_SUPPORT_GPU
347
348 static GrTextureDomain::Mode convert_tilemodes(
349 SkMatrixConvolutionImageFilter::TileMode tileMode) {
350 switch (tileMode) {
351 case SkMatrixConvolutionImageFilter::kClamp_TileMode:
352 return GrTextureDomain::kClamp_Mode;
353 case SkMatrixConvolutionImageFilter::kRepeat_TileMode:
354 return GrTextureDomain::kRepeat_Mode;
355 case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode:
356 return GrTextureDomain::kDecal_Mode;
357 default:
358 SkASSERT(false);
359 }
360 return GrTextureDomain::kIgnore_Mode;
361 }
362
363 bool SkMatrixConvolutionImageFilter::asFragmentProcessor(GrFragmentProcessor** f p,
364 GrTexture* texture,
365 const SkMatrix&,
366 const SkIRect& bounds) const {
367 if (!fp) {
368 return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE;
369 }
370 SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE);
371 *fp = GrMatrixConvolutionEffect::Create(texture,
372 bounds,
373 fKernelSize,
374 fKernel,
375 fGain,
376 fBias,
377 fKernelOffset,
378 convert_tilemodes(fTileMode),
379 fConvolveAlpha);
380 return true;
381 }
382 #endif
383
384 #ifndef SK_IGNORE_TO_STRING 409 #ifndef SK_IGNORE_TO_STRING
385 void SkMatrixConvolutionImageFilter::toString(SkString* str) const { 410 void SkMatrixConvolutionImageFilter::toString(SkString* str) const {
386 str->appendf("SkMatrixConvolutionImageFilter: ("); 411 str->appendf("SkMatrixConvolutionImageFilter: (");
387 str->appendf("size: (%d,%d) kernel: (", fKernelSize.width(), fKernelSize.hei ght()); 412 str->appendf("size: (%d,%d) kernel: (", fKernelSize.width(), fKernelSize.hei ght());
388 for (int y = 0; y < fKernelSize.height(); y++) { 413 for (int y = 0; y < fKernelSize.height(); y++) {
389 for (int x = 0; x < fKernelSize.width(); x++) { 414 for (int x = 0; x < fKernelSize.width(); x++) {
390 str->appendf("%f ", fKernel[y * fKernelSize.width() + x]); 415 str->appendf("%f ", fKernel[y * fKernelSize.width() + x]);
391 } 416 }
392 } 417 }
393 str->appendf(")"); 418 str->appendf(")");
394 str->appendf("gain: %f bias: %f ", fGain, fBias); 419 str->appendf("gain: %f bias: %f ", fGain, fBias);
395 str->appendf("offset: (%d, %d) ", fKernelOffset.fX, fKernelOffset.fY); 420 str->appendf("offset: (%d, %d) ", fKernelOffset.fX, fKernelOffset.fY);
396 str->appendf("convolveAlpha: %s", fConvolveAlpha ? "true" : "false"); 421 str->appendf("convolveAlpha: %s", fConvolveAlpha ? "true" : "false");
397 str->append(")"); 422 str->append(")");
398 } 423 }
399 #endif 424 #endif
OLDNEW
« no previous file with comments | « include/effects/SkMatrixConvolutionImageFilter.h ('k') | tests/ImageFilterTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698