A game framework written with osu! in mind.
at master 113 lines 4.9 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using osu.Framework.Graphics.OpenGL; 6using osu.Framework.Graphics.OpenGL.Buffers; 7using osuTK.Graphics.ES30; 8 9namespace osu.Framework.Graphics 10{ 11 /// <summary> 12 /// Contains data which is shared between all <see cref="BufferedDrawNode"/>s of a <see cref="Drawable"/>. 13 /// </summary> 14 /// <remarks> 15 /// This should be constructed _once_ per <see cref="Drawable"/>, and given to the constructor of <see cref="BufferedDrawNode"/>. 16 /// </remarks> 17 public class BufferedDrawNodeSharedData : IDisposable 18 { 19 /// <summary> 20 /// The version of drawn contents currently present in <see cref="MainBuffer"/> and <see cref="effectBuffers"/>. 21 /// This should only be modified by <see cref="BufferedDrawNode"/>. 22 /// </summary> 23 internal long DrawVersion = -1; 24 25 /// <summary> 26 /// The <see cref="FrameBuffer"/> which contains the original version of the rendered <see cref="Drawable"/>. 27 /// </summary> 28 public FrameBuffer MainBuffer { get; } 29 30 /// <summary> 31 /// Whether the frame buffer position should be snapped to the nearest pixel when blitting. 32 /// This amounts to setting the texture filtering mode to "nearest". 33 /// </summary> 34 public readonly bool PixelSnapping; 35 36 /// <summary> 37 /// A set of <see cref="FrameBuffer"/>s which are used in a ping-pong manner to render effects to. 38 /// </summary> 39 private readonly FrameBuffer[] effectBuffers; 40 41 /// <summary> 42 /// Creates a new <see cref="BufferedDrawNodeSharedData"/> with no effect buffers. 43 /// </summary> 44 public BufferedDrawNodeSharedData(RenderbufferInternalFormat[] formats = null, bool pixelSnapping = false) 45 : this(0, formats, pixelSnapping) 46 { 47 } 48 49 /// <summary> 50 /// Creates a new <see cref="BufferedDrawNodeSharedData"/> with a specific amount of effect buffers. 51 /// </summary> 52 /// <param name="effectBufferCount">The number of effect buffers.</param> 53 /// <param name="formats">The render buffer formats to attach to each frame buffer.</param> 54 /// <param name="pixelSnapping">Whether the frame buffer position should be snapped to the nearest pixel when blitting. 55 /// This amounts to setting the texture filtering mode to "nearest".</param> 56 /// <exception cref="ArgumentOutOfRangeException">If <paramref name="effectBufferCount"/> is less than 0.</exception> 57 public BufferedDrawNodeSharedData(int effectBufferCount, RenderbufferInternalFormat[] formats = null, bool pixelSnapping = false) 58 { 59 if (effectBufferCount < 0) 60 throw new ArgumentOutOfRangeException(nameof(effectBufferCount), "Must be positive."); 61 62 PixelSnapping = pixelSnapping; 63 All filterMode = pixelSnapping ? All.Nearest : All.Linear; 64 65 MainBuffer = new FrameBuffer(formats, filterMode); 66 effectBuffers = new FrameBuffer[effectBufferCount]; 67 68 for (int i = 0; i < effectBufferCount; i++) 69 effectBuffers[i] = new FrameBuffer(formats, filterMode); 70 } 71 72 private int currentEffectBuffer = -1; 73 74 /// <summary> 75 /// The <see cref="FrameBuffer"/> which contains the most up-to-date drawn effect. 76 /// </summary> 77 public FrameBuffer CurrentEffectBuffer => currentEffectBuffer == -1 ? MainBuffer : effectBuffers[currentEffectBuffer]; 78 79 /// <summary> 80 /// Retrieves the next <see cref="FrameBuffer"/> which effects can be rendered to. 81 /// </summary> 82 /// <exception cref="InvalidOperationException">If there are no available effect buffers.</exception> 83 public FrameBuffer GetNextEffectBuffer() 84 { 85 if (effectBuffers.Length == 0) 86 throw new InvalidOperationException($"The {nameof(BufferedDrawNode)} requested an effect buffer, but none were available."); 87 88 if (++currentEffectBuffer >= effectBuffers.Length) 89 currentEffectBuffer = 0; 90 return effectBuffers[currentEffectBuffer]; 91 } 92 93 /// <summary> 94 /// Resets <see cref="CurrentEffectBuffer"/>. 95 /// This should only be called by <see cref="BufferedDrawNode"/>. 96 /// </summary> 97 internal void ResetCurrentEffectBuffer() => currentEffectBuffer = -1; 98 99 public void Dispose() 100 { 101 GLWrapper.ScheduleDisposal(() => Dispose(true)); 102 GC.SuppressFinalize(this); 103 } 104 105 protected virtual void Dispose(bool isDisposing) 106 { 107 MainBuffer.Dispose(); 108 109 for (int i = 0; i < effectBuffers.Length; i++) 110 effectBuffers[i].Dispose(); 111 } 112 } 113}