Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkSwizzler.h" | 10 #include "SkSwizzler.h" |
| 11 #include "SkSwizzlerOpts.h" | |
| 11 #include "SkTemplates.h" | 12 #include "SkTemplates.h" |
| 12 | 13 |
| 13 SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, | 14 SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, |
| 14 uint8_t maxAlpha) { | 15 uint8_t maxAlpha) { |
| 15 // In the transparent case, this returns 0x0000 | 16 // In the transparent case, this returns 0x0000 |
| 16 // In the opaque case, this returns 0xFFFF | 17 // In the opaque case, this returns 0xFFFF |
| 17 // If the row is neither transparent nor opaque, returns something else | 18 // If the row is neither transparent nor opaque, returns something else |
| 18 return (((uint16_t) maxAlpha) << 8) | zeroAlpha; | 19 return (((uint16_t) maxAlpha) << 8) | zeroAlpha; |
| 19 } | 20 } |
| 20 | 21 |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 // FIXME: Support dithering? | 422 // FIXME: Support dithering? |
| 422 src += offset; | 423 src += offset; |
| 423 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; | 424 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; |
| 424 for (int x = 0; x < dstWidth; x++) { | 425 for (int x = 0; x < dstWidth; x++) { |
| 425 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); | 426 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); |
| 426 src += deltaSrc; | 427 src += deltaSrc; |
| 427 } | 428 } |
| 428 return SkSwizzler::kOpaque_ResultAlpha; | 429 return SkSwizzler::kOpaque_ResultAlpha; |
| 429 } | 430 } |
| 430 | 431 |
| 431 | |
| 432 // kRGBA | 432 // kRGBA |
| 433 static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( | 433 static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( |
| 434 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, | 434 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, |
| 435 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { | 435 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { |
| 436 | 436 |
| 437 src += offset; | 437 src += offset; |
| 438 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 438 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 439 INIT_RESULT_ALPHA; | 439 INIT_RESULT_ALPHA; |
| 440 for (int x = 0; x < dstWidth; x++) { | 440 for (int x = 0; x < dstWidth; x++) { |
| 441 unsigned alpha = src[3]; | 441 unsigned alpha = src[3]; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 const SkImageInfo& dstInfo, | 596 const SkImageInfo& dstInfo, |
| 597 const SkCodec::Options& options, | 597 const SkCodec::Options& options, |
| 598 const SkIRect* frame) { | 598 const SkIRect* frame) { |
| 599 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { | 599 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { |
| 600 return nullptr; | 600 return nullptr; |
| 601 } | 601 } |
| 602 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) | 602 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) |
| 603 && nullptr == ctable) { | 603 && nullptr == ctable) { |
| 604 return nullptr; | 604 return nullptr; |
| 605 } | 605 } |
| 606 RowProc proc = nullptr; | 606 RowProc optProc = nullptr; |
| 607 RowProc scalarProc = nullptr; | |
| 607 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized; | 608 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized; |
| 608 switch (sc) { | 609 switch (sc) { |
| 609 case kBit: | 610 case kBit: |
| 610 switch (dstInfo.colorType()) { | 611 switch (dstInfo.colorType()) { |
| 611 case kN32_SkColorType: | 612 case kN32_SkColorType: |
| 612 proc = &swizzle_bit_to_n32; | 613 optProc = &swizzle_bit_to_n32; |
| 613 break; | 614 break; |
| 614 case kIndex_8_SkColorType: | 615 case kIndex_8_SkColorType: |
| 615 proc = &swizzle_bit_to_index; | 616 optProc = &swizzle_bit_to_index; |
| 616 break; | 617 break; |
| 617 case kRGB_565_SkColorType: | 618 case kRGB_565_SkColorType: |
| 618 proc = &swizzle_bit_to_565; | 619 optProc = &swizzle_bit_to_565; |
| 619 break; | 620 break; |
| 620 case kGray_8_SkColorType: | 621 case kGray_8_SkColorType: |
| 621 proc = &swizzle_bit_to_grayscale; | 622 optProc = &swizzle_bit_to_grayscale; |
| 622 break; | 623 break; |
| 623 default: | 624 default: |
| 624 break; | 625 break; |
| 625 } | 626 } |
| 626 break; | 627 break; |
| 627 case kIndex1: | 628 case kIndex1: |
| 628 case kIndex2: | 629 case kIndex2: |
| 629 case kIndex4: | 630 case kIndex4: |
| 630 switch (dstInfo.colorType()) { | 631 switch (dstInfo.colorType()) { |
| 631 case kN32_SkColorType: | 632 case kN32_SkColorType: |
| 632 proc = &swizzle_small_index_to_n32; | 633 optProc = &swizzle_small_index_to_n32; |
| 633 break; | 634 break; |
| 634 case kRGB_565_SkColorType: | 635 case kRGB_565_SkColorType: |
| 635 proc = &swizzle_small_index_to_565; | 636 optProc = &swizzle_small_index_to_565; |
| 636 break; | 637 break; |
| 637 case kIndex_8_SkColorType: | 638 case kIndex_8_SkColorType: |
| 638 proc = &swizzle_small_index_to_index; | 639 optProc = &swizzle_small_index_to_index; |
| 639 break; | 640 break; |
| 640 default: | 641 default: |
| 641 break; | 642 break; |
| 642 } | 643 } |
| 643 break; | 644 break; |
| 644 case kIndex: | 645 case kIndex: |
| 645 switch (dstInfo.colorType()) { | 646 switch (dstInfo.colorType()) { |
| 646 case kN32_SkColorType: | 647 case kN32_SkColorType: |
| 647 // We assume the color premultiplied ctable (or not) as desi red. | 648 // We assume the color premultiplied ctable (or not) as desi red. |
| 648 if (SkCodec::kYes_ZeroInitialized == zeroInit) { | 649 if (SkCodec::kYes_ZeroInitialized == zeroInit) { |
| 649 proc = &swizzle_index_to_n32_skipZ; | 650 optProc = &swizzle_index_to_n32_skipZ; |
| 650 break; | 651 break; |
| 651 } else { | 652 } else { |
| 652 proc = &swizzle_index_to_n32; | 653 optProc = &swizzle_index_to_n32; |
| 653 break; | 654 break; |
| 654 } | 655 } |
| 655 break; | 656 break; |
| 656 case kRGB_565_SkColorType: | 657 case kRGB_565_SkColorType: |
| 657 proc = &swizzle_index_to_565; | 658 optProc = &swizzle_index_to_565; |
| 658 break; | 659 break; |
| 659 case kIndex_8_SkColorType: | 660 case kIndex_8_SkColorType: |
| 660 proc = &swizzle_index_to_index; | 661 optProc = &swizzle_index_to_index; |
| 661 break; | 662 break; |
| 662 default: | 663 default: |
| 663 break; | 664 break; |
| 664 } | 665 } |
| 665 break; | 666 break; |
| 666 case kGray: | 667 case kGray: |
| 667 switch (dstInfo.colorType()) { | 668 switch (dstInfo.colorType()) { |
| 668 case kN32_SkColorType: | 669 case kN32_SkColorType: |
| 669 proc = &swizzle_gray_to_n32; | 670 optProc = &swizzle_gray_to_n32; |
| 670 break; | 671 break; |
| 671 case kGray_8_SkColorType: | 672 case kGray_8_SkColorType: |
| 672 proc = &swizzle_gray_to_gray; | 673 optProc = &swizzle_gray_to_gray; |
| 673 break; | 674 break; |
| 674 case kRGB_565_SkColorType: | 675 case kRGB_565_SkColorType: |
| 675 proc = &swizzle_gray_to_565; | 676 optProc = &swizzle_gray_to_565; |
| 676 break; | 677 break; |
| 677 default: | 678 default: |
| 678 break; | 679 break; |
| 679 } | 680 } |
| 680 break; | 681 break; |
| 681 case kBGR: | 682 case kBGR: |
| 682 case kBGRX: | 683 case kBGRX: |
| 683 switch (dstInfo.colorType()) { | 684 switch (dstInfo.colorType()) { |
| 684 case kN32_SkColorType: | 685 case kN32_SkColorType: |
| 685 proc = &swizzle_bgrx_to_n32; | 686 optProc = &swizzle_bgrx_to_n32; |
| 686 break; | 687 break; |
| 687 case kRGB_565_SkColorType: | 688 case kRGB_565_SkColorType: |
| 688 proc = &swizzle_bgrx_to_565; | 689 optProc = &swizzle_bgrx_to_565; |
| 689 break; | 690 break; |
| 690 default: | 691 default: |
| 691 break; | 692 break; |
| 692 } | 693 } |
| 693 break; | 694 break; |
| 694 case kBGRA: | 695 case kBGRA: |
| 695 switch (dstInfo.colorType()) { | 696 switch (dstInfo.colorType()) { |
| 696 case kN32_SkColorType: | 697 case kN32_SkColorType: |
| 697 switch (dstInfo.alphaType()) { | 698 switch (dstInfo.alphaType()) { |
| 698 case kUnpremul_SkAlphaType: | 699 case kUnpremul_SkAlphaType: |
| 699 proc = &swizzle_bgra_to_n32_unpremul; | 700 optProc = &swizzle_bgra_to_n32_unpremul; |
| 700 break; | 701 break; |
| 701 case kPremul_SkAlphaType: | 702 case kPremul_SkAlphaType: |
| 702 proc = &swizzle_bgra_to_n32_premul; | 703 optProc = &swizzle_bgra_to_n32_premul; |
| 703 break; | 704 break; |
| 704 default: | 705 default: |
| 705 break; | 706 break; |
| 706 } | 707 } |
| 707 break; | 708 break; |
| 708 default: | 709 default: |
| 709 break; | 710 break; |
| 710 } | 711 } |
| 711 break; | 712 break; |
| 712 case kRGBX: | 713 case kRGBX: |
| 713 // TODO: Support other swizzles. | |
| 714 switch (dstInfo.colorType()) { | 714 switch (dstInfo.colorType()) { |
| 715 case kN32_SkColorType: | 715 case kN32_SkColorType: |
| 716 proc = &swizzle_rgbx_to_n32; | 716 optProc = &swizzle_rgbx_to_n32; |
| 717 break; | 717 break; |
| 718 case kRGB_565_SkColorType: | 718 case kRGB_565_SkColorType: |
| 719 proc = &swizzle_rgbx_to_565; | 719 optProc = &swizzle_rgbx_to_565; |
| 720 default: | 720 default: |
| 721 break; | 721 break; |
| 722 } | 722 } |
| 723 break; | 723 break; |
| 724 case kRGBA: | 724 case kRGBA: |
| 725 switch (dstInfo.colorType()) { | 725 switch (dstInfo.colorType()) { |
| 726 case kN32_SkColorType: | 726 case kN32_SkColorType: |
| 727 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { | 727 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { |
| 728 // Respect zeroInit? | 728 // Respect zeroInit? |
| 729 proc = &swizzle_rgba_to_n32_unpremul; | 729 optProc = &swizzle_rgba_to_n32_unpremul; |
| 730 } else { | 730 } else { |
| 731 optProc = &opt_swizzle_rgba_to_n32_premul; | |
| 731 if (SkCodec::kYes_ZeroInitialized == zeroInit) { | 732 if (SkCodec::kYes_ZeroInitialized == zeroInit) { |
| 732 proc = &swizzle_rgba_to_n32_premul_skipZ; | 733 scalarProc = &swizzle_rgba_to_n32_premul_skipZ; |
|
msarett
2016/01/08 13:56:00
We'll want to benchmark against the regular versio
mtklein
2016/01/08 15:20:19
There's more to this feature than just speed, righ
scroggo
2016/01/08 16:02:56
Yes.
mtklein
2016/01/08 16:23:01
And we're certain there really are runs of >=1024
scroggo
2016/01/08 16:50:51
Yes. (I can dig up the bug, but when the change fi
msarett
2016/01/11 20:33:24
I think Mike's idea to skip leading zeros will be
| |
| 733 } else { | 734 } else { |
|
mtklein
2016/01/08 15:20:19
If I'm right above about this being more than just
msarett
2016/01/11 20:33:24
Yes we could. I don't think that's a good option
| |
| 734 proc = &swizzle_rgba_to_n32_premul; | 735 scalarProc = &swizzle_rgba_to_n32_premul; |
| 735 } | 736 } |
| 736 } | 737 } |
| 737 break; | 738 break; |
| 738 default: | 739 default: |
| 739 break; | 740 break; |
| 740 } | 741 } |
| 741 break; | 742 break; |
| 742 case kRGB: | 743 case kRGB: |
| 743 switch (dstInfo.colorType()) { | 744 switch (dstInfo.colorType()) { |
| 744 case kN32_SkColorType: | 745 case kN32_SkColorType: |
| 745 proc = &swizzle_rgbx_to_n32; | 746 optProc = &swizzle_rgbx_to_n32; |
| 746 break; | 747 break; |
| 747 default: | 748 default: |
| 748 break; | 749 break; |
| 749 } | 750 } |
| 750 break; | 751 break; |
| 751 case kRGB_565: | 752 case kRGB_565: |
| 752 switch (dstInfo.colorType()) { | 753 switch (dstInfo.colorType()) { |
| 753 case kRGB_565_SkColorType: | 754 case kRGB_565_SkColorType: |
| 754 proc = &sample565; | 755 optProc = &sample565; |
| 755 break; | 756 break; |
| 756 default: | 757 default: |
| 757 break; | 758 break; |
| 758 } | 759 } |
| 759 break; | 760 break; |
| 760 case kCMYK: | 761 case kCMYK: |
| 761 switch (dstInfo.colorType()) { | 762 switch (dstInfo.colorType()) { |
| 762 case kN32_SkColorType: | 763 case kN32_SkColorType: |
| 763 proc = &swizzle_cmyk_to_n32; | 764 optProc = &swizzle_cmyk_to_n32; |
| 764 break; | 765 break; |
| 765 case kRGB_565_SkColorType: | 766 case kRGB_565_SkColorType: |
| 766 proc = &swizzle_cmyk_to_565; | 767 optProc = &swizzle_cmyk_to_565; |
| 767 break; | 768 break; |
| 768 default: | 769 default: |
| 769 break; | 770 break; |
| 770 } | 771 } |
| 771 break; | 772 break; |
| 772 default: | 773 default: |
| 773 break; | 774 break; |
| 774 } | 775 } |
| 775 if (nullptr == proc) { | 776 if (nullptr == optProc) { |
|
scroggo
2016/01/08 16:02:57
So are we guaranteed that there's an optProc, but
mtklein
2016/01/08 16:23:01
(That's what I find confusing. In reality, we're
msarett
2016/01/11 20:33:24
Done.
| |
| 776 return nullptr; | 777 return nullptr; |
| 777 } | 778 } |
| 779 if (nullptr == scalarProc) { | |
| 780 scalarProc = optProc; | |
| 781 } | |
| 778 | 782 |
| 779 // Store bpp in bytes if it is an even multiple, otherwise use bits | 783 // Store bpp in bytes if it is an even multiple, otherwise use bits |
| 780 int srcBPP = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel (sc); | 784 int srcBPP = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel (sc); |
| 781 int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType()); | 785 int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType()); |
| 782 | 786 |
| 783 int srcOffset = 0; | 787 int srcOffset = 0; |
| 784 int srcWidth = dstInfo.width(); | 788 int srcWidth = dstInfo.width(); |
| 785 int dstOffset = 0; | 789 int dstOffset = 0; |
| 786 int dstWidth = srcWidth; | 790 int dstWidth = srcWidth; |
| 787 if (options.fSubset) { | 791 if (options.fSubset) { |
| 788 // We do not currently support subset decodes for image types that may h ave | 792 // We do not currently support subset decodes for image types that may h ave |
| 789 // frames (gif). | 793 // frames (gif). |
| 790 SkASSERT(!frame); | 794 SkASSERT(!frame); |
| 791 srcOffset = options.fSubset->left(); | 795 srcOffset = options.fSubset->left(); |
| 792 srcWidth = options.fSubset->width(); | 796 srcWidth = options.fSubset->width(); |
| 793 dstWidth = srcWidth; | 797 dstWidth = srcWidth; |
| 794 } else if (frame) { | 798 } else if (frame) { |
| 795 dstOffset = frame->left(); | 799 dstOffset = frame->left(); |
| 796 srcWidth = frame->width(); | 800 srcWidth = frame->width(); |
| 797 } | 801 } |
| 798 | 802 |
| 799 return new SkSwizzler(proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth , srcBPP, dstBPP); | 803 return new SkSwizzler(optProc, scalarProc, ctable, srcOffset, srcWidth, dstO ffset, dstWidth, |
| 804 srcBPP, dstBPP); | |
| 800 } | 805 } |
| 801 | 806 |
| 802 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcOffset, int srcWidth, | 807 SkSwizzler::SkSwizzler(RowProc optProc, RowProc scalarProc, const SkPMColor* cta ble, int srcOffset, |
| 803 int dstOffset, int dstWidth, int srcBPP, int dstBPP) | 808 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP) |
| 804 : fRowProc(proc) | 809 : fRowProc(optProc) |
| 810 , fScalarRowProc(scalarProc) | |
| 805 , fColorTable(ctable) | 811 , fColorTable(ctable) |
| 806 , fSrcOffset(srcOffset) | 812 , fSrcOffset(srcOffset) |
| 807 , fDstOffset(dstOffset) | 813 , fDstOffset(dstOffset) |
| 808 , fSrcOffsetUnits(srcOffset * srcBPP) | 814 , fSrcOffsetUnits(srcOffset * srcBPP) |
| 809 , fDstOffsetBytes(dstOffset * dstBPP) | 815 , fDstOffsetBytes(dstOffset * dstBPP) |
| 810 , fSrcWidth(srcWidth) | 816 , fSrcWidth(srcWidth) |
| 811 , fDstWidth(dstWidth) | 817 , fDstWidth(dstWidth) |
| 812 , fSwizzleWidth(srcWidth) | 818 , fSwizzleWidth(srcWidth) |
| 813 , fAllocatedWidth(dstWidth) | 819 , fAllocatedWidth(dstWidth) |
| 814 , fSampleX(1) | 820 , fSampleX(1) |
| 815 , fSrcBPP(srcBPP) | 821 , fSrcBPP(srcBPP) |
| 816 , fDstBPP(dstBPP) | 822 , fDstBPP(dstBPP) |
| 817 {} | 823 {} |
| 818 | 824 |
| 819 int SkSwizzler::onSetSampleX(int sampleX) { | 825 int SkSwizzler::onSetSampleX(int sampleX) { |
|
mtklein
2016/01/08 15:20:19
I don't suppose x-sampling can move to the constru
scroggo
2016/01/08 16:02:57
It used to be in the constructor, but we moved it
msarett
2016/01/11 20:33:24
I think it makes sense to keep things this way for
| |
| 820 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be | 826 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be |
| 821 // way to report failure? | 827 // way to report failure? |
| 822 fSampleX = sampleX; | 828 fSampleX = sampleX; |
| 823 fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP; | 829 fSrcOffsetUnits = (get_start_coord(sampleX) + fSrcOffset) * fSrcBPP; |
| 824 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP; | 830 fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP; |
| 825 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX); | 831 fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX); |
| 826 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX); | 832 fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX); |
| 827 | 833 |
| 834 // The optimized swizzler routines do not (yet) support sampling. | |
| 835 fRowProc = fScalarRowProc; | |
|
mtklein
2016/01/08 15:20:19
This preference logic might be simpler to follow g
msarett
2016/01/11 20:33:24
Done.
| |
| 836 | |
| 828 return fAllocatedWidth; | 837 return fAllocatedWidth; |
| 829 } | 838 } |
| 830 | 839 |
| 831 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC T src) { | 840 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC T src) { |
| 832 SkASSERT(nullptr != dst && nullptr != src); | 841 SkASSERT(nullptr != dst && nullptr != src); |
| 833 return fRowProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth , fSrcBPP, | 842 return fRowProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth , fSrcBPP, |
| 834 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable); | 843 fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable); |
| 835 } | 844 } |
| OLD | NEW |