Chromium Code Reviews| Index: src/core/SkLinearBitmapPipeline.cpp |
| diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
| index 4e4226a3206367770dd35682e00e856479b0b7c3..3410ec1727f54c417e7623209a35ed552f4f419e 100644 |
| --- a/src/core/SkLinearBitmapPipeline.cpp |
| +++ b/src/core/SkLinearBitmapPipeline.cpp |
| @@ -65,7 +65,10 @@ public: |
| class SkLinearBitmapPipeline::PixelPlacerInterface { |
| public: |
| virtual ~PixelPlacerInterface() { } |
| - virtual void setDestination(SkPM4f* dst) = 0; |
| + // Count is normally not needed, but in these early stages of development it is useful to |
| + // check bounds. |
| + // TODO(herb): 4/6/2016 - remove count when code is stable. |
| + virtual void setDestination(void* dst, int count) = 0; |
| virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; |
| virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0; |
| }; |
| @@ -238,6 +241,12 @@ public: |
| processor->breakIntoEdges(span); |
| } |
| + void repeatSpan(Span span, int32_t repeatCount) { |
| + while (repeatCount --> 0) { |
| + processor->pointSpan(span); |
| + } |
| + } |
| + |
| BilerpTileStage* processor; |
| }; |
| @@ -364,13 +373,21 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( |
| SkShader::TileMode xMode, |
| SkShader::TileMode yMode, |
| SkFilterQuality filterQuality, |
| - SkLinearBitmapPipeline::TileStage* tileStage) { |
| + SkScalar dx, |
| + SkLinearBitmapPipeline::TileStage* tileStage) |
| +{ |
| switch (xMode) { |
| case SkShader::kClamp_TileMode: |
| choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions, next, tileStage); |
| break; |
| case SkShader::kRepeat_TileMode: |
| - choose_tiler_ymode<XRepeatStrategy>(yMode, filterQuality, dimensions, next, tileStage); |
| + if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) { |
| + choose_tiler_ymode<XRepeatUnitScaleStrategy>( |
| + yMode, kNone_SkFilterQuality, dimensions, next, tileStage); |
| + } else { |
| + choose_tiler_ymode<XRepeatStrategy>( |
| + yMode, filterQuality, dimensions, next, tileStage); |
| + } |
| break; |
| case SkShader::kMirror_TileMode: |
| choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions, next, tileStage); |
| @@ -402,7 +419,7 @@ public: |
| fSampler.nearestSpan(span); |
| } |
| - virtual void repeatSpan(Span span, int32_t repeatCount) override { |
| + void repeatSpan(Span span, int32_t repeatCount) override { |
| while (repeatCount > 0) { |
| fSampler.nearestSpan(span); |
| repeatCount--; |
| @@ -413,7 +430,7 @@ public: |
| SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge."); |
| } |
| - virtual void bilerpSpan(Span span, SkScalar y) override { |
| + void bilerpSpan(Span span, SkScalar y) override { |
| SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan."); |
| } |
| @@ -440,7 +457,7 @@ public: |
| fSampler.bilerpSpan(span); |
| } |
| - virtual void repeatSpan(Span span, int32_t repeatCount) override { |
| + void repeatSpan(Span span, int32_t repeatCount) override { |
| while (repeatCount > 0) { |
| fSampler.bilerpSpan(span); |
| repeatCount--; |
| @@ -451,7 +468,7 @@ public: |
| fSampler.bilerpEdge(xs, ys); |
| } |
| - virtual void bilerpSpan(Span span, SkScalar y) override { |
| + void bilerpSpan(Span span, SkScalar y) override { |
| fSampler.bilerpSpanWithY(span, y); |
| } |
| @@ -515,11 +532,13 @@ 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); |
| fDst += 1; |
| } |
| void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
| + SkASSERT(fDst + 4 <= fEnd); |
| SkPM4f* dst = fDst; |
| PlacePixel(dst, p0, 0); |
| PlacePixel(dst, p1, 1); |
| @@ -528,8 +547,9 @@ public: |
| fDst += 4; |
| } |
| - void setDestination(SkPM4f* dst) override { |
| - fDst = dst; |
| + void setDestination(void* dst, int count) override { |
| + fDst = static_cast<SkPM4f*>(dst); |
| + fEnd = fDst + count; |
| } |
| private: |
| @@ -547,6 +567,7 @@ private: |
| } |
| SkPM4f* fDst; |
| + SkPM4f* fEnd; |
| Sk4f fPostAlpha; |
| }; |
| @@ -572,7 +593,8 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| SkFilterQuality filterQuality, |
| SkShader::TileMode xTile, SkShader::TileMode yTile, |
| float postAlpha, |
| - const SkPixmap& srcPixmap) { |
| + const SkPixmap& srcPixmap) |
| +{ |
|
f(malita)
2016/04/07 00:56:45
Nit: brace on prev line, per Skia style.
herb_g
2016/04/07 14:37:03
MikeR suggested I move the brace down so he can se
|
| SkISize dimensions = srcPixmap.info().dimensions(); |
| const SkImageInfo& srcImageInfo = srcPixmap.info(); |
| @@ -588,6 +610,8 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| } |
| } |
| + SkScalar dx = adjustedInverse.getScaleX(); |
| + |
| // If it is an index 8 color type, the sampler converts to unpremul for better fidelity. |
| SkAlphaType alphaType = srcImageInfo.alphaType(); |
| if (srcPixmap.colorType() == kIndex_8_SkColorType) { |
| @@ -600,13 +624,13 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| auto samplerStage = choose_pixel_sampler(placementStage, |
| filterQuality, srcPixmap, &fSampleStage); |
| auto tilerStage = choose_tiler(samplerStage, |
| - dimensions, xTile, yTile, filterQuality, &fTiler); |
| + dimensions, xTile, yTile, filterQuality, dx, &fTiler); |
| fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage); |
| } |
| void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
| SkASSERT(count > 0); |
| - fPixelStage->setDestination(dst); |
| + fPixelStage->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 |