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) { |
| 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) { |
| 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 |