Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -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/fml/base32.cc
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ executable("flow_unittests") {
"matrix_decomposition_unittests.cc",
"mutators_stack_unittests.cc",
"raster_cache_unittests.cc",
"texture_unittests.cc",
]

deps = [
Expand Down
1 change: 1 addition & 0 deletions flow/texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ void TextureRegistry::RegisterTexture(std::shared_ptr<Texture> texture) {
}

void TextureRegistry::UnregisterTexture(int64_t id) {
mapping_[id]->OnTextureUnregistered();
mapping_.erase(id);
}

Expand Down
3 changes: 3 additions & 0 deletions flow/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
46 changes: 46 additions & 0 deletions flow/texture_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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 {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per convention, we note the class that declares the prototype for the method being overridden. So // |flutter::testing::Texture|.


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
74 changes: 74 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions shell/platform/android/android_external_texture_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,6 @@ void AndroidExternalTextureGL::Detach() {
}
}

void AndroidExternalTextureGL::OnTextureUnregistered() {}

} // namespace flutter
2 changes: 2 additions & 0 deletions shell/platform/android/android_external_texture_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class AndroidExternalTextureGL : public flutter::Texture {

void MarkNewFrameAvailable() override;

void OnTextureUnregistered() override;

private:
void Attach(jint textureName);

Expand Down
8 changes: 8 additions & 0 deletions shell/platform/darwin/ios/framework/Headers/FlutterTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/darwin/ios/ios_external_texture_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class IOSExternalTextureGL : public flutter::Texture {

void MarkNewFrameAvailable() override;

void OnTextureUnregistered() override;

private:
void CreateTextureFromPixelBuffer();

Expand Down
6 changes: 6 additions & 0 deletions shell/platform/darwin/ios/ios_external_texture_gl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,10 @@
new_frame_ready_ = true;
}

void IOSExternalTextureGL::OnTextureUnregistered() {
if ([external_texture_ respondsToSelector:@selector(onTextureUnregistered:)]) {
[external_texture_ onTextureUnregistered:external_texture_];
}
}

} // namespace flutter
3 changes: 3 additions & 0 deletions shell/platform/embedder/embedder_external_texture_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,7 @@ void EmbedderExternalTextureGL::OnGrContextDestroyed() {}
// |flutter::Texture|
void EmbedderExternalTextureGL::MarkNewFrameAvailable() {}

// |flutter::Texture|
void EmbedderExternalTextureGL::OnTextureUnregistered() {}

} // namespace flutter
3 changes: 3 additions & 0 deletions shell/platform/embedder/embedder_external_texture_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down