Chromium Code Reviews| Index: src/core/SkLinearBitmapPipeline.cpp |
| diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
| index 3410ec1727f54c417e7623209a35ed552f4f419e..dc2ee513ca259b00ac577190c4b1c38f51744fbf 100644 |
| --- a/src/core/SkLinearBitmapPipeline.cpp |
| +++ b/src/core/SkLinearBitmapPipeline.cpp |
| @@ -62,7 +62,14 @@ public: |
| virtual void bilerpSpan(Span span, SkScalar y) = 0; |
| }; |
| -class SkLinearBitmapPipeline::PixelPlacerInterface { |
| +class SkLinearBitmapPipeline::DestinationInterface { |
| +public: |
| + virtual ~DestinationInterface() { } |
| + virtual void setDestination(void* dst, int count) = 0; |
| +}; |
| + |
| +class SkLinearBitmapPipeline::PixelPlacerInterface |
| + : public SkLinearBitmapPipeline::DestinationInterface { |
| public: |
| virtual ~PixelPlacerInterface() { } |
| // Count is normally not needed, but in these early stages of development it is useful to |
| @@ -397,7 +404,6 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( |
| return tileStage->get(); |
| } |
| - |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // Source Sampling Stage |
| template <typename SourceStrategy, typename Next> |
| @@ -476,6 +482,78 @@ private: |
| GeneralSampler<SourceStrategy, Next> fSampler; |
| }; |
| +// RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the src and destination |
| +// are the same format and do not need in transformations in pixel space. Therefore, there is no |
| +// need to convert them to HiFi pixel format. |
| +class RGBA8888UnitRepeat final : public SkLinearBitmapPipeline::SampleProcessorInterface, |
| + public SkLinearBitmapPipeline::DestinationInterface { |
| +public: |
| + RGBA8888UnitRepeat(const uint32_t* src, int32_t width) |
| + : fSrc{src}, fWidth{width} { } |
| + |
| + void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
| + SkASSERT(fDest + n <= fEnd); |
| + // At this point xs and ys should be >= 0, so trunc is the same as floor. |
| + Sk4i iXs = SkNx_cast<int>(xs); |
| + Sk4i iYs = SkNx_cast<int>(ys); |
| + |
| + if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]); |
| + if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]); |
| + if (n >= 3) *fDest++ = *this->pixelAddress(iXs[2], iYs[2]); |
| + } |
| + |
| + void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
| + SkASSERT(fDest + 4 <= fEnd); |
| + Sk4i iXs = SkNx_cast<int>(xs); |
| + Sk4i iYs = SkNx_cast<int>(ys); |
| + *fDest++ = *this->pixelAddress(iXs[0], iYs[0]); |
| + *fDest++ = *this->pixelAddress(iXs[1], iYs[1]); |
| + *fDest++ = *this->pixelAddress(iXs[2], iYs[2]); |
| + *fDest++ = *this->pixelAddress(iXs[3], iYs[3]); |
| + } |
| + |
| + void pointSpan(Span span) override { |
| + SkASSERT(fDest + span.count() <= fEnd); |
| + int32_t x = (int32_t)span.startX(); |
| + int32_t y = (int32_t)span.startY(); |
| + const uint32_t* src = this->pixelAddress(x, y); |
| + memmove(fDest, src, span.count() * sizeof(uint32_t)); |
| + fDest += span.count(); |
| + } |
| + |
| + void repeatSpan(Span span, int32_t repeatCount) override { |
| + SkASSERT(fDest + span.count() * repeatCount <= fEnd); |
| + |
| + int32_t x = (int32_t)span.startX(); |
| + int32_t y = (int32_t)span.startY(); |
| + const uint32_t* src = this->pixelAddress(x, y); |
| + uint32_t* dest = fDest; |
| + while (repeatCount --> 0) { |
| + memmove(dest, src, span.count() * sizeof(uint32_t)); |
| + dest += span.count(); |
| + } |
| + fDest = dest; |
| + } |
| + |
| + void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Implemented"); } |
| + |
| + void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); } |
| + |
| + void setDestination(void* dst, int count) override { |
| + fDest = static_cast<uint32_t*>(dst); |
| + fEnd = fDest + count; |
| + } |
| + |
| +private: |
| + const uint32_t* pixelAddress(int32_t x, int32_t y) { |
| + return &fSrc[fWidth * y + x]; |
|
f(malita)
2016/04/08 12:58:12
Do we need to worry about row padding here or rowb
herb_g
2016/04/08 13:48:59
I talked with MikeR about this. RowBytes must alwa
|
| + } |
| + const uint32_t* const fSrc; |
| + const int32_t fWidth; |
| + uint32_t* fDest; |
| + uint32_t* fEnd; |
| +}; |
| + |
| using Placer = SkLinearBitmapPipeline::PixelPlacerInterface; |
| template<template <typename, typename> class Sampler> |
| @@ -531,6 +609,7 @@ template <SkAlphaType alphaType> |
| class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { |
| public: |
| PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
| + |
| void VECTORCALL placePixel(Sk4f pixel) override { |
| SkASSERT(fDst + 1 <= fEnd ); |
| PlacePixel(fDst, pixel, 0); |
| @@ -626,11 +705,14 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| auto tilerStage = choose_tiler(samplerStage, |
| dimensions, xTile, yTile, filterQuality, dx, &fTiler); |
| fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage); |
| + fLastStage = placementStage; |
| + |
| } |
| void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
| SkASSERT(count > 0); |
| - fPixelStage->setDestination(dst, count); |
| + fLastStage->setDestination(dst, count); |
| + |
| // The count and length arguments start out in a precise relation in order to keep the |
| // math correct through the different stages. Count is the number of pixel to produce. |
| // Since the code samples at pixel centers, length is the distance from the center of the |