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

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

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

Powered by Google App Engine
This is Rietveld 408576698