using System.Collections.Generic; namespace BizHawk.Client.EmuHawk { /// /// encapsulates thread-safe concept of pending/current display surfaces, reusing buffers where matching /// sizes are available and keeping them cleaned up when they don't seem like they'll need to be used anymore /// public class SwappableDisplaySurfaceSet { private DisplaySurface _pending, _current; private bool _isPending; private readonly Queue _releasedSurfaces = new Queue(); /// /// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested /// public DisplaySurface AllocateSurface(int width, int height, bool needsClear = true) { for (; ; ) { DisplaySurface trial; lock (this) { if (_releasedSurfaces.Count == 0) break; trial = _releasedSurfaces.Dequeue(); } if (trial.Width == width && trial.Height == height) { if (needsClear) { trial.Clear(); } return trial; } trial.Dispose(); } return new DisplaySurface(width, height); } /// /// sets the provided buffer as pending. takes control of the supplied buffer /// public void SetPending(DisplaySurface newPending) { lock (this) { if (_pending != null) _releasedSurfaces.Enqueue(_pending); _pending = newPending; _isPending = true; } } public void ReleaseSurface(DisplaySurface surface) { lock (this) _releasedSurfaces.Enqueue(surface); } /// /// returns the current buffer, making the most recent pending buffer (if there is such) as the new current first. /// public DisplaySurface GetCurrent() { lock (this) { if (_isPending) { if (_current != null) _releasedSurfaces.Enqueue(_current); _current = _pending; _pending = null; _isPending = false; } } return _current; } } }