display manager: sort out all the y-flipping madness and fix some bugs in gdi+ with screenshot and prescaling
This commit is contained in:
parent
d9b765ac89
commit
f0c34517e1
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue