Skip to content

Commit

Permalink
Allow embedders to set the root surface transformation. (flutter#6085)
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored Aug 28, 2018
1 parent 56bad48 commit 47a1ce0
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 34 deletions.
20 changes: 14 additions & 6 deletions flow/compositor_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,26 @@ void CompositorContext::EndFrame(ScopedFrame& frame,
std::unique_ptr<CompositorContext::ScopedFrame> CompositorContext::AcquireFrame(
GrContext* gr_context,
SkCanvas* canvas,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled) {
return std::make_unique<ScopedFrame>(*this, gr_context, canvas,
instrumentation_enabled);
return std::make_unique<ScopedFrame>(*this, //
gr_context, //
canvas, //
root_surface_transformation, //
instrumentation_enabled //
);
}

CompositorContext::ScopedFrame::ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
bool instrumentation_enabled)
CompositorContext::ScopedFrame::ScopedFrame(
CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled)
: context_(context),
gr_context_(gr_context),
canvas_(canvas),
root_surface_transformation_(root_surface_transformation),
instrumentation_enabled_(instrumentation_enabled) {
context_.BeginFrame(*this, instrumentation_enabled_);
}
Expand Down
7 changes: 7 additions & 0 deletions flow/compositor_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CompositorContext {
ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled);

virtual ~ScopedFrame();
Expand All @@ -34,6 +35,10 @@ class CompositorContext {

CompositorContext& context() const { return context_; }

const SkMatrix& root_surface_transformation() const {
return root_surface_transformation_;
}

GrContext* gr_context() const { return gr_context_; }

virtual bool Raster(LayerTree& layer_tree, bool ignore_raster_cache);
Expand All @@ -42,6 +47,7 @@ class CompositorContext {
CompositorContext& context_;
GrContext* gr_context_;
SkCanvas* canvas_;
const SkMatrix& root_surface_transformation_;
const bool instrumentation_enabled_;

FML_DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
Expand All @@ -54,6 +60,7 @@ class CompositorContext {
virtual std::unique_ptr<ScopedFrame> AcquireFrame(
GrContext* gr_context,
SkCanvas* canvas,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled);

void OnGrContextCreated();
Expand Down
1 change: 1 addition & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class Layer {

struct PaintContext {
SkCanvas& canvas;
const SkMatrix& root_surface_transformation;
const Stopwatch& frame_time;
const Stopwatch& engine_time;
TextureRegistry& texture_registry;
Expand Down
25 changes: 15 additions & 10 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,12 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
void LayerTree::Paint(CompositorContext::ScopedFrame& frame) const {
TRACE_EVENT0("flutter", "LayerTree::Paint");
Layer::PaintContext context = {
*frame.canvas(), //
frame.context().frame_time(), //
frame.context().engine_time(), //
frame.context().texture_registry(), //
checkerboard_offscreen_layers_ //
*frame.canvas(), //
frame.root_surface_transformation(), //
frame.context().frame_time(), //
frame.context().engine_time(), //
frame.context().texture_registry(), //
checkerboard_offscreen_layers_ //
};

if (root_layer_->needs_painting())
Expand All @@ -93,13 +94,17 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {

const Stopwatch unused_stopwatch;
TextureRegistry unused_texture_registry;
SkMatrix root_surface_transformation;
// No root surface transformation. So assume identity.
root_surface_transformation.reset();

Layer::PaintContext paint_context = {
*canvas, // canvas
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false // checkerboard offscreen layers
*canvas, // canvas
root_surface_transformation, // root surface transformation
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false // checkerboard offscreen layers
};

// Even if we don't have a root layer, we still need to create an empty
Expand Down
3 changes: 2 additions & 1 deletion flow/layers/picture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ void PictureLayer::Paint(PaintContext& context) const {
#endif

if (raster_cache_result_.is_valid()) {
raster_cache_result_.draw(context.canvas);
raster_cache_result_.draw(context.canvas,
context.root_surface_transformation);
} else {
context.canvas.drawPicture(picture());
}
Expand Down
8 changes: 6 additions & 2 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@

namespace flow {

void RasterCacheResult::draw(SkCanvas& canvas) const {
void RasterCacheResult::draw(
SkCanvas& canvas,
const SkMatrix& root_surface_transformation) const {
SkAutoCanvasRestore auto_restore(&canvas, true);
SkIRect bounds =
RasterCache::GetDeviceBounds(logical_rect_, canvas.getTotalMatrix());
FML_DCHECK(bounds.size() == image_->dimensions());
canvas.resetMatrix();
// Clear all transformations on the canvas except the root surface
// transormation.
canvas.setMatrix(root_surface_transformation);
canvas.drawImage(image_, bounds.fLeft, bounds.fTop);
}

Expand Down
3 changes: 2 additions & 1 deletion flow/raster_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class RasterCacheResult {

bool is_valid() const { return static_cast<bool>(image_); };

void draw(SkCanvas& canvas) const;
void draw(SkCanvas& canvas,
const SkMatrix& root_surface_transformation) const;

private:
sk_sp<SkImage> image_;
Expand Down
21 changes: 16 additions & 5 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {

auto canvas = frame->SkiaCanvas();

auto compositor_frame =
compositor_context_->AcquireFrame(surface_->GetContext(), canvas, true);
auto compositor_frame = compositor_context_->AcquireFrame(
surface_->GetContext(), canvas, surface_->GetRootTransformation(), true);

if (canvas) {
canvas->clear(SK_ColorBLACK);
Expand All @@ -134,8 +134,12 @@ static sk_sp<SkPicture> ScreenshotLayerTreeAsPicture(
recorder.beginRecording(
SkRect::MakeWH(tree->frame_size().width(), tree->frame_size().height()));

auto frame = compositor_context.AcquireFrame(
nullptr, recorder.getRecordingCanvas(), false);
SkMatrix root_surface_transformation;
root_surface_transformation.reset();

auto frame =
compositor_context.AcquireFrame(nullptr, recorder.getRecordingCanvas(),
root_surface_transformation, false);

frame->Raster(*tree, true);

Expand Down Expand Up @@ -174,7 +178,14 @@ static sk_sp<SkData> ScreenshotLayerTreeAsImage(

// Draw the current layer tree into the snapshot surface.
auto canvas = snapshot_surface->getCanvas();
auto frame = compositor_context.AcquireFrame(surface_context, canvas, false);

// There is no root surface transformation for the screenshot layer. Reset the
// matrix to identity.
SkMatrix root_surface_transformation;
root_surface_transformation.reset();

auto frame = compositor_context.AcquireFrame(
surface_context, canvas, root_surface_transformation, false);
canvas->clear(SK_ColorBLACK);
frame->Raster(*tree, true);
canvas->flush();
Expand Down
2 changes: 2 additions & 0 deletions shell/common/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Surface {

virtual std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) = 0;

virtual SkMatrix GetRootTransformation() const = 0;

virtual GrContext* GetContext() = 0;

private:
Expand Down
43 changes: 35 additions & 8 deletions shell/gpu/gpu_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ GPUSurfaceGL::~GPUSurfaceGL() {
delegate_->GLContextClearCurrent();
}

// |shell::Surface|
bool GPUSurfaceGL::IsValid() {
return valid_;
}
Expand Down Expand Up @@ -110,8 +111,8 @@ static sk_sp<SkSurface> WrapOnscreenSurface(GrContext* context,
framebuffer_info.fFBOID = static_cast<GrGLuint>(fbo);
framebuffer_info.fFormat = format;

GrBackendRenderTarget render_target(size.fWidth, // width
size.fHeight, // height
GrBackendRenderTarget render_target(size.width(), // width
size.height(), // height
0, // sample count
0, // stencil bits (TODO)
framebuffer_info // framebuffer info
Expand Down Expand Up @@ -168,7 +169,10 @@ bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
sk_sp<SkSurface> onscreen_surface, offscreen_surface;

onscreen_surface =
WrapOnscreenSurface(context_.get(), size, delegate_->GLContextFBO());
WrapOnscreenSurface(context_.get(), // GL context
size, // root surface size
delegate_->GLContextFBO() // window FBO ID
);

if (onscreen_surface == nullptr) {
// If the onscreen surface could not be wrapped. There is absolutely no
Expand All @@ -191,6 +195,12 @@ bool GPUSurfaceGL::CreateOrUpdateSurfaces(const SkISize& size) {
return true;
}

// |shell::Surface|
SkMatrix GPUSurfaceGL::GetRootTransformation() const {
return delegate_->GLContextSurfaceTransformation();
}

// |shell::Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
Expand All @@ -202,12 +212,17 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
return nullptr;
}

sk_sp<SkSurface> surface = AcquireRenderSurface(size);
const auto root_surface_transformation = GetRootTransformation();

sk_sp<SkSurface> surface =
AcquireRenderSurface(size, root_surface_transformation);

if (surface == nullptr) {
return nullptr;
}

surface->getCanvas()->setMatrix(root_surface_transformation);

SurfaceFrame::SubmitCallback submit_callback =
[weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
SkCanvas* canvas) {
Expand Down Expand Up @@ -244,8 +259,11 @@ bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {

// The FBO has changed, ask the delegate for the new FBO and do a surface
// re-wrap.
auto new_onscreen_surface = WrapOnscreenSurface(
context_.get(), current_size, delegate_->GLContextFBO());
auto new_onscreen_surface =
WrapOnscreenSurface(context_.get(), // GL context
current_size, // root surface size
delegate_->GLContextFBO() // window FBO ID
);

if (!new_onscreen_surface) {
return false;
Expand All @@ -257,14 +275,23 @@ bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
return true;
}

sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(const SkISize& size) {
if (!CreateOrUpdateSurfaces(size)) {
sk_sp<SkSurface> GPUSurfaceGL::AcquireRenderSurface(
const SkISize& untransformed_size,
const SkMatrix& root_surface_transformation) {
const auto transformed_rect = root_surface_transformation.mapRect(
SkRect::MakeWH(untransformed_size.width(), untransformed_size.height()));

const auto transformed_size =
SkISize::Make(transformed_rect.width(), transformed_rect.height());

if (!CreateOrUpdateSurfaces(transformed_size)) {
return nullptr;
}

return offscreen_surface_ != nullptr ? offscreen_surface_ : onscreen_surface_;
}

// |shell::Surface|
GrContext* GPUSurfaceGL::GetContext() {
return context_.get();
}
Expand Down
18 changes: 17 additions & 1 deletion shell/gpu/gpu_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef SHELL_GPU_GPU_SURFACE_GL_H_
#define SHELL_GPU_GPU_SURFACE_GL_H_

#include <memory>

#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/surface.h"
Expand All @@ -25,6 +27,12 @@ class GPUSurfaceGLDelegate {
virtual bool GLContextFBOResetAfterPresent() const { return false; }

virtual bool UseOffscreenSurface() const { return false; }

virtual SkMatrix GLContextSurfaceTransformation() const {
SkMatrix matrix;
matrix.setIdentity();
return matrix;
}
};

class GPUSurfaceGL : public Surface {
Expand All @@ -33,10 +41,16 @@ class GPUSurfaceGL : public Surface {

~GPUSurfaceGL() override;

// |shell::Surface|
bool IsValid() override;

// |shell::Surface|
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;

// |shell::Surface|
SkMatrix GetRootTransformation() const override;

// |shell::Surface|
GrContext* GetContext() override;

private:
Expand All @@ -49,7 +63,9 @@ class GPUSurfaceGL : public Surface {

bool CreateOrUpdateSurfaces(const SkISize& size);

sk_sp<SkSurface> AcquireRenderSurface(const SkISize& size);
sk_sp<SkSurface> AcquireRenderSurface(
const SkISize& untransformed_size,
const SkMatrix& root_surface_transformation);

bool PresentSurface(SkCanvas* canvas);

Expand Down
12 changes: 12 additions & 0 deletions shell/gpu/gpu_surface_software.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ GPUSurfaceSoftware::GPUSurfaceSoftware(GPUSurfaceSoftwareDelegate* delegate)

GPUSurfaceSoftware::~GPUSurfaceSoftware() = default;

// |shell::Surface|
bool GPUSurfaceSoftware::IsValid() {
return delegate_ != nullptr;
}

// |shell::Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceSoftware::AcquireFrame(
const SkISize& logical_size) {
if (!IsValid()) {
Expand Down Expand Up @@ -58,6 +60,16 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceSoftware::AcquireFrame(
return std::make_unique<SurfaceFrame>(backing_store, on_submit);
}

// |shell::Surface|
SkMatrix GPUSurfaceSoftware::GetRootTransformation() const {
// This backend does not currently support root surface transformations. Just
// return identity.
SkMatrix matrix;
matrix.reset();
return matrix;
}

// |shell::Surface|
GrContext* GPUSurfaceSoftware::GetContext() {
// There is no GrContext associated with a software surface.
return nullptr;
Expand Down
Loading

0 comments on commit 47a1ce0

Please sign in to comment.