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

Side by Side Diff: sky/sdk/lib/rendering/object.dart

Issue 1216833003: Make rendering use PaintingNodes for increased efficiency. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Feedback fixes plus missing critical line that makes it work Created 5 years, 5 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 import 'dart:math' as math; 5 import 'dart:math' as math;
6 import 'dart:sky' as sky; 6 import 'dart:sky' as sky;
7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; 7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
8 8
9 import '../base/hit_test.dart'; 9 import '../base/hit_test.dart';
10 import '../base/node.dart'; 10 import '../base/node.dart';
11 import '../base/scheduler.dart' as scheduler; 11 import '../base/scheduler.dart' as scheduler;
12 12
13 export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; 13 export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
14 export '../base/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; 14 export '../base/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult;
15 15
16 16
17 class ParentData { 17 class ParentData {
18 void detach() { 18 void detach() {
19 detachSiblings(); 19 detachSiblings();
20 } 20 }
21 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart 21 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart
22 void merge(ParentData other) { 22 void merge(ParentData other) {
23 // override this in subclasses to merge in data from other into this 23 // override this in subclasses to merge in data from other into this
24 assert(other.runtimeType == this.runtimeType); 24 assert(other.runtimeType == this.runtimeType);
25 } 25 }
26 String toString() => '<none>'; 26 String toString() => '<none>';
27 } 27 }
28 28
29 class PaintingCanvas extends sky.Canvas { 29 class PaintingCanvas extends sky.Canvas {
30 PaintingCanvas(sky.PictureRecorder recorder, Size bounds) : super(recorder, bo unds); 30 PaintingCanvas(sky.PictureRecorder recorder, Rect bounds) : super(recorder, bo unds);
31 31
32 List<RenderObject> _descendentsWithPaintingCanvases; // used by RenderObject._ updatePaintingCanvas() to find out which RenderObjects to ask to paint
32 void paintChild(RenderObject child, Point point) { 33 void paintChild(RenderObject child, Point point) {
33 child.paint(this, point.toOffset()); 34 if (child.createNewDisplayList) {
35 if (_descendentsWithPaintingCanvases == null)
36 _descendentsWithPaintingCanvases = new List<RenderObject>();
abarth-chromium 2015/07/06 20:50:58 You can simplify this pattern by writing: final L
iansf 2015/07/07 20:36:47 Done.
37 assert(!_descendentsWithPaintingCanvases.contains(child));
38 _descendentsWithPaintingCanvases.add(child);
39 translate(point.x, point.y);
40 drawPaintingNode(child._paintingNode);
41 translate(-point.x, -point.y);
abarth-chromium 2015/07/06 20:50:58 It looks like drawPaintingNode should take a Point
iansf 2015/07/07 20:36:47 Done.
42 } else {
43 child._paintOnCanvas(this, point.toOffset());
44 }
34 } 45 }
35 } 46 }
36 47
37 abstract class Constraints { 48 abstract class Constraints {
38 const Constraints(); 49 const Constraints();
39 bool get isTight; 50 bool get isTight;
40 } 51 }
41 52
42 abstract class RenderObject extends AbstractNode implements HitTestTarget { 53 abstract class RenderObject extends AbstractNode implements HitTestTarget {
43 54
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 _cleanRelayoutSubtreeRootChildren(); 142 _cleanRelayoutSubtreeRootChildren();
132 } 143 }
133 } 144 }
134 void _cleanRelayoutSubtreeRootChildren() { } // workaround for lack of inter-c lass mixins in Dart 145 void _cleanRelayoutSubtreeRootChildren() { } // workaround for lack of inter-c lass mixins in Dart
135 void scheduleInitialLayout() { 146 void scheduleInitialLayout() {
136 assert(attached); 147 assert(attached);
137 assert(parent == null); 148 assert(parent == null);
138 assert(_relayoutSubtreeRoot == null); 149 assert(_relayoutSubtreeRoot == null);
139 _relayoutSubtreeRoot = this; 150 _relayoutSubtreeRoot = this;
140 _nodesNeedingLayout.add(this); 151 _nodesNeedingLayout.add(this);
152 _nodesNeedingPaint.add(this);
141 scheduler.ensureVisualUpdate(); 153 scheduler.ensureVisualUpdate();
142 } 154 }
143 static void flushLayout() { 155 static void flushLayout() {
144 sky.tracing.begin('RenderObject.flushLayout'); 156 sky.tracing.begin('RenderObject.flushLayout');
145 _debugDoingLayout = true; 157 _debugDoingLayout = true;
146 try { 158 try {
147 List<RenderObject> dirtyNodes = _nodesNeedingLayout; 159 List<RenderObject> dirtyNodes = _nodesNeedingLayout;
148 _nodesNeedingLayout = new List<RenderObject>(); 160 _nodesNeedingLayout = new List<RenderObject>();
149 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { 161 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) {
150 if (node._needsLayout && node.attached) 162 if (node._needsLayout && node.attached)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 243
232 void rotate({ 244 void rotate({
233 int oldAngle, // 0..3 245 int oldAngle, // 0..3
234 int newAngle, // 0..3 246 int newAngle, // 0..3
235 Duration time 247 Duration time
236 }) { } 248 }) { }
237 249
238 250
239 // PAINTING 251 // PAINTING
240 252
241 static bool debugDoingPaint = false; 253 static List<RenderObject> _nodesNeedingPaint = new List<RenderObject>();
254 static bool _debugDoingPaint = false;
255 static bool get debugDoingPaint => _debugDoingPaint;
256
257 sky.PaintingNode _paintingNode = new sky.PaintingNode(); // only set if create NewDisplayList is true
abarth-chromium 2015/07/06 20:50:58 Without |final|, this call to new will happen all
iansf 2015/07/07 21:11:22 I made this final -- it's never reassigned.
258 sky.PaintingNode get paintingNode => _paintingNode;
259 bool _needsPaint = true;
260 bool get needsPaint => _needsPaint;
261 bool get createNewDisplayList => true;
abarth-chromium 2015/07/06 20:50:58 I'm not sure we want the default behavior to be to
iansf 2015/07/07 21:11:23 Done.
262
242 void markNeedsPaint() { 263 void markNeedsPaint() {
243 assert(!debugDoingPaint); 264 assert(!debugDoingPaint);
244 scheduler.ensureVisualUpdate(); 265 if (_needsPaint) return;
266 if (createNewDisplayList) {
267 _needsPaint = true;
268 _nodesNeedingPaint.add(this);
269 scheduler.ensureVisualUpdate();
270 } else if (parent != null) {
271 if (parent is RenderObject) {
272 (parent as RenderObject).markNeedsPaint(); // TODO(ianh): remove the cas t once the analyzer is cleverer
273 }
274 }
245 } 275 }
276
277 static void flushPaint() {
278 _debugDoingPaint = true;
279 List<RenderObject> dirtyNodes = _nodesNeedingPaint;
280 _nodesNeedingPaint = new List<RenderObject>();
281 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) {
282 if (node._needsPaint && node.attached)
283 node._updatePaintingCanvas();
284 });
285 assert(_nodesNeedingPaint.length == 0);
286 _debugDoingPaint = false;
abarth-chromium 2015/07/06 20:50:58 We should wrap the body of this function in a try
iansf 2015/07/07 20:36:47 Done.
287 }
288
289 void _updatePaintingCanvas() {
290 assert(!_needsLayout);
291 assert(createNewDisplayList);
292 sky.PictureRecorder recorder = new sky.PictureRecorder();
293 PaintingCanvas canvas = new PaintingCanvas(recorder, paintBounds);
294 _needsPaint = false;
295 try {
296 _paintOnCanvas(canvas, Offset.zero);
297 } catch (e, stack) {
abarth-chromium 2015/07/06 20:50:58 Capturing the stack here is going to be too expens
Hixie 2015/07/06 21:13:42 If you change this make sure the equivalent code i
iansf 2015/07/07 20:36:47 Done.
iansf 2015/07/07 20:36:47 Done.
298 print('Exception raised during _updatePaintingCanvas:\n${e}\nContext:\n${t his}');
299 print(stack);
300 return;
301 }
302 assert(!_needsLayout); // check that the paint() method didn't mark us dirty again
303 assert(!_needsPaint); // check that the paint() method didn't mark us dirty again
304 _paintingNode.setBackingDrawable(recorder.endRecordingAsDrawable());
305
306 if (canvas._descendentsWithPaintingCanvases != null) {
307 canvas._descendentsWithPaintingCanvases.forEach((node) {
abarth-chromium 2015/07/06 20:50:57 We should use a for-each loop rather than calling
iansf 2015/07/07 20:36:47 Done.
308 assert(node.attached == attached);
309 if (node._needsPaint)
310 node._updatePaintingCanvas();
311 });
312 }
313
314 }
315
316 void _paintOnCanvas(PaintingCanvas canvas, Offset offset) {
317 _needsPaint = false;
abarth-chromium 2015/07/06 20:50:58 Why do we set _needsPaint = false both here and on
iansf 2015/07/07 20:36:47 Done.
318 paint(canvas, offset);
319 assert(!_needsPaint);
320 }
321
322 Rect get paintBounds;
323
246 void paint(PaintingCanvas canvas, Offset offset) { } 324 void paint(PaintingCanvas canvas, Offset offset) { }
247 325
248 326
249 // EVENTS 327 // EVENTS
250 328
251 void handleEvent(sky.Event event, HitTestEntry entry) { 329 void handleEvent(sky.Event event, HitTestEntry entry) {
252 // override this if you have a client, to hand it to the client 330 // override this if you have a client, to hand it to the client
253 // override this if you want to do anything with the event 331 // override this if you want to do anything with the event
254 } 332 }
255 333
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 int count = 1; 607 int count = 1;
530 ChildType child = _firstChild; 608 ChildType child = _firstChild;
531 while (child != null) { 609 while (child != null) {
532 result += '${prefix}child ${count}: ${child.toString(prefix)}'; 610 result += '${prefix}child ${count}: ${child.toString(prefix)}';
533 count += 1; 611 count += 1;
534 child = child.parentData.nextSibling; 612 child = child.parentData.nextSibling;
535 } 613 }
536 return result; 614 return result;
537 } 615 }
538 } 616 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698