未验证 提交 0d59c9ec 编写于 作者: C Chris Yang 提交者: GitHub

Add `onUnregistered` callback in 'Texture' and 'FlutterTexture' (#12695)

Texture unregistration is finished on the GPU thread. The FlutterTexture implementation might not know when it is finished which leads to a race condition. Adding this callback so the FlutterTexture is aware of end of the unregistration process.
上级 c635d70c
......@@ -82,6 +82,7 @@ FILE: ../../../flutter/flow/skia_gpu_object.cc
FILE: ../../../flutter/flow/skia_gpu_object.h
FILE: ../../../flutter/flow/texture.cc
FILE: ../../../flutter/flow/texture.h
FILE: ../../../flutter/flow/texture_unittests.cc
FILE: ../../../flutter/flow/view_holder.cc
FILE: ../../../flutter/flow/view_holder.h
FILE: ../../../flutter/flutter_frontend_server/bin/starter.dart
......
......@@ -114,6 +114,7 @@ executable("flow_unittests") {
"matrix_decomposition_unittests.cc",
"mutators_stack_unittests.cc",
"raster_cache_unittests.cc",
"texture_unittests.cc",
]
deps = [
......
......@@ -15,6 +15,7 @@ void TextureRegistry::RegisterTexture(std::shared_ptr<Texture> texture) {
}
void TextureRegistry::UnregisterTexture(int64_t id) {
mapping_[id]->OnTextureUnregistered();
mapping_.erase(id);
}
......
......@@ -36,6 +36,9 @@ class Texture {
// Called on GPU thread.
virtual void MarkNewFrameAvailable() = 0;
// Called on GPU thread.
virtual void OnTextureUnregistered() = 0;
int64_t Id() { return id_; }
private:
......
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/flow/texture.h"
#include "gtest/gtest.h"
namespace flutter {
namespace testing {
class MockTexture : public Texture {
public:
MockTexture(int64_t textureId) : Texture(textureId) {}
~MockTexture() override = default;
// Called from GPU thread.
void Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze,
GrContext* context) override {}
void OnGrContextCreated() override {}
void OnGrContextDestroyed() override {}
void MarkNewFrameAvailable() override {}
void OnTextureUnregistered() override { unregistered_ = true; }
bool unregistered() { return unregistered_; }
private:
bool unregistered_ = false;
};
TEST(TextureRegistry, UnregisterTextureCallbackTriggered) {
TextureRegistry textureRegistry;
std::shared_ptr<MockTexture> mockTexture = std::make_shared<MockTexture>(0);
textureRegistry.RegisterTexture(mockTexture);
textureRegistry.UnregisterTexture(0);
ASSERT_TRUE(mockTexture->unregistered());
}
} // namespace testing
} // namespace flutter
......@@ -799,5 +799,79 @@ TEST_F(ShellTest, CanCreateImagefromDecompressedBytes) {
latch.Wait();
}
class MockTexture : public Texture {
public:
MockTexture(int64_t textureId,
std::shared_ptr<fml::AutoResetWaitableEvent> latch)
: Texture(textureId), latch_(latch) {}
~MockTexture() override = default;
// Called from GPU thread.
void Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze,
GrContext* context) override {}
void OnGrContextCreated() override {}
void OnGrContextDestroyed() override {}
void MarkNewFrameAvailable() override {
frames_available_++;
latch_->Signal();
}
void OnTextureUnregistered() override {
unregistered_ = true;
latch_->Signal();
}
bool unregistered() { return unregistered_; }
int frames_available() { return frames_available_; }
private:
bool unregistered_ = false;
int frames_available_ = 0;
std::shared_ptr<fml::AutoResetWaitableEvent> latch_;
};
TEST_F(ShellTest, TextureFrameMarkedAvailableAndUnregister) {
Settings settings = CreateSettingsForFixture();
auto configuration = RunConfiguration::InferFromSettings(settings);
auto task_runner = CreateNewThread();
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
task_runner);
std::unique_ptr<Shell> shell =
CreateShell(std::move(settings), std::move(task_runners));
ASSERT_TRUE(ValidateShell(shell.get()));
PlatformViewNotifyCreated(shell.get());
RunEngine(shell.get(), std::move(configuration));
std::shared_ptr<fml::AutoResetWaitableEvent> latch =
std::make_shared<fml::AutoResetWaitableEvent>();
std::shared_ptr<MockTexture> mockTexture =
std::make_shared<MockTexture>(0, latch);
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetGPUTaskRunner(), [&]() {
shell->GetPlatformView()->RegisterTexture(mockTexture);
shell->GetPlatformView()->MarkTextureFrameAvailable(0);
});
latch->Wait();
EXPECT_EQ(mockTexture->frames_available(), 1);
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetGPUTaskRunner(),
[&]() { shell->GetPlatformView()->UnregisterTexture(0); });
latch->Wait();
EXPECT_EQ(mockTexture->unregistered(), true);
}
} // namespace testing
} // namespace flutter
......@@ -135,4 +135,6 @@ void AndroidExternalTextureGL::Detach() {
}
}
void AndroidExternalTextureGL::OnTextureUnregistered() {}
} // namespace flutter
......@@ -30,6 +30,8 @@ class AndroidExternalTextureGL : public flutter::Texture {
void MarkNewFrameAvailable() override;
void OnTextureUnregistered() override;
private:
void Attach(jint textureName);
......
......@@ -15,6 +15,14 @@ NS_ASSUME_NONNULL_BEGIN
FLUTTER_EXPORT
@protocol FlutterTexture <NSObject>
- (CVPixelBufferRef _Nullable)copyPixelBuffer;
/**
* Called when the texture is unregistered.
*
* Called on the GPU thread.
*/
@optional
- (void)onTextureUnregistered:(NSObject<FlutterTexture>*)texture;
@end
FLUTTER_EXPORT
......
......@@ -27,6 +27,8 @@ class IOSExternalTextureGL : public flutter::Texture {
void MarkNewFrameAvailable() override;
void OnTextureUnregistered() override;
private:
void CreateTextureFromPixelBuffer();
......
......@@ -105,4 +105,10 @@ void IOSExternalTextureGL::MarkNewFrameAvailable() {
new_frame_ready_ = true;
}
void IOSExternalTextureGL::OnTextureUnregistered() {
if ([external_texture_ respondsToSelector:@selector(onTextureUnregistered:)]) {
[external_texture_ onTextureUnregistered:external_texture_];
}
}
} // namespace flutter
......@@ -44,4 +44,7 @@ void EmbedderExternalTextureGL::OnGrContextDestroyed() {}
// |flutter::Texture|
void EmbedderExternalTextureGL::MarkNewFrameAvailable() {}
// |flutter::Texture|
void EmbedderExternalTextureGL::OnTextureUnregistered() {}
} // namespace flutter
......@@ -41,6 +41,9 @@ class EmbedderExternalTextureGL : public flutter::Texture {
// |flutter::Texture|
void MarkNewFrameAvailable() override;
// |flutter::Texture|
void OnTextureUnregistered() override;
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureGL);
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册