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

Side by Side Diff: cc/paint/paint_op_buffer.h

Issue 2768143002: Back PaintRecord with PaintOpBuffer instead of SkPicture (Closed)
Patch Set: Fix win build Created 3 years, 8 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
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CC_PAINT_PAINT_OP_BUFFER_H_
6 #define CC_PAINT_PAINT_OP_BUFFER_H_
7
8 #include <stdint.h>
9
10 #include "base/logging.h"
11 #include "cc/paint/paint_canvas.h"
12 #include "cc/paint/paint_export.h"
13 #include "cc/paint/paint_flags.h"
14 #include "third_party/skia/include/core/SkPicture.h"
15 #include "third_party/skia/include/core/SkRect.h"
16 #include "third_party/skia/include/core/SkTextBlob.h"
17
18 // PaintOpBuffer is a reimplementation of SkLiteDL.
19 // See: third_party/skia/src/core/SkLiteDL.h.
20
21 namespace cc {
22
23 class DisplayItemList;
24
25 class ThreadsafeMatrix : public SkMatrix {
26 public:
27 ThreadsafeMatrix() : SkMatrix() { (void)getType(); }
vmpstr 2017/04/06 19:16:12 I think techincally this SkMatrix is not initializ
mtklein_C 2017/04/06 19:58:48 It's probably fine, but MSAN might hate you. Migh
enne (OOO) 2017/04/06 23:17:05 Apparently I don't need this constructor! Problem
28 explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
29 (void)getType();
30 }
31 };
32
33 class ThreadsafePath : public SkPath {
34 public:
35 explicit ThreadsafePath(const SkPath& path) : SkPath(path) {
36 updateBoundsCache();
37 }
38 };
39
40 enum class PaintOpType : uint8_t {
41 Annotate,
42 ClipPath,
43 ClipRect,
44 ClipRRect,
45 Concat,
46 DrawArc,
47 DrawCircle,
48 DrawColor,
49 DrawDisplayItemList,
50 DrawDRRect,
51 DrawImage,
52 DrawImageRect,
53 DrawIRect,
54 DrawLine,
55 DrawOval,
56 DrawPath,
57 DrawPosText,
58 DrawRecord,
59 DrawRect,
60 DrawRRect,
61 DrawText,
62 DrawTextBlob,
63 Noop,
64 Restore,
65 Rotate,
66 Save,
67 SaveLayer,
68 SaveLayerAlpha,
69 Scale,
70 SetMatrix,
71 Translate,
72 LastPaintOpType = Translate,
73 };
74
75 struct CC_PAINT_EXPORT PaintOp {
76 uint32_t type : 8;
77 uint32_t skip : 24;
78
79 PaintOpType GetType() const { return static_cast<PaintOpType>(type); }
80
81 void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
82 bool IsDrawOp() const;
83
84 // Only valid for draw ops.
85 void RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const;
86
87 int CountSlowPaths() const { return 0; }
88 size_t AdditionalBytesUsed() const { return 0; }
vmpstr 2017/04/06 19:16:12 Comment what "Additional" means.. like the data st
enne (OOO) 2017/04/06 23:17:05 Like referenced sub-records and display lists.
89
90 static constexpr bool kIsDrawOp = false;
91 // If an op has |kHasPaintFlags| set to true, it must:
92 // (1) Provide a PaintFlags member called |flags|
93 // (2) Provide a RasterWithFlags function instead of a Raster function.
94 static constexpr bool kHasPaintFlags = false;
95 static SkRect kUnsetRect;
96 };
97
98 struct PaintOpWithData : PaintOp {
99 // Having data is just a helper for ops that have a varying amount of data and
100 // want a way to store that inline. This is for ops that pass in a
101 // void* and a length.
102 explicit PaintOpWithData(size_t bytes) : bytes(bytes) {}
103
104 // Get data out by calling paint_op_data. This can't be part of the class
105 // because it needs to know the size of the derived type.
106 size_t bytes;
107 };
108
109 template <typename T>
110 const void* paint_op_data(const T* op) {
111 static_assert(std::is_convertible<T, PaintOpWithData>::value,
112 "T is not a PaintOpWithData");
113 // Arbitrary data for a PaintOp is stored after the PaintOp itself
114 // in the PaintOpBuffer. Therefore, to access this data, it's
115 // pointer math to increment past the size of T. Accessing the
116 // next op in the buffer is ((char*)op) + op->skip, with the data
117 // fitting between.
118 return op + 1;
119 }
120
121 template <typename T>
122 void* paint_op_data(T* op) {
123 static_assert(std::is_convertible<T, PaintOpWithData>::value,
124 "T is not a PaintOpWithData");
125 return op + 1;
126 }
127
128 struct PaintOpWithDataArrayBase : PaintOpWithData {
129 // Helper class for static asserts in push functions.
130 using PaintOpWithData::PaintOpWithData;
131 };
132
133 template <typename T>
134 struct PaintOpWithDataArray : PaintOpWithDataArrayBase {
135 // Paint op that has a T[count] and a char[bytes].
136 PaintOpWithDataArray(size_t bytes, size_t count)
137 : PaintOpWithDataArrayBase(bytes), count(count) {}
138 // Use paint_op_array to get array data.
139
140 size_t count;
141 };
142
143 template <typename M, typename T>
144 const M* paint_op_array(const T* op) {
145 static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
146 "T is not a PaintOpWithDataArray");
147 // See comment in paint_op_data. Array data is stored after
148 // any void* data. Memory layout here is: |op|data|array data|next op|
149 return SkTAddOffset<const M>(op + 1, op->bytes);
vmpstr 2017/04/06 19:16:12 |bytes| here is the size of "data" here right? (Ju
enne (OOO) 2017/04/06 23:17:05 Correct.
150 }
151 template <typename M, typename T>
152 M* paint_op_array(T* op) {
153 static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
154 "T is not a PaintOpWithDataArray");
155 return SkTAddOffset<M>(op + 1, op->bytes);
156 }
157
158 struct AnnotateOp final : PaintOp {
159 enum class AnnotationType {
160 URL,
161 LinkToDestination,
162 NamedDestination,
163 };
164
165 static constexpr PaintOpType kType = PaintOpType::Annotate;
166 AnnotateOp(PaintCanvas::AnnotationType annotation_type,
167 const SkRect& rect,
168 sk_sp<SkData> data);
169 ~AnnotateOp();
170 void Raster(SkCanvas* canvas) const;
171
172 PaintCanvas::AnnotationType annotation_type;
173 SkRect rect;
174 sk_sp<SkData> data;
175 };
176
177 struct ClipPathOp final : PaintOp {
178 static constexpr PaintOpType kType = PaintOpType::ClipPath;
179 ClipPathOp(SkPath path, SkClipOp op, bool antialias)
180 : path(path), op(op), antialias(antialias) {}
181 void Raster(SkCanvas* canvas) const;
182 int CountSlowPaths() const;
183
184 ThreadsafePath path;
185 SkClipOp op;
186 bool antialias;
187 };
188
189 struct ClipRectOp final : PaintOp {
190 static constexpr PaintOpType kType = PaintOpType::ClipRect;
191 ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
192 : rect(rect), op(op), antialias(antialias) {}
193 void Raster(SkCanvas* canvas) const;
194
195 SkRect rect;
196 SkClipOp op;
197 bool antialias;
198 };
199
200 struct ClipRRectOp final : PaintOp {
201 static constexpr PaintOpType kType = PaintOpType::ClipRRect;
202 ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
203 : rrect(rrect), op(op), antialias(antialias) {}
204 void Raster(SkCanvas* canvas) const;
205
206 SkRRect rrect;
207 SkClipOp op;
208 bool antialias;
209 };
210
211 struct ConcatOp final : PaintOp {
212 static constexpr PaintOpType kType = PaintOpType::Concat;
213 explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {}
214 void Raster(SkCanvas* canvas) const;
215
216 ThreadsafeMatrix matrix;
217 };
218
219 struct DrawArcOp final : PaintOp {
220 static constexpr PaintOpType kType = PaintOpType::DrawArc;
221 static constexpr bool kIsDrawOp = true;
222 static constexpr bool kHasPaintFlags = true;
223 DrawArcOp(const SkRect& oval,
224 SkScalar start_angle,
225 SkScalar sweep_angle,
226 bool use_center,
227 const PaintFlags& flags)
228 : oval(oval),
229 start_angle(start_angle),
230 sweep_angle(sweep_angle),
231 use_center(use_center),
232 flags(flags) {}
233 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
234
235 SkRect oval;
236 SkScalar start_angle;
237 SkScalar sweep_angle;
238 bool use_center;
239 PaintFlags flags;
240 };
241
242 struct DrawCircleOp final : PaintOp {
243 static constexpr PaintOpType kType = PaintOpType::DrawCircle;
244 static constexpr bool kIsDrawOp = true;
245 static constexpr bool kHasPaintFlags = true;
246 DrawCircleOp(SkScalar cx,
247 SkScalar cy,
248 SkScalar radius,
249 const PaintFlags& flags)
250 : cx(cx), cy(cy), radius(radius), flags(flags) {}
251 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
252
253 SkScalar cx;
254 SkScalar cy;
255 SkScalar radius;
256 PaintFlags flags;
257 };
258
259 struct DrawColorOp final : PaintOp {
260 static constexpr PaintOpType kType = PaintOpType::DrawColor;
261 static constexpr bool kIsDrawOp = true;
262 DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
263 void Raster(SkCanvas* canvas) const;
264
265 SkColor color;
266 SkBlendMode mode;
267 };
268
269 struct DrawDisplayItemListOp final : PaintOp {
270 static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList;
271 static constexpr bool kIsDrawOp = true;
272 explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list);
273 ~DrawDisplayItemListOp();
274 void Raster(SkCanvas* canvas) const;
275 size_t AdditionalBytesUsed() const;
276 // TODO(enne): DisplayItemList should know number of slow paths.
277
278 scoped_refptr<DisplayItemList> list;
279 };
280
281 struct DrawDRRectOp final : PaintOp {
282 static constexpr PaintOpType kType = PaintOpType::DrawDRRect;
283 static constexpr bool kIsDrawOp = true;
284 static constexpr bool kHasPaintFlags = true;
285 DrawDRRectOp(const SkRRect& outer,
286 const SkRRect& inner,
287 const PaintFlags& flags)
288 : outer(outer), inner(inner), flags(flags) {}
289 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
290
291 SkRRect outer;
292 SkRRect inner;
293 PaintFlags flags;
294 };
295
296 struct DrawImageOp final : PaintOp {
297 static constexpr PaintOpType kType = PaintOpType::DrawImage;
298 static constexpr bool kIsDrawOp = true;
299 static constexpr bool kHasPaintFlags = true;
300 DrawImageOp(sk_sp<const SkImage> image,
301 SkScalar left,
302 SkScalar top,
303 const PaintFlags* flags);
304 ~DrawImageOp();
305 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
306
307 sk_sp<const SkImage> image;
308 SkScalar left;
309 SkScalar top;
310 PaintFlags flags;
311 };
312
313 struct DrawImageRectOp final : PaintOp {
314 static constexpr PaintOpType kType = PaintOpType::DrawImageRect;
315 static constexpr bool kIsDrawOp = true;
316 static constexpr bool kHasPaintFlags = true;
317 DrawImageRectOp(sk_sp<const SkImage> image,
318 const SkRect& src,
319 const SkRect& dst,
320 const PaintFlags* flags,
321 PaintCanvas::SrcRectConstraint constraint);
322 ~DrawImageRectOp();
323 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
324
325 sk_sp<const SkImage> image;
326 PaintFlags flags;
327 SkRect src;
328 SkRect dst;
329 PaintCanvas::SrcRectConstraint constraint;
330 };
331
332 struct DrawIRectOp final : PaintOp {
333 static constexpr PaintOpType kType = PaintOpType::DrawIRect;
334 static constexpr bool kIsDrawOp = true;
335 static constexpr bool kHasPaintFlags = true;
336 DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
337 : rect(rect), flags(flags) {}
338 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
339
340 SkIRect rect;
341 PaintFlags flags;
342 };
343
344 struct DrawLineOp final : PaintOp {
345 static constexpr PaintOpType kType = PaintOpType::DrawLine;
346 static constexpr bool kIsDrawOp = true;
347 static constexpr bool kHasPaintFlags = true;
348 DrawLineOp(SkScalar x0,
349 SkScalar y0,
350 SkScalar x1,
351 SkScalar y1,
352 const PaintFlags& flags)
353 : x0(x0), y0(y0), x1(x1), y1(y1), flags(flags) {}
354 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
355 int CountSlowPaths() const;
356
357 SkScalar x0;
358 SkScalar y0;
359 SkScalar x1;
360 SkScalar y1;
361 PaintFlags flags;
362 };
363
364 struct DrawOvalOp final : PaintOp {
365 static constexpr PaintOpType kType = PaintOpType::DrawOval;
366 static constexpr bool kIsDrawOp = true;
367 static constexpr bool kHasPaintFlags = true;
368 DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
369 : oval(oval), flags(flags) {}
370 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
371
372 SkRect oval;
373 PaintFlags flags;
374 };
375
376 struct DrawPathOp final : PaintOp {
377 static constexpr PaintOpType kType = PaintOpType::DrawPath;
378 static constexpr bool kIsDrawOp = true;
379 static constexpr bool kHasPaintFlags = true;
380 DrawPathOp(const SkPath& path, const PaintFlags& flags)
381 : path(path), flags(flags) {}
382 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
383 int CountSlowPaths() const;
384
385 ThreadsafePath path;
386 PaintFlags flags;
387 };
388
389 struct DrawPosTextOp final : PaintOpWithDataArray<SkPoint> {
390 static constexpr PaintOpType kType = PaintOpType::DrawPosText;
391 static constexpr bool kIsDrawOp = true;
392 static constexpr bool kHasPaintFlags = true;
393 DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags);
394 ~DrawPosTextOp();
395 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
396
397 PaintFlags flags;
398 };
399
400 struct DrawRecordOp final : PaintOp {
401 static constexpr PaintOpType kType = PaintOpType::DrawRecord;
402 static constexpr bool kIsDrawOp = true;
403 explicit DrawRecordOp(sk_sp<const PaintRecord> record);
404 ~DrawRecordOp();
405 void Raster(SkCanvas* canvas) const;
406 size_t AdditionalBytesUsed() const;
407
408 sk_sp<const PaintRecord> record;
409 };
410
411 struct DrawRectOp final : PaintOp {
412 static constexpr PaintOpType kType = PaintOpType::DrawRect;
413 static constexpr bool kIsDrawOp = true;
414 static constexpr bool kHasPaintFlags = true;
415 DrawRectOp(const SkRect& rect, const PaintFlags& flags)
416 : rect(rect), flags(flags) {}
417 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
418
419 SkRect rect;
420 PaintFlags flags;
421 };
422
423 struct DrawRRectOp final : PaintOp {
424 static constexpr PaintOpType kType = PaintOpType::DrawRRect;
425 static constexpr bool kIsDrawOp = true;
426 static constexpr bool kHasPaintFlags = true;
427 DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
428 : rrect(rrect), flags(flags) {}
429 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
430
431 SkRRect rrect;
432 PaintFlags flags;
433 };
434
435 struct DrawTextOp final : PaintOpWithData {
436 static constexpr PaintOpType kType = PaintOpType::DrawText;
437 static constexpr bool kIsDrawOp = true;
438 static constexpr bool kHasPaintFlags = true;
439 DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
440 : PaintOpWithData(bytes), x(x), y(y), flags(flags) {}
441 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
442
443 SkScalar x;
444 SkScalar y;
445 PaintFlags flags;
446 };
447
448 struct DrawTextBlobOp final : PaintOp {
449 static constexpr PaintOpType kType = PaintOpType::DrawTextBlob;
450 static constexpr bool kIsDrawOp = true;
451 static constexpr bool kHasPaintFlags = true;
452 DrawTextBlobOp(sk_sp<SkTextBlob> blob,
453 SkScalar x,
454 SkScalar y,
455 const PaintFlags& flags);
456 ~DrawTextBlobOp();
457 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
458
459 sk_sp<SkTextBlob> blob;
460 SkScalar x;
461 SkScalar y;
462 PaintFlags flags;
463 };
464
465 struct NoopOp final : PaintOp {
vmpstr 2017/04/06 19:16:12 :D
enne (OOO) 2017/04/06 23:17:05 I know, I know. NoOp just looked weird as an alte
466 static constexpr PaintOpType kType = PaintOpType::Noop;
467 void Raster(SkCanvas* canvas) const {}
468 };
469
470 struct RestoreOp final : PaintOp {
471 static constexpr PaintOpType kType = PaintOpType::Restore;
472 void Raster(SkCanvas* canvas) const;
473 };
474
475 struct RotateOp final : PaintOp {
476 static constexpr PaintOpType kType = PaintOpType::Rotate;
477 explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
478 void Raster(SkCanvas* canvas) const;
479
480 SkScalar degrees;
481 };
482
483 struct SaveOp final : PaintOp {
484 static constexpr PaintOpType kType = PaintOpType::Save;
485 void Raster(SkCanvas* canvas) const;
486 };
487
488 struct SaveLayerOp final : PaintOp {
489 static constexpr PaintOpType kType = PaintOpType::SaveLayer;
490 static constexpr bool kHasPaintFlags = true;
491 SaveLayerOp(const SkRect* bounds, const PaintFlags* flags)
492 : bounds(bounds ? *bounds : kUnsetRect) {
493 if (flags)
494 this->flags = *flags;
495 }
496 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
497
498 SkRect bounds;
499 PaintFlags flags;
500 };
501
502 struct SaveLayerAlphaOp final : PaintOp {
503 static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha;
504 SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha)
505 : bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {}
506 void Raster(SkCanvas* canvas) const;
507
508 SkRect bounds;
509 uint8_t alpha;
510 };
511
512 struct ScaleOp final : PaintOp {
513 static constexpr PaintOpType kType = PaintOpType::Scale;
514 ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
515 void Raster(SkCanvas* canvas) const;
516
517 SkScalar sx;
518 SkScalar sy;
519 };
520
521 struct SetMatrixOp final : PaintOp {
522 static constexpr PaintOpType kType = PaintOpType::SetMatrix;
523 explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {}
524 // This is the only op that needs the original matrix.
vmpstr 2017/04/06 19:16:12 Can you comment on what original means here? Does
mtklein_C 2017/04/06 19:58:48 When you record a setMatrix(), you're doing it in
vmpstr 2017/04/06 20:37:47 Hmm ok. I guess my question is then if we try and
vmpstr 2017/04/06 20:40:50 Oh sorry, I completely misunderstood that this is
525 // TODO(enne): Find some cleaner way to do this?
526 void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
527
528 ThreadsafeMatrix matrix;
529 };
530
531 struct TranslateOp final : PaintOp {
532 static constexpr PaintOpType kType = PaintOpType::Translate;
533 TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
534 void Raster(SkCanvas* canvas) const;
535
536 SkScalar dx;
537 SkScalar dy;
538 };
539
540 using LargestPaintOp = DrawDRRectOp;
vmpstr 2017/04/06 19:16:12 Is there a way to make this future proof?
enne (OOO) 2017/04/06 23:17:05 There's static asserts that tell you which op is b
541
542 class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
543 public:
544 enum { kPageSize = 4096 };
545
546 PaintOpBuffer();
547 explicit PaintOpBuffer(const SkRect& cull_rect);
548 ~PaintOpBuffer() override;
549
550 void Reset();
551
552 void playback(SkCanvas* canvas) const;
553 void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
554
555 // TODO(enne): These are no longer approximate. Rename these.
vmpstr 2017/04/06 19:16:12 Cool! You can then ignore my previous comment abou
556 int approximateOpCount() const { return op_count_; }
557 size_t approximateBytesUsed() const {
558 return sizeof(*this) + reserved_ + subrecord_bytes_used_;
559 }
560 int numSlowPaths() const { return num_slow_paths_; }
561
562 const SkRect& cullRect() const { return cull_rect_; }
563
564 PaintOp* GetFirstOp() const {
565 return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
566 }
567
568 template <typename T, typename... Args>
569 void push(Args&&... args) {
570 static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
571 static_assert(!std::is_convertible<T, PaintOpWithData>::value,
572 "Type needs to use push_with_data");
573 push_internal<T>(0, std::forward<Args>(args)...);
574 }
575
576 template <typename T, typename... Args>
577 void push_with_data(const void* data, size_t bytes, Args&&... args) {
578 static_assert(std::is_convertible<T, PaintOpWithData>::value,
579 "T is not a PaintOpWithData");
580 #if !defined(OS_CHROMEOS)
581 // TODO(enne): non-linux chromeos builds think that DrawTextOp
582 // can be converted to a PaintOpWithDataArrayBase. OOPS.
583 static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
584 "Type needs to use push_with_data_array");
585 #endif
586 DCHECK_GE(bytes, 0u);
587 T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
588 memcpy(paint_op_data(op), data, bytes);
589
590 #if DCHECK_IS_ON()
591 // Double check the data fits between op and next op and doesn't clobber.
592 char* op_start = reinterpret_cast<char*>(op);
593 char* op_end = op_start + sizeof(T);
594 char* next_op = op_start + op->skip;
595 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
596 char* data_end = data_start + bytes;
597 DCHECK_GE(data_start, op_end);
598 DCHECK_LT(data_start, next_op);
599 DCHECK_LE(data_end, next_op);
600 #endif
601 }
602
603 template <typename T, typename M, typename... Args>
604 void push_with_data_array(const void* data,
605 size_t bytes,
606 const M* array,
607 size_t count,
608 Args&&... args) {
609 static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
610 "T is not a PaintOpWithDataArray");
611 DCHECK_GE(bytes, 0u);
612 DCHECK_GE(count, 0u);
613 size_t array_size = sizeof(M) * count;
614 size_t total_size = bytes + array_size;
615 T* op =
616 push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
617 memcpy(paint_op_data(op), data, bytes);
618 memcpy(paint_op_array<M>(op), array, array_size);
619
620 #if DCHECK_IS_ON()
621 // Double check data and array don't clobber op, next op, or each other
622 char* op_start = reinterpret_cast<char*>(op);
623 char* op_end = op_start + sizeof(T);
624 char* next_op = op_start + op->skip;
625 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
626 char* data_end = data_start + bytes;
627 char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
628 char* array_end = array_start + array_size;
629 DCHECK_GE(data_start, op_end);
630 DCHECK_LE(data_start, array_start);
631 DCHECK_GE(array_start, data_end);
632 DCHECK_LE(array_end, next_op);
633 #endif
634 }
635
636 class Iterator {
637 public:
638 explicit Iterator(const PaintOpBuffer* buffer)
639 : buffer_(buffer), ptr_(buffer_->data_.get()) {}
640
641 PaintOp* operator->() const {
642 return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
643 }
644 PaintOp* operator*() const { return operator->(); }
645 Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
646 Iterator end() {
647 return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
648 buffer_->approximateOpCount());
649 }
650 bool operator!=(const Iterator& other) {
651 // Not valid to compare iterators on different buffers.
652 DCHECK_EQ(other.buffer_, buffer_);
653 return other.op_idx_ != op_idx_;
654 }
655 Iterator& operator++() {
656 if (!op_idx_++)
657 return *this;
658 PaintOp* op = **this;
659 uint32_t type = op->type;
660 CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
661 ptr_ += op->skip;
662 return *this;
663 }
664 operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
665
666 // Return the next op without advancing the iterator, or nullptr if none.
667 PaintOp* peek1() const {
668 if (op_idx_ + 1 >= buffer_->approximateOpCount())
669 return nullptr;
670 if (!op_idx_)
671 return reinterpret_cast<PaintOp*>(ptr_);
672 return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
673 }
674
675 // Return the op two ops ahead without advancing the iterator, or nullptr if
676 // none.
677 PaintOp* peek2() const {
678 if (op_idx_ + 2 >= buffer_->approximateOpCount())
679 return nullptr;
680 char* next = ptr_ + (*this)->skip;
681 PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
682 if (!op_idx_)
683 return next_op;
684 return reinterpret_cast<PaintOp*>(next + next_op->skip);
685 }
686
687 private:
688 Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
689 : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
690
691 const PaintOpBuffer* buffer_;
vmpstr 2017/04/06 19:16:12 = nullptr for consistency?
692 char* ptr_;
693 int op_idx_ = 0;
694 };
695
696 private:
697 template <typename T, bool HasFlags>
698 struct CountSlowPathsFromFlags {
699 static int Count(const T* op) { return 0; }
700 };
701
702 template <typename T>
703 struct CountSlowPathsFromFlags<T, true> {
704 static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
705 };
706
707 template <typename T, typename... Args>
708 T* push_internal(size_t bytes, Args&&... args) {
709 size_t skip = SkAlignPtr(sizeof(T) + bytes);
710 DCHECK_LT(skip, static_cast<size_t>(1) << 24);
711 if (used_ + skip > reserved_ || !op_count_) {
712 if (!op_count_) {
713 if (bytes) {
714 // Internal first_op buffer doesn't have room for extra data.
715 // If the op wants extra bytes, then we'll just store a Noop
716 // in the first_op and proceed from there. This seems unlikely
717 // to be a common case.
718 push<NoopOp>();
719 } else {
720 T* op = reinterpret_cast<T*>(&first_op_[0]);
721 new (op) T{std::forward<Args>(args)...};
722 op->type = static_cast<uint32_t>(T::kType);
723 op->skip = 0;
724 op_count_++;
725 return op;
726 }
727 }
728
729 static_assert(SkIsPow2(kPageSize),
730 "This math needs updating for non-pow2.");
731 // Next greater multiple of kPageSize.
732 reserved_ = (used_ + skip + kPageSize) & ~(kPageSize - 1);
733 data_.realloc(reserved_);
734 }
735 DCHECK_LE(used_ + skip, reserved_);
736
737 T* op = reinterpret_cast<T*>(data_.get() + used_);
738 used_ += skip;
739 new (op) T(std::forward<Args>(args)...);
740 op->type = static_cast<uint32_t>(T::kType);
741 op->skip = skip;
742 op_count_++;
743
744 num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
745 num_slow_paths_ += op->CountSlowPaths();
746
747 subrecord_bytes_used_ += op->AdditionalBytesUsed();
748
749 return op;
750 }
751
752 char first_op_[sizeof(LargestPaintOp)];
753 SkAutoTMalloc<char> data_;
754 size_t used_ = 0;
755 size_t reserved_ = 0;
756 int op_count_ = 0;
757
758 // Record paths for veto-to-msaa for gpu raster.
759 int num_slow_paths_ = 0;
760 // Record additional bytes used by referenced sub-records and display lists.
761 size_t subrecord_bytes_used_ = 0;
762 SkRect cull_rect_;
763
764 DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
765 };
766
767 } // namespace cc
768
769 #endif // CC_PAINT_PAINT_OP_BUFFER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698