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 |