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

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

Issue 2820133005: Revert of Back PaintRecord with PaintOpBuffer instead of SkPicture (Closed)
Patch Set: 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
« no previous file with comments | « cc/paint/paint_image.cc ('k') | cc/paint/paint_op_buffer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(const PaintImage& image,
303 SkScalar left,
304 SkScalar top,
305 const PaintFlags* flags);
306 ~DrawImageOp();
307 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
308
309 PaintImage 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(const PaintImage& 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 PaintImage 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 { kInitialBufferSize = 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 // Resize the PaintOpBuffer to exactly fit the current amount of used space.
569 void ShrinkToFit();
570
571 const SkRect& cullRect() const { return cull_rect_; }
572
573 PaintOp* GetFirstOp() const {
574 return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
575 }
576
577 template <typename T, typename... Args>
578 void push(Args&&... args) {
579 static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
580 static_assert(!std::is_convertible<T, PaintOpWithData>::value,
581 "Type needs to use push_with_data");
582 push_internal<T>(0, std::forward<Args>(args)...);
583 }
584
585 template <typename T, typename... Args>
586 void push_with_data(const void* data, size_t bytes, Args&&... args) {
587 static_assert(std::is_convertible<T, PaintOpWithData>::value,
588 "T is not a PaintOpWithData");
589 #if !defined(OS_CHROMEOS)
590 // TODO(enne): non-linux chromeos builds think that DrawTextOp
591 // can be converted to a PaintOpWithDataArrayBase. OOPS.
592 static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
593 "Type needs to use push_with_data_array");
594 #endif
595 DCHECK_GE(bytes, 0u);
596 T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
597 memcpy(paint_op_data(op), data, bytes);
598
599 #if DCHECK_IS_ON()
600 // Double check the data fits between op and next op and doesn't clobber.
601 char* op_start = reinterpret_cast<char*>(op);
602 char* op_end = op_start + sizeof(T);
603 char* next_op = op_start + op->skip;
604 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
605 char* data_end = data_start + bytes;
606 DCHECK_GE(data_start, op_end);
607 DCHECK_LT(data_start, next_op);
608 DCHECK_LE(data_end, next_op);
609 #endif
610 }
611
612 template <typename T, typename M, typename... Args>
613 void push_with_data_array(const void* data,
614 size_t bytes,
615 const M* array,
616 size_t count,
617 Args&&... args) {
618 static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
619 "T is not a PaintOpWithDataArray");
620 DCHECK_GE(bytes, 0u);
621 DCHECK_GE(count, 0u);
622 size_t array_size = sizeof(M) * count;
623 size_t total_size = bytes + array_size;
624 T* op =
625 push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
626 memcpy(paint_op_data(op), data, bytes);
627 memcpy(paint_op_array<M>(op), array, array_size);
628
629 #if DCHECK_IS_ON()
630 // Double check data and array don't clobber op, next op, or each other
631 char* op_start = reinterpret_cast<char*>(op);
632 char* op_end = op_start + sizeof(T);
633 char* next_op = op_start + op->skip;
634 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
635 char* data_end = data_start + bytes;
636 char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
637 char* array_end = array_start + array_size;
638 DCHECK_GE(data_start, op_end);
639 DCHECK_LE(data_start, array_start);
640 DCHECK_GE(array_start, data_end);
641 DCHECK_LE(array_end, next_op);
642 #endif
643 }
644
645 class Iterator {
646 public:
647 explicit Iterator(const PaintOpBuffer* buffer)
648 : buffer_(buffer), ptr_(buffer_->data_.get()) {}
649
650 PaintOp* operator->() const {
651 return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
652 }
653 PaintOp* operator*() const { return operator->(); }
654 Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
655 Iterator end() {
656 return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
657 buffer_->approximateOpCount());
658 }
659 bool operator!=(const Iterator& other) {
660 // Not valid to compare iterators on different buffers.
661 DCHECK_EQ(other.buffer_, buffer_);
662 return other.op_idx_ != op_idx_;
663 }
664 Iterator& operator++() {
665 if (!op_idx_++)
666 return *this;
667 PaintOp* op = **this;
668 uint32_t type = op->type;
669 CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
670 ptr_ += op->skip;
671 return *this;
672 }
673 operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
674
675 int op_idx() const { return op_idx_; }
676
677 // Return the next op without advancing the iterator, or nullptr if none.
678 PaintOp* peek1() const {
679 if (op_idx_ + 1 >= buffer_->approximateOpCount())
680 return nullptr;
681 if (!op_idx_)
682 return reinterpret_cast<PaintOp*>(ptr_);
683 return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
684 }
685
686 // Return the op two ops ahead without advancing the iterator, or nullptr if
687 // none.
688 PaintOp* peek2() const {
689 if (op_idx_ + 2 >= buffer_->approximateOpCount())
690 return nullptr;
691 char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip;
692 PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
693 if (!op_idx_)
694 return next_op;
695 return reinterpret_cast<PaintOp*>(next + next_op->skip);
696 }
697
698 private:
699 Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
700 : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
701
702 const PaintOpBuffer* buffer_ = nullptr;
703 char* ptr_ = nullptr;
704 int op_idx_ = 0;
705 };
706
707 private:
708 template <typename T, bool HasFlags>
709 struct CountSlowPathsFromFlags {
710 static int Count(const T* op) { return 0; }
711 };
712
713 template <typename T>
714 struct CountSlowPathsFromFlags<T, true> {
715 static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
716 };
717
718 template <typename T, typename... Args>
719 T* push_internal(size_t bytes, Args&&... args) {
720 size_t skip = SkAlignPtr(sizeof(T) + bytes);
721 DCHECK_LT(skip, static_cast<size_t>(1) << 24);
722 if (used_ + skip > reserved_ || !op_count_) {
723 if (!op_count_) {
724 if (bytes) {
725 // Internal first_op buffer doesn't have room for extra data.
726 // If the op wants extra bytes, then we'll just store a Noop
727 // in the first_op and proceed from there. This seems unlikely
728 // to be a common case.
729 push<NoopOp>();
730 } else {
731 T* op = reinterpret_cast<T*>(&first_op_[0]);
732 new (op) T{std::forward<Args>(args)...};
733 op->type = static_cast<uint32_t>(T::kType);
734 op->skip = 0;
735 op_count_++;
736 return op;
737 }
738 }
739
740 // Start reserved_ at kInitialBufferSize and then double.
741 // ShrinkToFit can make this smaller afterwards.
742 while (used_ + skip > reserved_)
743 reserved_ = reserved_ ? reserved_ * 2 : kInitialBufferSize;
744 data_.realloc(reserved_);
745 }
746 DCHECK_LE(used_ + skip, reserved_);
747
748 T* op = reinterpret_cast<T*>(data_.get() + used_);
749 used_ += skip;
750 new (op) T(std::forward<Args>(args)...);
751 op->type = static_cast<uint32_t>(T::kType);
752 op->skip = skip;
753 op_count_++;
754
755 num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
756 num_slow_paths_ += op->CountSlowPaths();
757
758 subrecord_bytes_used_ += op->AdditionalBytesUsed();
759
760 return op;
761 }
762
763 // As a performance optimization because n=1 is an extremely common case just
764 // store the first op in the PaintOpBuffer itself to avoid an extra alloc.
765 char first_op_[sizeof(LargestPaintOp)];
766 SkAutoTMalloc<char> data_;
767 size_t used_ = 0;
768 size_t reserved_ = 0;
769 int op_count_ = 0;
770
771 // Record paths for veto-to-msaa for gpu raster.
772 int num_slow_paths_ = 0;
773 // Record additional bytes used by referenced sub-records and display lists.
774 size_t subrecord_bytes_used_ = 0;
775 SkRect cull_rect_;
776
777 DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
778 };
779
780 } // namespace cc
781
782 #endif // CC_PAINT_PAINT_OP_BUFFER_H_
OLDNEW
« no previous file with comments | « cc/paint/paint_image.cc ('k') | cc/paint/paint_op_buffer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698