display manager: sort out all the y-flipping madness and fix some bugs in gdi+ with screenshot and prescaling

This commit is contained in:
zeromus 2015-08-30 09:19:49 -05:00
parent d9b765ac89
commit f0c34517e1
9 changed files with 56 additions and 60 deletions

View File

@ -576,7 +576,7 @@ namespace BizHawk.Client.EmuHawk
{
using (var bb = GlobalWin.DisplayManager.RenderOffscreen(Global.Emulator.VideoProvider(), Global.Config.Screenshot_CaptureOSD))
{
bb.Normalize(true);
bb.DiscardAlpha();
using (var img = bb.ToSysdrawingBitmap())
Clipboard.SetImage(img);
}

View File

@ -2285,7 +2285,7 @@ namespace BizHawk.Client.EmuHawk
public BitmapBuffer CaptureOSD()
{
var bb = GlobalWin.DisplayManager.RenderOffscreen(Global.Emulator.VideoProvider(), true);
bb.Normalize(true);
bb.DiscardAlpha();
return bb;
}

View File

@ -118,7 +118,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
public void Begin(int width, int height, bool yflipped = false)
public void Begin(int width, int height)
{
Begin();
@ -234,15 +234,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
private void SetupMatrix(sd.Graphics g)
{
//first we need to make a transform that will change us from the default GDI+ transformation (a top left identity transformation) to an opengl-styled one
//(this is necessary because a 'GuiProjectionMatrix' etc. call doesnt have any sense of the size of the destination viewport it's meant for)
var vcb = g.VisibleClipBounds;
float vw = vcb.Width;
float vh = vcb.Height;
Matrix4 fixmat = Matrix4.CreateTranslation(vw / 2, -vh / 2, 0);
fixmat *= Matrix4.CreateScale(vw / 2, -vh / 2, 1);
Matrix4 mat = Projection.Top * Modelview.Top * fixmat;
//projection is always identity, so who cares i guess
//Matrix4 mat = Projection.Top * Modelview.Top;
Matrix4 mat = Modelview.Top;
g.Transform = new sd.Drawing2D.Matrix(mat.M11, mat.M12, mat.M21, mat.M22, mat.M41, mat.M42);
}

View File

@ -202,10 +202,12 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
public unsafe BitmapBuffer ResolveTexture2d(Texture2d tex)
{
var tw = tex.Opaque as TextureWrapper;
return new BitmapBuffer(tw.SDBitmap, new BitmapLoadOptions()
var blow = new BitmapLoadOptions()
{
AllowWrap = false //must be an independent resource
});
};
var bb = new BitmapBuffer(tw.SDBitmap,blow);
return bb;
}
public Texture2d LoadTexture(string path)
@ -228,39 +230,24 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
public Matrix4 CreateGuiProjectionMatrix(sd.Size dims)
{
Matrix4 ret = Matrix4.Identity;
//must handle 0s here otherwise we generate infinity and that causes problems later with gdi+
//gdi+ is additionally sensitive to otherwise reasonable (say, 0,0,0,0 matrices) so use a 1 here i guess
if (dims.Width == 0)
ret.M11 = 1;
else ret.M11 = 2.0f / (float)dims.Width;
if (dims.Height == 0)
ret.M22 = 1;
else ret.M22 = 2.0f / (float)dims.Height;
return ret;
//see CreateGuiViewMatrix for more
return Matrix4.Identity;
}
public Matrix4 CreateGuiViewMatrix(sd.Size dims, bool autoflip)
{
Matrix4 ret = Matrix4.Identity;
ret.M22 = -1.0f;
ret.M41 = -(float)dims.Width * 0.5f;
ret.M42 = (float)dims.Height * 0.5f;
if (autoflip)
{
if (_CurrRenderTarget == null) { }
else
{
//flip as long as we're not a final render target
ret.M22 = 1.0f;
}
}
return ret;
//on account of gdi+ working internally with a default view exactly like we want, we don't need to setup a new one here
//furthermore, we _cant_, without inverting the GuiView and GuiProjection before drawing, to completely undo it
//this might be feasible, but its kind of slow and annoying and worse, seemingly numerically unstable
//if (autoflip && _CurrRenderTarget != null)
//{
// Matrix4 ret = Matrix4.Identity;
// ret.M22 = -1;
// ret.M42 = dims.Height;
// return ret;
//}
//else
return Matrix4.Identity;
}
public void SetViewport(int x, int y, int width, int height)
@ -393,6 +380,12 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
public void BindRenderTarget(RenderTarget rt)
{
if (_CurrentOffscreenGraphics != null)
{
_CurrentOffscreenGraphics.Dispose();
_CurrentOffscreenGraphics = null;
}
_CurrRenderTarget = rt;
if (CurrentRenderTargetWrapper != null)
{
@ -401,7 +394,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
//dont do anything til swapbuffers
}
else
CurrentRenderTargetWrapper.MyBufferedGraphics.Render();
{
//CurrentRenderTargetWrapper.MyBufferedGraphics.Render();
}
}
if (rt == null)
@ -411,14 +406,20 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
}
else
{
var tw = rt.Texture2d.Opaque as TextureWrapper;
CurrentRenderTargetWrapper = rt.Opaque as RenderTargetWrapper;
if (CurrentRenderTargetWrapper.MyBufferedGraphics == null)
CurrentRenderTargetWrapper.CreateGraphics();
_CurrentOffscreenGraphics = Graphics.FromImage(tw.SDBitmap);
//if (CurrentRenderTargetWrapper.MyBufferedGraphics == null)
// CurrentRenderTargetWrapper.CreateGraphics();
}
}
Graphics _CurrentOffscreenGraphics;
public Graphics GetCurrentGraphics()
{
if (_CurrentOffscreenGraphics != null)
return _CurrentOffscreenGraphics;
var rtw = CurrentRenderTargetWrapper;
return rtw.MyBufferedGraphics.Graphics;
}

View File

@ -672,9 +672,6 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
var bb = new BitmapBuffer(tex.IntWidth, tex.IntHeight, pixels);
target.UnlockRectangle(0);
target.Dispose(); //buffer churn warning
//TEMPORARY until flipping is sorted out
bb.YFlip();
return bb;
}

View File

@ -105,6 +105,9 @@ namespace BizHawk.Bizware.BizwareGL
Pixels = newPixels;
}
/// <summary>
/// Makes sure the alpha channel is clean and optionally y-flips
/// </summary>
public unsafe void Normalize(bool yflip)
{
var bmpdata = LockBits();
@ -114,6 +117,7 @@ namespace BizHawk.Bizware.BizwareGL
fixed (int* d = newPixels)
{
if (yflip)
{
for (int y = 0, si = 0, di = (Height - 1) * Width; y < Height; y++)
{
for (int x = 0; x < Width; x++, si++, di++)
@ -122,9 +126,16 @@ namespace BizHawk.Bizware.BizwareGL
}
di -= Width * 2;
}
}
else
{
//TODO
for (int y = 0, i=0; y < Height; y++)
{
for (int x = 0; x < Width; x++, i++)
{
d[i] = s[i] | unchecked((int)0xFF000000);
}
}
}
}

View File

@ -137,19 +137,13 @@ namespace BizHawk.Bizware.BizwareGL
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
public void Begin(int width, int height, bool yflipped = false)
public void Begin(int width, int height)
{
Begin();
Projection = Owner.CreateGuiProjectionMatrix(width, height);
Modelview = Owner.CreateGuiViewMatrix(width, height);
//if (yflipped)
//{
// //not sure this is the best way to do it. could be done in the view matrix creation
// Modelview.Scale(1, -1);
// Modelview.Translate(0, -height);
//}
Owner.SetViewport(width, height);
}

View File

@ -14,8 +14,7 @@ namespace BizHawk.Bizware.BizwareGL
/// <summary>
/// begin rendering, initializing viewport and projections to the given dimensions
/// </summary>
/// <param name="yflipped">Whether the matrices should be Y-flipped, for use with render targets</param>
void Begin(int width, int height, bool yflipped = false);
void Begin(int width, int height);
/// <summary>
/// draws the specified Art resource

View File

@ -72,7 +72,7 @@ namespace BizHawk.Bizware.BizwareGL
void Draw()
{
if (rt == null) return;
GuiRenderer.Begin(Width, Height, true);
GuiRenderer.Begin(Width, Height);
GuiRenderer.SetBlendState(GL.BlendNoneCopy);
GuiRenderer.Draw(rt.Texture2d);
GuiRenderer.End();