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

Side by Side Diff: src/core/SkMipMap.cpp

Issue 1593073002: speedup mip builders (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: smarten up loop setup (via fmalita) Created 4 years, 11 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 | « no previous file | no next file » | 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 "SkMipMap.h" 8 #include "SkMipMap.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 // 376 //
377 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50 ,50) 377 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50 ,50)
378 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) 378 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50)
379 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings, 379 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings,
380 // else for even cases, we just use a 2x box filter. 380 // else for even cases, we just use a 2x box filter.
381 // 381 //
382 // This produces 4 possible filters: 2x2 2x3 3x2 3x3 where WxH indicates the nu mber of src pixels 382 // This produces 4 possible filters: 2x2 2x3 3x2 3x3 where WxH indicates the nu mber of src pixels
383 // we need to sample in each dimension to produce 1 dst pixel. 383 // we need to sample in each dimension to produce 1 dst pixel.
384 // 384 //
385 385
386 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src RB) { 386 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src RB, int count) {
387 auto p0 = static_cast<const typename F::Type*>(src); 387 auto p0 = static_cast<const typename F::Type*>(src);
388 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 388 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
389 auto d = static_cast<typename F::Type*>(dst);
389 390
390 auto c00 = F::Expand(p0[0]); 391 for (int i = 0; i < count; ++i) {
391 auto c01 = F::Expand(p0[1]); 392 auto c00 = F::Expand(p0[0]);
392 auto c10 = F::Expand(p1[0]); 393 auto c01 = F::Expand(p0[1]);
393 auto c11 = F::Expand(p1[1]); 394 auto c10 = F::Expand(p1[0]);
395 auto c11 = F::Expand(p1[1]);
394 396
395 auto c = c00 + c10 + c01 + c11; 397 auto c = c00 + c10 + c01 + c11;
396 *(typename F::Type*)dst = F::Compact(c >> 2); 398 d[i] = F::Compact(c >> 2);
399 p0 += 2;
400 p1 += 2;
401 }
397 } 402 }
398 403
399 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src RB) { 404 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src RB, int count) {
405 SkASSERT(count > 0);
400 auto p0 = static_cast<const typename F::Type*>(src); 406 auto p0 = static_cast<const typename F::Type*>(src);
401 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 407 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
408 auto d = static_cast<typename F::Type*>(dst);
409
410 auto c02 = F::Expand(p0[0]);
411 auto c12 = F::Expand(p1[0]);
412 for (int i = 0; i < count; ++i) {
413 auto c00 = c02;
414 auto c01 = F::Expand(p0[1]);
415 c02 = F::Expand(p0[2]);
416 auto c10 = c12;
417 auto c11 = F::Expand(p1[1]);
418 c12 = F::Expand(p1[2]);
402 419
403 auto c00 = F::Expand(p0[0]); 420 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12);
404 auto c01 = F::Expand(p0[1]); 421 d[i] = F::Compact(c >> 3);
405 auto c02 = F::Expand(p0[2]); 422 p0 += 2;
406 auto c10 = F::Expand(p1[0]); 423 p1 += 2;
407 auto c11 = F::Expand(p1[1]); 424 }
408 auto c12 = F::Expand(p1[2]);
409
410 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12);
411 *(typename F::Type*)dst = F::Compact(c >> 3);
412 } 425 }
413 426
414 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src RB) { 427 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src RB, int count) {
415 auto p0 = static_cast<const typename F::Type*>(src); 428 auto p0 = static_cast<const typename F::Type*>(src);
416 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 429 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
417 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 430 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
431 auto d = static_cast<typename F::Type*>(dst);
432
433 for (int i = 0; i < count; ++i) {
434 auto c00 = F::Expand(p0[0]);
435 auto c01 = F::Expand(p0[1]);
436 auto c10 = F::Expand(p1[0]);
437 auto c11 = F::Expand(p1[1]);
438 auto c20 = F::Expand(p2[0]);
439 auto c21 = F::Expand(p2[1]);
418 440
419 auto c00 = F::Expand(p0[0]); 441 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
420 auto c01 = F::Expand(p0[1]); 442 d[i] = F::Compact(c >> 3);
421 auto c10 = F::Expand(p1[0]); 443 p0 += 2;
422 auto c11 = F::Expand(p1[1]); 444 p1 += 2;
423 auto c20 = F::Expand(p2[0]); 445 p2 += 2;
424 auto c21 = F::Expand(p2[1]); 446 }
425 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
426 *(typename F::Type*)dst = F::Compact(c >> 3);
427 } 447 }
428 448
429 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src RB) { 449 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src RB, int count) {
430 auto p0 = static_cast<const typename F::Type*>(src); 450 auto p0 = static_cast<const typename F::Type*>(src);
431 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 451 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
432 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 452 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
453 auto d = static_cast<typename F::Type*>(dst);
433 454
434 auto c00 = F::Expand(p0[0]); 455 auto c02 = F::Expand(p0[0]);
435 auto c01 = F::Expand(p0[1]); 456 auto c12 = F::Expand(p1[0]);
436 auto c02 = F::Expand(p0[2]); 457 auto c22 = F::Expand(p2[0]);
437 auto c10 = F::Expand(p1[0]); 458 for (int i = 0; i < count; ++i) {
438 auto c11 = F::Expand(p1[1]); 459 auto c00 = c02;
439 auto c12 = F::Expand(p1[2]); 460 auto c01 = F::Expand(p0[1]);
440 auto c20 = F::Expand(p2[0]); 461 c02 = F::Expand(p0[2]);
441 auto c21 = F::Expand(p2[1]); 462 auto c10 = c12;
442 auto c22 = F::Expand(p2[2]); 463 auto c11 = F::Expand(p1[1]);
464 c12 = F::Expand(p1[2]);
465 auto c20 = c22;
466 auto c21 = F::Expand(p2[1]);
467 c22 = F::Expand(p2[2]);
443 468
444 auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c2 0, c21, c22); 469 auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_12 1(c20, c21, c22);
445 *(typename F::Type*)dst = F::Compact(c >> 4); 470 d[i] = F::Compact(c >> 4);
471 p0 += 2;
472 p1 += 2;
473 p2 += 2;
474 }
446 } 475 }
447 476
448 //////////////////////////////////////////////////////////////////////////////// /////////////////// 477 //////////////////////////////////////////////////////////////////////////////// ///////////////////
449 478
450 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { 479 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) {
451 if (levelCount < 0) { 480 if (levelCount < 0) {
452 return 0; 481 return 0;
453 } 482 }
454 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; 483 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize;
455 if (!sk_64_isS32(size)) { 484 if (!sk_64_isS32(size)) {
456 return 0; 485 return 0;
457 } 486 }
458 return sk_64_asS32(size); 487 return sk_64_asS32(size);
459 } 488 }
460 489
461 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { 490 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
462 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB); 491 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
463 492
464 FilterProc* proc_2_2 = nullptr; 493 FilterProc* proc_2_2 = nullptr;
465 FilterProc* proc_2_3 = nullptr; 494 FilterProc* proc_2_3 = nullptr;
466 FilterProc* proc_3_2 = nullptr; 495 FilterProc* proc_3_2 = nullptr;
467 FilterProc* proc_3_3 = nullptr; 496 FilterProc* proc_3_3 = nullptr;
468 497
469 const SkColorType ct = src.colorType(); 498 const SkColorType ct = src.colorType();
470 const SkAlphaType at = src.alphaType(); 499 const SkAlphaType at = src.alphaType();
471 switch (ct) { 500 switch (ct) {
472 case kRGBA_8888_SkColorType: 501 case kRGBA_8888_SkColorType:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 mipmap->fLevels = (Level*)mipmap->writable_data(); 581 mipmap->fLevels = (Level*)mipmap->writable_data();
553 582
554 Level* levels = mipmap->fLevels; 583 Level* levels = mipmap->fLevels;
555 uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; 584 uint8_t* baseAddr = (uint8_t*)&levels[countLevels];
556 uint8_t* addr = baseAddr; 585 uint8_t* addr = baseAddr;
557 int width = src.width(); 586 int width = src.width();
558 int height = src.height(); 587 int height = src.height();
559 uint32_t rowBytes; 588 uint32_t rowBytes;
560 SkPixmap srcPM(srcPixmap); 589 SkPixmap srcPM(srcPixmap);
561 590
562 int prevW = width;
563 int prevH = height;
564 for (int i = 0; i < countLevels; ++i) { 591 for (int i = 0; i < countLevels; ++i) {
592 FilterProc* proc;
593 if (height & 1) { // src-height is 3
594 if (width & 1) { // src-width is 3
595 proc = proc_3_3;
596 } else { // src-width is 2
597 proc = proc_2_3;
598 }
599 } else { // src-height is 2
600 if (width & 1) { // src-width is 3
601 proc = proc_3_2;
602 } else { // src-width is 2
603 proc = proc_2_2;
604 }
605 }
565 width >>= 1; 606 width >>= 1;
566 height >>= 1; 607 height >>= 1;
567 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); 608 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width));
568 609
569 levels[i].fPixels = addr; 610 levels[i].fPixels = addr;
570 levels[i].fWidth = width; 611 levels[i].fWidth = width;
571 levels[i].fHeight = height; 612 levels[i].fHeight = height;
572 levels[i].fRowBytes = rowBytes; 613 levels[i].fRowBytes = rowBytes;
573 levels[i].fScale = (float)width / src.width(); 614 levels[i].fScale = (float)width / src.width();
574 615
575 SkPixmap dstPM(SkImageInfo::Make(width, height, ct, at), addr, rowBytes) ; 616 SkPixmap dstPM(SkImageInfo::Make(width, height, ct, at), addr, rowBytes) ;
576 617
577 const size_t pixelSize = srcPM.info().bytesPerPixel();
578
579 const void* srcBasePtr = srcPM.addr(); 618 const void* srcBasePtr = srcPM.addr();
580 void* dstBasePtr = dstPM.writable_addr(); 619 void* dstBasePtr = dstPM.writable_addr();
581 620
582 FilterProc* proc;
583 if (prevH & 1) { // src-height is 3
584 if (prevW & 1) { // src-width is 3
585 proc = proc_3_3;
586 } else { // src-width is 2
587 proc = proc_2_3;
588 }
589 } else { // src-height is 2
590 if (prevW & 1) { // src-width is 3
591 proc = proc_3_2;
592 } else { // src-width is 2
593 proc = proc_2_2;
594 }
595 }
596
597 const size_t srcRB = srcPM.rowBytes(); 621 const size_t srcRB = srcPM.rowBytes();
598 for (int y = 0; y < height; y++) { 622 for (int y = 0; y < height; y++) {
599 const void* srcPtr = srcBasePtr; 623 proc(dstBasePtr, srcBasePtr, srcRB, width);
600 void* dstPtr = dstBasePtr;
601
602 for (int x = 0; x < width; x++) {
603 proc(dstPtr, srcPtr, srcRB);
604 srcPtr = (char*)srcPtr + pixelSize * 2;
605 dstPtr = (char*)dstPtr + pixelSize;
606 }
607
608 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows 624 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows
609 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); 625 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes();
610 } 626 }
611 srcPM = dstPM; 627 srcPM = dstPM;
612 addr += height * rowBytes; 628 addr += height * rowBytes;
613 prevW = width;
614 prevH = height;
615 } 629 }
616 SkASSERT(addr == baseAddr + size); 630 SkASSERT(addr == baseAddr + size);
617 631
618 return mipmap; 632 return mipmap;
619 } 633 }
620 #endif 634 #endif
621 635
622 /////////////////////////////////////////////////////////////////////////////// 636 ///////////////////////////////////////////////////////////////////////////////
623 637
624 bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const { 638 bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const {
(...skipping 20 matching lines...) Expand all
645 } 659 }
646 660
647 if (level > fCount) { 661 if (level > fCount) {
648 level = fCount; 662 level = fCount;
649 } 663 }
650 if (levelPtr) { 664 if (levelPtr) {
651 *levelPtr = fLevels[level - 1]; 665 *levelPtr = fLevels[level - 1];
652 } 666 }
653 return true; 667 return true;
654 } 668 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698