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 "SkCoreBlitters.h" | 8 #include "SkCoreBlitters.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkShader.h" | 10 #include "SkShader.h" |
| 11 #include "SkUtils.h" | 11 #include "SkUtils.h" |
| 12 #include "SkXfermode.h" | 12 #include "SkXfermode.h" |
| 13 #include "SkBlitMask.h" | 13 #include "SkBlitMask.h" |
| 14 #include "SkTemplates.h" | |
| 15 | |
| 16 template <typename State> class SkState_Blitter : public SkRasterBlitter { | |
| 17 typedef SkRasterBlitter INHERITED; | |
| 18 State fState; | |
| 19 | |
| 20 public: | |
| 21 SkState_Blitter(const SkPixmap& device, const SkPaint& paint) | |
| 22 : INHERITED(device) | |
| 23 , fState(device.info(), paint, nullptr) | |
| 24 {} | |
| 25 | |
| 26 void blitH(int x, int y, int width) override { | |
| 27 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
| 28 | |
| 29 fState.fProc1(fState, State::WritableAddr(fDevice, x, y), fState.fPM4f, width, nullptr); | |
| 30 } | |
| 31 | |
| 32 void blitV(int x, int y, int height, SkAlpha alpha) override { | |
| 33 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
| 34 | |
| 35 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 36 size_t deviceRB = fDevice.rowBytes(); | |
| 37 | |
| 38 for (int i = 0; i < height; ++i) { | |
| 39 fState.fProc1(fState, device, fState.fPM4f, 1, &alpha); | |
| 40 device = (typename State::DstType*)((char*)device + deviceRB); | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 void blitRect(int x, int y, int width, int height) override { | |
| 45 SkASSERT(x >= 0 && y >= 0 && | |
| 46 x + width <= fDevice.width() && y + height <= fDevice.height()) ; | |
| 47 | |
| 48 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 49 size_t deviceRB = fDevice.rowBytes(); | |
| 50 | |
| 51 do { | |
| 52 fState.fProc1(fState, device, fState.fPM4f, width, nullptr); | |
| 53 y += 1; | |
| 54 device = (typename State::DstType*)((char*)device + deviceRB); | |
| 55 } while (--height > 0); | |
| 56 } | |
| 57 | |
| 58 void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[] ) override { | |
| 59 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 60 | |
| 61 for (;;) { | |
| 62 int count = *runs; | |
| 63 if (count <= 0) { | |
| 64 break; | |
| 65 } | |
| 66 int aa = *antialias; | |
| 67 if (aa) { | |
| 68 if (aa == 255) { | |
| 69 fState.fProc1(fState, device, fState.fPM4f, count, nullptr); | |
| 70 } else { | |
| 71 for (int i = 0; i < count; ++i) { | |
| 72 fState.fProc1(fState, &device[i], fState.fPM4f, 1, antia lias); | |
| 73 } | |
| 74 } | |
| 75 } | |
| 76 device += count; | |
| 77 runs += count; | |
| 78 antialias += count; | |
| 79 x += count; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void blitMask(const SkMask& mask, const SkIRect& clip) override { | |
| 84 // we only handle kA8 | |
| 85 if (SkMask::kA8_Format != mask.fFormat) { | |
| 86 this->INHERITED::blitMask(mask, clip); | |
| 87 return; | |
| 88 } | |
| 89 | |
| 90 SkASSERT(mask.fBounds.contains(clip)); | |
| 91 | |
| 92 const int x = clip.fLeft; | |
| 93 const int width = clip.width(); | |
| 94 const int y = clip.fTop; | |
| 95 const int height = clip.height(); | |
| 96 | |
| 97 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 98 const size_t dstRB = fDevice.rowBytes(); | |
| 99 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
| 100 const size_t maskRB = mask.fRowBytes; | |
| 101 | |
| 102 for (int i = 0; i < height; ++i) { | |
| 103 fState.fProc1(fState, device, fState.fPM4f, width, maskRow); | |
| 104 device = (typename State::DstType*)((char*)device + dstRB); | |
| 105 maskRow += maskRB; | |
| 106 } | |
| 107 } | |
| 108 }; | |
| 109 | |
| 110 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 111 | |
| 112 template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter { | |
| 113 public: | |
| 114 SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, | |
| 115 SkShader::Context* shaderContext) | |
| 116 : INHERITED(device, paint, shaderContext) | |
| 117 , fState(device.info(), paint, shaderContext) | |
| 118 {} | |
| 119 | |
| 120 void blitH(int x, int y, int width) override { | |
| 121 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
| 122 | |
| 123 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 124 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
| 125 fState.fProcN(fState, device, fState.fBuffer, width, nullptr); | |
| 126 } | |
| 127 | |
| 128 void blitV(int x, int y, int height, SkAlpha alpha) override { | |
| 129 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
| 130 | |
| 131 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 132 size_t deviceRB = fDevice.rowBytes(); | |
| 133 const int bottom = y + height; | |
| 134 | |
| 135 if (fConstInY) { | |
| 136 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); | |
| 137 } | |
| 138 for (; y < bottom; ++y) { | |
| 139 if (!fConstInY) { | |
|
f(malita)
2016/02/15 04:31:17
Is it worth hoisting this conditional out? I imag
reed2
2016/02/15 15:25:22
Was trying to keep everything very succinct until
| |
| 140 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); | |
| 141 } | |
| 142 fState.fProcN(fState, device, fState.fBuffer, 1, &alpha); | |
| 143 device = (typename State::DstType*)((char*)device + deviceRB); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void blitRect(int x, int y, int width, int height) override { | |
| 148 SkASSERT(x >= 0 && y >= 0 && | |
| 149 x + width <= fDevice.width() && y + height <= fDevice.height()) ; | |
| 150 | |
| 151 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 152 size_t deviceRB = fDevice.rowBytes(); | |
| 153 const int bottom = y + height; | |
| 154 | |
| 155 if (fConstInY) { | |
| 156 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
| 157 } | |
| 158 for (; y < bottom; ++y) { | |
| 159 if (!fConstInY) { | |
|
f(malita)
2016/02/15 04:31:17
Ditto.
| |
| 160 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
| 161 } | |
| 162 fState.fProcN(fState, device, fState.fBuffer, width, nullptr); | |
| 163 device = (typename State::DstType*)((char*)device + deviceRB); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[] ) override { | |
| 168 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 169 | |
| 170 for (;;) { | |
| 171 int count = *runs; | |
| 172 if (count <= 0) { | |
| 173 break; | |
| 174 } | |
| 175 int aa = *antialias; | |
| 176 if (aa) { | |
| 177 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count); | |
| 178 if (aa == 255) { | |
| 179 fState.fProcN(fState, device, fState.fBuffer, count, nullptr ); | |
| 180 } else { | |
| 181 for (int i = 0; i < count; ++i) { | |
| 182 fState.fProcN(fState, &device[i], &fState.fBuffer[i], 1, antialias); | |
| 183 } | |
| 184 } | |
| 185 } | |
| 186 device += count; | |
| 187 runs += count; | |
| 188 antialias += count; | |
| 189 x += count; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 void blitMask(const SkMask& mask, const SkIRect& clip) override { | |
| 194 // we only handle kA8 | |
| 195 if (SkMask::kA8_Format != mask.fFormat) { | |
| 196 this->INHERITED::blitMask(mask, clip); | |
| 197 return; | |
| 198 } | |
| 199 | |
| 200 SkASSERT(mask.fBounds.contains(clip)); | |
| 201 | |
| 202 const int x = clip.fLeft; | |
| 203 const int width = clip.width(); | |
| 204 int y = clip.fTop; | |
| 205 | |
| 206 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
| 207 const size_t deviceRB = fDevice.rowBytes(); | |
| 208 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
| 209 const size_t maskRB = mask.fRowBytes; | |
| 210 | |
| 211 if (fConstInY) { | |
| 212 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
| 213 } | |
| 214 for (; y < clip.fBottom; ++y) { | |
| 215 if (!fConstInY) { | |
| 216 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
| 217 } | |
| 218 fState.fProcN(fState, device, fState.fBuffer, width, maskRow); | |
| 219 device = (typename State::DstType*)((char*)device + deviceRB); | |
| 220 maskRow += maskRB; | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 private: | |
| 225 State fState; | |
| 226 | |
| 227 typedef SkShaderBlitter INHERITED; | |
| 228 }; | |
| 14 | 229 |
| 15 //////////////////////////////////////////////////////////////////////////////// ////// | 230 //////////////////////////////////////////////////////////////////////////////// ////// |
| 16 | 231 |
| 17 SkARGB32_Shader4f_Blitter::SkARGB32_Shader4f_Blitter(const SkPixmap& device, | 232 static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderConte xt) { |
| 18 const SkPaint& paint, SkShader::Context* shaderContext) | 233 return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqu eAlpha_Flag) |
| 19 : INHERITED(device, paint, shaderContext) | 234 : 0xFF == paint.getAlpha(); |
| 20 { | 235 } |
| 21 const uint32_t shaderFlags = shaderContext->getFlags(); | 236 |
| 22 | 237 struct State32 : SkXfermode::PM4fState { |
| 23 SkASSERT(shaderFlags & SkShader::kSupports4f_Flag); | 238 typedef uint32_t DstType; |
| 24 | 239 |
| 25 fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f))); | 240 SkXfermode::PM4fProc1 fProc1; |
| 26 | 241 SkXfermode::PM4fProcN fProcN; |
| 27 fState.fXfer = SkSafeRef(paint.getXfermode()); | 242 SkPM4f fPM4f; |
| 28 fState.fFlags = 0; | 243 SkPM4f* fBuffer; |
| 29 if (shaderFlags & SkShader::kOpaqueAlpha_Flag) { | 244 |
| 30 fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; | 245 State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Conte xt* shaderContext) { |
| 31 } | 246 fXfer = SkSafeRef(paint.getXfermode()); |
| 32 if (device.info().isSRGB()) { | 247 fFlags = 0; |
| 33 fState.fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag; | 248 if (is_opaque(paint, shaderContext)) { |
| 34 } | 249 fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; |
| 35 if (fState.fXfer) { | 250 } |
| 36 fProc1 = fState.fXfer->getPM4fProc1(fState.fFlags); | 251 if (info.isSRGB()) { |
| 37 fProcN = fState.fXfer->getPM4fProcN(fState.fFlags); | 252 fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag; |
| 253 } | |
| 254 if (fXfer) { | |
| 255 fProc1 = fXfer->getPM4fProc1(fFlags); | |
| 256 fProcN = fXfer->getPM4fProcN(fFlags); | |
| 257 } else { | |
| 258 fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fFlags) ; | |
| 259 fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fFlags) ; | |
| 260 } | |
| 261 | |
| 262 fBuffer = nullptr; | |
| 263 if (shaderContext) { | |
| 264 fBuffer = new SkPM4f[info.width()]; | |
| 265 } else { | |
| 266 fPM4f = SkColor4f::FromColor(paint.getColor()).premul(); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 ~State32() { | |
| 271 SkSafeUnref(fXfer); | |
| 272 delete[] fBuffer; | |
| 273 } | |
| 274 | |
| 275 static DstType* WritableAddr(const SkPixmap& device, int x, int y) { | |
| 276 return device.writable_addr32(x, y); | |
| 277 } | |
| 278 }; | |
| 279 | |
| 280 struct State64 : SkXfermode::U64State { | |
| 281 typedef uint64_t DstType; | |
| 282 | |
| 283 SkXfermode::U64Proc1 fProc1; | |
| 284 SkXfermode::U64ProcN fProcN; | |
| 285 SkPM4f fPM4f; | |
| 286 SkPM4f* fBuffer; | |
| 287 | |
| 288 State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Conte xt* shaderContext) { | |
| 289 fXfer = SkSafeRef(paint.getXfermode()); | |
| 290 fFlags = 0; | |
| 291 if (is_opaque(paint, shaderContext)) { | |
| 292 fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; | |
| 293 } | |
| 294 if (kRGBA_F16_SkColorType == info.colorType()) { | |
| 295 fFlags |= SkXfermode::kDstIsFloat16_U64Flag; | |
| 296 } | |
| 297 | |
| 298 SkXfermode::Mode mode; | |
| 299 if (SkXfermode::AsMode(fXfer, &mode)) { | |
| 300 mode = SkXfermode::kSrcOver_Mode; | |
| 301 } | |
| 302 fProc1 = SkXfermode::GetU64Proc1(mode, fFlags); | |
| 303 fProcN = SkXfermode::GetU64ProcN(mode, fFlags); | |
| 304 | |
| 305 fBuffer = nullptr; | |
| 306 if (shaderContext) { | |
| 307 fBuffer = new SkPM4f[info.width()]; | |
| 308 } else { | |
| 309 fPM4f = SkColor4f::FromColor(paint.getColor()).premul(); | |
| 310 } | |
| 311 } | |
| 312 | |
| 313 ~State64() { | |
| 314 SkSafeUnref(fXfer); | |
| 315 delete[] fBuffer; | |
| 316 } | |
| 317 | |
| 318 static DstType* WritableAddr(const SkPixmap& device, int x, int y) { | |
| 319 return device.writable_addr64(x, y); | |
| 320 } | |
| 321 }; | |
| 322 | |
| 323 template <typename State> SkBlitter* create(const SkPixmap& device, const SkPain t& paint, | |
| 324 SkShader::Context* shaderContext, | |
| 325 SkTBlitterAllocator* allocator) { | |
| 326 SkASSERT(allocator != nullptr); | |
| 327 | |
| 328 if (shaderContext) { | |
| 329 return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext); | |
| 38 } else { | 330 } else { |
| 39 fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fState.fFla gs); | 331 SkColor color = paint.getColor(); |
| 40 fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fState.fFla gs); | 332 if (0 == SkColorGetA(color)) { |
| 41 } | 333 return nullptr; |
| 42 | 334 } |
| 43 fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag); | 335 return allocator->createT<SkState_Blitter<State>>(device, paint); |
| 336 } | |
| 44 } | 337 } |
| 45 | 338 |
| 46 SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() { | 339 SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, |
| 47 SkSafeUnref(fState.fXfer); | 340 SkShader::Context* shaderContext, |
| 48 sk_free(fBuffer); | 341 SkTBlitterAllocator* allocator) { |
| 342 return create<State32>(device, paint, shaderContext, allocator); | |
| 49 } | 343 } |
| 50 | 344 |
| 51 void SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) { | 345 SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint, |
| 52 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | 346 SkShader::Context* shaderContext, |
| 53 | 347 SkTBlitterAllocator* allocator) { |
| 54 uint32_t* device = fDevice.writable_addr32(x, y); | 348 return create<State64>(device, paint, shaderContext, allocator); |
| 55 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
| 56 fProcN(fState, device, fBuffer, width, nullptr); | |
| 57 } | 349 } |
| 58 | |
| 59 void SkARGB32_Shader4f_Blitter::blitRect(int x, int y, int width, int height) { | |
| 60 SkASSERT(x >= 0 && y >= 0 && | |
| 61 x + width <= fDevice.width() && y + height <= fDevice.height()); | |
| 62 | |
| 63 uint32_t* device = fDevice.writable_addr32(x, y); | |
| 64 size_t deviceRB = fDevice.rowBytes(); | |
| 65 | |
| 66 if (fConstInY) { | |
| 67 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
| 68 do { | |
| 69 fProcN(fState, device, fBuffer, width, nullptr); | |
| 70 y += 1; | |
| 71 device = (uint32_t*)((char*)device + deviceRB); | |
| 72 } while (--height > 0); | |
| 73 } else { | |
| 74 do { | |
| 75 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
| 76 fProcN(fState, device, fBuffer, width, nullptr); | |
| 77 y += 1; | |
| 78 device = (uint32_t*)((char*)device + deviceRB); | |
| 79 } while (--height > 0); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void SkARGB32_Shader4f_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[ ], | |
| 84 const int16_t runs[]) { | |
| 85 uint32_t* device = fDevice.writable_addr32(x, y); | |
| 86 | |
| 87 for (;;) { | |
| 88 int count = *runs; | |
| 89 if (count <= 0) { | |
| 90 break; | |
| 91 } | |
| 92 int aa = *antialias; | |
| 93 if (aa) { | |
| 94 fShaderContext->shadeSpan4f(x, y, fBuffer, count); | |
| 95 if (aa == 255) { | |
| 96 fProcN(fState, device, fBuffer, count, nullptr); | |
| 97 } else { | |
| 98 // count is almost always 1 | |
| 99 for (int i = count - 1; i >= 0; --i) { | |
| 100 fProcN(fState, &device[i], &fBuffer[i], 1, antialias); | |
| 101 } | |
| 102 } | |
| 103 } | |
| 104 device += count; | |
| 105 runs += count; | |
| 106 antialias += count; | |
| 107 x += count; | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 void SkARGB32_Shader4f_Blitter::blitMask(const SkMask& mask, const SkIRect& clip ) { | |
| 112 // we only handle kA8 | |
| 113 if (SkMask::kA8_Format != mask.fFormat) { | |
| 114 this->INHERITED::blitMask(mask, clip); | |
| 115 return; | |
| 116 } | |
| 117 | |
| 118 SkASSERT(mask.fBounds.contains(clip)); | |
| 119 | |
| 120 const int x = clip.fLeft; | |
| 121 const int width = clip.width(); | |
| 122 int y = clip.fTop; | |
| 123 int height = clip.height(); | |
| 124 | |
| 125 char* dstRow = (char*)fDevice.writable_addr32(x, y); | |
| 126 const size_t dstRB = fDevice.rowBytes(); | |
| 127 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
| 128 const size_t maskRB = mask.fRowBytes; | |
| 129 | |
| 130 do { | |
| 131 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
| 132 fProcN(fState, reinterpret_cast<SkPMColor*>(dstRow), fBuffer, width, mas kRow); | |
| 133 dstRow += dstRB; | |
| 134 maskRow += maskRB; | |
| 135 y += 1; | |
| 136 } while (--height > 0); | |
| 137 } | |
| 138 | |
| 139 void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { | |
| 140 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
| 141 | |
| 142 uint32_t* device = fDevice.writable_addr32(x, y); | |
| 143 size_t deviceRB = fDevice.rowBytes(); | |
| 144 | |
| 145 if (fConstInY) { | |
| 146 fShaderContext->shadeSpan4f(x, y, fBuffer, 1); | |
| 147 do { | |
| 148 fProcN(fState, device, fBuffer, 1, &alpha); | |
| 149 device = (uint32_t*)((char*)device + deviceRB); | |
| 150 } while (--height > 0); | |
| 151 } else { | |
| 152 do { | |
| 153 fShaderContext->shadeSpan4f(x, y, fBuffer, 1); | |
| 154 fProcN(fState, device, fBuffer, 1, &alpha); | |
| 155 y += 1; | |
| 156 device = (uint32_t*)((char*)device + deviceRB); | |
| 157 } while (--height > 0); | |
| 158 } | |
| 159 } | |
| OLD | NEW |