未验证 提交 47a1ce0e 编写于 作者: C Chinmay Garde 提交者: GitHub

Allow embedders to set the root surface transformation. (#6085)

上级 56bad48a
......@@ -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_);
}
......
......@@ -26,6 +26,7 @@ class CompositorContext {
ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled);
virtual ~ScopedFrame();
......@@ -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);
......@@ -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);
......@@ -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();
......
......@@ -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;
......
......@@ -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())
......@@ -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
......
......@@ -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());
}
......
......@@ -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);
}
......
......@@ -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_;
......
......@@ -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);
......@@ -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);
......@@ -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();
......
......@@ -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:
......
......@@ -83,6 +83,7 @@ GPUSurfaceGL::~GPUSurfaceGL() {
delegate_->GLContextClearCurrent();
}
// |shell::Surface|
bool GPUSurfaceGL::IsValid() {
return valid_;
}
......@@ -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
......@@ -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
......@@ -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;
......@@ -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) {
......@@ -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;
......@@ -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();
}
......
......@@ -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"
......@@ -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 {
......@@ -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:
......@@ -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);
......
......@@ -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()) {
......@@ -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;
......
......@@ -15,6 +15,7 @@ namespace shell {
class GPUSurfaceSoftwareDelegate {
public:
virtual sk_sp<SkSurface> AcquireBackingStore(const SkISize& size) = 0;
virtual bool PresentBackingStore(sk_sp<SkSurface> backing_store) = 0;
};
......@@ -24,10 +25,16 @@ class GPUSurfaceSoftware : public Surface {
~GPUSurfaceSoftware() 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:
......
......@@ -15,10 +15,12 @@ GPUSurfaceVulkan::GPUSurfaceVulkan(
GPUSurfaceVulkan::~GPUSurfaceVulkan() = default;
// |shell::Surface|
bool GPUSurfaceVulkan::IsValid() {
return window_.IsValid();
}
// |shell::Surface|
std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
const SkISize& size) {
auto surface = window_.AcquireSurface();
......@@ -42,6 +44,16 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
std::move(callback));
}
// |shell::Surface|
SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
// This backend does not support delegating to the underlying platform to
// query for root surface transformations. Just return identity.
SkMatrix matrix;
matrix.reset();
return matrix;
}
// |shell::Surface|
GrContext* GPUSurfaceVulkan::GetContext() {
return window_.GetSkiaGrContext();
}
......
......@@ -22,10 +22,16 @@ class GPUSurfaceVulkan : public Surface {
~GPUSurfaceVulkan() 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:
......
......@@ -21,16 +21,22 @@ class IOSSurfaceSoftware final : public IOSSurface,
~IOSSurfaceSoftware() override;
// |shell::IOSSurface|
bool IsValid() const override;
// |shell::IOSSurface|
bool ResourceContextMakeCurrent() override;
// |shell::IOSSurface|
void UpdateStorageSizeIfNecessary() override;
// |shell::IOSSurface|
std::unique_ptr<Surface> CreateGPUSurface() override;
// |shell::GPUSurfaceSoftwareDelegate|
sk_sp<SkSurface> AcquireBackingStore(const SkISize& size) override;
// |shell::GPUSurfaceSoftwareDelegate|
bool PresentBackingStore(sk_sp<SkSurface> backing_store) override;
private:
......
......@@ -128,6 +128,24 @@ FlutterResult FlutterEngineRun(size_t version,
user_data]() { return ptr(user_data); };
}
std::function<SkMatrix(void)> gl_surface_transformation_callback = nullptr;
if (SAFE_ACCESS(open_gl_config, surface_transformation, nullptr) != nullptr) {
gl_surface_transformation_callback =
[ptr = config->open_gl.surface_transformation, user_data]() {
FlutterTransformation transformation = ptr(user_data);
return SkMatrix::MakeAll(transformation.scaleX, //
transformation.skewX, //
transformation.transX, //
transformation.skewY, //
transformation.scaleY, //
transformation.transY, //
transformation.pers0, //
transformation.pers1, //
transformation.pers2 //
);
};
}
bool fbo_reset_after_present =
SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);
......@@ -194,6 +212,7 @@ FlutterResult FlutterEngineRun(size_t version,
fbo_callback, // gl_fbo_callback
platform_message_response_callback, // platform_message_response_callback
make_resource_current_callback, // gl_make_resource_current_callback
gl_surface_transformation_callback // gl_surface_transformation_callback
};
shell::Shell::CreateCallback<shell::PlatformView> on_create_platform_view =
......
......@@ -31,7 +31,29 @@ typedef enum {
typedef struct _FlutterEngine* FlutterEngine;
typedef struct {
// horizontal scale factor
double scaleX;
// horizontal skew factor
double skewX;
// horizontal translation
double transX;
// vertical skew factor
double skewY;
// vertical scale factor
double scaleY;
// vertical translation
double transY;
// input x-axis perspective factor
double pers0;
// input y-axis perspective factor
double pers1;
// perspective scale factor
double pers2;
} FlutterTransformation;
typedef bool (*BoolCallback)(void* /* user data */);
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
typedef uint32_t (*UIntCallback)(void* /* user data */);
typedef struct {
......@@ -47,6 +69,9 @@ typedef struct {
// engine will ask the embedder for an updated FBO target (via an fbo_callback
// invocation) after a present call.
bool fbo_reset_after_present;
// The transformation to apply to the render target before any rendering
// operations. This callback is optional.
TransformationCallback surface_transformation;
} FlutterOpenGLRendererConfig;
typedef struct {
......
......@@ -43,6 +43,17 @@ bool PlatformViewEmbedder::GLContextFBOResetAfterPresent() const {
return fbo_reset_after_present_;
}
// |shell::GPUSurfaceGLDelegate|
SkMatrix PlatformViewEmbedder::GLContextSurfaceTransformation() const {
auto callback = dispatch_table_.gl_surface_transformation_callback;
if (!callback) {
SkMatrix matrix;
matrix.setIdentity();
return matrix;
}
return callback();
}
void PlatformViewEmbedder::HandlePlatformMessage(
fml::RefPtr<blink::PlatformMessage> message) {
if (!message) {
......
......@@ -25,6 +25,8 @@ class PlatformViewEmbedder final : public PlatformView,
PlatformMessageResponseCallback
platform_message_response_callback; // optional
std::function<bool(void)> gl_make_resource_current_callback; // optional
std::function<SkMatrix(void)>
gl_surface_transformation_callback; // optional
};
PlatformViewEmbedder(PlatformView::Delegate& delegate,
......@@ -49,6 +51,9 @@ class PlatformViewEmbedder final : public PlatformView,
// |shell::GPUSurfaceGLDelegate|
bool GLContextFBOResetAfterPresent() const override;
// |shell::GPUSurfaceGLDelegate|
SkMatrix GLContextSurfaceTransformation() const override;
// |shell::PlatformView|
void HandlePlatformMessage(
fml::RefPtr<blink::PlatformMessage> message) override;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册