Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/core/SkBlitter_PM4f.cpp

Issue 1697863002: blitters for sRGB and float16 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkBlitter.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 }
OLDNEW
« no previous file with comments | « src/core/SkBlitter.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698