| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 #ifndef SkLinearBitmapPipeline_sampler_DEFINED | 8 #ifndef SkLinearBitmapPipeline_sampler_DEFINED |
| 9 #define SkLinearBitmapPipeline_sampler_DEFINED | 9 #define SkLinearBitmapPipeline_sampler_DEFINED |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 Sk4s fxs = xs - xs.floor(); | 42 Sk4s fxs = xs - xs.floor(); |
| 43 Sk4s fys = ys - ys.floor(); | 43 Sk4s fys = ys - ys.floor(); |
| 44 Sk4s fxys{fxs * fys}; | 44 Sk4s fxys{fxs * fys}; |
| 45 Sk4f sum = px11 * fxys; | 45 Sk4f sum = px11 * fxys; |
| 46 sum = sum + px01 * (fys - fxys); | 46 sum = sum + px01 * (fys - fxys); |
| 47 sum = sum + px10 * (fxs - fxys); | 47 sum = sum + px10 * (fxs - fxys); |
| 48 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); | 48 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); |
| 49 return sum; | 49 return sum; |
| 50 } | 50 } |
| 51 | 51 |
| 52 template<typename SourceStrategy, typename Next> | 52 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 53 // PixelGetter is the lowest level interface to the source data. There is a Pixe
lGetter for each |
| 54 // of the different SkColorTypes. |
| 55 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; |
| 56 |
| 57 template <SkColorProfileType colorProfile> |
| 58 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { |
| 59 public: |
| 60 using Element = uint32_t; |
| 61 PixelGetter(const SkPixmap& srcPixmap) { } |
| 62 |
| 63 Sk4f getPixelAt(const uint32_t* src) { |
| 64 return colorProfile == kSRGB_SkColorProfileType |
| 65 ? Sk4f_fromS32(*src) |
| 66 : Sk4f_fromL32(*src); |
| 67 } |
| 68 }; |
| 69 |
| 70 template <SkColorProfileType colorProfile> |
| 71 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { |
| 72 public: |
| 73 using Element = uint32_t; |
| 74 PixelGetter(const SkPixmap& srcPixmap) { } |
| 75 |
| 76 Sk4f getPixelAt(const uint32_t* src) { |
| 77 Sk4f pixel = colorProfile == kSRGB_SkColorProfileType |
| 78 ? Sk4f_fromS32(*src) |
| 79 : Sk4f_fromL32(*src); |
| 80 return SkNx_shuffle<2, 1, 0, 3>(pixel); |
| 81 } |
| 82 }; |
| 83 |
| 84 template <SkColorProfileType colorProfile> |
| 85 class PixelGetter<kIndex_8_SkColorType, colorProfile> { |
| 86 public: |
| 87 using Element = uint8_t; |
| 88 PixelGetter(const SkPixmap& srcPixmap) { |
| 89 SkColorTable* skColorTable = srcPixmap.ctable(); |
| 90 SkASSERT(skColorTable != nullptr); |
| 91 |
| 92 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 93 for (int i = 0; i < skColorTable->count(); i++) { |
| 94 fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
| 95 } |
| 96 } |
| 97 |
| 98 PixelGetter(const PixelGetter& strategy) { |
| 99 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 100 // TODO: figure out the count. |
| 101 for (int i = 0; i < 256; i++) { |
| 102 fColorTable[i] = strategy.fColorTable[i]; |
| 103 } |
| 104 } |
| 105 |
| 106 Sk4f getPixelAt(const uint8_t* src) { |
| 107 return fColorTable[*src]; |
| 108 } |
| 109 |
| 110 private: |
| 111 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
| 112 Sk4f convertPixel(SkPMColor pmColor) { |
| 113 Sk4f pixel = to_4f(pmColor); |
| 114 float alpha = get_alpha(pixel); |
| 115 if (alpha != 0.0f) { |
| 116 float invAlpha = 1.0f / alpha; |
| 117 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
| 118 pixel = pixel * normalize; |
| 119 if (colorProfile == kSRGB_SkColorProfileType) { |
| 120 pixel = linear_to_srgb(pixel); |
| 121 } |
| 122 return pixel; |
| 123 } else { |
| 124 return Sk4f{0.0f}; |
| 125 } |
| 126 } |
| 127 SkAutoMalloc fColorTableStorage{kColorTableSize}; |
| 128 Sk4f* fColorTable; |
| 129 }; |
| 130 |
| 131 template <> |
| 132 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { |
| 133 public: |
| 134 using Element = uint64_t; |
| 135 PixelGetter(const SkPixmap& srcPixmap) { } |
| 136 |
| 137 Sk4f getPixelAt(const uint64_t* src) { |
| 138 return SkHalfToFloat_01(*src); |
| 139 } |
| 140 }; |
| 141 |
| 142 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 143 // PixelAccessor handles all the same plumbing for all the PixelGetters. |
| 144 template <SkColorType colorType, SkColorProfileType colorProfile> |
| 145 class PixelAccessor { |
| 146 using Element = typename PixelGetter<colorType, colorProfile>::Element; |
| 147 public: |
| 148 PixelAccessor(const SkPixmap& srcPixmap) |
| 149 : fSrc{static_cast<const Element*>(srcPixmap.addr())} |
| 150 , fWidth{srcPixmap.rowBytesAsPixels()} |
| 151 , fGetter{srcPixmap} { } |
| 152 |
| 153 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { |
| 154 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 155 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 156 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 157 switch (n) { |
| 158 case 3: |
| 159 *px2 = this->getPixelAt(bufferLoc[2]); |
| 160 case 2: |
| 161 *px1 = this->getPixelAt(bufferLoc[1]); |
| 162 case 1: |
| 163 *px0 = this->getPixelAt(bufferLoc[0]); |
| 164 default: |
| 165 break; |
| 166 } |
| 167 } |
| 168 |
| 169 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { |
| 170 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 171 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 172 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 173 *px0 = this->getPixelAt(bufferLoc[0]); |
| 174 *px1 = this->getPixelAt(bufferLoc[1]); |
| 175 *px2 = this->getPixelAt(bufferLoc[2]); |
| 176 *px3 = this->getPixelAt(bufferLoc[3]); |
| 177 } |
| 178 |
| 179 void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2,
Sk4f* px3) { |
| 180 *px0 = this->getPixelFromRow(src, index + 0); |
| 181 *px1 = this->getPixelFromRow(src, index + 1); |
| 182 *px2 = this->getPixelFromRow(src, index + 2); |
| 183 *px3 = this->getPixelFromRow(src, index + 3); |
| 184 } |
| 185 |
| 186 Sk4f getPixelFromRow(const void* row, int index) { |
| 187 const Element* src = static_cast<const Element*>(row); |
| 188 return fGetter.getPixelAt(src + index); |
| 189 } |
| 190 |
| 191 Sk4f getPixelAt(int index) { |
| 192 return this->getPixelFromRow(fSrc, index); |
| 193 } |
| 194 |
| 195 const void* row(int y) const { return fSrc + y * fWidth[0]; } |
| 196 |
| 197 private: |
| 198 const Element* const fSrc; |
| 199 const Sk4i fWidth; |
| 200 PixelGetter<colorType, colorProfile> fGetter; |
| 201 }; |
| 202 |
| 203 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 204 // GeneralSampler handles all the different sampling scenarios. It makes runtime
decisions to |
| 205 // choose the fastest stratagy given a particular job. It ultimately uses PixelG
etters to access |
| 206 // the pixels. |
| 207 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> |
| 53 class GeneralSampler { | 208 class GeneralSampler { |
| 54 public: | 209 public: |
| 55 template<typename... Args> | 210 template<typename... Args> |
| 56 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) | 211 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) |
| 57 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } | 212 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
| 58 | 213 |
| 59 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, | 214 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, |
| 60 const GeneralSampler& sampler) | 215 const GeneralSampler& sampler) |
| 61 : fNext{next}, fStrategy{sampler.fStrategy} { } | 216 : fNext{next}, fStrategy{sampler.fStrategy} { } |
| 62 | 217 |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 while (count > 0) { | 705 while (count > 0) { |
| 551 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; | 706 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; |
| 552 this->bilerpEdge(xs, ys); | 707 this->bilerpEdge(xs, ys); |
| 553 x += dx; | 708 x += dx; |
| 554 count -= 1; | 709 count -= 1; |
| 555 } | 710 } |
| 556 } | 711 } |
| 557 } | 712 } |
| 558 | 713 |
| 559 Next* const fNext; | 714 Next* const fNext; |
| 560 SourceStrategy fStrategy; | 715 PixelAccessor<colorType, colorProfile> fStrategy; |
| 561 }; | 716 }; |
| 562 | 717 |
| 563 template <typename PixelGetter> | |
| 564 class PixelAccessor { | |
| 565 public: | |
| 566 PixelAccessor(const SkPixmap& srcPixmap) | |
| 567 : fWidth{srcPixmap.rowBytesAsPixels()} | |
| 568 , fGetter{srcPixmap} { } | |
| 569 | |
| 570 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | |
| 571 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
| 572 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 573 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 574 switch (n) { | |
| 575 case 3: | |
| 576 *px2 = fGetter.getPixelAt(bufferLoc[2]); | |
| 577 case 2: | |
| 578 *px1 = fGetter.getPixelAt(bufferLoc[1]); | |
| 579 case 1: | |
| 580 *px0 = fGetter.getPixelAt(bufferLoc[0]); | |
| 581 default: | |
| 582 break; | |
| 583 } | |
| 584 } | |
| 585 | |
| 586 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
| 587 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
| 588 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 589 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 590 *px0 = fGetter.getPixelAt(bufferLoc[0]); | |
| 591 *px1 = fGetter.getPixelAt(bufferLoc[1]); | |
| 592 *px2 = fGetter.getPixelAt(bufferLoc[2]); | |
| 593 *px3 = fGetter.getPixelAt(bufferLoc[3]); | |
| 594 } | |
| 595 | |
| 596 void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2,
Sk4f* px3) { | |
| 597 *px0 = fGetter.getPixelFromRow(src, index + 0); | |
| 598 *px1 = fGetter.getPixelFromRow(src, index + 1); | |
| 599 *px2 = fGetter.getPixelFromRow(src, index + 2); | |
| 600 *px3 = fGetter.getPixelFromRow(src, index + 3); | |
| 601 } | |
| 602 | |
| 603 Sk4f getPixelFromRow(const void* row, int index) { | |
| 604 return fGetter.getPixelFromRow(row, index); | |
| 605 } | |
| 606 | |
| 607 const void* row(int y) { return fGetter.row(y); } | |
| 608 | |
| 609 private: | |
| 610 const Sk4i fWidth; | |
| 611 PixelGetter fGetter; | |
| 612 }; | |
| 613 | |
| 614 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; | |
| 615 | |
| 616 template <SkColorProfileType colorProfile> | |
| 617 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { | |
| 618 public: | |
| 619 PixelGetter(const SkPixmap& srcPixmap) | |
| 620 : fSrc{srcPixmap.addr32()} | |
| 621 , fWidth{srcPixmap.rowBytesAsPixels()} { } | |
| 622 | |
| 623 Sk4f getPixelFromRow(const void* row, int index) { | |
| 624 const uint32_t* src = static_cast<const uint32_t*>(row) + index; | |
| 625 return colorProfile == kSRGB_SkColorProfileType | |
| 626 ? Sk4f_fromS32(*src) | |
| 627 : Sk4f_fromL32(*src); | |
| 628 } | |
| 629 | |
| 630 Sk4f getPixelAt(int index) { | |
| 631 return this->getPixelFromRow(fSrc, index); | |
| 632 } | |
| 633 | |
| 634 const void* row(int y) { return fSrc + y * fWidth; } | |
| 635 | |
| 636 private: | |
| 637 const uint32_t* const fSrc; | |
| 638 const int fWidth; | |
| 639 }; | |
| 640 | |
| 641 using Pixel8888SRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
| 642 using Pixel8888LRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kLinear_
SkColorProfileType>>; | |
| 643 | |
| 644 template <SkColorProfileType colorProfile> | |
| 645 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { | |
| 646 public: | |
| 647 PixelGetter(const SkPixmap& srcPixmap) | |
| 648 : fSrc{srcPixmap.addr32()} | |
| 649 , fWidth{srcPixmap.rowBytesAsPixels()} { } | |
| 650 | |
| 651 Sk4f getPixelFromRow(const void* row, int index) { | |
| 652 const uint32_t* src = static_cast<const uint32_t*>(row) + index; | |
| 653 Sk4f pixel = colorProfile == kSRGB_SkColorProfileType | |
| 654 ? Sk4f_fromS32(*src) | |
| 655 : Sk4f_fromL32(*src); | |
| 656 return SkNx_shuffle<2, 1, 0, 3>(pixel); | |
| 657 } | |
| 658 | |
| 659 Sk4f getPixelAt(int index) { | |
| 660 return this->getPixelFromRow(fSrc, index); | |
| 661 } | |
| 662 | |
| 663 const void* row(int y) { return fSrc + y * fWidth; } | |
| 664 | |
| 665 private: | |
| 666 const uint32_t* const fSrc; | |
| 667 const int fWidth; | |
| 668 }; | |
| 669 | |
| 670 using Pixel8888SBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
| 671 using Pixel8888LBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kLinear_
SkColorProfileType>>; | |
| 672 | |
| 673 template <SkColorProfileType colorProfile> | |
| 674 class PixelGetter<kIndex_8_SkColorType, colorProfile> { | |
| 675 public: | |
| 676 PixelGetter(const SkPixmap& srcPixmap) | |
| 677 : fSrc{srcPixmap.addr8()}, fWidth{static_cast<int>(srcPixmap.rowBytes())
} { | |
| 678 SkASSERT(srcPixmap.colorType() == kIndex_8_SkColorType); | |
| 679 SkColorTable* skColorTable = srcPixmap.ctable(); | |
| 680 SkASSERT(skColorTable != nullptr); | |
| 681 | |
| 682 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | |
| 683 for (int i = 0; i < skColorTable->count(); i++) { | |
| 684 fColorTable[i] = this->convertPixel((*skColorTable)[i]); | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 PixelGetter(const PixelGetter& strategy) | |
| 689 : fSrc{strategy.fSrc}, fWidth{strategy.fWidth} { | |
| 690 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | |
| 691 // TODO: figure out the count. | |
| 692 for (int i = 0; i < 256; i++) { | |
| 693 fColorTable[i] = strategy.fColorTable[i]; | |
| 694 } | |
| 695 } | |
| 696 | |
| 697 Sk4f getPixelFromRow(const void* row, int index) { | |
| 698 const uint8_t* src = static_cast<const uint8_t*>(row) + index; | |
| 699 Sk4f pixel = fColorTable[*src]; | |
| 700 return pixel; | |
| 701 } | |
| 702 | |
| 703 Sk4f getPixelAt(int index) { | |
| 704 return this->getPixelFromRow(fSrc, index); | |
| 705 } | |
| 706 | |
| 707 const void* row(int y) { return fSrc + y * fWidth; } | |
| 708 | |
| 709 private: | |
| 710 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; | |
| 711 Sk4f convertPixel(SkPMColor pmColor) { | |
| 712 Sk4f pixel = to_4f(pmColor); | |
| 713 float alpha = get_alpha(pixel); | |
| 714 if (alpha != 0.0f) { | |
| 715 float invAlpha = 1.0f / alpha; | |
| 716 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; | |
| 717 pixel = pixel * normalize; | |
| 718 if (colorProfile == kSRGB_SkColorProfileType) { | |
| 719 pixel = linear_to_srgb(pixel); | |
| 720 } | |
| 721 return pixel; | |
| 722 } else { | |
| 723 return Sk4f{0.0f}; | |
| 724 } | |
| 725 } | |
| 726 const uint8_t* const fSrc; | |
| 727 const int fWidth; | |
| 728 SkAutoMalloc fColorTableStorage{kColorTableSize}; | |
| 729 Sk4f* fColorTable; | |
| 730 }; | |
| 731 | |
| 732 using PixelIndex8SRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
| 733 using PixelIndex8LRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kLinear_
SkColorProfileType>>; | |
| 734 | |
| 735 template <> | |
| 736 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { | |
| 737 public: | |
| 738 PixelGetter(const SkPixmap& srcPixmap) | |
| 739 : fSrc{srcPixmap.addr64()} | |
| 740 , fWidth{static_cast<int>(srcPixmap.rowBytesAsPixels())} { } | |
| 741 | |
| 742 Sk4f getPixelFromRow(const void* row, int index) { | |
| 743 const uint64_t* src = static_cast<const uint64_t*>(row) + index; | |
| 744 return SkHalfToFloat_01(*src); | |
| 745 } | |
| 746 | |
| 747 Sk4f getPixelAt(int index) { | |
| 748 return this->getPixelFromRow(fSrc, index); | |
| 749 } | |
| 750 | |
| 751 const void* row(int y) { return fSrc + y * fWidth; } | |
| 752 | |
| 753 private: | |
| 754 const uint64_t* const fSrc; | |
| 755 const int fWidth; | |
| 756 }; | |
| 757 | |
| 758 using PixelHalfLinear = PixelAccessor<PixelGetter<kRGBA_F16_SkColorType, kLinear
_SkColorProfileType>>; | |
| 759 | 718 |
| 760 } // namespace | 719 } // namespace |
| 761 | 720 |
| 762 #endif // SkLinearBitmapPipeline_sampler_DEFINED | 721 #endif // SkLinearBitmapPipeline_sampler_DEFINED |
| OLD | NEW |