Switch painting over to using PictureLayer
Currently we have a single PictureLayer that everyone draws into. A future patch will teach the system to use multiple PictureLayers.
This commit is contained in:
parent
4b462bab5d
commit
7cba729110
@ -8,6 +8,7 @@ import 'dart:sky' as sky;
|
|||||||
import 'package:sky/base/debug.dart';
|
import 'package:sky/base/debug.dart';
|
||||||
import 'package:sky/painting/box_painter.dart';
|
import 'package:sky/painting/box_painter.dart';
|
||||||
import 'package:sky/painting/text_style.dart';
|
import 'package:sky/painting/text_style.dart';
|
||||||
|
import 'package:sky/rendering/layer.dart';
|
||||||
import 'package:sky/rendering/object.dart';
|
import 'package:sky/rendering/object.dart';
|
||||||
import 'package:vector_math/vector_math.dart';
|
import 'package:vector_math/vector_math.dart';
|
||||||
|
|
||||||
@ -1703,6 +1704,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||||||
markNeedsLayout();
|
markNeedsLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContainerLayer _rootLayer;
|
||||||
|
|
||||||
// We never call layout() on this class, so this should never get
|
// We never call layout() on this class, so this should never get
|
||||||
// checked. (This class is laid out using scheduleInitialLayout().)
|
// checked. (This class is laid out using scheduleInitialLayout().)
|
||||||
bool debugDoesMeetConstraints() { assert(false); return false; }
|
bool debugDoesMeetConstraints() { assert(false); return false; }
|
||||||
@ -1746,15 +1749,22 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||||||
void paintFrame() {
|
void paintFrame() {
|
||||||
sky.tracing.begin('RenderView.paintFrame');
|
sky.tracing.begin('RenderView.paintFrame');
|
||||||
try {
|
try {
|
||||||
double devicePixelRatio = sky.view.devicePixelRatio;
|
final double devicePixelRatio = sky.view.devicePixelRatio;
|
||||||
sky.PictureRecorder recorder = new sky.PictureRecorder();
|
|
||||||
Rect cullRect = Point.origin & (size * devicePixelRatio);
|
// TODO(abarth): Really |_rootLayer| should be a TransformLayer that
|
||||||
PaintingCanvas canvas = new PaintingCanvas(recorder, cullRect);
|
// applies the devicePixelRatio.
|
||||||
PaintingContext context = new PaintingContext(canvas);
|
Rect scaledBounds = Point.origin & (size * devicePixelRatio);
|
||||||
canvas.drawColor(const Color(0xFF000000), sky.TransferMode.src);
|
PaintingContext context = new PaintingContext(scaledBounds);
|
||||||
canvas.scale(devicePixelRatio, devicePixelRatio);
|
_rootLayer = new ContainerLayer(bounds: Point.origin & size);
|
||||||
|
_rootLayer.add(context.layer);
|
||||||
|
context.canvas.drawColor(const Color(0xFF000000), sky.TransferMode.src);
|
||||||
|
context.canvas.scale(devicePixelRatio, devicePixelRatio);
|
||||||
context.paintChild(child, Point.origin);
|
context.paintChild(child, Point.origin);
|
||||||
sky.view.picture = recorder.endRecording();
|
context.endRecording();
|
||||||
|
|
||||||
|
// TODO(abarth): Once we have more than one PictureLayer, we should walk
|
||||||
|
// the layer tree to generate the final picture.
|
||||||
|
sky.view.picture = (_rootLayer.firstChild as PictureLayer).picture;
|
||||||
} finally {
|
} finally {
|
||||||
sky.tracing.end('RenderView.paintFrame');
|
sky.tracing.end('RenderView.paintFrame');
|
||||||
}
|
}
|
||||||
|
140
packages/flutter/lib/rendering/layer.dart
Normal file
140
packages/flutter/lib/rendering/layer.dart
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:sky' as sky;
|
||||||
|
import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
|
||||||
|
|
||||||
|
import 'package:vector_math/vector_math.dart';
|
||||||
|
|
||||||
|
class Layer {
|
||||||
|
Layer({ this.bounds });
|
||||||
|
|
||||||
|
Rect bounds;
|
||||||
|
|
||||||
|
ContainerLayer _parent;
|
||||||
|
ContainerLayer get parent => _parent;
|
||||||
|
|
||||||
|
Layer _nextSibling;
|
||||||
|
Layer get nextSibling => _nextSibling;
|
||||||
|
|
||||||
|
Layer _previousSibling;
|
||||||
|
Layer get previousSibling => _previousSibling;
|
||||||
|
|
||||||
|
void detach() {
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PictureLayer extends Layer {
|
||||||
|
PictureLayer({ Rect bounds })
|
||||||
|
: super(bounds: bounds);
|
||||||
|
|
||||||
|
sky.Picture picture;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerLayer extends Layer {
|
||||||
|
ContainerLayer({ Rect bounds }) : super(bounds: bounds);
|
||||||
|
|
||||||
|
Layer _firstChild;
|
||||||
|
Layer get firstChild => _firstChild;
|
||||||
|
|
||||||
|
Layer _lastChild;
|
||||||
|
Layer get lastChild => _lastChild;
|
||||||
|
|
||||||
|
bool _debugUltimatePreviousSiblingOf(Layer child, { Layer equals }) {
|
||||||
|
while (child._previousSibling != null) {
|
||||||
|
assert(child._previousSibling != child);
|
||||||
|
child = child._previousSibling;
|
||||||
|
}
|
||||||
|
return child == equals;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _debugUltimateNextSiblingOf(Layer child, { Layer equals }) {
|
||||||
|
while (child._nextSibling != null) {
|
||||||
|
assert(child._nextSibling != child);
|
||||||
|
child = child._nextSibling;
|
||||||
|
}
|
||||||
|
return child == equals;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Layer child, { Layer before }) {
|
||||||
|
assert(child != this);
|
||||||
|
assert(before != this);
|
||||||
|
assert(child != before);
|
||||||
|
assert(child != _firstChild);
|
||||||
|
assert(child != _lastChild);
|
||||||
|
assert(child._parent == null);
|
||||||
|
assert(child._nextSibling == null);
|
||||||
|
assert(child._previousSibling == null);
|
||||||
|
child._parent = this;
|
||||||
|
if (before == null) {
|
||||||
|
child._previousSibling = _lastChild;
|
||||||
|
if (_lastChild != null)
|
||||||
|
_lastChild._nextSibling = child;
|
||||||
|
_lastChild = child;
|
||||||
|
if (_firstChild == null)
|
||||||
|
_firstChild = child;
|
||||||
|
} else {
|
||||||
|
assert(_firstChild != null);
|
||||||
|
assert(_lastChild != null);
|
||||||
|
assert(_debugUltimatePreviousSiblingOf(before, equals: _firstChild));
|
||||||
|
assert(_debugUltimateNextSiblingOf(before, equals: _lastChild));
|
||||||
|
if (before._previousSibling == null) {
|
||||||
|
assert(before == _firstChild);
|
||||||
|
child._nextSibling = before;
|
||||||
|
before._previousSibling = child;
|
||||||
|
_firstChild = child;
|
||||||
|
} else {
|
||||||
|
child._previousSibling = before._previousSibling;
|
||||||
|
child._nextSibling = before;
|
||||||
|
child._previousSibling._nextSibling = child;
|
||||||
|
child._nextSibling._previousSibling = child;
|
||||||
|
assert(before._previousSibling == child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(Layer child) {
|
||||||
|
assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
|
||||||
|
assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
|
||||||
|
assert(child._parent == this);
|
||||||
|
if (child._previousSibling == null) {
|
||||||
|
assert(_firstChild == child);
|
||||||
|
_firstChild = child._nextSibling;
|
||||||
|
} else {
|
||||||
|
child._previousSibling._nextSibling = child._nextSibling;
|
||||||
|
}
|
||||||
|
if (child._nextSibling == null) {
|
||||||
|
assert(_lastChild == child);
|
||||||
|
_lastChild = child._previousSibling;
|
||||||
|
} else {
|
||||||
|
child._nextSibling._previousSibling = child._previousSibling;
|
||||||
|
}
|
||||||
|
child._previousSibling = null;
|
||||||
|
child._nextSibling = null;
|
||||||
|
child._parent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TransformLayer extends ContainerLayer {
|
||||||
|
TransformLayer({ this.transform, Rect bounds }) : super(bounds: bounds);
|
||||||
|
|
||||||
|
Matrix4 transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClipLayer extends ContainerLayer {
|
||||||
|
ClipLayer({ Rect bounds }) : super(bounds: bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorFilterLayer extends ContainerLayer {
|
||||||
|
ColorFilterLayer({
|
||||||
|
Rect bounds,
|
||||||
|
this.color,
|
||||||
|
this.transferMode
|
||||||
|
}) : super(bounds: bounds);
|
||||||
|
|
||||||
|
Color color;
|
||||||
|
sky.TransferMode transferMode;
|
||||||
|
}
|
@ -10,6 +10,7 @@ import 'package:sky/base/debug.dart';
|
|||||||
import 'package:sky/base/hit_test.dart';
|
import 'package:sky/base/hit_test.dart';
|
||||||
import 'package:sky/base/node.dart';
|
import 'package:sky/base/node.dart';
|
||||||
import 'package:sky/base/scheduler.dart' as scheduler;
|
import 'package:sky/base/scheduler.dart' as scheduler;
|
||||||
|
import 'package:sky/rendering/layer.dart';
|
||||||
import 'package:vector_math/vector_math.dart';
|
import 'package:vector_math/vector_math.dart';
|
||||||
|
|
||||||
export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
|
export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
|
||||||
@ -32,9 +33,27 @@ class PaintingCanvas extends sky.Canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PaintingContext {
|
class PaintingContext {
|
||||||
final PaintingCanvas canvas;
|
PaintingCanvas canvas;
|
||||||
|
|
||||||
PaintingContext(this.canvas);
|
PictureLayer get layer => _layer;
|
||||||
|
PictureLayer _layer;
|
||||||
|
|
||||||
|
sky.PictureRecorder _recorder;
|
||||||
|
|
||||||
|
PaintingContext(Rect bounds) {
|
||||||
|
_layer = new PictureLayer(bounds: bounds);
|
||||||
|
_recorder = new sky.PictureRecorder();
|
||||||
|
canvas = new PaintingCanvas(_recorder, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
PaintingContext.forTesting(this.canvas);
|
||||||
|
|
||||||
|
void endRecording() {
|
||||||
|
canvas = null;
|
||||||
|
_layer.picture = _recorder.endRecording();
|
||||||
|
_recorder = null;
|
||||||
|
_layer = null;
|
||||||
|
}
|
||||||
|
|
||||||
void paintChild(RenderObject child, Point point) {
|
void paintChild(RenderObject child, Point point) {
|
||||||
// TODO(abarth): Support compositing.
|
// TODO(abarth): Support compositing.
|
||||||
@ -318,6 +337,12 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
bool _needsPaint = true;
|
bool _needsPaint = true;
|
||||||
bool get needsPaint => _needsPaint;
|
bool get needsPaint => _needsPaint;
|
||||||
|
|
||||||
|
PictureLayer _layer;
|
||||||
|
PictureLayer get layer {
|
||||||
|
assert(requiresCompositing);
|
||||||
|
return _layer;
|
||||||
|
}
|
||||||
|
|
||||||
void markNeedsPaint() {
|
void markNeedsPaint() {
|
||||||
assert(!debugDoingPaint);
|
assert(!debugDoingPaint);
|
||||||
if (!attached) return; // Don't try painting things that aren't in the hierarchy
|
if (!attached) return; // Don't try painting things that aren't in the hierarchy
|
||||||
@ -357,9 +382,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
void _repaint() {
|
void _repaint() {
|
||||||
assert(!_needsLayout);
|
assert(!_needsLayout);
|
||||||
assert(requiresCompositing);
|
assert(requiresCompositing);
|
||||||
sky.PictureRecorder recorder = new sky.PictureRecorder();
|
assert(_layer != null);
|
||||||
sky.Canvas canvas = new sky.Canvas(recorder, paintBounds);
|
PaintingContext context = new PaintingContext(paintBounds);
|
||||||
PaintingContext context = new PaintingContext(canvas);
|
_layer.parent.add(context.layer, before: _layer);
|
||||||
|
_layer.detach();
|
||||||
|
_layer = context._layer;
|
||||||
_needsPaint = false;
|
_needsPaint = false;
|
||||||
try {
|
try {
|
||||||
_paintWithContext(context, Offset.zero);
|
_paintWithContext(context, Offset.zero);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user