diff --git a/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs b/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs index 959b947a71..128b58cdfa 100644 --- a/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs +++ b/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs @@ -495,6 +495,7 @@ TESTEROO: { //wrap the videoprovider data in a BitmapBuffer (no point to refactoring that many IVideoProviders) bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer); + bb.DiscardAlpha(); //now, acquire the data sent from the videoProvider into a texture videoTexture = VideoTextureFrugalizer.Get(bb); diff --git a/BizHawk.Client.EmuHawk/DisplayManager/Filters/Gui.cs b/BizHawk.Client.EmuHawk/DisplayManager/Filters/Gui.cs index ae1529b7ad..bc0887770b 100644 --- a/BizHawk.Client.EmuHawk/DisplayManager/Filters/Gui.cs +++ b/BizHawk.Client.EmuHawk/DisplayManager/Filters/Gui.cs @@ -260,7 +260,7 @@ namespace BizHawk.Client.EmuHawk.Filters GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit); GuiRenderer.Begin(OutputSize.Width, OutputSize.Height); - GuiRenderer.SetBlendState(GL.BlendNone); + GuiRenderer.SetBlendState(GL.BlendNoneCopy); if(FilterOption != eFilterOption.None) InputTexture.SetFilterLinear(); diff --git a/BizHawk.Client.EmuHawk/DisplayManager/Filters/Utils.cs b/BizHawk.Client.EmuHawk/DisplayManager/Filters/Utils.cs index 3d3338c854..0eabf4c64b 100644 --- a/BizHawk.Client.EmuHawk/DisplayManager/Filters/Utils.cs +++ b/BizHawk.Client.EmuHawk/DisplayManager/Filters/Utils.cs @@ -64,7 +64,7 @@ namespace BizHawk.Client.EmuHawk.Filters { var renderer = FilterProgram.GuiRenderer; renderer.Begin(FindOutput().SurfaceFormat.Size); - renderer.SetBlendState(FilterProgram.GL.BlendNone); + renderer.SetBlendState(FilterProgram.GL.BlendNoneCopy); renderer.Draw(InputTexture); renderer.End(); } diff --git a/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs b/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs index 4ae19f2966..d0b7cb5be4 100644 --- a/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs +++ b/BizHawk.Client.EmuHawk/DisplayManager/TextureFrugalizer.cs @@ -51,6 +51,9 @@ namespace BizHawk.Client.EmuHawk //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) { diff --git a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GLControlWrapper_GdiPlus.cs b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GLControlWrapper_GdiPlus.cs index 7fc865a1f7..409300f646 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GLControlWrapper_GdiPlus.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GLControlWrapper_GdiPlus.cs @@ -73,9 +73,15 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus return; using (var g = CreateGraphics()) + { + //not sure we had proof we needed this but it cant hurt + g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; RenderTargetWrapper.MyBufferedGraphics.Render(g); + } //not too sure about this.. i think we have to re-allocate it so we can support a changed window size. did we do this at the right time anyway? + //maybe I should try caching harder, I hate to reallocate these constantly RenderTargetWrapper.CreateGraphics(); } } diff --git a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GdiPlusGuiRenderer.cs b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GdiPlusGuiRenderer.cs index 28ce2ef7ba..ad1e8b6299 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GdiPlusGuiRenderer.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/GdiPlusGuiRenderer.cs @@ -89,9 +89,10 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus sd.Color CurrentModulateColor = sd.Color.White; + IBlendState CurrentBlendState; public void SetBlendState(IBlendState rsBlend) { - + CurrentBlendState = rsBlend; } MatrixStack _Projection, _Modelview; @@ -121,6 +122,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus { Begin(); + CurrentBlendState = Gdi.BlendNormal; + Projection = Owner.CreateGuiProjectionMatrix(width, height); Modelview = Owner.CreateGuiViewMatrix(width, height); } @@ -172,6 +175,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus new sd.PointF(x+w,y), new sd.PointF(x,y+h), }; + g.DrawImage(tw.SDBitmap, destPoints, new sd.RectangleF(x0, y0, x1 - x0, y1 - y0), sd.GraphicsUnit.Pixel, CurrentImageAttributes); //g.DrawImage(tw.SDBitmap, 0, 0); //test } @@ -199,18 +203,50 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; if (tw.MagFilter == TextureMagFilter.Nearest) g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + + + //--------- + + if (CurrentBlendState == Gdi.BlendNormal) + { + g.CompositingMode = sd.Drawing2D.CompositingMode.SourceOver; + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default; //? + + //CurrentImageAttributes.ClearColorMatrix(ColorAdjustType.Bitmap); + } + else + //if(CurrentBlendState == Gdi.BlendNoneCopy) + //if(CurrentBlendState == Gdi.BlendNoneOpaque) + { + g.CompositingMode = sd.Drawing2D.CompositingMode.SourceCopy; + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; + + //WARNING : DO NOT USE COLOR MATRIX TO WIPE THE ALPHA + //ITS SOOOOOOOOOOOOOOOOOOOOOOOOOOOO SLOW + //instead, we added kind of hacky support for 24bpp images + } + } unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h) { var tw = Gdi.TextureWrapperForTexture(tex); var g = Gdi.GetCurrentGraphics(); - PrepDraw(g,tw); + PrepDraw(g, tw); + //a little bit of a fastpath.. I think it's safe - if (w == tex.Width && h == tex.Height && x == (int)x && y == (int)y) - g.DrawImageUnscaled(tw.SDBitmap, (int)x, (int)y); - else - g.DrawImage(tw.SDBitmap, x, y, w, h); + //if (w == tex.Width && h == tex.Height && x == (int)x && y == (int)y) + // g.DrawImageUnscaled(tw.SDBitmap, (int)x, (int)y); + //else + { + sd.PointF[] destPoints = new sd.PointF[] { + new sd.PointF(x,y), + new sd.PointF(x+w,y), + new sd.PointF(x,y+h), + }; + //g.DrawImage(tw.SDBitmap, x, y, w, h); //original + g.DrawImage(tw.SDBitmap, destPoints, new sd.RectangleF(0, 0, tex.Width, tex.Height), sd.GraphicsUnit.Pixel, CurrentImageAttributes); + } } unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy) diff --git a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/IGL_GdiPlus.cs b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/IGL_GdiPlus.cs index dea33570f3..441d88b918 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/IGL_GdiPlus.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.GdiPlus/IGL_GdiPlus.cs @@ -130,9 +130,10 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus } class MyBlendState : IBlendState { } - static MyBlendState _rsBlendNone = new MyBlendState(), _rsBlendNormal = new MyBlendState(); + static MyBlendState _rsBlendNoneVerbatim = new MyBlendState(), _rsBlendNoneOpaque = new MyBlendState(), _rsBlendNormal = new MyBlendState(); - public IBlendState BlendNone { get { return _rsBlendNone; } } + public IBlendState BlendNoneCopy { get { return _rsBlendNoneVerbatim; } } + public IBlendState BlendNoneOpaque { get { return _rsBlendNoneOpaque; } } public IBlendState BlendNormal { get { return _rsBlendNormal; } } public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required) diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs index 89b07af065..b82390bf07 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs @@ -145,9 +145,15 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK GL.BlendFuncSeparate(mybs.colorSource, mybs.colorDest, mybs.alphaSource, mybs.alphaDest); } else GL.Disable(EnableCap.Blend); + if (rsBlend == _rsBlendNoneOpaque) + { + //make sure constant color is set correctly + GL.BlendColor(new Color4(255, 255, 255, 255)); + } } - public IBlendState BlendNone { get { return _rsBlendNone; } } + public IBlendState BlendNoneCopy { get { return _rsBlendNoneVerbatim; } } + public IBlendState BlendNoneOpaque { get { return _rsBlendNoneOpaque; } } public IBlendState BlendNormal { get { return _rsBlendNormal; } } public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required) @@ -641,13 +647,23 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK void CreateRenderStates() { - _rsBlendNone = new MyBlendState(false, BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero, BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero); - _rsBlendNormal = new MyBlendState(true, + _rsBlendNoneVerbatim = new MyBlendState( + false, + BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero, + BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero); + + _rsBlendNoneOpaque = new MyBlendState( + false, + BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero, + BlendingFactorSrc.ConstantAlpha, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero); + + _rsBlendNormal = new MyBlendState( + true, BlendingFactorSrc.SrcAlpha, BlendEquationMode.FuncAdd, BlendingFactorDest.OneMinusSrcAlpha, BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero); } - MyBlendState _rsBlendNone, _rsBlendNormal; + MyBlendState _rsBlendNoneVerbatim, _rsBlendNoneOpaque, _rsBlendNormal; //state caches int sActiveTexture; diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/RetroShader.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/RetroShader.cs index 5dc1275a8a..5b5f2221cc 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/RetroShader.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/RetroShader.cs @@ -82,7 +82,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk pData[i++] = 1; pData[i++] = v1; //texcoord - Owner.SetBlendState(Owner.BlendNone); + Owner.SetBlendState(Owner.BlendNoneCopy); Owner.BindArrayData(pData); Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); } diff --git a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs index 53a2f71f3d..d175d709d1 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs @@ -153,9 +153,10 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX } class MyBlendState : IBlendState { } - static MyBlendState _rsBlendNone = new MyBlendState(), _rsBlendNormal = new MyBlendState(); + static MyBlendState _rsBlendNoneOpaque = new MyBlendState(), _rsBlendNoneVerbatim = new MyBlendState(), _rsBlendNormal = new MyBlendState(); - public IBlendState BlendNone { get { return _rsBlendNone; } } + public IBlendState BlendNoneCopy { get { return _rsBlendNoneVerbatim; } } + public IBlendState BlendNoneOpaque { get { return _rsBlendNoneOpaque; } } public IBlendState BlendNormal { get { return _rsBlendNormal; } } public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required) diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs index 759ee6efd3..7a7723501c 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs @@ -29,6 +29,11 @@ namespace BizHawk.Bizware.BizwareGL public int Width, Height; public int[] Pixels; + /// + /// Whether this instance should be considered as having alpha (ARGB) or not (XRBG) + /// + public bool HasAlpha = true; + public Size Size { get { return new Size(Width, Height); } } sd.Bitmap WrappedBitmap; @@ -241,6 +246,14 @@ namespace BizHawk.Bizware.BizwareGL this.Height = height; } + /// + /// Suggests that this BitmapBuffer is now XRGB instead of ARGB but doesn't actually change any of the pixels data. + /// Should affect how things get exported from here, though, I think + /// + public void DiscardAlpha() + { + HasAlpha = false; + } void LoadInternal(Stream stream, sd.Bitmap bitmap, BitmapLoadOptions options) { @@ -464,16 +477,21 @@ namespace BizHawk.Bizware.BizwareGL /// public unsafe Bitmap ToSysdrawingBitmap() { - Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); + var pf = PixelFormat.Format32bppArgb; + if (!HasAlpha) + pf = PixelFormat.Format24bppRgb; + Bitmap bmp = new Bitmap(Width, Height, pf); ToSysdrawingBitmap(bmp); return bmp; } /// - /// Dumps this BitmapBuffer to an existing System.Drawing.Bitmap + /// Dumps this BitmapBuffer to an existing System.Drawing.Bitmap. + /// Some features of this may not be super fast (in particular, 32bpp to 24bpp conversion; we might fix that later with a customized loop) /// public unsafe void ToSysdrawingBitmap(Bitmap bmp) { + //note: we lock it as 32bpp even if the bitmap is 24bpp so we can write to it more conveniently. var bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); if (bmp.Width != 0 && bmp.Height != 0) diff --git a/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs index d9b98fd91d..379645424a 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs @@ -155,7 +155,13 @@ namespace BizHawk.Bizware.BizwareGL /// retrieves a blend state for opaque rendering /// Alpha values are copied from the source fragment. /// - IBlendState BlendNone { get; } + IBlendState BlendNoneCopy { get; } + + /// + /// retrieves a blend state for opaque rendering + /// Alpha values are written as opaque + /// + IBlendState BlendNoneOpaque { get; } /// /// retrieves a blend state for normal (non-premultiplied) alpha blending. diff --git a/Bizware/BizHawk.Bizware.BizwareGL/RetainedGraphicsControl.cs b/Bizware/BizHawk.Bizware.BizwareGL/RetainedGraphicsControl.cs index 795f4983da..a4932493ee 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/RetainedGraphicsControl.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/RetainedGraphicsControl.cs @@ -73,7 +73,7 @@ namespace BizHawk.Bizware.BizwareGL { if (rt == null) return; GuiRenderer.Begin(Width, Height, true); - GuiRenderer.SetBlendState(GL.BlendNone); + GuiRenderer.SetBlendState(GL.BlendNoneCopy); GuiRenderer.Draw(rt.Texture2d); GuiRenderer.End(); base.SwapBuffers();