using System.Windows.Forms; using BizHawk.Bizware.BizwareGL; namespace BizHawk.Client.EmuHawk { /// /// Adapts a GraphicsControl to gain the power of remembering what was drawn to it, and keeping it presented in response to Paint events /// public class RetainedGraphicsControl : GraphicsControl { public RetainedGraphicsControl(IGL gl) : base(gl) { _gl = gl; _guiRenderer = new GuiRenderer(gl); } /// /// Control whether rendering goes into the retaining buffer (it's slower) or straight to the viewport. /// This could be useful as a performance hack, or if someone was very clever, they could wait for a control to get deactivated, enable retaining, and render it one more time. /// Of course, even better still is to be able to repaint viewports continually, but sometimes that's annoying. /// public bool Retain { get => _retain; set { if (_retain && !value) { _rt.Dispose(); _rt = null; } _retain = value; } } private bool _retain = true; private readonly IGL _gl; private RenderTarget _rt; private readonly GuiRenderer _guiRenderer; public override void Begin() { base.Begin(); if (_retain) { // TODO - frugalize me _rt?.Dispose(); _rt = _gl.CreateRenderTarget(Width, Height); _rt.Bind(); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // todo - check whether we're begun? base.Begin(); Draw(); base.End(); } private void Draw() { if (_rt == null) { return; } _guiRenderer.Begin(Width, Height); _guiRenderer.SetBlendState(_gl.BlendNoneCopy); _guiRenderer.Draw(_rt.Texture2d); _guiRenderer.End(); base.SwapBuffers(); } public override void SwapBuffers() { // if we're not retaining, then we haven't been collecting into a framebuffer. just swap it if (!_retain) { base.SwapBuffers(); return; } // if we're retaining, then we cant draw until we unbind! its semantically a bit odd, but we expect users to call SwapBuffers() before end, so we cant unbind in End() even thoug hit makes a bit more sense. _rt.Unbind(); Draw(); } public override void End() { if (_retain) { _rt.Unbind(); } base.End(); } } }