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)) using (var bb = GlobalWin.DisplayManager.RenderOffscreen(Global.Emulator.VideoProvider(), Global.Config.Screenshot_CaptureOSD))
{ {
bb.Normalize(true); bb.DiscardAlpha();
using (var img = bb.ToSysdrawingBitmap()) using (var img = bb.ToSysdrawingBitmap())
Clipboard.SetImage(img); Clipboard.SetImage(img);
} }

View File

@ -2285,7 +2285,7 @@ namespace BizHawk.Client.EmuHawk
public BitmapBuffer CaptureOSD() public BitmapBuffer CaptureOSD()
{ {
var bb = GlobalWin.DisplayManager.RenderOffscreen(Global.Emulator.VideoProvider(), true); var bb = GlobalWin.DisplayManager.RenderOffscreen(Global.Emulator.VideoProvider(), true);
bb.Normalize(true); bb.DiscardAlpha();
return bb; 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(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(); Begin();
@ -234,15 +234,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
private void SetupMatrix(sd.Graphics g) 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 //projection is always identity, so who cares i guess
//(this is necessary because a 'GuiProjectionMatrix' etc. call doesnt have any sense of the size of the destination viewport it's meant for) //Matrix4 mat = Projection.Top * Modelview.Top;
var vcb = g.VisibleClipBounds; Matrix4 mat = Modelview.Top;
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;
g.Transform = new sd.Drawing2D.Matrix(mat.M11, mat.M12, mat.M21, mat.M22, mat.M41, mat.M42); 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) public unsafe BitmapBuffer ResolveTexture2d(Texture2d tex)
{ {
var tw = tex.Opaque as TextureWrapper; var tw = tex.Opaque as TextureWrapper;
return new BitmapBuffer(tw.SDBitmap, new BitmapLoadOptions() var blow = new BitmapLoadOptions()
{ {
AllowWrap = false //must be an independent resource AllowWrap = false //must be an independent resource
}); };
var bb = new BitmapBuffer(tw.SDBitmap,blow);
return bb;
} }
public Texture2d LoadTexture(string path) public Texture2d LoadTexture(string path)
@ -228,39 +230,24 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
public Matrix4 CreateGuiProjectionMatrix(sd.Size dims) public Matrix4 CreateGuiProjectionMatrix(sd.Size dims)
{ {
Matrix4 ret = Matrix4.Identity; //see CreateGuiViewMatrix for more
return 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;
} }
public Matrix4 CreateGuiViewMatrix(sd.Size dims, bool autoflip) public Matrix4 CreateGuiViewMatrix(sd.Size dims, bool autoflip)
{ {
Matrix4 ret = Matrix4.Identity; //on account of gdi+ working internally with a default view exactly like we want, we don't need to setup a new one here
ret.M22 = -1.0f; //furthermore, we _cant_, without inverting the GuiView and GuiProjection before drawing, to completely undo it
ret.M41 = -(float)dims.Width * 0.5f; //this might be feasible, but its kind of slow and annoying and worse, seemingly numerically unstable
ret.M42 = (float)dims.Height * 0.5f; //if (autoflip && _CurrRenderTarget != null)
if (autoflip) //{
{ // Matrix4 ret = Matrix4.Identity;
if (_CurrRenderTarget == null) { } // ret.M22 = -1;
else // ret.M42 = dims.Height;
{ // return ret;
//flip as long as we're not a final render target //}
ret.M22 = 1.0f; //else
} return Matrix4.Identity;
}
return ret;
} }
public void SetViewport(int x, int y, int width, int height) 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) public void BindRenderTarget(RenderTarget rt)
{ {
if (_CurrentOffscreenGraphics != null)
{
_CurrentOffscreenGraphics.Dispose();
_CurrentOffscreenGraphics = null;
}
_CurrRenderTarget = rt; _CurrRenderTarget = rt;
if (CurrentRenderTargetWrapper != null) if (CurrentRenderTargetWrapper != null)
{ {
@ -401,7 +394,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
//dont do anything til swapbuffers //dont do anything til swapbuffers
} }
else else
CurrentRenderTargetWrapper.MyBufferedGraphics.Render(); {
//CurrentRenderTargetWrapper.MyBufferedGraphics.Render();
}
} }
if (rt == null) if (rt == null)
@ -411,14 +406,20 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
} }
else else
{ {
var tw = rt.Texture2d.Opaque as TextureWrapper;
CurrentRenderTargetWrapper = rt.Opaque as RenderTargetWrapper; CurrentRenderTargetWrapper = rt.Opaque as RenderTargetWrapper;
if (CurrentRenderTargetWrapper.MyBufferedGraphics == null) _CurrentOffscreenGraphics = Graphics.FromImage(tw.SDBitmap);
CurrentRenderTargetWrapper.CreateGraphics(); //if (CurrentRenderTargetWrapper.MyBufferedGraphics == null)
// CurrentRenderTargetWrapper.CreateGraphics();
} }
} }
Graphics _CurrentOffscreenGraphics;
public Graphics GetCurrentGraphics() public Graphics GetCurrentGraphics()
{ {
if (_CurrentOffscreenGraphics != null)
return _CurrentOffscreenGraphics;
var rtw = CurrentRenderTargetWrapper; var rtw = CurrentRenderTargetWrapper;
return rtw.MyBufferedGraphics.Graphics; 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); var bb = new BitmapBuffer(tex.IntWidth, tex.IntHeight, pixels);
target.UnlockRectangle(0); target.UnlockRectangle(0);
target.Dispose(); //buffer churn warning target.Dispose(); //buffer churn warning
//TEMPORARY until flipping is sorted out
bb.YFlip();
return bb; return bb;
} }

View File

@ -105,6 +105,9 @@ namespace BizHawk.Bizware.BizwareGL
Pixels = newPixels; Pixels = newPixels;
} }
/// <summary>
/// Makes sure the alpha channel is clean and optionally y-flips
/// </summary>
public unsafe void Normalize(bool yflip) public unsafe void Normalize(bool yflip)
{ {
var bmpdata = LockBits(); var bmpdata = LockBits();
@ -114,6 +117,7 @@ namespace BizHawk.Bizware.BizwareGL
fixed (int* d = newPixels) fixed (int* d = newPixels)
{ {
if (yflip) if (yflip)
{
for (int y = 0, si = 0, di = (Height - 1) * Width; y < Height; y++) for (int y = 0, si = 0, di = (Height - 1) * Width; y < Height; y++)
{ {
for (int x = 0; x < Width; x++, si++, di++) for (int x = 0; x < Width; x++, si++, di++)
@ -122,9 +126,16 @@ namespace BizHawk.Bizware.BizwareGL
} }
di -= Width * 2; di -= Width * 2;
} }
}
else 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(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(); Begin();
Projection = Owner.CreateGuiProjectionMatrix(width, height); Projection = Owner.CreateGuiProjectionMatrix(width, height);
Modelview = Owner.CreateGuiViewMatrix(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); Owner.SetViewport(width, height);
} }

View File

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

View File

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