mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[CP][Impeller] Fix crash when using BackdropFilters in certain GLES drivers. (#163581)
This is a cherry picked of https://github.com/flutter/flutter/pull/163345 and https://github.com/flutter/flutter/pull/163327 combined, as they both are parts of the same bug. The issues are: https://github.com/flutter/flutter/issues/163304 https://github.com/flutter/flutter/issues/163421 And potentially others, though we don't have clear repros or stack traces for all of them.
This commit is contained in:
parent
652d388b0a
commit
383d56ed91
@ -30,6 +30,7 @@ INTERNAL NOTE
|
||||
### [3.29.0](https://github.com/flutter/flutter/releases/tag/3.29.0)
|
||||
Initial stable release.
|
||||
|
||||
- [flutter/163304](https://github.com/flutter/flutter/issues/163304) Fixes crash when using backdrop filter on GLES backend.
|
||||
- [flutter/161334](https://github.com/flutter/flutter/issues/161334) Disable Vulkan on certain Xclipse GPU models.
|
||||
|
||||
## Flutter 3.27 Changes
|
||||
|
||||
@ -1677,6 +1677,14 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
|
||||
return input_texture;
|
||||
}
|
||||
|
||||
bool Canvas::SupportsBlitToOnscreen() const {
|
||||
return renderer_.GetContext()
|
||||
->GetCapabilities()
|
||||
->SupportsTextureToTextureBlits() &&
|
||||
renderer_.GetContext()->GetBackendType() !=
|
||||
Context::BackendType::kOpenGLES;
|
||||
}
|
||||
|
||||
bool Canvas::BlitToOnscreen(bool is_onscreen) {
|
||||
auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
|
||||
command_buffer->SetLabel("EntityPass Root Command Buffer");
|
||||
@ -1684,9 +1692,7 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
|
||||
.inline_pass_context->GetPassTarget()
|
||||
.GetRenderTarget();
|
||||
|
||||
if (renderer_.GetContext()
|
||||
->GetCapabilities()
|
||||
->SupportsTextureToTextureBlits()) {
|
||||
if (SupportsBlitToOnscreen()) {
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
|
||||
render_target_.GetRenderTargetTexture());
|
||||
|
||||
@ -251,6 +251,16 @@ class Canvas {
|
||||
// Visible for testing.
|
||||
bool RequiresReadback() const { return requires_readback_; }
|
||||
|
||||
// Whether the current device has the capabilities to blit an offscreen
|
||||
// texture into the onscreen.
|
||||
//
|
||||
// This requires the availibility of the blit framebuffer command, but is
|
||||
// disabled for GLES. A simple glBlitFramebuffer does not support resolving
|
||||
// different sample counts which may be present in GLES when using MSAA.
|
||||
//
|
||||
// Visible for testing.
|
||||
bool SupportsBlitToOnscreen() const;
|
||||
|
||||
private:
|
||||
ContentContext& renderer_;
|
||||
RenderTarget render_target_;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "impeller/display_list/aiks_unittests.h"
|
||||
#include "impeller/display_list/canvas.h"
|
||||
#include "impeller/geometry/geometry_asserts.h"
|
||||
#include "impeller/playground/playground.h"
|
||||
#include "impeller/renderer/render_target.h"
|
||||
|
||||
namespace impeller {
|
||||
@ -278,5 +279,17 @@ TEST_P(AiksTest, BackdropCountDownWithNestedSaveLayers) {
|
||||
EXPECT_TRUE(canvas->RequiresReadback());
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, SupportsBlitToOnscreen) {
|
||||
ContentContext context(GetContext(), nullptr);
|
||||
auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
|
||||
/*requires_readback=*/true);
|
||||
|
||||
if (GetBackend() == PlaygroundBackend::kOpenGLES) {
|
||||
EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
|
||||
} else {
|
||||
EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@ -65,4 +65,23 @@ TEST_P(TextureGLESTest, CanSetSyncFence) {
|
||||
ASSERT_FALSE(sync_fence.has_value());
|
||||
}
|
||||
|
||||
TEST_P(TextureGLESTest, Binds2DTexture) {
|
||||
TextureDescriptor desc;
|
||||
desc.storage_mode = StorageMode::kDevicePrivate;
|
||||
desc.size = {100, 100};
|
||||
desc.format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
desc.type = TextureType::kTexture2DMultisample;
|
||||
desc.sample_count = SampleCount::kCount4;
|
||||
|
||||
auto texture = GetContext()->GetResourceAllocator()->CreateTexture(desc);
|
||||
|
||||
ASSERT_TRUE(texture);
|
||||
|
||||
EXPECT_EQ(
|
||||
TextureGLES::Cast(*texture).ComputeTypeForBinding(GL_READ_FRAMEBUFFER),
|
||||
TextureGLES::Type::kTexture);
|
||||
EXPECT_EQ(TextureGLES::Cast(*texture).ComputeTypeForBinding(GL_FRAMEBUFFER),
|
||||
TextureGLES::Type::kTextureMultisampled);
|
||||
}
|
||||
|
||||
} // namespace impeller::testing
|
||||
|
||||
@ -392,6 +392,15 @@ static std::optional<GLenum> ToRenderBufferFormat(PixelFormat format) {
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
TextureGLES::Type TextureGLES::ComputeTypeForBinding(GLenum target) const {
|
||||
// When binding to a GL_READ_FRAMEBUFFER, any multisampled
|
||||
// textures must be bound as single sampled.
|
||||
if (target == GL_READ_FRAMEBUFFER && type_ == Type::kTextureMultisampled) {
|
||||
return Type::kTexture;
|
||||
}
|
||||
return type_;
|
||||
}
|
||||
|
||||
void TextureGLES::InitializeContentsIfNecessary() const {
|
||||
if (!IsValid() || slices_initialized_[0]) {
|
||||
return;
|
||||
@ -588,7 +597,7 @@ bool TextureGLES::SetAsFramebufferAttachment(
|
||||
}
|
||||
const auto& gl = reactor_->GetProcTable();
|
||||
|
||||
switch (type_) {
|
||||
switch (ComputeTypeForBinding(target)) {
|
||||
case Type::kTexture:
|
||||
gl.FramebufferTexture2D(target, // target
|
||||
ToAttachmentType(attachment_type), // attachment
|
||||
|
||||
@ -144,6 +144,9 @@ class TextureGLES final : public Texture,
|
||||
// Visible for testing.
|
||||
std::optional<HandleGLES> GetSyncFence() const;
|
||||
|
||||
// visible for testing
|
||||
Type ComputeTypeForBinding(GLenum target) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ReactorGLES> reactor_;
|
||||
const Type type_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user