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

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

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

Powered by Google App Engine
This is Rietveld 408576698