From e8e387b549d1f1caa50b790bf1633ece3d0b1b7e Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Mon, 16 Aug 2021 08:02:23 +0900
Subject: [PATCH 1/3] Cache buffered background to fix multiplayer lounge
 performance

Consider this a request for comment. It's the cleanest solution I can
come up with without dropping either the blur, or use of
`ModelBackedDrawable`.

Intended to resolve https://github.com/ppy/osu/issues/14276.
---
 .../Components/OnlinePlayBackgroundSprite.cs  |  6 +--
 .../Screens/OnlinePlay/OnlinePlayScreen.cs    | 48 +++++++++++++++----
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
index d8dfac496d..e2ba0b03b0 100644
--- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
@@ -10,12 +10,12 @@ namespace osu.Game.Screens.OnlinePlay.Components
 {
     public class OnlinePlayBackgroundSprite : OnlinePlayComposite
     {
-        private readonly BeatmapSetCoverType beatmapSetCoverType;
+        protected readonly BeatmapSetCoverType BeatmapSetCoverType;
         private UpdateableBeatmapBackgroundSprite sprite;
 
         public OnlinePlayBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover)
         {
-            this.beatmapSetCoverType = beatmapSetCoverType;
+            BeatmapSetCoverType = beatmapSetCoverType;
         }
 
         [BackgroundDependencyLoader]
@@ -33,6 +33,6 @@ namespace osu.Game.Screens.OnlinePlay.Components
             sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value;
         }
 
-        protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(beatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
+        protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
     }
 }
diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
index c2ad0285b1..72b63ab4d4 100644
--- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
@@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Logging;
 using osu.Framework.Screens;
+using osu.Game.Beatmaps;
 using osu.Game.Beatmaps.Drawables;
 using osu.Game.Graphics.Containers;
 using osu.Game.Input;
@@ -104,14 +105,9 @@ namespace osu.Game.Screens.OnlinePlay
                         RelativeSizeAxes = Axes.Both,
                         Children = new Drawable[]
                         {
-                            new BufferedContainer
+                            new BeatmapBackgroundSprite
                             {
-                                RelativeSizeAxes = Axes.Both,
-                                BlurSigma = new Vector2(10),
-                                Child = new BeatmapBackgroundSprite
-                                {
-                                    RelativeSizeAxes = Axes.Both
-                                }
+                                RelativeSizeAxes = Axes.Both
                             },
                             new Box
                             {
@@ -306,11 +302,45 @@ namespace osu.Game.Screens.OnlinePlay
 
         private class BeatmapBackgroundSprite : OnlinePlayBackgroundSprite
         {
-            protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both };
+            protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BlurredBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
 
-            private class BackgroundSprite : UpdateableBeatmapBackgroundSprite
+            public class BlurredBackgroundSprite : UpdateableBeatmapBackgroundSprite
             {
+                public BlurredBackgroundSprite(BeatmapSetCoverType type)
+                    : base(type)
+                {
+                }
+
                 protected override double LoadDelay => 200;
+
+                protected override Drawable CreateDrawable(BeatmapInfo model) =>
+                    new BufferedLoader(base.CreateDrawable(model));
+            }
+
+            // This class is an unfortunate requirement due to `LongRunningLoad` requiring direct async loading.
+            // It means that if the web request fetching the beatmap background takes too long, it will suddenly appear.
+            internal class BufferedLoader : BufferedContainer
+            {
+                private readonly Drawable drawable;
+
+                public BufferedLoader(Drawable drawable)
+                {
+                    this.drawable = drawable;
+
+                    RelativeSizeAxes = Axes.Both;
+                    BlurSigma = new Vector2(10);
+                    CacheDrawnFrameBuffer = true;
+                }
+
+                [BackgroundDependencyLoader]
+                private void load()
+                {
+                    LoadComponentAsync(drawable, d =>
+                    {
+                        Add(d);
+                        ForceRedraw();
+                    });
+                }
             }
         }
 

From d35886ef196c032075e68bfcc1913f6469187465 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Mon, 16 Aug 2021 11:03:49 +0900
Subject: [PATCH 2/3] Reduce frame buffer render scale for blurred background

---
 osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
index 72b63ab4d4..fd265e9978 100644
--- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
@@ -329,6 +329,7 @@ namespace osu.Game.Screens.OnlinePlay
 
                     RelativeSizeAxes = Axes.Both;
                     BlurSigma = new Vector2(10);
+                    FrameBufferScale = new Vector2(0.5f);
                     CacheDrawnFrameBuffer = true;
                 }
 

From f0fe79b568724b5151a8b9544438463ee56014a4 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Mon, 16 Aug 2021 11:04:21 +0900
Subject: [PATCH 3/3] Remove buffered container workarounds for now

---
 .../Lounge/Components/DrawableRoom.cs         | 65 +++++++------------
 1 file changed, 25 insertions(+), 40 deletions(-)

diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
index 193fb0cf57..c8ecd65574 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
@@ -158,21 +158,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
             Children = new Drawable[]
             {
                 // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites.
-                new BufferedContainer
+                new Box
                 {
                     RelativeSizeAxes = Axes.Both,
-                    Children = new Drawable[]
-                    {
-                        new Box
-                        {
-                            RelativeSizeAxes = Axes.Both,
-                            Colour = colours.Background5,
-                        },
-                        new OnlinePlayBackgroundSprite
-                        {
-                            RelativeSizeAxes = Axes.Both
-                        },
-                    }
+                    Colour = colours.Background5,
+                },
+                new OnlinePlayBackgroundSprite
+                {
+                    RelativeSizeAxes = Axes.Both
                 },
                 new Container
                 {
@@ -187,37 +180,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
                         CornerRadius = corner_radius,
                         Children = new Drawable[]
                         {
-                            // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites.
-                            new BufferedContainer
+                            new GridContainer
                             {
                                 RelativeSizeAxes = Axes.Both,
-                                Children = new Drawable[]
+                                ColumnDimensions = new[]
                                 {
-                                    new GridContainer
-                                    {
-                                        RelativeSizeAxes = Axes.Both,
-                                        ColumnDimensions = new[]
-                                        {
-                                            new Dimension(GridSizeMode.Relative, 0.2f)
-                                        },
-                                        Content = new[]
-                                        {
-                                            new Drawable[]
-                                            {
-                                                new Box
-                                                {
-                                                    RelativeSizeAxes = Axes.Both,
-                                                    Colour = colours.Background5,
-                                                },
-                                                new Box
-                                                {
-                                                    RelativeSizeAxes = Axes.Both,
-                                                    Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f))
-                                                },
-                                            }
-                                        }
-                                    },
+                                    new Dimension(GridSizeMode.Relative, 0.2f)
                                 },
+                                Content = new[]
+                                {
+                                    new Drawable[]
+                                    {
+                                        new Box
+                                        {
+                                            RelativeSizeAxes = Axes.Both,
+                                            Colour = colours.Background5,
+                                        },
+                                        new Box
+                                        {
+                                            RelativeSizeAxes = Axes.Both,
+                                            Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f))
+                                        },
+                                    }
+                                }
                             },
                             new Container
                             {