diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index 53659103be9f19150796875e2e51cb8749fdc99a..3863bde7acbf95b527f1afe0bcc82789c6feef80 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -32,18 +32,26 @@ void CompositorContext::EndFrame(ScopedFrame& frame, std::unique_ptr CompositorContext::AcquireFrame( GrContext* gr_context, SkCanvas* canvas, + const SkMatrix& root_surface_transformation, bool instrumentation_enabled) { - return std::make_unique(*this, gr_context, canvas, - instrumentation_enabled); + return std::make_unique(*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_); } diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 5a6700ff3186f5589abaddf23a6e9ac0dd15401f..522c5359934ffee3c7d8fe33dfa47ebb5bb8e893 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -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 AcquireFrame( GrContext* gr_context, SkCanvas* canvas, + const SkMatrix& root_surface_transformation, bool instrumentation_enabled); void OnGrContextCreated(); diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 173c2890b6ae88a16fa804253f4b044900a6c668..53e32941e8d1dbaa4c04a0a050ca733999d1ddd1 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -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; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 8f6f7494ae2faf224ef21b08e7bc4eb473ce9590..007bd0fbd9530c11887203ca50996f2cc724e6d9 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -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 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 diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 3cbf15a609ad1c78bfd5edd01f2e960faf478a01..9389e0862c398c7476445abf09076c1f4cf49723 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -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()); } diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index a3aef6e3d14107a6941fec2d8ff00e17c205b1d9..aadebb72d039eaa0a34a26605551957c852259d9 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -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); } diff --git a/flow/raster_cache.h b/flow/raster_cache.h index 348ab8000da399209db0db81a47a0f67fb6bb85d..b2084d3bf1c7445bd997ba4e96befbe380a270d8 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -28,7 +28,8 @@ class RasterCacheResult { bool is_valid() const { return static_cast(image_); }; - void draw(SkCanvas& canvas) const; + void draw(SkCanvas& canvas, + const SkMatrix& root_surface_transformation) const; private: sk_sp image_; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index e2721a5d0e9402ae118d3359b398d317bd568d2e..6f0ddd53a19078812bee559840df9de806dc28b2 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -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 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 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(); diff --git a/shell/common/surface.h b/shell/common/surface.h index f178dda441bb4c026c34a527b815269808f5d6e8..beef9765da490d2601872e9c7f9679dcd255dd1a 100644 --- a/shell/common/surface.h +++ b/shell/common/surface.h @@ -51,6 +51,8 @@ class Surface { virtual std::unique_ptr AcquireFrame(const SkISize& size) = 0; + virtual SkMatrix GetRootTransformation() const = 0; + virtual GrContext* GetContext() = 0; private: diff --git a/shell/gpu/gpu_surface_gl.cc b/shell/gpu/gpu_surface_gl.cc index bb2350b8ee327a6353a23468a8a12a49a88fb7ae..505f9e40eead534376c1454e963a8e726b9629b1 100644 --- a/shell/gpu/gpu_surface_gl.cc +++ b/shell/gpu/gpu_surface_gl.cc @@ -83,6 +83,7 @@ GPUSurfaceGL::~GPUSurfaceGL() { delegate_->GLContextClearCurrent(); } +// |shell::Surface| bool GPUSurfaceGL::IsValid() { return valid_; } @@ -110,8 +111,8 @@ static sk_sp WrapOnscreenSurface(GrContext* context, framebuffer_info.fFBOID = static_cast(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 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 GPUSurfaceGL::AcquireFrame(const SkISize& size) { if (delegate_ == nullptr) { return nullptr; @@ -202,12 +212,17 @@ std::unique_ptr GPUSurfaceGL::AcquireFrame(const SkISize& size) { return nullptr; } - sk_sp surface = AcquireRenderSurface(size); + const auto root_surface_transformation = GetRootTransformation(); + + sk_sp 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 GPUSurfaceGL::AcquireRenderSurface(const SkISize& size) { - if (!CreateOrUpdateSurfaces(size)) { +sk_sp 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(); } diff --git a/shell/gpu/gpu_surface_gl.h b/shell/gpu/gpu_surface_gl.h index 0eb42dcaeab4c188c6b8aeef7b144e592ce025b5..971e4649dc1a8eff89fd5adeefd735b14577a7f6 100644 --- a/shell/gpu/gpu_surface_gl.h +++ b/shell/gpu/gpu_surface_gl.h @@ -5,6 +5,8 @@ #ifndef SHELL_GPU_GPU_SURFACE_GL_H_ #define SHELL_GPU_GPU_SURFACE_GL_H_ +#include + #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 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 AcquireRenderSurface(const SkISize& size); + sk_sp AcquireRenderSurface( + const SkISize& untransformed_size, + const SkMatrix& root_surface_transformation); bool PresentSurface(SkCanvas* canvas); diff --git a/shell/gpu/gpu_surface_software.cc b/shell/gpu/gpu_surface_software.cc index 1d5f851c5bbc51a4cfc160482d239927e7c05fba..7598aa243d33e15ad60842651792c61e8b10ea5d 100644 --- a/shell/gpu/gpu_surface_software.cc +++ b/shell/gpu/gpu_surface_software.cc @@ -14,10 +14,12 @@ GPUSurfaceSoftware::GPUSurfaceSoftware(GPUSurfaceSoftwareDelegate* delegate) GPUSurfaceSoftware::~GPUSurfaceSoftware() = default; +// |shell::Surface| bool GPUSurfaceSoftware::IsValid() { return delegate_ != nullptr; } +// |shell::Surface| std::unique_ptr GPUSurfaceSoftware::AcquireFrame( const SkISize& logical_size) { if (!IsValid()) { @@ -58,6 +60,16 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame( return std::make_unique(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; diff --git a/shell/gpu/gpu_surface_software.h b/shell/gpu/gpu_surface_software.h index ca09537f92e14256bc90c12225e8ac6c358c7393..95940c4702454e2b047be81cc29222eb1619e1dc 100644 --- a/shell/gpu/gpu_surface_software.h +++ b/shell/gpu/gpu_surface_software.h @@ -15,6 +15,7 @@ namespace shell { class GPUSurfaceSoftwareDelegate { public: virtual sk_sp AcquireBackingStore(const SkISize& size) = 0; + virtual bool PresentBackingStore(sk_sp backing_store) = 0; }; @@ -24,10 +25,16 @@ class GPUSurfaceSoftware : public Surface { ~GPUSurfaceSoftware() override; + // |shell::Surface| bool IsValid() override; + // |shell::Surface| std::unique_ptr AcquireFrame(const SkISize& size) override; + // |shell::Surface| + SkMatrix GetRootTransformation() const override; + + // |shell::Surface| GrContext* GetContext() override; private: diff --git a/shell/gpu/gpu_surface_vulkan.cc b/shell/gpu/gpu_surface_vulkan.cc index cf92b921bc8f96bee9795f1a51e1cb7980b428bf..728fca6a0028ea071bf5044442614c99ce560161 100644 --- a/shell/gpu/gpu_surface_vulkan.cc +++ b/shell/gpu/gpu_surface_vulkan.cc @@ -15,10 +15,12 @@ GPUSurfaceVulkan::GPUSurfaceVulkan( GPUSurfaceVulkan::~GPUSurfaceVulkan() = default; +// |shell::Surface| bool GPUSurfaceVulkan::IsValid() { return window_.IsValid(); } +// |shell::Surface| std::unique_ptr GPUSurfaceVulkan::AcquireFrame( const SkISize& size) { auto surface = window_.AcquireSurface(); @@ -42,6 +44,16 @@ std::unique_ptr 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(); } diff --git a/shell/gpu/gpu_surface_vulkan.h b/shell/gpu/gpu_surface_vulkan.h index 996dd13254d2e4033f1a7107961efed9696b4d19..fe4a34b81424069deb03865a7e97dfee98cf2ba5 100644 --- a/shell/gpu/gpu_surface_vulkan.h +++ b/shell/gpu/gpu_surface_vulkan.h @@ -22,10 +22,16 @@ class GPUSurfaceVulkan : public Surface { ~GPUSurfaceVulkan() override; + // |shell::Surface| bool IsValid() override; + // |shell::Surface| std::unique_ptr AcquireFrame(const SkISize& size) override; + // |shell::Surface| + SkMatrix GetRootTransformation() const override; + + // |shell::Surface| GrContext* GetContext() override; private: diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index ab2b483d1d236de97027969855077dc41fa8b309..154f057489f48b0640f72f2c715a2422044e2320 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -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 CreateGPUSurface() override; + // |shell::GPUSurfaceSoftwareDelegate| sk_sp AcquireBackingStore(const SkISize& size) override; + // |shell::GPUSurfaceSoftwareDelegate| bool PresentBackingStore(sk_sp backing_store) override; private: diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 553350931d50bf6f4672904fd11a3169f18d670a..37509d6761bb00f2065cc8423ec348c08084966f 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -128,6 +128,24 @@ FlutterResult FlutterEngineRun(size_t version, user_data]() { return ptr(user_data); }; } + std::function 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 on_create_platform_view = diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index fa5bb7ba3934eaa0458217cc7edb5126845d8b80..68bed60eeaa925c21b222b1f232127728a5a7f5c 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -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 { diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index a4dea939df97cd2e0eb6c0b2e82c7023181bbf0c..31fcc7da32db717042e40fc2a77b1d8a35aad359 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -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 message) { if (!message) { diff --git a/shell/platform/embedder/platform_view_embedder.h b/shell/platform/embedder/platform_view_embedder.h index ae1b19787bbdd8959fc69abe6d92fbcfc5934265..0442003f9ff0d615cd4245078aa3770da854bc44 100644 --- a/shell/platform/embedder/platform_view_embedder.h +++ b/shell/platform/embedder/platform_view_embedder.h @@ -25,6 +25,8 @@ class PlatformViewEmbedder final : public PlatformView, PlatformMessageResponseCallback platform_message_response_callback; // optional std::function gl_make_resource_current_callback; // optional + std::function + 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 message) override;