提交 1a062aab 编写于 作者: A Adam Barth

Add a compositing step to the lifecycle

Now we have the ability to draw multiple PictureLayers. We still squash all the
pictures together into a single SkPicture for simplicity. In the future, we'll
submit them to C++ separately and composite them on the GPU thread.
上级 128ab6c0
......@@ -4,6 +4,8 @@
#include "sky/engine/core/painting/Picture.h"
#include "sky/engine/core/painting/Canvas.h"
namespace blink {
PassRefPtr<Picture> Picture::create(PassRefPtr<SkPicture> skPicture)
......@@ -21,4 +23,9 @@ Picture::~Picture()
{
}
void Picture::playback(Canvas* canvas)
{
m_picture->playback(canvas->skCanvas());
}
} // namespace blink
......@@ -12,6 +12,8 @@
namespace blink {
class Canvas;
class Picture : public RefCounted<Picture>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
......@@ -20,6 +22,8 @@ public:
SkPicture* toSkia() const { return m_picture.get(); }
void playback(Canvas* canvas);
private:
explicit Picture(PassRefPtr<SkPicture> skPicture);
......
......@@ -2,4 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
interface Picture {
// Replays the drawing commands on the specified canvas. Note that
// this has the effect of unfurling this picture into the destination
// canvas. Using the Canvas drawPicture entry point gives the destination
// canvas the option of just taking a ref.
void playback(Canvas canvas);
};
......@@ -39,6 +39,13 @@ class Rect {
Rect deflate(double delta) {
return inflate(-delta);
}
Rect intersect(Rect other) {
return new Rect.fromLTRB(
math.max(left, other.left),
math.max(top, other.top),
math.max(right, other.right),
math.max(bottom, other.bottom));
}
double get width => right - left;
double get height => bottom - top;
......
......@@ -1750,26 +1750,31 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
sky.tracing.begin('RenderView.paintFrame');
try {
final double devicePixelRatio = sky.view.devicePixelRatio;
// TODO(abarth): Really |_rootLayer| should be a TransformLayer that
// applies the devicePixelRatio.
Matrix4 transform = new Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0);
Rect bounds = Point.origin & size;
Rect scaledBounds = Point.origin & (size * devicePixelRatio);
PaintingContext context = new PaintingContext(scaledBounds);
_rootLayer = new ContainerLayer(bounds: Point.origin & size);
_rootLayer = new TransformLayer(bounds: scaledBounds, transform: transform);
PaintingContext context = new PaintingContext(bounds);
_rootLayer.add(context.layer);
context.canvas.drawColor(const Color(0xFF000000), sky.TransferMode.src);
context.canvas.scale(devicePixelRatio, devicePixelRatio);
context.paintChild(child, Point.origin);
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 {
sky.tracing.end('RenderView.paintFrame');
}
}
void compositeFrame() {
sky.tracing.begin('RenderView.compositeFrame');
try {
sky.PictureRecorder recorder = new sky.PictureRecorder();
sky.Canvas canvas = new sky.Canvas(recorder, _rootLayer.bounds);
_rootLayer.paint(canvas);
sky.view.picture = recorder.endRecording();
} finally {
sky.tracing.end('RenderView.compositeFrame');
}
}
Rect get paintBounds => Point.origin & size;
}
......
......@@ -7,7 +7,7 @@ import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
import 'package:vector_math/vector_math.dart';
class Layer {
abstract class Layer {
Layer({ this.bounds });
Rect bounds;
......@@ -25,6 +25,8 @@ class Layer {
if (_parent != null)
_parent.remove(this);
}
void paint(sky.Canvas canvas);
}
class PictureLayer extends Layer {
......@@ -32,11 +34,23 @@ class PictureLayer extends Layer {
: super(bounds: bounds);
sky.Picture picture;
void paint(sky.Canvas canvas) {
canvas.drawPicture(picture);
}
}
class ContainerLayer extends Layer {
ContainerLayer({ Rect bounds }) : super(bounds: bounds);
void paint(sky.Canvas canvas) {
Layer child = firstChild;
while (child != null) {
child.paint(canvas);
child = child.nextSibling;
}
}
Layer _firstChild;
Layer get firstChild => _firstChild;
......@@ -122,10 +136,24 @@ class TransformLayer extends ContainerLayer {
TransformLayer({ this.transform, Rect bounds }) : super(bounds: bounds);
Matrix4 transform;
void paint(sky.Canvas canvas) {
canvas.save();
canvas.concat(transform.storage);
super.paint(canvas);
canvas.restore();
}
}
class ClipLayer extends ContainerLayer {
ClipLayer({ Rect bounds }) : super(bounds: bounds);
void paint(sky.Canvas canvas) {
canvas.save();
canvas.clipRect(bounds);
super.paint(canvas);
canvas.restore();
}
}
class ColorFilterLayer extends ContainerLayer {
......@@ -137,4 +165,14 @@ class ColorFilterLayer extends ContainerLayer {
Color color;
sky.TransferMode transferMode;
void paint(sky.Canvas canvas) {
Paint paint = new Paint()
..color = color
..setTransferMode(transferMode);
canvas.saveLayer(bounds, paint);
super.paint(canvas);
canvas.restore();
}
}
......@@ -41,14 +41,24 @@ class PaintingContext {
sky.PictureRecorder _recorder;
PaintingContext(Rect bounds) {
_startRecording(bounds);
}
PaintingContext.forTesting(this.canvas);
void _startRecording(Rect bounds) {
assert(_layer == null);
assert(_recorder == null);
assert(canvas == null);
_layer = new PictureLayer(bounds: bounds);
_recorder = new sky.PictureRecorder();
canvas = new PaintingCanvas(_recorder, bounds);
}
PaintingContext.forTesting(this.canvas);
void endRecording() {
assert(_layer != null);
assert(_recorder != null);
assert(canvas != null);
canvas = null;
_layer.picture = _recorder.endRecording();
_recorder = null;
......@@ -56,9 +66,22 @@ class PaintingContext {
}
void paintChild(RenderObject child, Point point) {
// TODO(abarth): Support compositing.
assert(!child.requiresCompositing);
child._paintWithContext(this, point.toOffset());
final Offset offset = point.toOffset();
if (!child.requiresCompositing)
return child._paintWithContext(this, offset);
final Layer originalLayer = layer;
endRecording();
Rect bounds = child.paintBounds.shift(offset);
PaintingContext context = new PaintingContext(bounds);
originalLayer.parent.add(context.layer, before: originalLayer.nextSibling);
child._paintWithContext(context, Offset.zero);
context.endRecording();
_startRecording(originalLayer.bounds);
originalLayer.parent.add(layer, before: context.layer.nextSibling);
}
}
......
......@@ -73,6 +73,7 @@ class SkyBinding {
RenderObject.flushLayout();
RenderObject.flushPaint();
_renderView.paintFrame();
_renderView.compositeFrame();
}
final List<EventListener> _eventListeners = new List<EventListener>();
......
......@@ -159,6 +159,9 @@ class TestRenderView extends RenderView {
RenderObject.debugDoingPaint = false;
}
void compositeFrame() {
}
// TEST API:
void syncCheckFrame() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册