Skip to content

Commit 7e0bb3b

Browse files
authored
Allow freezing a texture. (flutter#5938)
This is needed to avoid jank when resizing an embedded Android view. See flutter#19572 (comment)
1 parent 3cbb5e2 commit 7e0bb3b

13 files changed

+52
-28
lines changed

flow/layers/default_layer_builder.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,16 @@ void DefaultLayerBuilder::PushPicture(const SkPoint& offset,
163163

164164
void DefaultLayerBuilder::PushTexture(const SkPoint& offset,
165165
const SkSize& size,
166-
int64_t texture_id) {
166+
int64_t texture_id,
167+
bool freeze) {
167168
if (!current_layer_) {
168169
return;
169170
}
170171
auto layer = std::make_unique<flow::TextureLayer>();
171172
layer->set_offset(offset);
172173
layer->set_size(size);
173174
layer->set_texture_id(texture_id);
175+
layer->set_freeze(freeze);
174176
current_layer_->Add(std::move(layer));
175177
}
176178

flow/layers/default_layer_builder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class DefaultLayerBuilder final : public LayerBuilder {
7070
// |flow::LayerBuilder|
7171
void PushTexture(const SkPoint& offset,
7272
const SkSize& size,
73-
int64_t texture_id) override;
73+
int64_t texture_id,
74+
bool freeze) override;
7475

7576
#if defined(OS_FUCHSIA)
7677
// |flow::LayerBuilder|

flow/layers/layer_builder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class LayerBuilder {
6868

6969
virtual void PushTexture(const SkPoint& offset,
7070
const SkSize& size,
71-
int64_t texture_id) = 0;
71+
int64_t texture_id,
72+
bool freeze) = 0;
7273

7374
#if defined(OS_FUCHSIA)
7475
virtual void PushChildScene(

flow/layers/texture_layer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void TextureLayer::Paint(PaintContext& context) const {
2323
if (!texture) {
2424
return;
2525
}
26-
texture->Paint(context.canvas, paint_bounds());
26+
texture->Paint(context.canvas, paint_bounds(), freeze_);
2727
}
2828

2929
} // namespace flow

flow/layers/texture_layer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class TextureLayer : public Layer {
2222
void set_offset(const SkPoint& offset) { offset_ = offset; }
2323
void set_size(const SkSize& size) { size_ = size; }
2424
void set_texture_id(int64_t texture_id) { texture_id_ = texture_id; }
25+
void set_freeze(bool freeze) { freeze_ = freeze; }
2526

2627
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
2728
void Paint(PaintContext& context) const override;
@@ -30,6 +31,7 @@ class TextureLayer : public Layer {
3031
SkPoint offset_;
3132
SkSize size_;
3233
int64_t texture_id_;
34+
bool freeze_;
3335

3436
FML_DISALLOW_COPY_AND_ASSIGN(TextureLayer);
3537
};

flow/texture.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Texture {
2222
virtual ~Texture();
2323

2424
// Called from GPU thread.
25-
virtual void Paint(SkCanvas& canvas, const SkRect& bounds) = 0;
25+
virtual void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) = 0;
2626

2727
// Called from GPU thread.
2828
virtual void OnGrContextCreated() = 0;

lib/ui/compositing.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,19 @@ class SceneBuilder extends NativeFieldWrapperClass2 {
235235
/// Adds a backend texture to the scene.
236236
///
237237
/// The texture is scaled to the given size and rasterized at the given offset.
238-
void addTexture(int textureId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0 }) {
238+
///
239+
/// If `freeze` is true the texture that is added to the scene will not
240+
/// be updated with new frames. `freeze` is used when resizing an embedded
241+
/// Android view: When resizing an Android view there is a short period during
242+
/// which the framework cannot tell if the newest texture frame has the
243+
/// previous or new size, to workaround this the framework "freezes" the
244+
/// texture just before resizing the Android view and unfreezes it when it is
245+
/// certain that a frame with the new size is ready.
246+
void addTexture(int textureId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0 , bool freeze: false}) {
239247
assert(offset != null, 'Offset argument was null');
240-
_addTexture(offset.dx, offset.dy, width, height, textureId);
248+
_addTexture(offset.dx, offset.dy, width, height, textureId, freeze);
241249
}
242-
void _addTexture(double dx, double dy, double width, double height, int textureId) native 'SceneBuilder_addTexture';
250+
void _addTexture(double dx, double dy, double width, double height, int textureId, bool freeze) native 'SceneBuilder_addTexture';
243251

244252
/// (Fuchsia-only) Adds a scene rendered by another application to the scene
245253
/// for this application.

lib/ui/compositing/scene_builder.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ void SceneBuilder::addTexture(double dx,
138138
double dy,
139139
double width,
140140
double height,
141-
int64_t textureId) {
141+
int64_t textureId,
142+
bool freeze) {
142143
layer_builder_->PushTexture(SkPoint::Make(dx, dy),
143-
SkSize::Make(width, height), textureId);
144+
SkSize::Make(width, height), textureId, freeze);
144145
}
145146

146147
void SceneBuilder::addChildScene(double dx,

lib/ui/compositing/scene_builder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class SceneBuilder : public RefCountedDartWrappable<SceneBuilder> {
7070
double dy,
7171
double width,
7272
double height,
73-
int64_t textureId);
73+
int64_t textureId,
74+
bool freeze);
7475

7576
void addChildScene(double dx,
7677
double dy,

shell/platform/android/android_external_texture_gl.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ void AndroidExternalTextureGL::MarkNewFrameAvailable() {
2626
new_frame_ready_ = true;
2727
}
2828

29-
void AndroidExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) {
29+
void AndroidExternalTextureGL::Paint(SkCanvas& canvas,
30+
const SkRect& bounds,
31+
bool freeze) {
3032
if (state_ == AttachmentState::detached) {
3133
return;
3234
}
@@ -35,7 +37,7 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) {
3537
Attach(static_cast<jint>(texture_name_));
3638
state_ = AttachmentState::attached;
3739
}
38-
if (new_frame_ready_) {
40+
if (!freeze && new_frame_ready_) {
3941
Update();
4042
new_frame_ready_ = false;
4143
}

shell/platform/android/android_external_texture_gl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ class AndroidExternalTextureGL : public flow::Texture {
1919

2020
~AndroidExternalTextureGL() override;
2121

22-
virtual void Paint(SkCanvas& canvas, const SkRect& bounds) override;
22+
virtual void Paint(SkCanvas& canvas,
23+
const SkRect& bounds,
24+
bool freeze) override;
2325

2426
virtual void OnGrContextCreated() override;
2527

shell/platform/darwin/ios/ios_external_texture_gl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ class IOSExternalTextureGL : public flow::Texture {
1919
~IOSExternalTextureGL() override;
2020

2121
// Called from GPU thread.
22-
virtual void Paint(SkCanvas& canvas, const SkRect& bounds) override;
22+
virtual void Paint(SkCanvas& canvas,
23+
const SkRect& bounds,
24+
bool freeze) override;
2325

2426
virtual void OnGrContextCreated() override;
2527

shell/platform/darwin/ios/ios_external_texture_gl.mm

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
IOSExternalTextureGL::~IOSExternalTextureGL() = default;
2626

27-
void IOSExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds) {
27+
void IOSExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) {
2828
if (!cache_ref_) {
2929
CVOpenGLESTextureCacheRef cache;
3030
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL,
@@ -37,18 +37,20 @@
3737
}
3838
}
3939
fml::CFRef<CVPixelBufferRef> bufferRef;
40-
bufferRef.Reset([external_texture_ copyPixelBuffer]);
41-
if (bufferRef != nullptr) {
42-
CVOpenGLESTextureRef texture;
43-
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
44-
kCFAllocatorDefault, cache_ref_, bufferRef, nullptr, GL_TEXTURE_2D, GL_RGBA,
45-
static_cast<int>(CVPixelBufferGetWidth(bufferRef)),
46-
static_cast<int>(CVPixelBufferGetHeight(bufferRef)), GL_BGRA, GL_UNSIGNED_BYTE, 0,
47-
&texture);
48-
texture_ref_.Reset(texture);
49-
if (err != noErr) {
50-
FML_LOG(WARNING) << "Could not create texture from pixel buffer: " << err;
51-
return;
40+
if (!freeze) {
41+
bufferRef.Reset([external_texture_ copyPixelBuffer]);
42+
if (bufferRef != nullptr) {
43+
CVOpenGLESTextureRef texture;
44+
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
45+
kCFAllocatorDefault, cache_ref_, bufferRef, nullptr, GL_TEXTURE_2D, GL_RGBA,
46+
static_cast<int>(CVPixelBufferGetWidth(bufferRef)),
47+
static_cast<int>(CVPixelBufferGetHeight(bufferRef)), GL_BGRA, GL_UNSIGNED_BYTE, 0,
48+
&texture);
49+
texture_ref_.Reset(texture);
50+
if (err != noErr) {
51+
FML_LOG(WARNING) << "Could not create texture from pixel buffer: " << err;
52+
return;
53+
}
5254
}
5355
}
5456
if (!texture_ref_) {

0 commit comments

Comments
 (0)