Chromium Code Reviews| 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 #include "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
| 9 #include "SkPM4f.h" | 9 #include "SkPM4f.h" |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <cmath> | 12 #include <cmath> |
| 13 #include <limits> | 13 #include <limits> |
| 14 #include "SkColor.h" | 14 #include "SkColor.h" |
| 15 #include "SkSize.h" | 15 #include "SkSize.h" |
| 16 | 16 |
| 17 // Tweak ABI of functions that pass Sk4f by value to pass them via registers. | |
| 18 #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | |
| 19 #define VECTORCALL __vectorcall | |
| 20 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON) | |
| 21 #define VECTORCALL __attribute__((pcs("aapcs-vfp"))) | |
| 22 #else | |
| 23 #define VECTORCALL | |
| 24 #endif | |
| 25 | |
| 26 class SkLinearBitmapPipeline::PointProcessorInterface { | |
| 27 public: | |
| 28 virtual ~PointProcessorInterface() { } | |
| 29 virtual void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) = 0; | |
| 30 virtual void VECTORCALL pointList4(Sk4f xs, Sk4f ys) = 0; | |
| 31 | |
| 32 // The pointSpan method efficiently process horizontal spans of pixels. | |
| 33 // * start - the point where to start the span. | |
| 34 // * length - the number of pixels to traverse in source space. | |
| 35 // * count - the number of pixels to produce in destination space. | |
| 36 // Both start and length are mapped through the inversion matrix to produce values in source | |
| 37 // space. After the matrix operation, the tilers may break the spans up into smaller spans. | |
| 38 // The tilers can produce spans that seem nonsensical. | |
| 39 // * The clamp tiler can create spans with length of 0. This indicates to co py an edge pixel out | |
| 40 // to the edge of the destination scan. | |
| 41 // * The mirror tiler can produce spans with negative length. This indicates that the source | |
| 42 // should be traversed in the opposite direction to the destination pixels . | |
| 43 virtual void pointSpan(SkPoint start, SkScalar length, int count) = 0; | |
| 44 }; | |
| 45 | |
| 46 class SkLinearBitmapPipeline::BilerpProcessorInterface | |
| 47 : public SkLinearBitmapPipeline::PointProcessorInterface { | |
| 48 public: | |
| 49 // The x's and y's are setup in the following order: | |
| 50 // +--------+--------+ | |
| 51 // | | | | |
| 52 // | px00 | px10 | | |
| 53 // | 0 | 1 | | |
| 54 // +--------+--------+ | |
| 55 // | | | | |
| 56 // | px01 | px11 | | |
| 57 // | 2 | 3 | | |
| 58 // +--------+--------+ | |
| 59 // These pixels coordinates are arranged in the following order in xs and ys : | |
| 60 // px00 px10 px01 px11 | |
| 61 virtual void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) = 0; | |
| 62 }; | |
| 63 | |
| 64 class SkLinearBitmapPipeline::PixelPlacerInterface { | |
| 65 public: | |
| 66 virtual ~PixelPlacerInterface() { } | |
| 67 virtual void setDestination(SkPM4f* dst) = 0; | |
| 68 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; | |
| 69 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; | |
| 70 }; | |
| 71 | |
| 72 namespace { | |
| 73 | |
| 17 struct X { | 74 struct X { |
| 18 explicit X(SkScalar val) : fVal{val} { } | 75 explicit X(SkScalar val) : fVal{val} { } |
| 19 explicit X(SkPoint pt) : fVal{pt.fX} { } | 76 explicit X(SkPoint pt) : fVal{pt.fX} { } |
| 20 explicit X(SkSize s) : fVal{s.fWidth} { } | 77 explicit X(SkSize s) : fVal{s.fWidth} { } |
| 21 explicit X(SkISize s) : fVal(s.fWidth) { } | 78 explicit X(SkISize s) : fVal(s.fWidth) { } |
| 22 operator float () const {return fVal;} | 79 operator float () const {return fVal;} |
| 23 private: | 80 private: |
| 24 float fVal; | 81 float fVal; |
| 25 }; | 82 }; |
| 26 | 83 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 // to work over. | 118 // to work over. |
| 62 // start - is the starting pixel. This is in destination space before the matr ix stage, and in | 119 // start - is the starting pixel. This is in destination space before the matr ix stage, and in |
| 63 // source space after the matrix stage. | 120 // source space after the matrix stage. |
| 64 // length - is this distance between the first pixel center and the last pixel center. Like start, | 121 // length - is this distance between the first pixel center and the last pixel center. Like start, |
| 65 // this is in destination space before the matrix stage, and in source space after. | 122 // this is in destination space before the matrix stage, and in source space after. |
| 66 // count - the number of pixels in source space to produce. | 123 // count - the number of pixels in source space to produce. |
| 67 // next - a pointer to the next stage. | 124 // next - a pointer to the next stage. |
| 68 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to | 125 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to |
| 69 // point lists for processing. | 126 // point lists for processing. |
| 70 template<typename Strategy, typename Next> | 127 template<typename Strategy, typename Next> |
| 71 class PointProcessor final : public PointProcessorInterface { | 128 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace { |
| 72 public: | 129 public: |
| 73 template <typename... Args> | 130 template <typename... Args> |
| 74 PointProcessor(Next* next, Args&&... args) | 131 PointProcessor(Next* next, Args&&... args) |
| 75 : fNext{next} | 132 : fNext{next} |
| 76 , fStrategy{std::forward<Args>(args)...}{ } | 133 , fStrategy{std::forward<Args>(args)...}{ } |
| 77 | 134 |
| 78 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 135 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
| 79 Sk4f newXs = xs; | 136 Sk4f newXs = xs; |
| 80 Sk4f newYs = ys; | 137 Sk4f newYs = ys; |
|
f(malita)
2016/02/22 22:48:08
Are the locals still needed?
mtklein
2016/02/22 23:00:55
Nope.
| |
| 81 fStrategy.processPoints(&newXs, &newYs); | 138 fStrategy.processPoints(&newXs, &newYs); |
| 82 fNext->pointListFew(n, newXs, newYs); | 139 fNext->pointListFew(n, newXs, newYs); |
| 83 } | 140 } |
| 84 | 141 |
| 85 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 142 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
| 86 Sk4f newXs = xs; | 143 Sk4f newXs = xs; |
| 87 Sk4f newYs = ys; | 144 Sk4f newYs = ys; |
| 88 fStrategy.processPoints(&newXs, &newYs); | 145 fStrategy.processPoints(&newXs, &newYs); |
| 89 fNext->pointList4(newXs, newYs); | 146 fNext->pointList4(newXs, newYs); |
| 90 } | 147 } |
| 91 | 148 |
| 92 void pointSpan(SkPoint start, SkScalar length, int count) override { | 149 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 93 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { | 150 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
| 94 span_fallback(start, length, count, this); | 151 span_fallback(start, length, count, this); |
| 95 } | 152 } |
| 96 } | 153 } |
| 97 | 154 |
| 98 private: | 155 private: |
| 99 Next* const fNext; | 156 Next* const fNext; |
| 100 Strategy fStrategy; | 157 Strategy fStrategy; |
| 101 }; | 158 }; |
| 102 | 159 |
| 103 // See PointProcessor for responsibilities of Strategy. | 160 // See PointProcessor for responsibilities of Strategy. |
| 104 template<typename Strategy, typename Next> | 161 template<typename Strategy, typename Next> |
| 105 class BilerpProcessor final : public BilerpProcessorInterface { | 162 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface { |
| 106 public: | 163 public: |
| 107 template <typename... Args> | 164 template <typename... Args> |
| 108 BilerpProcessor(Next* next, Args&&... args) | 165 BilerpProcessor(Next* next, Args&&... args) |
| 109 : fNext{next} | 166 : fNext{next} |
| 110 , fStrategy{std::forward<Args>(args)...}{ } | 167 , fStrategy{std::forward<Args>(args)...}{ } |
| 111 | 168 |
| 112 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 169 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
| 113 Sk4f newXs = xs; | 170 Sk4f newXs = xs; |
| 114 Sk4f newYs = ys; | 171 Sk4f newYs = ys; |
| 115 fStrategy.processPoints(&newXs, &newYs); | 172 fStrategy.processPoints(&newXs, &newYs); |
| 116 fNext->pointListFew(n, newXs, newYs); | 173 fNext->pointListFew(n, newXs, newYs); |
| 117 } | 174 } |
| 118 | 175 |
| 119 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 176 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
| 120 Sk4f newXs = xs; | 177 Sk4f newXs = xs; |
| 121 Sk4f newYs = ys; | 178 Sk4f newYs = ys; |
| 122 fStrategy.processPoints(&newXs, &newYs); | 179 fStrategy.processPoints(&newXs, &newYs); |
| 123 fNext->pointList4(newXs, newYs); | 180 fNext->pointList4(newXs, newYs); |
| 124 } | 181 } |
| 125 | 182 |
| 126 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 183 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
| 127 Sk4f newXs = xs; | 184 Sk4f newXs = xs; |
| 128 Sk4f newYs = ys; | 185 Sk4f newYs = ys; |
| 129 fStrategy.processPoints(&newXs, &newYs); | 186 fStrategy.processPoints(&newXs, &newYs); |
| 130 fNext->bilerpList(newXs, newYs); | 187 fNext->bilerpList(newXs, newYs); |
| 131 } | 188 } |
| 132 | 189 |
| 133 void pointSpan(SkPoint start, SkScalar length, int count) override { | 190 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 134 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { | 191 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
| 135 span_fallback(start, length, count, this); | 192 span_fallback(start, length, count, this); |
| 136 } | 193 } |
| 137 } | 194 } |
| 138 | 195 |
| 139 private: | 196 private: |
| 140 Next* const fNext; | 197 Next* const fNext; |
| 141 Strategy fStrategy; | 198 Strategy fStrategy; |
| 142 }; | 199 }; |
| 143 | 200 |
| 144 class SkippedStage final : public BilerpProcessorInterface { | 201 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce { |
| 145 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 202 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
| 146 SkFAIL("Skipped stage."); | 203 SkFAIL("Skipped stage."); |
| 147 } | 204 } |
| 148 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { | 205 void VECTORCALL pointList4(Sk4f Xs, Sk4f Ys) override { |
| 149 SkFAIL("Skipped stage."); | 206 SkFAIL("Skipped stage."); |
| 150 } | 207 } |
| 151 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 208 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
| 152 SkFAIL("Skipped stage."); | 209 SkFAIL("Skipped stage."); |
| 153 } | 210 } |
| 154 void pointSpan(SkPoint start, SkScalar length, int count) override { | 211 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 155 SkFAIL("Skipped stage."); | 212 SkFAIL("Skipped stage."); |
| 156 } | 213 } |
| 157 }; | 214 }; |
| 158 | 215 |
| 159 class TranslateMatrixStrategy { | 216 class TranslateMatrixStrategy { |
| 160 public: | 217 public: |
| 161 TranslateMatrixStrategy(SkVector offset) | 218 TranslateMatrixStrategy(SkVector offset) |
| 162 : fXOffset{X(offset)} | 219 : fXOffset{X(offset)} |
| 163 , fYOffset{Y(offset)} { } | 220 , fYOffset{Y(offset)} { } |
| 164 | 221 |
| 165 void processPoints(Sk4f* xs, Sk4f* ys) { | 222 void processPoints(Sk4f* xs, Sk4f* ys) { |
| 166 *xs = *xs + fXOffset; | 223 *xs = *xs + fXOffset; |
| 167 *ys = *ys + fYOffset; | 224 *ys = *ys + fYOffset; |
| 168 } | 225 } |
| 169 | 226 |
| 170 template <typename Next> | 227 template <typename Next> |
| 171 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 228 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
| 172 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count ); | 229 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count ); |
| 173 return true; | 230 return true; |
| 174 } | 231 } |
| 175 | 232 |
| 176 private: | 233 private: |
| 177 const Sk4f fXOffset, fYOffset; | 234 const Sk4f fXOffset, fYOffset; |
| 178 }; | 235 }; |
| 179 template <typename Next = PointProcessorInterface> | 236 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
| 180 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; | 237 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; |
| 181 | 238 |
| 182 class ScaleMatrixStrategy { | 239 class ScaleMatrixStrategy { |
| 183 public: | 240 public: |
| 184 ScaleMatrixStrategy(SkVector offset, SkVector scale) | 241 ScaleMatrixStrategy(SkVector offset, SkVector scale) |
| 185 : fXOffset{X(offset)}, fYOffset{Y(offset)} | 242 : fXOffset{X(offset)}, fYOffset{Y(offset)} |
| 186 , fXScale{X(scale)}, fYScale{Y(scale)} { } | 243 , fXScale{X(scale)}, fYScale{Y(scale)} { } |
| 187 void processPoints(Sk4f* xs, Sk4f* ys) { | 244 void processPoints(Sk4f* xs, Sk4f* ys) { |
| 188 *xs = *xs * fXScale + fXOffset; | 245 *xs = *xs * fXScale + fXOffset; |
| 189 *ys = *ys * fYScale + fYOffset; | 246 *ys = *ys * fYScale + fYOffset; |
| 190 } | 247 } |
| 191 | 248 |
| 192 template <typename Next> | 249 template <typename Next> |
| 193 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 250 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
| 194 SkPoint newStart = | 251 SkPoint newStart = |
| 195 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; | 252 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; |
| 196 SkScalar newLength = length * fXScale[0]; | 253 SkScalar newLength = length * fXScale[0]; |
| 197 next->pointSpan(newStart, newLength, count); | 254 next->pointSpan(newStart, newLength, count); |
| 198 return true; | 255 return true; |
| 199 } | 256 } |
| 200 | 257 |
| 201 private: | 258 private: |
| 202 const Sk4f fXOffset, fYOffset; | 259 const Sk4f fXOffset, fYOffset; |
| 203 const Sk4f fXScale, fYScale; | 260 const Sk4f fXScale, fYScale; |
| 204 }; | 261 }; |
| 205 template <typename Next = PointProcessorInterface> | 262 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
| 206 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; | 263 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; |
| 207 | 264 |
| 208 class AffineMatrixStrategy { | 265 class AffineMatrixStrategy { |
| 209 public: | 266 public: |
| 210 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) | 267 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) |
| 211 : fXOffset{X(offset)}, fYOffset{Y(offset)} | 268 : fXOffset{X(offset)}, fYOffset{Y(offset)} |
| 212 , fXScale{X(scale)}, fYScale{Y(scale)} | 269 , fXScale{X(scale)}, fYScale{Y(scale)} |
| 213 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } | 270 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } |
| 214 void processPoints(Sk4f* xs, Sk4f* ys) { | 271 void processPoints(Sk4f* xs, Sk4f* ys) { |
| 215 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; | 272 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; |
| 216 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; | 273 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; |
| 217 | 274 |
| 218 *xs = newXs; | 275 *xs = newXs; |
| 219 *ys = newYs; | 276 *ys = newYs; |
| 220 } | 277 } |
| 221 | 278 |
| 222 template <typename Next> | 279 template <typename Next> |
| 223 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 280 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
| 224 return false; | 281 return false; |
| 225 } | 282 } |
| 226 | 283 |
| 227 private: | 284 private: |
| 228 const Sk4f fXOffset, fYOffset; | 285 const Sk4f fXOffset, fYOffset; |
| 229 const Sk4f fXScale, fYScale; | 286 const Sk4f fXScale, fYScale; |
| 230 const Sk4f fXSkew, fYSkew; | 287 const Sk4f fXSkew, fYSkew; |
| 231 }; | 288 }; |
| 232 template <typename Next = PointProcessorInterface> | 289 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
| 233 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; | 290 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; |
| 234 | 291 |
| 235 static PointProcessorInterface* choose_matrix( | 292 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( |
| 236 PointProcessorInterface* next, | 293 SkLinearBitmapPipeline::PointProcessorInterface* next, |
| 237 const SkMatrix& inverse, | 294 const SkMatrix& inverse, |
| 238 SkLinearBitmapPipeline::MatrixStage* matrixProc) { | 295 SkLinearBitmapPipeline::MatrixStage* matrixProc) { |
| 239 if (inverse.hasPerspective()) { | 296 if (inverse.hasPerspective()) { |
| 240 SkFAIL("Not implemented."); | 297 SkFAIL("Not implemented."); |
| 241 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { | 298 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { |
| 242 matrixProc->Initialize<AffineMatrix<>>( | 299 matrixProc->Initialize<AffineMatrix<>>( |
| 243 next, | 300 next, |
| 244 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, | 301 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
| 245 SkVector{inverse.getScaleX(), inverse.getScaleY()}, | 302 SkVector{inverse.getScaleX(), inverse.getScaleY()}, |
| 246 SkVector{inverse.getSkewX(), inverse.getSkewY()}); | 303 SkVector{inverse.getSkewX(), inverse.getSkewY()}); |
| 247 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { | 304 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { |
| 248 matrixProc->Initialize<ScaleMatrix<>>( | 305 matrixProc->Initialize<ScaleMatrix<>>( |
| 249 next, | 306 next, |
| 250 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, | 307 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
| 251 SkVector{inverse.getScaleX(), inverse.getScaleY()}); | 308 SkVector{inverse.getScaleX(), inverse.getScaleY()}); |
| 252 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0 f) { | 309 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0 f) { |
| 253 matrixProc->Initialize<TranslateMatrix<>>( | 310 matrixProc->Initialize<TranslateMatrix<>>( |
| 254 next, | 311 next, |
| 255 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); | 312 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); |
| 256 } else { | 313 } else { |
| 257 matrixProc->Initialize<SkippedStage>(); | 314 matrixProc->Initialize<SkippedStage>(); |
| 258 return next; | 315 return next; |
| 259 } | 316 } |
| 260 return matrixProc->get(); | 317 return matrixProc->get(); |
| 261 } | 318 } |
| 262 | 319 |
| 263 template <typename Next = BilerpProcessorInterface> | 320 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
| 264 class ExpandBilerp final : public PointProcessorInterface { | 321 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e { |
| 265 public: | 322 public: |
| 266 ExpandBilerp(Next* next) : fNext{next} { } | 323 ExpandBilerp(Next* next) : fNext{next} { } |
| 267 | 324 |
| 268 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 325 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
| 269 SkASSERT(0 < n && n < 4); | 326 SkASSERT(0 < n && n < 4); |
| 270 // px00 px10 px01 px11 | 327 // px00 px10 px01 px11 |
| 271 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, | 328 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, |
| 272 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; | 329 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; |
| 273 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); | 330 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); |
| 274 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); | 331 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); |
| 275 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); | 332 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); |
| 276 } | 333 } |
| 277 | 334 |
| 278 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 335 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
| 279 // px00 px10 px01 px11 | 336 // px00 px10 px01 px11 |
| 280 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, | 337 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, |
| 281 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; | 338 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; |
| 282 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); | 339 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); |
| 283 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); | 340 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); |
| 284 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); | 341 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); |
| 285 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); | 342 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); |
| 286 } | 343 } |
| 287 | 344 |
| 288 void pointSpan(SkPoint start, SkScalar length, int count) override { | 345 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 289 span_fallback(start, length, count, this); | 346 span_fallback(start, length, count, this); |
| 290 } | 347 } |
| 291 | 348 |
| 292 private: | 349 private: |
| 293 Next* const fNext; | 350 Next* const fNext; |
| 294 }; | 351 }; |
| 295 | 352 |
| 296 static PointProcessorInterface* choose_filter( | 353 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( |
| 297 BilerpProcessorInterface* next, | 354 SkLinearBitmapPipeline::BilerpProcessorInterface* next, |
| 298 SkFilterQuality filterQuailty, | 355 SkFilterQuality filterQuailty, |
| 299 SkLinearBitmapPipeline::FilterStage* filterProc) { | 356 SkLinearBitmapPipeline::FilterStage* filterProc) { |
| 300 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { | 357 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { |
| 301 filterProc->Initialize<SkippedStage>(); | 358 filterProc->Initialize<SkippedStage>(); |
| 302 return next; | 359 return next; |
| 303 } else { | 360 } else { |
| 304 filterProc->Initialize<ExpandBilerp<>>(next); | 361 filterProc->Initialize<ExpandBilerp<>>(next); |
| 305 return filterProc->get(); | 362 return filterProc->get(); |
| 306 } | 363 } |
| 307 } | 364 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 329 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 386 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
| 330 return false; | 387 return false; |
| 331 } | 388 } |
| 332 | 389 |
| 333 private: | 390 private: |
| 334 const Sk4f fXMin{SK_FloatNegativeInfinity}; | 391 const Sk4f fXMin{SK_FloatNegativeInfinity}; |
| 335 const Sk4f fYMin{SK_FloatNegativeInfinity}; | 392 const Sk4f fYMin{SK_FloatNegativeInfinity}; |
| 336 const Sk4f fXMax{SK_FloatInfinity}; | 393 const Sk4f fXMax{SK_FloatInfinity}; |
| 337 const Sk4f fYMax{SK_FloatInfinity}; | 394 const Sk4f fYMax{SK_FloatInfinity}; |
| 338 }; | 395 }; |
| 339 template <typename Next = BilerpProcessorInterface> | 396 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
| 340 using Clamp = BilerpProcessor<ClampStrategy, Next>; | 397 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
| 341 | 398 |
| 342 class RepeatStrategy { | 399 class RepeatStrategy { |
| 343 public: | 400 public: |
| 344 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } | 401 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } |
| 345 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } | 402 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } |
| 346 RepeatStrategy(SkSize max) | 403 RepeatStrategy(SkSize max) |
| 347 : fXMax{X(max)} | 404 : fXMax{X(max)} |
| 348 , fXInvMax{1.0f / X(max)} | 405 , fXInvMax{1.0f / X(max)} |
| 349 , fYMax{Y(max)} | 406 , fYMax{Y(max)} |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 363 return false; | 420 return false; |
| 364 } | 421 } |
| 365 | 422 |
| 366 private: | 423 private: |
| 367 const Sk4f fXMax{0.0f}; | 424 const Sk4f fXMax{0.0f}; |
| 368 const Sk4f fXInvMax{0.0f}; | 425 const Sk4f fXInvMax{0.0f}; |
| 369 const Sk4f fYMax{0.0f}; | 426 const Sk4f fYMax{0.0f}; |
| 370 const Sk4f fYInvMax{0.0f}; | 427 const Sk4f fYInvMax{0.0f}; |
| 371 }; | 428 }; |
| 372 | 429 |
| 373 template <typename Next = BilerpProcessorInterface> | 430 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
| 374 using Repeat = BilerpProcessor<RepeatStrategy, Next>; | 431 using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
| 375 | 432 |
| 376 static BilerpProcessorInterface* choose_tiler( | 433 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler( |
| 377 BilerpProcessorInterface* next, | 434 SkLinearBitmapPipeline::BilerpProcessorInterface* next, |
| 378 SkSize dimensions, | 435 SkSize dimensions, |
| 379 SkShader::TileMode xMode, | 436 SkShader::TileMode xMode, |
| 380 SkShader::TileMode yMode, | 437 SkShader::TileMode yMode, |
| 381 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, | 438 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, |
| 382 SkLinearBitmapPipeline::TileStage* tileProcY) { | 439 SkLinearBitmapPipeline::TileStage* tileProcY) { |
| 383 if (xMode == yMode) { | 440 if (xMode == yMode) { |
| 384 switch (xMode) { | 441 switch (xMode) { |
| 385 case SkShader::kClamp_TileMode: | 442 case SkShader::kClamp_TileMode: |
| 386 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); | 443 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); |
| 387 break; | 444 break; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 415 case SkShader::kMirror_TileMode: | 472 case SkShader::kMirror_TileMode: |
| 416 SkFAIL("Not implemented."); | 473 SkFAIL("Not implemented."); |
| 417 break; | 474 break; |
| 418 } | 475 } |
| 419 } | 476 } |
| 420 return tileProcXOrBoth->get(); | 477 return tileProcXOrBoth->get(); |
| 421 } | 478 } |
| 422 | 479 |
| 423 class sRGBFast { | 480 class sRGBFast { |
| 424 public: | 481 public: |
| 425 static Sk4f sRGBToLinear(Sk4fArg pixel) { | 482 static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) { |
| 426 Sk4f l = pixel * pixel; | 483 Sk4f l = pixel * pixel; |
| 427 return Sk4f{l[0], l[1], l[2], pixel[3]}; | 484 return Sk4f{l[0], l[1], l[2], pixel[3]}; |
| 428 } | 485 } |
| 429 }; | 486 }; |
| 430 | 487 |
| 431 template <SkColorProfileType colorProfile> | 488 template <SkColorProfileType colorProfile> |
| 432 class Passthrough8888 { | 489 class Passthrough8888 { |
| 433 public: | 490 public: |
| 434 Passthrough8888(int width, const uint32_t* src) | 491 Passthrough8888(int width, const uint32_t* src) |
| 435 : fSrc{src}, fWidth{width}{ } | 492 : fSrc{src}, fWidth{width}{ } |
| 436 | 493 |
| 437 void getFewPixels(int n, Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { | 494 void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { |
| 438 Sk4i XIs = SkNx_cast<int, float>(xs); | 495 Sk4i XIs = SkNx_cast<int, float>(xs); |
| 439 Sk4i YIs = SkNx_cast<int, float>(ys); | 496 Sk4i YIs = SkNx_cast<int, float>(ys); |
| 440 Sk4i bufferLoc = YIs * fWidth + XIs; | 497 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 441 switch (n) { | 498 switch (n) { |
| 442 case 3: | 499 case 3: |
| 443 *px2 = getPixel(fSrc, bufferLoc[2]); | 500 *px2 = getPixel(fSrc, bufferLoc[2]); |
| 444 case 2: | 501 case 2: |
| 445 *px1 = getPixel(fSrc, bufferLoc[1]); | 502 *px1 = getPixel(fSrc, bufferLoc[1]); |
| 446 case 1: | 503 case 1: |
| 447 *px0 = getPixel(fSrc, bufferLoc[0]); | 504 *px0 = getPixel(fSrc, bufferLoc[0]); |
| 448 default: | 505 default: |
| 449 break; | 506 break; |
| 450 } | 507 } |
| 451 } | 508 } |
| 452 | 509 |
| 453 void get4Pixels(Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4 f* px3) { | 510 void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) { |
| 454 Sk4i XIs = SkNx_cast<int, float>(xs); | 511 Sk4i XIs = SkNx_cast<int, float>(xs); |
| 455 Sk4i YIs = SkNx_cast<int, float>(ys); | 512 Sk4i YIs = SkNx_cast<int, float>(ys); |
| 456 Sk4i bufferLoc = YIs * fWidth + XIs; | 513 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 457 *px0 = getPixel(fSrc, bufferLoc[0]); | 514 *px0 = getPixel(fSrc, bufferLoc[0]); |
| 458 *px1 = getPixel(fSrc, bufferLoc[1]); | 515 *px1 = getPixel(fSrc, bufferLoc[1]); |
| 459 *px2 = getPixel(fSrc, bufferLoc[2]); | 516 *px2 = getPixel(fSrc, bufferLoc[2]); |
| 460 *px3 = getPixel(fSrc, bufferLoc[3]); | 517 *px3 = getPixel(fSrc, bufferLoc[3]); |
| 461 } | 518 } |
| 462 | 519 |
| 463 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } | 520 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 489 // +--------+--------+ | 546 // +--------+--------+ |
| 490 // | 547 // |
| 491 // | 548 // |
| 492 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x | 549 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x |
| 493 // and y: | 550 // and y: |
| 494 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy | 551 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy |
| 495 // * px10 -> x(1 - y) = x - xy | 552 // * px10 -> x(1 - y) = x - xy |
| 496 // * px01 -> (1 - x)y = y - xy | 553 // * px01 -> (1 - x)y = y - xy |
| 497 // * px11 -> xy | 554 // * px11 -> xy |
| 498 // So x * y is calculated first and then used to calculate all the other factors . | 555 // So x * y is calculated first and then used to calculate all the other factors . |
| 499 static Sk4f bilerp4(Sk4fArg xs, Sk4fArg ys, Sk4fArg px00, Sk4fArg px10, | 556 static Sk4f VECTORCALL bilerp4(Sk4f xs, Sk4f ys, Sk4f px00, Sk4f px10, |
| 500 Sk4fArg px01, Sk4fArg px11) { | 557 Sk4f px01, Sk4f px11) { |
| 501 // Calculate fractional xs and ys. | 558 // Calculate fractional xs and ys. |
| 502 Sk4f fxs = xs - xs.floor(); | 559 Sk4f fxs = xs - xs.floor(); |
| 503 Sk4f fys = ys - ys.floor(); | 560 Sk4f fys = ys - ys.floor(); |
| 504 Sk4f fxys{fxs * fys}; | 561 Sk4f fxys{fxs * fys}; |
| 505 Sk4f sum = px11 * fxys; | 562 Sk4f sum = px11 * fxys; |
| 506 sum = sum + px01 * (fys - fxys); | 563 sum = sum + px01 * (fys - fxys); |
| 507 sum = sum + px10 * (fxs - fxys); | 564 sum = sum + px10 * (fxs - fxys); |
| 508 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); | 565 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); |
| 509 return sum; | 566 return sum; |
| 510 } | 567 } |
| 511 | 568 |
| 512 template <typename SourceStrategy> | 569 template <typename SourceStrategy> |
| 513 class Sampler final : public BilerpProcessorInterface { | 570 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface { |
| 514 public: | 571 public: |
| 515 template <typename... Args> | 572 template <typename... Args> |
| 516 Sampler(PixelPlacerInterface* next, Args&&... args) | 573 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args) |
| 517 : fNext{next} | 574 : fNext{next} |
| 518 , fStrategy{std::forward<Args>(args)...} { } | 575 , fStrategy{std::forward<Args>(args)...} { } |
| 519 | 576 |
| 520 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 577 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
| 521 SkASSERT(0 < n && n < 4); | 578 SkASSERT(0 < n && n < 4); |
| 522 Sk4f px0, px1, px2; | 579 Sk4f px0, px1, px2; |
| 523 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); | 580 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); |
| 524 if (n >= 1) fNext->placePixel(px0); | 581 if (n >= 1) fNext->placePixel(px0); |
| 525 if (n >= 2) fNext->placePixel(px1); | 582 if (n >= 2) fNext->placePixel(px1); |
| 526 if (n >= 3) fNext->placePixel(px2); | 583 if (n >= 3) fNext->placePixel(px2); |
| 527 } | 584 } |
| 528 | 585 |
| 529 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 586 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
| 530 Sk4f px0, px1, px2, px3; | 587 Sk4f px0, px1, px2, px3; |
| 531 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); | 588 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
| 532 fNext->place4Pixels(px0, px1, px2, px3); | 589 fNext->place4Pixels(px0, px1, px2, px3); |
| 533 } | 590 } |
| 534 | 591 |
| 535 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 592 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
| 536 Sk4f px00, px10, px01, px11; | 593 Sk4f px00, px10, px01, px11; |
| 537 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); | 594 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); |
| 538 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | 595 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
| 539 fNext->placePixel(pixel); | 596 fNext->placePixel(pixel); |
| 540 } | 597 } |
| 541 | 598 |
| 542 void pointSpan(SkPoint start, SkScalar length, int count) override { | 599 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 543 span_fallback(start, length, count, this); | 600 span_fallback(start, length, count, this); |
| 544 } | 601 } |
| 545 | 602 |
| 546 private: | 603 private: |
| 547 PixelPlacerInterface* const fNext; | 604 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; |
| 548 SourceStrategy fStrategy; | 605 SourceStrategy fStrategy; |
| 549 }; | 606 }; |
| 550 | 607 |
| 551 static BilerpProcessorInterface* choose_pixel_sampler( | 608 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_pixel_sampler( |
| 552 PixelPlacerInterface* next, | 609 SkLinearBitmapPipeline::PixelPlacerInterface* next, |
| 553 const SkPixmap& srcPixmap, | 610 const SkPixmap& srcPixmap, |
| 554 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 611 SkLinearBitmapPipeline::SampleStage* sampleStage) { |
| 555 const SkImageInfo& imageInfo = srcPixmap.info(); | 612 const SkImageInfo& imageInfo = srcPixmap.info(); |
| 556 switch (imageInfo.colorType()) { | 613 switch (imageInfo.colorType()) { |
| 557 case kRGBA_8888_SkColorType: | 614 case kRGBA_8888_SkColorType: |
| 558 case kBGRA_8888_SkColorType: | 615 case kBGRA_8888_SkColorType: |
| 559 if (kN32_SkColorType == imageInfo.colorType()) { | 616 if (kN32_SkColorType == imageInfo.colorType()) { |
| 560 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 617 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
| 561 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( | 618 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( |
| 562 next, static_cast<int>(srcPixmap.rowBytes() / 4), | 619 next, static_cast<int>(srcPixmap.rowBytes() / 4), |
| 563 srcPixmap.addr32()); | 620 srcPixmap.addr32()); |
| 564 } else { | 621 } else { |
| 565 sampleStage->Initialize<Sampler<Passthrough8888<kLinear_SkCo lorProfileType>>>( | 622 sampleStage->Initialize<Sampler<Passthrough8888<kLinear_SkCo lorProfileType>>>( |
| 566 next, static_cast<int>(srcPixmap.rowBytes() / 4), | 623 next, static_cast<int>(srcPixmap.rowBytes() / 4), |
| 567 srcPixmap.addr32()); | 624 srcPixmap.addr32()); |
| 568 } | 625 } |
| 569 } else { | 626 } else { |
| 570 SkFAIL("Not implemented. No 8888 Swizzle"); | 627 SkFAIL("Not implemented. No 8888 Swizzle"); |
| 571 } | 628 } |
| 572 break; | 629 break; |
| 573 default: | 630 default: |
| 574 SkFAIL("Not implemented. Unsupported src"); | 631 SkFAIL("Not implemented. Unsupported src"); |
| 575 break; | 632 break; |
| 576 } | 633 } |
| 577 return sampleStage->get(); | 634 return sampleStage->get(); |
| 578 } | 635 } |
| 579 | 636 |
| 580 template <SkAlphaType alphaType> | 637 template <SkAlphaType alphaType> |
| 581 class PlaceFPPixel final : public PixelPlacerInterface { | 638 class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { |
| 582 public: | 639 public: |
| 583 void placePixel(Sk4fArg pixel) override { | 640 void VECTORCALL placePixel(Sk4f pixel) override { |
| 584 PlacePixel(fDst, pixel, 0); | 641 PlacePixel(fDst, pixel, 0); |
| 585 fDst += 1; | 642 fDst += 1; |
| 586 } | 643 } |
| 587 | 644 |
| 588 void place4Pixels(Sk4fArg p0, Sk4fArg p1, Sk4fArg p2, Sk4fArg p3) override { | 645 void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
| 589 SkPM4f* dst = fDst; | 646 SkPM4f* dst = fDst; |
| 590 PlacePixel(dst, p0, 0); | 647 PlacePixel(dst, p0, 0); |
| 591 PlacePixel(dst, p1, 1); | 648 PlacePixel(dst, p1, 1); |
| 592 PlacePixel(dst, p2, 2); | 649 PlacePixel(dst, p2, 2); |
| 593 PlacePixel(dst, p3, 3); | 650 PlacePixel(dst, p3, 3); |
| 594 fDst += 4; | 651 fDst += 4; |
| 595 } | 652 } |
| 596 | 653 |
| 597 void setDestination(SkPM4f* dst) override { | 654 void setDestination(SkPM4f* dst) override { |
| 598 fDst = dst; | 655 fDst = dst; |
| 599 } | 656 } |
| 600 | 657 |
| 601 private: | 658 private: |
| 602 static void PlacePixel(SkPM4f* dst, Sk4fArg pixel, int index) { | 659 static void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) { |
| 603 Sk4f newPixel = pixel; | 660 Sk4f newPixel = pixel; |
| 604 if (alphaType == kUnpremul_SkAlphaType) { | 661 if (alphaType == kUnpremul_SkAlphaType) { |
| 605 newPixel = Premultiply(pixel); | 662 newPixel = Premultiply(pixel); |
| 606 } | 663 } |
| 607 newPixel.store(dst + index); | 664 newPixel.store(dst + index); |
| 608 } | 665 } |
| 609 static Sk4f Premultiply(Sk4fArg pixel) { | 666 static Sk4f VECTORCALL Premultiply(Sk4f pixel) { |
| 610 float alpha = pixel[3]; | 667 float alpha = pixel[3]; |
| 611 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; | 668 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; |
| 612 } | 669 } |
| 613 | 670 |
| 614 SkPM4f* fDst; | 671 SkPM4f* fDst; |
| 615 }; | 672 }; |
| 616 | 673 |
| 617 static PixelPlacerInterface* choose_pixel_placer( | 674 static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer( |
| 618 SkAlphaType alphaType, | 675 SkAlphaType alphaType, |
| 619 SkLinearBitmapPipeline::PixelStage* placerStage) { | 676 SkLinearBitmapPipeline::PixelStage* placerStage) { |
| 620 if (alphaType == kUnpremul_SkAlphaType) { | 677 if (alphaType == kUnpremul_SkAlphaType) { |
| 621 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); | 678 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); |
| 622 } else { | 679 } else { |
| 623 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType | 680 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType |
| 624 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); | 681 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); |
| 625 } | 682 } |
| 626 return placerStage->get(); | 683 return placerStage->get(); |
| 627 } | 684 } |
| 685 } // namespace | |
| 686 | |
| 687 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} | |
| 628 | 688 |
| 629 SkLinearBitmapPipeline::SkLinearBitmapPipeline( | 689 SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| 630 const SkMatrix& inverse, | 690 const SkMatrix& inverse, |
| 631 SkFilterQuality filterQuality, | 691 SkFilterQuality filterQuality, |
| 632 SkShader::TileMode xTile, SkShader::TileMode yTile, | 692 SkShader::TileMode xTile, SkShader::TileMode yTile, |
| 633 const SkPixmap& srcPixmap) { | 693 const SkPixmap& srcPixmap) { |
| 634 SkSize size = SkSize::Make(srcPixmap.width(), srcPixmap.height()); | 694 SkSize size = SkSize::Make(srcPixmap.width(), srcPixmap.height()); |
| 635 const SkImageInfo& srcImageInfo = srcPixmap.info(); | 695 const SkImageInfo& srcImageInfo = srcPixmap.info(); |
| 636 | 696 |
| 637 // As the stages are built, the chooser function may skip a stage. For examp le, with the | 697 // As the stages are built, the chooser function may skip a stage. For examp le, with the |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 651 if (count == 1) { | 711 if (count == 1) { |
| 652 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); | 712 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); |
| 653 } else { | 713 } else { |
| 654 // The count and length arguments start out in a precise relation in ord er to keep the | 714 // The count and length arguments start out in a precise relation in ord er to keep the |
| 655 // math correct through the different stages. Count is the number of pix el to produce. | 715 // math correct through the different stages. Count is the number of pix el to produce. |
| 656 // Since the code samples at pixel centers, length is the distance from the center of the | 716 // Since the code samples at pixel centers, length is the distance from the center of the |
| 657 // first pixel to the center of the last pixel. This implies that length is count-1. | 717 // first pixel to the center of the last pixel. This implies that length is count-1. |
| 658 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); | 718 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); |
| 659 } | 719 } |
| 660 } | 720 } |
| OLD | NEW |