diff --git a/flow/layers/default_layer_builder.cc b/flow/layers/default_layer_builder.cc index 33fac9704bb66..c6f4b80e82564 100644 --- a/flow/layers/default_layer_builder.cc +++ b/flow/layers/default_layer_builder.cc @@ -163,7 +163,8 @@ void DefaultLayerBuilder::PushPicture(const SkPoint& offset, void DefaultLayerBuilder::PushTexture(const SkPoint& offset, const SkSize& size, - int64_t texture_id) { + int64_t texture_id, + bool freeze) { if (!current_layer_) { return; } @@ -171,6 +172,7 @@ void DefaultLayerBuilder::PushTexture(const SkPoint& offset, layer->set_offset(offset); layer->set_size(size); layer->set_texture_id(texture_id); + layer->set_freeze(freeze); current_layer_->Add(std::move(layer)); } diff --git a/flow/layers/default_layer_builder.h b/flow/layers/default_layer_builder.h index 0dd87a3dd75a8..2601344668ed7 100644 --- a/flow/layers/default_layer_builder.h +++ b/flow/layers/default_layer_builder.h @@ -70,7 +70,8 @@ class DefaultLayerBuilder final : public LayerBuilder { // |flow::LayerBuilder| void PushTexture(const SkPoint& offset, const SkSize& size, - int64_t texture_id) override; + int64_t texture_id, + bool freeze) override; #if defined(OS_FUCHSIA) // |flow::LayerBuilder| diff --git a/flow/layers/layer_builder.h b/flow/layers/layer_builder.h index c1b34bf306434..8fa83e222f9ca 100644 --- a/flow/layers/layer_builder.h +++ b/flow/layers/layer_builder.h @@ -68,7 +68,8 @@ class LayerBuilder { virtual void PushTexture(const SkPoint& offset, const SkSize& size, - int64_t texture_id) = 0; + int64_t texture_id, + bool freeze) = 0; #if defined(OS_FUCHSIA) virtual void PushChildScene( diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index cdc081924518c..52ebdc37dbcab 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -23,7 +23,7 @@ void TextureLayer::Paint(PaintContext& context) const { if (!texture) { return; } - texture->Paint(context.canvas, paint_bounds()); + texture->Paint(context.canvas, paint_bounds(), freeze_); } } // namespace flow diff --git a/flow/layers/texture_layer.h b/flow/layers/texture_layer.h index 93581c3472b0e..bf2a17fd27ac7 100644 --- a/flow/layers/texture_layer.h +++ b/flow/layers/texture_layer.h @@ -22,6 +22,7 @@ class TextureLayer : public Layer { void set_offset(const SkPoint& offset) { offset_ = offset; } void set_size(const SkSize& size) { size_ = size; } void set_texture_id(int64_t texture_id) { texture_id_ = texture_id; } + void set_freeze(bool freeze) { freeze_ = freeze; } void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; @@ -30,6 +31,7 @@ class TextureLayer : public Layer { SkPoint offset_; SkSize size_; int64_t texture_id_; + bool freeze_; FML_DISALLOW_COPY_AND_ASSIGN(TextureLayer); }; diff --git a/flow/texture.h b/flow/texture.h index 92e0130da35ff..0af62ccbad2a1 100644 --- a/flow/texture.h +++ b/flow/texture.h @@ -22,7 +22,7 @@ class Texture { virtual ~Texture(); // Called from GPU thread. - virtual void Paint(SkCanvas& canvas, const SkRect& bounds) = 0; + virtual void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) = 0; // Called from GPU thread. virtual void OnGrContextCreated() = 0; diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 9e3b4a3060b9c..2371bbb95d498 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -235,11 +235,19 @@ class SceneBuilder extends NativeFieldWrapperClass2 { /// Adds a backend texture to the scene. /// /// The texture is scaled to the given size and rasterized at the given offset. - void addTexture(int textureId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0 }) { + /// + /// If `freeze` is true the texture that is added to the scene will not + /// be updated with new frames. `freeze` is used when resizing an embedded + /// Android view: When resizing an Android view there is a short period during + /// which the framework cannot tell if the newest texture frame has the + /// previous or new size, to workaround this the framework "freezes" the + /// texture just before resizing the Android view and unfreezes it when it is + /// certain that a frame with the new size is ready. + void addTexture(int textureId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0 , bool freeze: false}) { assert(offset != null, 'Offset argument was null'); - _addTexture(offset.dx, offset.dy, width, height, textureId); + _addTexture(offset.dx, offset.dy, width, height, textureId, freeze); } - void _addTexture(double dx, double dy, double width, double height, int textureId) native 'SceneBuilder_addTexture'; + void _addTexture(double dx, double dy, double width, double height, int textureId, bool freeze) native 'SceneBuilder_addTexture'; /// (Fuchsia-only) Adds a scene rendered by another application to the scene /// for this application. diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 2c0ade64b20fe..61a3c60ddee3e 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -138,9 +138,10 @@ void SceneBuilder::addTexture(double dx, double dy, double width, double height, - int64_t textureId) { + int64_t textureId, + bool freeze) { layer_builder_->PushTexture(SkPoint::Make(dx, dy), - SkSize::Make(width, height), textureId); + SkSize::Make(width, height), textureId, freeze); } void SceneBuilder::addChildScene(double dx, diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index 5f17bf265c478..0ad46b36138a1 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -70,7 +70,8 @@ class SceneBuilder : public RefCountedDartWrappable { double dy, double width, double height, - int64_t textureId); + int64_t textureId, + bool freeze); void addChildScene(double dx, double dy, diff --git a/shell/platform/android/android_external_texture_gl.cc b/shell/platform/android/android_external_texture_gl.cc index 35db9cbbfdb95..f644376e5fdd4 100644 --- a/shell/platform/android/android_external_texture_gl.cc +++ b/shell/platform/android/android_external_texture_gl.cc @@ -26,7 +26,9 @@ void AndroidExternalTextureGL::MarkNewFrameAvailable() { new_frame_ready_ = true; } -void AndroidExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) { +void AndroidExternalTextureGL::Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze) { if (state_ == AttachmentState::detached) { return; } @@ -35,7 +37,7 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) { Attach(static_cast(texture_name_)); state_ = AttachmentState::attached; } - if (new_frame_ready_) { + if (!freeze && new_frame_ready_) { Update(); new_frame_ready_ = false; } diff --git a/shell/platform/android/android_external_texture_gl.h b/shell/platform/android/android_external_texture_gl.h index 98b8f7ae0da88..b96eb33191f5d 100644 --- a/shell/platform/android/android_external_texture_gl.h +++ b/shell/platform/android/android_external_texture_gl.h @@ -19,7 +19,9 @@ class AndroidExternalTextureGL : public flow::Texture { ~AndroidExternalTextureGL() override; - virtual void Paint(SkCanvas& canvas, const SkRect& bounds) override; + virtual void Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze) override; virtual void OnGrContextCreated() override; diff --git a/shell/platform/darwin/ios/ios_external_texture_gl.h b/shell/platform/darwin/ios/ios_external_texture_gl.h index 929d10c7c9ba9..0ad69483385f2 100644 --- a/shell/platform/darwin/ios/ios_external_texture_gl.h +++ b/shell/platform/darwin/ios/ios_external_texture_gl.h @@ -19,7 +19,9 @@ class IOSExternalTextureGL : public flow::Texture { ~IOSExternalTextureGL() override; // Called from GPU thread. - virtual void Paint(SkCanvas& canvas, const SkRect& bounds) override; + virtual void Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze) override; virtual void OnGrContextCreated() override; diff --git a/shell/platform/darwin/ios/ios_external_texture_gl.mm b/shell/platform/darwin/ios/ios_external_texture_gl.mm index 4802504b5f0d5..638894b8aba5b 100644 --- a/shell/platform/darwin/ios/ios_external_texture_gl.mm +++ b/shell/platform/darwin/ios/ios_external_texture_gl.mm @@ -24,7 +24,7 @@ IOSExternalTextureGL::~IOSExternalTextureGL() = default; -void IOSExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) { +void IOSExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) { if (!cache_ref_) { CVOpenGLESTextureCacheRef cache; CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, @@ -37,18 +37,20 @@ } } fml::CFRef bufferRef; - bufferRef.Reset([external_texture_ copyPixelBuffer]); - if (bufferRef != nullptr) { - CVOpenGLESTextureRef texture; - CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage( - kCFAllocatorDefault, cache_ref_, bufferRef, nullptr, GL_TEXTURE_2D, GL_RGBA, - static_cast(CVPixelBufferGetWidth(bufferRef)), - static_cast(CVPixelBufferGetHeight(bufferRef)), GL_BGRA, GL_UNSIGNED_BYTE, 0, - &texture); - texture_ref_.Reset(texture); - if (err != noErr) { - FML_LOG(WARNING) << "Could not create texture from pixel buffer: " << err; - return; + if (!freeze) { + bufferRef.Reset([external_texture_ copyPixelBuffer]); + if (bufferRef != nullptr) { + CVOpenGLESTextureRef texture; + CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage( + kCFAllocatorDefault, cache_ref_, bufferRef, nullptr, GL_TEXTURE_2D, GL_RGBA, + static_cast(CVPixelBufferGetWidth(bufferRef)), + static_cast(CVPixelBufferGetHeight(bufferRef)), GL_BGRA, GL_UNSIGNED_BYTE, 0, + &texture); + texture_ref_.Reset(texture); + if (err != noErr) { + FML_LOG(WARNING) << "Could not create texture from pixel buffer: " << err; + return; + } } } if (!texture_ref_) {