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 |