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

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

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

Powered by Google App Engine
This is Rietveld 408576698