From eccbe1ce2a8e6a0a5a64da5b4ad1dc5619fe245d Mon Sep 17 00:00:00 2001 From: adelikat Date: Mon, 9 Mar 2015 21:06:40 +0000 Subject: [PATCH] MultiHawk - removing more stuff --- .../DisplayManager/TextureFrugalizer.cs | 2 +- .../BizHawk.Client.MultiHawk.csproj | 8 - .../DisplayManager/DisplayManager.cs | 38 +- .../DisplayManager/DisplaySurface.cs | 185 ---------- .../DisplayManager/FilterManager.cs | 263 -------------- .../DisplayManager/Filters/BaseFilter.cs | 134 ------- .../DisplayManager/Filters/Gui.cs | 334 ------------------ .../DisplayManager/Filters/Retro.cs | 285 --------------- .../DisplayManager/Filters/Utils.cs | 90 ----- .../DisplayManager/TextureFrugalizer.cs | 82 ----- 10 files changed, 20 insertions(+), 1401 deletions(-) delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/DisplaySurface.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/FilterManager.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/Filters/BaseFilter.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/Filters/Gui.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/Filters/Retro.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/Filters/Utils.cs delete mode 100644 BizHawk.Client.MultiHawk/DisplayManager/TextureFrugalizer.cs diff --git a/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs b/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs index d0b7cb5be4..607d9780ec 100644 --- a/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs +++ b/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs @@ -13,7 +13,7 @@ namespace BizHawk.Client.EmuHawk /// Recycles a pair of temporary textures (in case double-buffering helps any) to contain a BitmapBuffer's or DisplaySurface's contents, as long as the dimensions match. /// When the dimensions dont match, a new one will be allocated /// - class TextureFrugalizer : IDisposable + public class TextureFrugalizer : IDisposable { public TextureFrugalizer(IGL gl) { diff --git a/BizHawk.Client.MultiHawk/BizHawk.Client.MultiHawk.csproj b/BizHawk.Client.MultiHawk/BizHawk.Client.MultiHawk.csproj index 4f5407e9ac..32789a93d2 100644 --- a/BizHawk.Client.MultiHawk/BizHawk.Client.MultiHawk.csproj +++ b/BizHawk.Client.MultiHawk/BizHawk.Client.MultiHawk.csproj @@ -72,15 +72,7 @@ RecordMovie.cs - - - - - - - - Form diff --git a/BizHawk.Client.MultiHawk/DisplayManager/DisplayManager.cs b/BizHawk.Client.MultiHawk/DisplayManager/DisplayManager.cs index 853e51b2df..71a3e1de83 100644 --- a/BizHawk.Client.MultiHawk/DisplayManager/DisplayManager.cs +++ b/BizHawk.Client.MultiHawk/DisplayManager/DisplayManager.cs @@ -9,7 +9,7 @@ using System.Drawing; using BizHawk.Emulation.Common; using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk.FilterManager; +using BizHawk.Client.EmuHawk.FilterManager; using BizHawk.Bizware.BizwareGL; using OpenTK; @@ -52,7 +52,7 @@ namespace BizHawk.Client.MultiHawk else Renderer = new GDIPlusGuiRenderer((BizHawk.Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus)GL); - VideoTextureFrugalizer = new TextureFrugalizer(GL); + VideoTextureFrugalizer = new BizHawk.Client.EmuHawk.TextureFrugalizer(GL); ShaderChainFrugalizers = new RenderTargetFrugalizer[16]; //hacky hardcoded limit.. need some other way to manage these for (int i = 0; i < 16; i++) @@ -96,11 +96,11 @@ namespace BizHawk.Client.MultiHawk /// int currEmuWidth, currEmuHeight; - TextureFrugalizer VideoTextureFrugalizer; - Dictionary LuaSurfaceFrugalizers = new Dictionary(); + BizHawk.Client.EmuHawk.TextureFrugalizer VideoTextureFrugalizer; + Dictionary LuaSurfaceFrugalizers = new Dictionary(); RenderTargetFrugalizer[] ShaderChainFrugalizers; - Filters.RetroShaderChain ShaderChain_user; + BizHawk.Client.EmuHawk.Filters.RetroShaderChain ShaderChain_user; public void RefreshUserShader() { @@ -110,7 +110,7 @@ namespace BizHawk.Client.MultiHawk { var fi = new FileInfo(Global.Config.DispUserFilterPath); using (var stream = fi.OpenRead()) - ShaderChain_user = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.GetDirectoryName(Global.Config.DispUserFilterPath)); + ShaderChain_user = new BizHawk.Client.EmuHawk.Filters.RetroShaderChain(GL, new BizHawk.Client.EmuHawk.Filters.RetroShaderPreset(stream), Path.GetDirectoryName(Global.Config.DispUserFilterPath)); } } @@ -118,14 +118,14 @@ namespace BizHawk.Client.MultiHawk { //select user special FX shader chain Dictionary selectedChainProperties = new Dictionary(); - Filters.RetroShaderChain selectedChain = null; + BizHawk.Client.EmuHawk.Filters.RetroShaderChain selectedChain = null; if (Global.Config.TargetDisplayFilter == 3 && ShaderChain_user != null && ShaderChain_user.Available) selectedChain = ShaderChain_user; - Filters.FinalPresentation fPresent = new Filters.FinalPresentation(chain_outsize); - Filters.SourceImage fInput = new Filters.SourceImage(chain_insize); - Filters.OSD fOSD = new Filters.OSD(); + BizHawk.Client.EmuHawk.Filters.FinalPresentation fPresent = new BizHawk.Client.EmuHawk.Filters.FinalPresentation(chain_outsize); + BizHawk.Client.EmuHawk.Filters.SourceImage fInput = new BizHawk.Client.EmuHawk.Filters.SourceImage(chain_insize); + BizHawk.Client.EmuHawk.Filters.OSD fOSD = new BizHawk.Client.EmuHawk.Filters.OSD(); fOSD.RenderCallback = () => { if (!includeOSD) @@ -142,11 +142,11 @@ namespace BizHawk.Client.MultiHawk chain.AddFilter(fInput, "input"); //choose final filter - Filters.FinalPresentation.eFilterOption finalFilter = Filters.FinalPresentation.eFilterOption.None; - if (Global.Config.DispFinalFilter == 1) finalFilter = Filters.FinalPresentation.eFilterOption.Bilinear; - if (Global.Config.DispFinalFilter == 2) finalFilter = Filters.FinalPresentation.eFilterOption.Bicubic; - - finalFilter = Filters.FinalPresentation.eFilterOption.None; + BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.None; + if (Global.Config.DispFinalFilter == 1) finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.Bilinear; + if (Global.Config.DispFinalFilter == 2) finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.Bicubic; + + finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.None; fPresent.FilterOption = finalFilter; @@ -156,12 +156,12 @@ namespace BizHawk.Client.MultiHawk return chain; } - void AppendRetroShaderChain(FilterProgram program, string name, Filters.RetroShaderChain retroChain, Dictionary properties) + void AppendRetroShaderChain(FilterProgram program, string name, BizHawk.Client.EmuHawk.Filters.RetroShaderChain retroChain, Dictionary properties) { for (int i = 0; i < retroChain.Passes.Length; i++) { var pass = retroChain.Passes[i]; - var rsp = new Filters.RetroShaderPass(retroChain, i); + var rsp = new BizHawk.Client.EmuHawk.Filters.RetroShaderPass(retroChain, i); string fname = string.Format("{0}[{1}]", name, i); program.AddFilter(rsp, fname); rsp.Parameters = properties; @@ -420,11 +420,11 @@ TESTEROO: filterProgram.GL = GL; //setup the source image filter - Filters.SourceImage fInput = filterProgram["input"] as Filters.SourceImage; + BizHawk.Client.EmuHawk.Filters.SourceImage fInput = filterProgram["input"] as BizHawk.Client.EmuHawk.Filters.SourceImage; fInput.Texture = videoTexture; //setup the final presentation filter - Filters.FinalPresentation fPresent = filterProgram["presentation"] as Filters.FinalPresentation; + BizHawk.Client.EmuHawk.Filters.FinalPresentation fPresent = filterProgram["presentation"] as BizHawk.Client.EmuHawk.Filters.FinalPresentation; fPresent.VirtualTextureSize = new Size(vw, vh); fPresent.TextureSize = new Size(bufferWidth, bufferHeight); fPresent.BackgroundColor = videoProvider.BackgroundColor; diff --git a/BizHawk.Client.MultiHawk/DisplayManager/DisplaySurface.cs b/BizHawk.Client.MultiHawk/DisplayManager/DisplaySurface.cs deleted file mode 100644 index 742d4b0fa6..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/DisplaySurface.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using BizHawk.Common; -using BizHawk.Client.Common; - -namespace BizHawk.Client.MultiHawk -{ - /// - /// This is a wrapper for a Bitmap, basically, which can also be a int[]. - /// It should be phased out, in favor of BitmapBuffer and Texture2d's - /// - public unsafe class DisplaySurface : IDisposable - { - Bitmap bmp; - BitmapData bmpdata; - int[] pixels; - - public unsafe void Clear() - { - FromBitmap(false); - Util.Memset(PixelPtr, 0, Stride * Height); - } - - public Bitmap PeekBitmap() - { - ToBitmap(); - return bmp; - } - - /// - /// returns a Graphics object used to render to this surface. be sure to dispose it! - /// - public Graphics GetGraphics() - { - ToBitmap(); - return Graphics.FromImage(bmp); - } - - public unsafe void ToBitmap(bool copy=true) - { - if (isBitmap) return; - isBitmap = true; - - if (bmp == null) - { - bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); - } - - if (copy) - { - bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - - int w = Width; - int h = Height; - int stride = bmpdata.Stride / 4; - int* bmpbuf = (int*)bmpdata.Scan0.ToPointer(); - for (int y = 0, i = 0; y < h; y++) - for (int x = 0; x < w; x++) - bmpbuf[y * stride + x] = pixels[i++]; - - bmp.UnlockBits(bmpdata); - } - - } - - public bool IsBitmap { get { return isBitmap; } } - bool isBitmap = false; - - public unsafe void FromBitmap(bool copy=true) - { - if (!isBitmap) return; - isBitmap = false; - - if (copy) - { - bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - - int w = Width; - int h = Height; - int stride = bmpdata.Stride / 4; - int* bmpbuf = (int*)bmpdata.Scan0.ToPointer(); - for (int y = 0, i = 0; y < h; y++) - for (int x = 0; x < w; x++) - pixels[i++] = bmpbuf[y * stride + x]; - - bmp.UnlockBits(bmpdata); - } - } - - - public static DisplaySurface DisplaySurfaceWrappingBitmap(Bitmap bmp) - { - DisplaySurface ret = new DisplaySurface(); - ret.Width = bmp.Width; - ret.Height = bmp.Height; - ret.bmp = bmp; - ret.isBitmap = true; - return ret; - } - - private DisplaySurface() - { - } - - public DisplaySurface(int width, int height) - { - //can't create a bitmap with zero dimensions, so for now, just bump it up to one - if (width == 0) width = 1; - if (height == 0) height = 1; - - Width = width; - Height = height; - - pixels = new int[width * height]; - LockPixels(); - } - - public int* PixelPtr { get { return (int*)ptr; } } - public IntPtr PixelIntPtr { get { return new IntPtr(ptr); } } - public int Stride { get { return Width*4; } } - public int OffsetOf(int x, int y) { return y * Stride + x*4; } - - void* ptr; - GCHandle handle; - void LockPixels() - { - UnlockPixels(); - handle = GCHandle.Alloc(pixels, GCHandleType.Pinned); - ptr = handle.AddrOfPinnedObject().ToPointer(); - } - - void UnlockPixels() - { - if(handle.IsAllocated) handle.Free(); - } - - /// - /// returns a new surface - /// - /// - /// - /// - public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1) - { - int new_width = Width + xpad0 + xpad1; - int new_height = Height + ypad0 + ypad1; - DisplaySurface ret = new DisplaySurface(new_width, new_height); - int* dptr = ret.PixelPtr; - int* sptr = PixelPtr; - int dstride = ret.Stride / 4; - int sstride = Stride / 4; - for (int y = 0; y < Height; y++) - for (int x = 0; x < Width; x++) - { - dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x]; - } - return ret; - - } - - public int Width { get; private set; } - public int Height { get; private set; } - - public void Dispose() - { - if (bmp != null) - bmp.Dispose(); - bmp = null; - UnlockPixels(); - } - - public void AcceptIntArray(int[] newpixels) - { - FromBitmap(false); - UnlockPixels(); - pixels = newpixels; - LockPixels(); - } - } - -} diff --git a/BizHawk.Client.MultiHawk/DisplayManager/FilterManager.cs b/BizHawk.Client.MultiHawk/DisplayManager/FilterManager.cs deleted file mode 100644 index d46f78870c..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/FilterManager.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Drawing; - -using BizHawk.Common; -using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk.Filters; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.Drivers.OpenTK; - -using OpenTK; -using OpenTK.Graphics; - -namespace BizHawk.Client.MultiHawk.FilterManager -{ - public enum SurfaceDisposition - { - Unspecified, Texture, RenderTarget - } - - public class SurfaceFormat - { - public SurfaceFormat(Size size) { this.Size = size; } - public Size Size { get; private set; } - } - - public class SurfaceState - { - public SurfaceState() { } - public SurfaceState(SurfaceFormat surfaceFormat, SurfaceDisposition surfaceDisposition = SurfaceDisposition.Unspecified) - { - this.SurfaceFormat = surfaceFormat; - this.SurfaceDisposition = surfaceDisposition; - } - public SurfaceFormat SurfaceFormat; - public SurfaceDisposition SurfaceDisposition; - } - - public interface IRenderTargetProvider - { - RenderTarget Get(Size size); - } - - public class FilterProgram - { - public List Filters = new List(); - Dictionary FilterNameIndex = new Dictionary(); - public List Program = new List(); - - public BaseFilter this[string name] - { - get - { - BaseFilter ret; - FilterNameIndex.TryGetValue(name, out ret); - return ret; - } - } - - public enum ProgramStepType - { - Run, - NewTarget, - FinalTarget - } - - //services to filters: - public IGuiRenderer GuiRenderer; - public IGL GL; - public IRenderTargetProvider RenderTargetProvider; - public RenderTarget GetRenderTarget(string channel = "default") { return CurrRenderTarget; } - public RenderTarget CurrRenderTarget; - - public void AddFilter(BaseFilter filter, string name = "") - { - Filters.Add(filter); - FilterNameIndex[name] = filter; - } - - /// - /// Receives a point in the coordinate space of the output of the filter program and untransforms it back to input points - /// - public Vector2 UntransformPoint(string channel, Vector2 point) - { - for (int i = Filters.Count - 1; i >= 0; i--) - { - var filter = Filters[i]; - point = filter.UntransformPoint(channel, point); - } - return point; - } - - /// - /// Receives a point in the input space of the filter program and transforms it through to output points - /// - public Vector2 TransformPoint(string channel, Vector2 point) - { - for (int i = 0; i < Filters.Count; i++) - { - var filter = Filters[i]; - point = filter.TransformPoint(channel, point); - } - return point; - } - - public class ProgramStep - { - public ProgramStep(ProgramStepType type, object args, string comment = null) - { - this.Type = type; - this.Args = args; - this.Comment = comment; - } - public ProgramStepType Type; - public object Args; - public string Comment; - public override string ToString() - { - if (Type == ProgramStepType.Run) - return string.Format("Run {0} ({1})", (int)Args, Comment); - if (Type == ProgramStepType.NewTarget) - return string.Format("NewTarget {0}", (Size)Args); - if (Type == ProgramStepType.FinalTarget) - return string.Format("FinalTarget"); - return null; - } - } - - public void Compile(string channel, Size insize, Size outsize, bool finalTarget) - { - RETRY: - - Program.Clear(); - - //prep filters for initialization - foreach (var f in Filters) - { - f.BeginInitialization(this); - f.Initialize(); - } - - //propagate input size forwards through filter chain to allow a 'flex' filter to determine what its input will be - Size presize = insize; - for (int i = 0; i < Filters.Count; i++) - { - var filter = Filters[i]; - presize = filter.PresizeInput(channel, presize); - } - - //propagate output size backwards through filter chain to allow a 'flex' filter to determine its output based on the desired output needs - presize = outsize; - for (int i = Filters.Count - 1; i >= 0; i--) - { - var filter = Filters[i]; - presize = filter.PresizeOutput(channel, presize); - } - - SurfaceState currState = null; - - for (int i = 0; i < Filters.Count; i++) - { - BaseFilter f = Filters[i]; - - //check whether this filter needs input. if so, notify it of the current pipeline state - var iosi = f.FindInput(channel); - if (iosi != null) - { - iosi.SurfaceFormat = currState.SurfaceFormat; - f.SetInputFormat(channel, currState); - - //check if the desired disposition needs to change from texture to render target - //(if so, insert a render filter) - if (iosi.SurfaceDisposition == SurfaceDisposition.RenderTarget && currState.SurfaceDisposition == SurfaceDisposition.Texture) - { - var renderer = new Render(); - Filters.Insert(i, renderer); - goto RETRY; - } - //check if the desired disposition needs to change from a render target to a texture - //(if so, the current render target gets resolved, and made no longer current - else if (iosi.SurfaceDisposition == SurfaceDisposition.Texture && currState.SurfaceDisposition == SurfaceDisposition.RenderTarget) - { - var resolver = new Resolve(); - Filters.Insert(i, resolver); - goto RETRY; - } - } - - //now, the filter will have set its output state depending on its input state. check if it outputs: - iosi = f.FindOutput(channel); - if (iosi != null) - { - if (currState == null) - { - currState = new SurfaceState(); - currState.SurfaceFormat = iosi.SurfaceFormat; - currState.SurfaceDisposition = iosi.SurfaceDisposition; - } - else - { - //if output disposition is unspecified, change it to whatever we've got right now - if (iosi.SurfaceDisposition == SurfaceDisposition.Unspecified) - { - iosi.SurfaceDisposition = currState.SurfaceDisposition; - } - - bool newTarget = false; - if (iosi.SurfaceFormat.Size != currState.SurfaceFormat.Size) - newTarget = true; - else if (currState.SurfaceDisposition == SurfaceDisposition.Texture && iosi.SurfaceDisposition == SurfaceDisposition.RenderTarget) - newTarget = true; - - if (newTarget) - { - currState = new SurfaceState(); - iosi.SurfaceFormat = currState.SurfaceFormat = iosi.SurfaceFormat; - iosi.SurfaceDisposition = currState.SurfaceDisposition = iosi.SurfaceDisposition; - Program.Add(new ProgramStep(ProgramStepType.NewTarget, currState.SurfaceFormat.Size)); - } - else - { - currState.SurfaceDisposition = iosi.SurfaceDisposition; - } - } - - - } - - Program.Add(new ProgramStep(ProgramStepType.Run, i, f.GetType().Name)); - - } //filter loop - - //if the current output disposition is a texture, we need to render it - if (currState.SurfaceDisposition == SurfaceDisposition.Texture) - { - var renderer = new Render(); - Filters.Insert(Filters.Count, renderer); - goto RETRY; - } - - //patch the program so that the final rendertarget set operation is the framebuffer instead - if (finalTarget) - { - for (int i = Program.Count - 1; i >= 0; i--) - { - var ps = Program[i]; - if (ps.Type == ProgramStepType.NewTarget) - { - var size = (Size)ps.Args; - Debug.Assert(size == outsize); - ps.Type = ProgramStepType.FinalTarget; - ps.Args = size; - break; - } - } - } - } - } -} \ No newline at end of file diff --git a/BizHawk.Client.MultiHawk/DisplayManager/Filters/BaseFilter.cs b/BizHawk.Client.MultiHawk/DisplayManager/Filters/BaseFilter.cs deleted file mode 100644 index aaee50d831..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/Filters/BaseFilter.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Drawing; - -using BizHawk.Common; -using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk.FilterManager; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.Drivers.OpenTK; - -using OpenTK; -using OpenTK.Graphics; - -//Here's how to make a filter: -//1. Reset your state entirely in Initialize(). -// The filter will be re-initialized several times while the chain is getting worked out, but not re-instantiated. -// This is sort of annoying, but there's pretty good reasons for it (some external process has created the filters and set parameters needed to govern their chaining and surface properties) -//2. In Initialize(), be sure to use DeclareInput -//(something about PresizeInput()) -//3. PresizeOutput() will be called next -//4. In SetInputFormat(), use DeclareOutput to set the output based on your desires, or the provided input format. -//5. In Run(), the render target is already set. If using a texture, use InputTexture -//6. In Run(), if supplying an output texture, use YieldOutput - -namespace BizHawk.Client.MultiHawk.Filters -{ - public class BaseFilter - { - //initialization stuff - public void BeginInitialization(FilterProgram program) { IOSurfaceInfos.Clear(); FilterProgram = program; } - public virtual void Initialize() { } - public virtual Size PresizeInput(string channel, Size size) { return size; } - public virtual Size PresizeOutput(string channel, Size size) { return size; } - public virtual void SetInputFormat(string channel, SurfaceState state) { } - public Dictionary Parameters = new Dictionary(); - - //runtime signals - public virtual Vector2 UntransformPoint(string channel, Vector2 point) - { - //base class behaviour here just uses the input and output sizes, if appropriate. few filters will have to do anything more complex - var input = FindInput(channel); - var output = FindOutput(channel); - if (input != null && output != null) - { - point.X *= ((float)input.SurfaceFormat.Size.Width) / (float)output.SurfaceFormat.Size.Width; - point.Y *= ((float)input.SurfaceFormat.Size.Height) / (float)output.SurfaceFormat.Size.Height; - } - return point; - } - - public virtual Vector2 TransformPoint(string channel, Vector2 point) - { - //base class behaviour here just uses the input and output sizes, if appropriate. few filters will have to do anything more complex - var input = FindInput(channel); - var output = FindOutput(channel); - if (input != null && output != null) - { - point.X *= ((float)output.SurfaceFormat.Size.Width) / (float)input.SurfaceFormat.Size.Width; - point.Y *= ((float)output.SurfaceFormat.Size.Height) / (float)input.SurfaceFormat.Size.Height; - } - return point; - } - - public void SetInput(Texture2d tex) - { - InputTexture = tex; - } - public virtual void Run() { } - public Texture2d GetOutput() { return OutputTexture; } - - //filter actions - protected void YieldOutput(Texture2d tex) - { - OutputTexture = tex; - } - - protected FilterProgram FilterProgram; - protected Texture2d InputTexture; - private Texture2d OutputTexture; - - //setup utilities - protected IOSurfaceInfo DeclareInput(SurfaceDisposition disposition = SurfaceDisposition.Unspecified, string channel = "default") { return DeclareIO(SurfaceDirection.Input, channel, disposition); } - protected IOSurfaceInfo DeclareOutput(SurfaceDisposition disposition = SurfaceDisposition.Unspecified, string channel = "default") { return DeclareIO(SurfaceDirection.Output, channel, disposition); } - - protected IOSurfaceInfo DeclareOutput(SurfaceState state, string channel = "default") - { - var iosi = DeclareIO(SurfaceDirection.Output, channel, state.SurfaceDisposition); - iosi.SurfaceFormat = state.SurfaceFormat; - return iosi; - } - - public IOSurfaceInfo FindInput(string channel = "default") { return FindIOSurfaceInfo(channel, SurfaceDirection.Input); } - public IOSurfaceInfo FindOutput(string channel = "default") { return FindIOSurfaceInfo(channel, SurfaceDirection.Output); } - - private IOSurfaceInfo DeclareIO(SurfaceDirection direction, string channel, SurfaceDisposition disposition) - { - var iosi = new IOSurfaceInfo(); - iosi.SurfaceDirection = direction; - iosi.Channel = channel; - iosi.SurfaceDisposition = disposition; - IOSurfaceInfos.Add(iosi); - return iosi; - } - - List IOSurfaceInfos = new List(); - - - IOSurfaceInfo FindIOSurfaceInfo(string channel, SurfaceDirection direction) - { - foreach (var iosi in IOSurfaceInfos) - if (iosi.Channel == channel && iosi.SurfaceDirection == direction) - return iosi; - return null; - } - - public class IOSurfaceInfo - { - public SurfaceFormat SurfaceFormat; - public SurfaceDirection SurfaceDirection; - public SurfaceDisposition SurfaceDisposition; - public string Channel; - } - - public enum SurfaceDirection - { - Input, Output - } - } - -} \ No newline at end of file diff --git a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Gui.cs b/BizHawk.Client.MultiHawk/DisplayManager/Filters/Gui.cs deleted file mode 100644 index 7cab1a0cbe..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Gui.cs +++ /dev/null @@ -1,334 +0,0 @@ -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Drawing; - -using BizHawk.Common; -using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk; -using BizHawk.Client.MultiHawk.FilterManager; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.Drivers.OpenTK; - -using OpenTK; -using OpenTK.Graphics; - -namespace BizHawk.Client.MultiHawk.Filters -{ - /// - /// applies letterboxing logic to figure out how to fit the source dimensions into the target dimensions. - /// In the future this could also apply rules like integer-only scaling, etc. - /// - class LetterboxingLogic - { - /// - /// the location within the destination region of the output content (scaled and translated) - /// - public int vx, vy, vw, vh; - - /// - /// the scale factor eventually used - /// - public float WidthScale, HeightScale; - - //do maths on the viewport and the native resolution and the user settings to get a display rectangle - public LetterboxingLogic(bool maintainAspect, bool maintainInteger, int targetWidth, int targetHeight, int sourceWidth, int sourceHeight, Size textureSize, Size virtualSize) - { - int textureWidth = textureSize.Width; - int textureHeight = textureSize.Height; - int virtualWidth = virtualSize.Width; - int virtualHeight = virtualSize.Height; - - //zero 02-jun-2014 - we passed these in, but ignored them. kind of weird.. - int oldSourceWidth = sourceWidth; - int oldSourceHeight = sourceHeight; - sourceWidth = (int)virtualWidth; - sourceHeight = (int)virtualHeight; - - //this doesnt make sense - if (!maintainAspect) - maintainInteger = false; - - float widthScale = (float)targetWidth / sourceWidth; - float heightScale = (float)targetHeight / sourceHeight; - - if (maintainAspect - //zero 20-jul-2014 - hacks upon hacks, this function needs rewriting - && !maintainInteger - ) - { - if (widthScale > heightScale) widthScale = heightScale; - if (heightScale > widthScale) heightScale = widthScale; - } - - if (maintainInteger) - { - //just totally different code - //apply the zooming algorithm (pasted and reworked, for now) - - Vector2 VS = new Vector2(virtualWidth, virtualHeight); - Vector2 BS = new Vector2(textureWidth, textureHeight); - Vector2 AR = Vector2.Divide(VS, BS); - float target_par = (AR.X / AR.Y); - Vector2 PS = new Vector2(1, 1); //this would malfunction for AR <= 0.5 or AR >= 2.0 - - for(;;) - { - //TODO - would be good not to run this per frame.... - Vector2[] trials = new[] { - PS + new Vector2(1, 0), - PS + new Vector2(0, 1), - PS + new Vector2(1, 1) - }; - bool[] trials_limited = new bool[3] { false,false,false}; - int bestIndex = -1; - float bestValue = 1000.0f; - for (int t = 0; t < trials.Length; t++) - { - Vector2 vTrial = trials[t]; - trials_limited[t] = false; - - //check whether this is going to exceed our allotted area - int test_vw = (int)(vTrial.X * textureWidth); - int test_vh = (int)(vTrial.Y * textureHeight); - if (test_vw > targetWidth) trials_limited[t] = true; - if (test_vh > targetHeight) trials_limited[t] = true; - - //I. - float test_ar = vTrial.X / vTrial.Y; - - //II. - //Vector2 calc = Vector2.Multiply(trials[t], VS); - //float test_ar = calc.X / calc.Y; - - //not clear which approach is superior - float deviation_linear = Math.Abs(test_ar - target_par); - float deviation_geom = test_ar / target_par; - if (deviation_geom < 1) deviation_geom = 1.0f / deviation_geom; - - float value = deviation_linear; - if (value < bestValue) - { - bestIndex = t; - bestValue = value; - } - } - - //last result was best, so bail out - if (bestIndex == -1) - break; - - //if the winner ran off the edge, bail out - if (trials_limited[bestIndex]) - break; - - PS = trials[bestIndex]; - } - - vw = (int)(PS.X * textureWidth); - vh = (int)(PS.Y * textureHeight); - widthScale = PS.X; - heightScale = PS.Y; - } - else - { - vw = (int)(widthScale * sourceWidth); - vh = (int)(heightScale * sourceHeight); - } - - //determine letterboxing parameters - vx = (targetWidth - vw) / 2; - vy = (targetHeight - vh) / 2; - - //zero 09-oct-2014 - changed this for TransformPoint. scenario: basic 1x (but system-specified AR) NES window. - //vw would be 293 but WidthScale would be 1.0. I think it should be something different. - //FinalPresentation doesnt use the LL.WidthScale, so this is unlikely to be breaking anything old that depends on it - //WidthScale = widthScale; - //HeightScale = heightScale; - WidthScale = (float)vw / oldSourceWidth; - HeightScale = (float)vh / oldSourceHeight; - } - - } - - public class FinalPresentation : BaseFilter - { - public enum eFilterOption - { - None, Bilinear, Bicubic - } - - public eFilterOption FilterOption = eFilterOption.None; - public RetroShaderChain BicubicFilter; - - public FinalPresentation(Size size) - { - this.OutputSize = size; - } - - Size OutputSize, InputSize; - public Size TextureSize, VirtualTextureSize; - public int BackgroundColor; - public IGuiRenderer GuiRenderer; - public IGL GL; - bool nop; - LetterboxingLogic LL; - Size ContentSize; - - public override void Initialize() - { - DeclareInput(); - nop = false; - } - - public override Size PresizeOutput(string channel, Size size) - { - if (FilterOption == eFilterOption.Bicubic) - { - size.Width = LL.vw; - size.Height = LL.vh; - return size; - } - return base.PresizeOutput(channel, size); - } - - public override Size PresizeInput(string channel, Size size) - { - if (FilterOption != eFilterOption.Bicubic) - return size; - - LL = new LetterboxingLogic(Global.Config.DispFixAspectRatio, Global.Config.DispFixScaleInteger, OutputSize.Width, OutputSize.Height, size.Width, size.Height, TextureSize, VirtualTextureSize); - - return size; - } - - public override void SetInputFormat(string channel, SurfaceState state) - { - bool need = false; - if (state.SurfaceFormat.Size != OutputSize) - need = true; - if (FilterOption != eFilterOption.None) - need = true; - - if (!need) - { - nop = true; - ContentSize = state.SurfaceFormat.Size; - return; - } - - FindInput().SurfaceDisposition = SurfaceDisposition.Texture; - DeclareOutput(new SurfaceState(new SurfaceFormat(OutputSize), SurfaceDisposition.RenderTarget)); - InputSize = state.SurfaceFormat.Size; - LL = new LetterboxingLogic(Global.Config.DispFixAspectRatio, Global.Config.DispFixScaleInteger, OutputSize.Width, OutputSize.Height, InputSize.Width, InputSize.Height, TextureSize, VirtualTextureSize); - ContentSize = new Size(LL.vw,LL.vh); - } - - public Size GetContentSize() { return ContentSize; } - - public override Vector2 UntransformPoint(string channel, Vector2 point) - { - if (nop) - return point; - point.X -= LL.vx; - point.Y -= LL.vy; - point.X /= LL.WidthScale; - point.Y /= LL.HeightScale; - return point; - } - - public override Vector2 TransformPoint(string channel, Vector2 point) - { - if (nop) - return point; - point.X *= LL.WidthScale; - point.Y *= LL.HeightScale; - point.X += LL.vx; - point.Y += LL.vy; - return point; - } - - public override void Run() - { - if (nop) - return; - - GL.SetClearColor(Color.FromArgb(BackgroundColor)); - GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit); - - GuiRenderer.Begin(OutputSize.Width, OutputSize.Height); - GuiRenderer.SetBlendState(GL.BlendNoneCopy); - - if(FilterOption != eFilterOption.None) - InputTexture.SetFilterLinear(); - else - InputTexture.SetFilterNearest(); - - if (FilterOption == eFilterOption.Bicubic) - { - } - - - GuiRenderer.Draw(InputTexture,LL.vx,LL.vy,LL.vw,LL.vh); - - GuiRenderer.End(); - } - } - - public class LuaLayer : BaseFilter - { - public override void Initialize() - { - DeclareInput(SurfaceDisposition.RenderTarget); - } - public override void SetInputFormat(string channel, SurfaceState state) - { - DeclareOutput(state); - } - - Texture2d Texture; - - public void SetTexture(Texture2d tex) - { - Texture = tex; - } - - public override void Run() - { - var outSize = FindOutput().SurfaceFormat.Size; - FilterProgram.GuiRenderer.Begin(outSize); - FilterProgram.GuiRenderer.SetBlendState(FilterProgram.GL.BlendNormal); - FilterProgram.GuiRenderer.Draw(Texture); - FilterProgram.GuiRenderer.End(); - } - } - - public class OSD : BaseFilter - { - //this class has the ability to disable its operations for higher performance when the callback is removed, - //without having to take it out of the chain. although, its presence in the chain may slow down performance due to added resolves/renders - //so, we should probably rebuild the chain. - - public override void Initialize() - { - if (RenderCallback == null) return; - DeclareInput(SurfaceDisposition.RenderTarget); - } - public override void SetInputFormat(string channel, SurfaceState state) - { - if (RenderCallback == null) return; - DeclareOutput(state); - } - - public Action RenderCallback; - - public override void Run() - { - if (RenderCallback == null) return; - RenderCallback(); - } - } -} \ No newline at end of file diff --git a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Retro.cs b/BizHawk.Client.MultiHawk/DisplayManager/Filters/Retro.cs deleted file mode 100644 index 633f697344..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Retro.cs +++ /dev/null @@ -1,285 +0,0 @@ -//https://github.com/Themaister/RetroArch/wiki/GLSL-shaders -//https://github.com/Themaister/Emulator-Shader-Pack/blob/master/Cg/README -//https://github.com/libretro/common-shaders/ - -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Drawing; - -using BizHawk.Common; -using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk; -using BizHawk.Client.MultiHawk.FilterManager; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.Drivers.OpenTK; - -using OpenTK; -using OpenTK.Graphics; - -namespace BizHawk.Client.MultiHawk.Filters -{ - public class RetroShaderChain : IDisposable - { - public RetroShaderChain(IGL owner, RetroShaderPreset preset, string baseDirectory, bool debug = false) - { - Owner = owner; - this.Preset = preset; - Passes = preset.Passes.ToArray(); - - bool ok = true; - - //load up the shaders - Shaders = new RetroShader[preset.Passes.Count]; - for (int i = 0; i < preset.Passes.Count; i++) - { - RetroShaderPreset.ShaderPass pass = preset.Passes[i]; - - //acquire content - string path = Path.Combine(baseDirectory, pass.ShaderPath); - if (!File.Exists(path)) - { - ok = false; - break; - } - string content = File.ReadAllText(path); - - var shader = new RetroShader(Owner, content, debug); - Shaders[i] = shader; - if (!shader.Pipeline.Available) - ok = false; - } - - Available = ok; - } - - public void Dispose() - { - //todo - } - - /// - /// Whether this shader chain is available (it wont be available if some resources failed to load or compile) - /// - public bool Available { get; private set; } - - public readonly IGL Owner; - public readonly RetroShaderPreset Preset; - public readonly RetroShader[] Shaders; - public readonly RetroShaderPreset.ShaderPass[] Passes; - } - - public class RetroShaderPreset - { - /// - /// Parses an instance from a stream to a CGP file - /// - public RetroShaderPreset(Stream stream) - { - var content = new StreamReader(stream).ReadToEnd(); - Dictionary dict = new Dictionary(); - - //parse the key-value-pair format of the file - content = content.Replace("\r", ""); - foreach (var _line in content.Split('\n')) - { - var line = _line.Trim(); - if (line.StartsWith("#")) continue; //lines that are solely comments - if (line == "") continue; //empty line - int eq = line.IndexOf('='); - var key = line.Substring(0, eq).Trim(); - var value = line.Substring(eq + 1).Trim(); - int quote = value.IndexOf('\"'); - if (quote != -1) - value = value.Substring(quote + 1, value.IndexOf('\"', quote + 1) - (quote + 1)); - else - { - //remove comments from end of value. exclusive from above condition, since comments after quoted strings would be snipped by the quoted string extraction - int hash = value.IndexOf('#'); - if (hash != -1) - value = value.Substring(0, hash); - value = value.Trim(); - } - dict[key.ToLower()] = value; - } - - //process the keys - int nShaders = FetchInt(dict, "shaders", 0); - for (int i = 0; i < nShaders; i++) - { - ShaderPass sp = new ShaderPass(); - sp.Index = i; - Passes.Add(sp); - - sp.InputFilterLinear = FetchBool(dict, "filter_linear" + i, false); //Should this value not be defined, the filtering option is implementation defined. - sp.OuputFloat = FetchBool(dict, "float_framebuffer" + i, false); - sp.FrameCountMod = FetchInt(dict, "frame_count_mod" + i, 1); - sp.ShaderPath = FetchString(dict, "shader" + i, "?"); //todo - change extension to .cg for better compatibility? just change .cg to .glsl transparently at last second? - - //If no scale type is assumed, it is assumed that it is set to "source" with scaleN set to 1.0. - //It is possible to set scale_type_xN and scale_type_yN to specialize the scaling type in either direction. scale_typeN however overrides both of these. - sp.ScaleTypeX = (ScaleType)Enum.Parse(typeof(ScaleType), FetchString(dict, "scale_type_x" + i, "Source"), true); - sp.ScaleTypeY = (ScaleType)Enum.Parse(typeof(ScaleType), FetchString(dict, "scale_type_y" + i, "Source"), true); - ScaleType st = (ScaleType)Enum.Parse(typeof(ScaleType), FetchString(dict, "scale_type" + i, "NotSet"), true); - if (st != ScaleType.NotSet) - sp.ScaleTypeX = sp.ScaleTypeY = st; - - //scaleN controls both scaling type in horizontal and vertical directions. If scaleN is defined, scale_xN and scale_yN have no effect. - sp.Scale.X = FetchFloat(dict, "scale_x" + i, 1); - sp.Scale.Y = FetchFloat(dict, "scale_y" + i, 1); - float scale = FetchFloat(dict, "scale" + i, -999); - if (scale != -999) - sp.Scale.X = sp.Scale.Y = FetchFloat(dict, "scale" + i, 1); - - //TODO - LUTs - } - } - - public List Passes = new List(); - - public enum ScaleType - { - NotSet, Source, Viewport, Absolute - } - - public class ShaderPass - { - public int Index; - public string ShaderPath; - public bool InputFilterLinear; - public bool OuputFloat; - public int FrameCountMod; - public ScaleType ScaleTypeX; - public ScaleType ScaleTypeY; - public Vector2 Scale; - } - - string FetchString(Dictionary dict, string key, string @default) - { - string str; - if (dict.TryGetValue(key, out str)) - return str; - else return @default; - } - - int FetchInt(Dictionary dict, string key, int @default) - { - string str; - if (dict.TryGetValue(key, out str)) - return int.Parse(str); - else return @default; - } - - float FetchFloat(Dictionary dict, string key, float @default) - { - string str; - if (dict.TryGetValue(key, out str)) - return float.Parse(str); - else return @default; - } - - bool FetchBool(Dictionary dict, string key, bool @default) - { - string str; - if (dict.TryGetValue(key, out str)) - return ParseBool(str); - else return @default; - } - - - bool ParseBool(string value) - { - if (value == "1") return true; - if (value == "0") return false; - value = value.ToLower(); - if (value == "true") return true; - if (value == "false") return false; - throw new InvalidOperationException("Unparseable bool in CGP file content"); - } - } - - public class RetroShaderPass : BaseFilter - { - RetroShaderChain RSC; - RetroShaderPreset.ShaderPass SP; - int RSI; - Size OutputSize; - - public override string ToString() - { - return string.Format("RetroShaderPass[#{0}]", RSI); - } - - public RetroShaderPass(RetroShaderChain RSC, int index) - { - this.RSC = RSC; - this.RSI = index; - this.SP = RSC.Passes[index]; - } - - public override void Initialize() - { - DeclareInput(SurfaceDisposition.Texture); - } - - public override void SetInputFormat(string channel, SurfaceState state) - { - Size insize = state.SurfaceFormat.Size; - if (SP.ScaleTypeX == RetroShaderPreset.ScaleType.Absolute) OutputSize.Width = (int)SP.Scale.X; - if (SP.ScaleTypeY == RetroShaderPreset.ScaleType.Absolute) OutputSize.Width = (int)SP.Scale.Y; - if (SP.ScaleTypeX == RetroShaderPreset.ScaleType.Source) OutputSize.Width = (int)(insize.Width * SP.Scale.X); - if (SP.ScaleTypeY == RetroShaderPreset.ScaleType.Source) OutputSize.Height = (int)(insize.Height * SP.Scale.Y); - - var outState = new SurfaceState(); - outState.SurfaceFormat = new SurfaceFormat(OutputSize); - outState.SurfaceDisposition = SurfaceDisposition.RenderTarget; - DeclareOutput(outState); - } - - public override Size PresizeOutput(string channel, Size size) - { - OutputSize = size; - return size; - } - - public override Size PresizeInput(string channel, Size insize) - { - Size outsize = insize; - if (SP.ScaleTypeX == RetroShaderPreset.ScaleType.Absolute) outsize.Width = (int)SP.Scale.X; - if (SP.ScaleTypeY == RetroShaderPreset.ScaleType.Absolute) outsize.Width = (int)SP.Scale.Y; - if (SP.ScaleTypeX == RetroShaderPreset.ScaleType.Source) outsize.Width = (int)(insize.Width * SP.Scale.X); - if (SP.ScaleTypeY == RetroShaderPreset.ScaleType.Source) outsize.Height = (int)(insize.Height * SP.Scale.Y); - return outsize; - } - - public override void Run() - { - var shader = RSC.Shaders[RSI]; - - shader.Bind(); - - //apply all parameters to this shader.. even if it was meant for other shaders. kind of lame. - if(Parameters != null) - foreach (var kvp in Parameters) - { - if (kvp.Value is float) - shader.Pipeline[kvp.Key].Set((float)kvp.Value); - } - - var input = InputTexture; - if (SP.InputFilterLinear) - InputTexture.SetFilterLinear(); - else - InputTexture.SetFilterNearest(); - RSC.Shaders[RSI].Run(input, input.Size, OutputSize, InputTexture.IsUpsideDown); - - //maintain invariant.. i think. - InputTexture.SetFilterNearest(); - } - } - - -} diff --git a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Utils.cs b/BizHawk.Client.MultiHawk/DisplayManager/Filters/Utils.cs deleted file mode 100644 index f3c7696034..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/Filters/Utils.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Drawing; - -using BizHawk.Common; -using BizHawk.Client.Common; -using BizHawk.Client.MultiHawk; -using BizHawk.Client.MultiHawk.FilterManager; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.Drivers.OpenTK; - -using OpenTK; -using OpenTK.Graphics; - -namespace BizHawk.Client.MultiHawk.Filters -{ - public class SourceImage : BaseFilter - { - public SourceImage(Size size) - { - this.Size = size; - } - - Size Size; - - public Texture2d Texture; - - public override void Run() - { - YieldOutput(Texture); - } - - public override void Initialize() - { - DeclareOutput(new SurfaceState(new SurfaceFormat(Size), SurfaceDisposition.Texture)); - } - - public override void SetInputFormat(string channel, SurfaceState format) - { - DeclareOutput(SurfaceDisposition.Texture); - } - } - - /// - /// transforms an input texture to an output render target (by rendering it) - /// - class Render : BaseFilter - { - public override void Initialize() - { - DeclareInput(SurfaceDisposition.Texture); - } - - public override void SetInputFormat(string channel, SurfaceState state) - { - DeclareOutput(new SurfaceState(state.SurfaceFormat, SurfaceDisposition.RenderTarget)); - } - - public override void Run() - { - var renderer = FilterProgram.GuiRenderer; - renderer.Begin(FindOutput().SurfaceFormat.Size); - renderer.SetBlendState(FilterProgram.GL.BlendNoneCopy); - renderer.Draw(InputTexture); - renderer.End(); - } - } - - class Resolve : BaseFilter - { - public override void Initialize() - { - DeclareInput(SurfaceDisposition.RenderTarget); - } - - public override void SetInputFormat(string channel, SurfaceState state) - { - DeclareOutput(new SurfaceState(state.SurfaceFormat, SurfaceDisposition.Texture)); - } - - public override void Run() - { - YieldOutput(FilterProgram.GetRenderTarget().Texture2d); - } - } -} \ No newline at end of file diff --git a/BizHawk.Client.MultiHawk/DisplayManager/TextureFrugalizer.cs b/BizHawk.Client.MultiHawk/DisplayManager/TextureFrugalizer.cs deleted file mode 100644 index a43b1d282b..0000000000 --- a/BizHawk.Client.MultiHawk/DisplayManager/TextureFrugalizer.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; - -using BizHawk.Common; -using BizHawk.Emulation.Common; -using BizHawk.Client.Common; - -using BizHawk.Bizware.BizwareGL; - -namespace BizHawk.Client.MultiHawk -{ - /// - /// Recycles a pair of temporary textures (in case double-buffering helps any) to contain a BitmapBuffer's or DisplaySurface's contents, as long as the dimensions match. - /// When the dimensions dont match, a new one will be allocated - /// - class TextureFrugalizer : IDisposable - { - public TextureFrugalizer(IGL gl) - { - GL = gl; - ResetList(); - } - - public void Dispose() - { - foreach (var ct in CurrentTextures) - if(ct != null) - ct.Dispose(); - ResetList(); - } - - void ResetList() - { - CurrentTextures = new List(); - CurrentTextures.Add(null); - CurrentTextures.Add(null); - } - - IGL GL; - List CurrentTextures; - - public Texture2d Get(DisplaySurface ds) - { - using (var bb = new BitmapBuffer(ds.PeekBitmap(), new BitmapLoadOptions())) - { - return Get(bb); - } - } - public Texture2d Get(BitmapBuffer bb) - { - //get the current entry - Texture2d CurrentTexture = CurrentTextures[0]; - - //TODO - its a bit cruddy here that we dont respect the current texture HasAlpha condition (in fact, theres no such concept) - //we might need to deal with that in the future to fix some bugs. - - //check if its rotten and needs recreating - if (CurrentTexture == null || CurrentTexture.IntWidth != bb.Width || CurrentTexture.IntHeight != bb.Height) - { - //needs recreating. be sure to kill the old one... - if (CurrentTexture != null) - CurrentTexture.Dispose(); - //and make a new one - CurrentTexture = GL.LoadTexture(bb); - } - else - { - //its good! just load in the data - GL.LoadTextureData(CurrentTexture, bb); - } - - //now shuffle the buffers - CurrentTextures[0] = CurrentTextures[1]; - CurrentTextures[1] = CurrentTexture; - - //deterministic state, i guess - CurrentTexture.SetFilterNearest(); - - return CurrentTexture; - } - } -} \ No newline at end of file