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

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

Issue 2768143002: Back PaintRecord with PaintOpBuffer instead of SkPicture (Closed)
Patch Set: Rebase 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 CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix {
26 public:
27 explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
28 (void)getType();
29 }
30 };
31
32 class CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT PaintOpWithDataArrayBase : PaintOpWithData {
131 // Helper class for static asserts in push functions.
132 using PaintOpWithData::PaintOpWithData;
133 };
134
135 template <typename T>
136 struct CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT 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 CC_PAINT_EXPORT DrawDisplayItemListOp final : PaintOp {
272 static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList;
273 static constexpr bool kIsDrawOp = true;
274 explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list);
275 // Windows wants to generate these when types are exported, so
276 // provide them here explicitly so that DisplayItemList doesn't have
277 // to be defined in this header.
278 DrawDisplayItemListOp(const DrawDisplayItemListOp& op);
279 DrawDisplayItemListOp& operator=(const DrawDisplayItemListOp& op);
280 ~DrawDisplayItemListOp();
281 void Raster(SkCanvas* canvas) const;
282 size_t AdditionalBytesUsed() const;
283 // TODO(enne): DisplayItemList should know number of slow paths.
284
285 scoped_refptr<DisplayItemList> list;
286 };
287
288 struct CC_PAINT_EXPORT DrawDRRectOp final : PaintOp {
289 static constexpr PaintOpType kType = PaintOpType::DrawDRRect;
290 static constexpr bool kIsDrawOp = true;
291 static constexpr bool kHasPaintFlags = true;
292 DrawDRRectOp(const SkRRect& outer,
293 const SkRRect& inner,
294 const PaintFlags& flags)
295 : outer(outer), inner(inner), flags(flags) {}
296 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
297
298 SkRRect outer;
299 SkRRect inner;
300 PaintFlags flags;
301 };
302
303 struct CC_PAINT_EXPORT DrawImageOp final : PaintOp {
304 static constexpr PaintOpType kType = PaintOpType::DrawImage;
305 static constexpr bool kIsDrawOp = true;
306 static constexpr bool kHasPaintFlags = true;
307 DrawImageOp(const PaintImage& image,
308 SkScalar left,
309 SkScalar top,
310 const PaintFlags* flags);
311 ~DrawImageOp();
312 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
313
314 PaintImage image;
315 SkScalar left;
316 SkScalar top;
317 PaintFlags flags;
318 };
319
320 struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOp {
321 static constexpr PaintOpType kType = PaintOpType::DrawImageRect;
322 static constexpr bool kIsDrawOp = true;
323 static constexpr bool kHasPaintFlags = true;
324 DrawImageRectOp(const PaintImage& image,
325 const SkRect& src,
326 const SkRect& dst,
327 const PaintFlags* flags,
328 PaintCanvas::SrcRectConstraint constraint);
329 ~DrawImageRectOp();
330 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
331
332 PaintImage image;
333 PaintFlags flags;
334 SkRect src;
335 SkRect dst;
336 PaintCanvas::SrcRectConstraint constraint;
337 };
338
339 struct CC_PAINT_EXPORT DrawIRectOp final : PaintOp {
340 static constexpr PaintOpType kType = PaintOpType::DrawIRect;
341 static constexpr bool kIsDrawOp = true;
342 static constexpr bool kHasPaintFlags = true;
343 DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
344 : rect(rect), flags(flags) {}
345 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
346
347 SkIRect rect;
348 PaintFlags flags;
349 };
350
351 struct CC_PAINT_EXPORT DrawLineOp final : PaintOp {
352 static constexpr PaintOpType kType = PaintOpType::DrawLine;
353 static constexpr bool kIsDrawOp = true;
354 static constexpr bool kHasPaintFlags = true;
355 DrawLineOp(SkScalar x0,
356 SkScalar y0,
357 SkScalar x1,
358 SkScalar y1,
359 const PaintFlags& flags)
360 : x0(x0), y0(y0), x1(x1), y1(y1), flags(flags) {}
361 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
362 int CountSlowPaths() const;
363
364 SkScalar x0;
365 SkScalar y0;
366 SkScalar x1;
367 SkScalar y1;
368 PaintFlags flags;
369 };
370
371 struct CC_PAINT_EXPORT DrawOvalOp final : PaintOp {
372 static constexpr PaintOpType kType = PaintOpType::DrawOval;
373 static constexpr bool kIsDrawOp = true;
374 static constexpr bool kHasPaintFlags = true;
375 DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
376 : oval(oval), flags(flags) {}
377 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
378
379 SkRect oval;
380 PaintFlags flags;
381 };
382
383 struct CC_PAINT_EXPORT DrawPathOp final : PaintOp {
384 static constexpr PaintOpType kType = PaintOpType::DrawPath;
385 static constexpr bool kIsDrawOp = true;
386 static constexpr bool kHasPaintFlags = true;
387 DrawPathOp(const SkPath& path, const PaintFlags& flags)
388 : path(path), flags(flags) {}
389 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
390 int CountSlowPaths() const;
391
392 ThreadsafePath path;
393 PaintFlags flags;
394 };
395
396 struct CC_PAINT_EXPORT DrawPosTextOp final : PaintOpWithDataArray<SkPoint> {
397 static constexpr PaintOpType kType = PaintOpType::DrawPosText;
398 static constexpr bool kIsDrawOp = true;
399 static constexpr bool kHasPaintFlags = true;
400 DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags);
401 ~DrawPosTextOp();
402 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
403
404 PaintFlags flags;
405 };
406
407 struct CC_PAINT_EXPORT DrawRecordOp final : PaintOp {
408 static constexpr PaintOpType kType = PaintOpType::DrawRecord;
409 static constexpr bool kIsDrawOp = true;
410 explicit DrawRecordOp(sk_sp<const PaintRecord> record);
411 ~DrawRecordOp();
412 void Raster(SkCanvas* canvas) const;
413 size_t AdditionalBytesUsed() const;
414
415 sk_sp<const PaintRecord> record;
416 };
417
418 struct CC_PAINT_EXPORT DrawRectOp final : PaintOp {
419 static constexpr PaintOpType kType = PaintOpType::DrawRect;
420 static constexpr bool kIsDrawOp = true;
421 static constexpr bool kHasPaintFlags = true;
422 DrawRectOp(const SkRect& rect, const PaintFlags& flags)
423 : rect(rect), flags(flags) {}
424 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
425
426 SkRect rect;
427 PaintFlags flags;
428 };
429
430 struct CC_PAINT_EXPORT DrawRRectOp final : PaintOp {
431 static constexpr PaintOpType kType = PaintOpType::DrawRRect;
432 static constexpr bool kIsDrawOp = true;
433 static constexpr bool kHasPaintFlags = true;
434 DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
435 : rrect(rrect), flags(flags) {}
436 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
437
438 SkRRect rrect;
439 PaintFlags flags;
440 };
441
442 struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData {
443 static constexpr PaintOpType kType = PaintOpType::DrawText;
444 static constexpr bool kIsDrawOp = true;
445 static constexpr bool kHasPaintFlags = true;
446 DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
447 : PaintOpWithData(bytes), x(x), y(y), flags(flags) {}
448 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
449
450 SkScalar x;
451 SkScalar y;
452 PaintFlags flags;
453 };
454
455 struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOp {
456 static constexpr PaintOpType kType = PaintOpType::DrawTextBlob;
457 static constexpr bool kIsDrawOp = true;
458 static constexpr bool kHasPaintFlags = true;
459 DrawTextBlobOp(sk_sp<SkTextBlob> blob,
460 SkScalar x,
461 SkScalar y,
462 const PaintFlags& flags);
463 ~DrawTextBlobOp();
464 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
465
466 sk_sp<SkTextBlob> blob;
467 SkScalar x;
468 SkScalar y;
469 PaintFlags flags;
470 };
471
472 struct CC_PAINT_EXPORT NoopOp final : PaintOp {
473 static constexpr PaintOpType kType = PaintOpType::Noop;
474 void Raster(SkCanvas* canvas) const {}
475 };
476
477 struct CC_PAINT_EXPORT RestoreOp final : PaintOp {
478 static constexpr PaintOpType kType = PaintOpType::Restore;
479 void Raster(SkCanvas* canvas) const;
480 };
481
482 struct CC_PAINT_EXPORT RotateOp final : PaintOp {
483 static constexpr PaintOpType kType = PaintOpType::Rotate;
484 explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
485 void Raster(SkCanvas* canvas) const;
486
487 SkScalar degrees;
488 };
489
490 struct CC_PAINT_EXPORT SaveOp final : PaintOp {
491 static constexpr PaintOpType kType = PaintOpType::Save;
492 void Raster(SkCanvas* canvas) const;
493 };
494
495 struct CC_PAINT_EXPORT SaveLayerOp final : PaintOp {
496 static constexpr PaintOpType kType = PaintOpType::SaveLayer;
497 static constexpr bool kHasPaintFlags = true;
498 SaveLayerOp(const SkRect* bounds, const PaintFlags* flags)
499 : bounds(bounds ? *bounds : kUnsetRect) {
500 if (flags)
501 this->flags = *flags;
502 }
503 void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
504
505 SkRect bounds;
506 PaintFlags flags;
507 };
508
509 struct CC_PAINT_EXPORT SaveLayerAlphaOp final : PaintOp {
510 static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha;
511 SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha)
512 : bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {}
513 void Raster(SkCanvas* canvas) const;
514
515 SkRect bounds;
516 uint8_t alpha;
517 };
518
519 struct CC_PAINT_EXPORT ScaleOp final : PaintOp {
520 static constexpr PaintOpType kType = PaintOpType::Scale;
521 ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
522 void Raster(SkCanvas* canvas) const;
523
524 SkScalar sx;
525 SkScalar sy;
526 };
527
528 struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp {
529 static constexpr PaintOpType kType = PaintOpType::SetMatrix;
530 explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {}
531 // This is the only op that needs the original ctm of the SkCanvas
532 // used for raster (since SetMatrix is relative to the recording origin and
533 // shouldn't clobber the SkCanvas raster origin).
534 //
535 // TODO(enne): Find some cleaner way to do this, possibly by making
536 // all SetMatrix calls Concat??
537 void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
538
539 ThreadsafeMatrix matrix;
540 };
541
542 struct CC_PAINT_EXPORT TranslateOp final : PaintOp {
543 static constexpr PaintOpType kType = PaintOpType::Translate;
544 TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
545 void Raster(SkCanvas* canvas) const;
546
547 SkScalar dx;
548 SkScalar dy;
549 };
550
551 using LargestPaintOp = DrawDRRectOp;
552
553 class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
554 public:
555 enum { kInitialBufferSize = 4096 };
556
557 PaintOpBuffer();
558 explicit PaintOpBuffer(const SkRect& cull_rect);
559 ~PaintOpBuffer() override;
560
561 void Reset();
562
563 void playback(SkCanvas* canvas) const;
564 void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
565
566 // TODO(enne): These are no longer approximate. Rename these.
567 int approximateOpCount() const { return op_count_; }
568 size_t approximateBytesUsed() const {
569 return sizeof(*this) + reserved_ + subrecord_bytes_used_;
570 }
571 int numSlowPaths() const { return num_slow_paths_; }
572
573 // Resize the PaintOpBuffer to exactly fit the current amount of used space.
574 void ShrinkToFit();
575
576 const SkRect& cullRect() const { return cull_rect_; }
577
578 PaintOp* GetFirstOp() const {
579 return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
580 }
581
582 template <typename T, typename... Args>
583 void push(Args&&... args) {
584 static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
585 static_assert(!std::is_convertible<T, PaintOpWithData>::value,
586 "Type needs to use push_with_data");
587 push_internal<T>(0, std::forward<Args>(args)...);
588 }
589
590 template <typename T, typename... Args>
591 void push_with_data(const void* data, size_t bytes, Args&&... args) {
592 static_assert(std::is_convertible<T, PaintOpWithData>::value,
593 "T is not a PaintOpWithData");
594 #if !defined(OS_CHROMEOS)
595 // TODO(enne): non-linux chromeos builds think that DrawTextOp
596 // can be converted to a PaintOpWithDataArrayBase. OOPS.
597 static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
598 "Type needs to use push_with_data_array");
599 #endif
600 DCHECK_GE(bytes, 0u);
601 T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
602 memcpy(paint_op_data(op), data, bytes);
603
604 #if DCHECK_IS_ON()
605 // Double check the data fits between op and next op and doesn't clobber.
606 char* op_start = reinterpret_cast<char*>(op);
607 char* op_end = op_start + sizeof(T);
608 char* next_op = op_start + op->skip;
609 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
610 char* data_end = data_start + bytes;
611 DCHECK_GE(data_start, op_end);
612 DCHECK_LT(data_start, next_op);
613 DCHECK_LE(data_end, next_op);
614 #endif
615 }
616
617 template <typename T, typename M, typename... Args>
618 void push_with_data_array(const void* data,
619 size_t bytes,
620 const M* array,
621 size_t count,
622 Args&&... args) {
623 static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
624 "T is not a PaintOpWithDataArray");
625 DCHECK_GE(bytes, 0u);
626 DCHECK_GE(count, 0u);
627 size_t array_size = sizeof(M) * count;
628 size_t total_size = bytes + array_size;
629 T* op =
630 push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
631 memcpy(paint_op_data(op), data, bytes);
632 memcpy(paint_op_array<M>(op), array, array_size);
633
634 #if DCHECK_IS_ON()
635 // Double check data and array don't clobber op, next op, or each other
636 char* op_start = reinterpret_cast<char*>(op);
637 char* op_end = op_start + sizeof(T);
638 char* next_op = op_start + op->skip;
639 char* data_start = reinterpret_cast<char*>(paint_op_data(op));
640 char* data_end = data_start + bytes;
641 char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
642 char* array_end = array_start + array_size;
643 DCHECK_GE(data_start, op_end);
644 DCHECK_LE(data_start, array_start);
645 DCHECK_GE(array_start, data_end);
646 DCHECK_LE(array_end, next_op);
647 #endif
648 }
649
650 class Iterator {
651 public:
652 explicit Iterator(const PaintOpBuffer* buffer)
653 : buffer_(buffer), ptr_(buffer_->data_.get()) {}
654
655 PaintOp* operator->() const {
656 return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
657 }
658 PaintOp* operator*() const { return operator->(); }
659 Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
660 Iterator end() {
661 return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
662 buffer_->approximateOpCount());
663 }
664 bool operator!=(const Iterator& other) {
665 // Not valid to compare iterators on different buffers.
666 DCHECK_EQ(other.buffer_, buffer_);
667 return other.op_idx_ != op_idx_;
668 }
669 Iterator& operator++() {
670 if (!op_idx_++)
671 return *this;
672 PaintOp* op = **this;
673 uint32_t type = op->type;
674 CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
675 ptr_ += op->skip;
676 return *this;
677 }
678 operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
679
680 int op_idx() const { return op_idx_; }
681
682 // Return the next op without advancing the iterator, or nullptr if none.
683 PaintOp* peek1() const {
684 if (op_idx_ + 1 >= buffer_->approximateOpCount())
685 return nullptr;
686 if (!op_idx_)
687 return reinterpret_cast<PaintOp*>(ptr_);
688 return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
689 }
690
691 // Return the op two ops ahead without advancing the iterator, or nullptr if
692 // none.
693 PaintOp* peek2() const {
694 if (op_idx_ + 2 >= buffer_->approximateOpCount())
695 return nullptr;
696 char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip;
697 PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
698 if (!op_idx_)
699 return next_op;
700 return reinterpret_cast<PaintOp*>(next + next_op->skip);
701 }
702
703 private:
704 Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
705 : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
706
707 const PaintOpBuffer* buffer_ = nullptr;
708 char* ptr_ = nullptr;
709 int op_idx_ = 0;
710 };
711
712 private:
713 template <typename T, bool HasFlags>
714 struct CountSlowPathsFromFlags {
715 static int Count(const T* op) { return 0; }
716 };
717
718 template <typename T>
719 struct CountSlowPathsFromFlags<T, true> {
720 static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
721 };
722
723 template <typename T, typename... Args>
724 T* push_internal(size_t bytes, Args&&... args) {
725 size_t skip = SkAlignPtr(sizeof(T) + bytes);
726 DCHECK_LT(skip, static_cast<size_t>(1) << 24);
727 if (used_ + skip > reserved_ || !op_count_) {
728 if (!op_count_) {
729 if (bytes) {
730 // Internal first_op buffer doesn't have room for extra data.
731 // If the op wants extra bytes, then we'll just store a Noop
732 // in the first_op and proceed from there. This seems unlikely
733 // to be a common case.
734 push<NoopOp>();
735 } else {
736 T* op = reinterpret_cast<T*>(&first_op_[0]);
737 new (op) T{std::forward<Args>(args)...};
738 op->type = static_cast<uint32_t>(T::kType);
739 op->skip = 0;
740 op_count_++;
741 return op;
742 }
743 }
744
745 // Start reserved_ at kInitialBufferSize and then double.
746 // ShrinkToFit can make this smaller afterwards.
747 while (used_ + skip > reserved_)
748 reserved_ = reserved_ ? reserved_ * 2 : kInitialBufferSize;
749 data_.realloc(reserved_);
750 }
751 DCHECK_LE(used_ + skip, reserved_);
752
753 T* op = reinterpret_cast<T*>(data_.get() + used_);
754 used_ += skip;
755 new (op) T(std::forward<Args>(args)...);
756 op->type = static_cast<uint32_t>(T::kType);
757 op->skip = skip;
758 op_count_++;
759
760 num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
761 num_slow_paths_ += op->CountSlowPaths();
762
763 subrecord_bytes_used_ += op->AdditionalBytesUsed();
764
765 return op;
766 }
767
768 // As a performance optimization because n=1 is an extremely common case just
769 // store the first op in the PaintOpBuffer itself to avoid an extra alloc.
770 char first_op_[sizeof(LargestPaintOp)];
danakj 2017/04/20 17:32:32 This needs to be aligned or parts of the op can fa
771 SkAutoTMalloc<char> data_;
772 size_t used_ = 0;
773 size_t reserved_ = 0;
774 int op_count_ = 0;
775
776 // Record paths for veto-to-msaa for gpu raster.
777 int num_slow_paths_ = 0;
778 // Record additional bytes used by referenced sub-records and display lists.
779 size_t subrecord_bytes_used_ = 0;
780 SkRect cull_rect_;
781
782 DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
783 };
784
785 } // namespace cc
786
787 #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