forked from firka/flutter
Allow embedders to set the root surface transformation. (flutter/engine#6085)
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user