display manager speedup-dont use any gdi+ unless absolutely necessary (d3d renderer less sensitive to window size)

This commit is contained in:
zeromus 2012-06-10 19:52:54 +00:00
parent 7d23581764
commit 2b5fd9e8d9
2 changed files with 120 additions and 110 deletions

View File

@ -109,47 +109,92 @@ namespace BizHawk.MultiClient
{ {
} }
public class DisplaySurface : IDisposable 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;
}
/// <summary> /// <summary>
/// returns a Graphics object used to render to this surface. be sure to dispose it! /// returns a Graphics object used to render to this surface. be sure to dispose it!
/// </summary> /// </summary>
public Graphics GetGraphics() public Graphics GetGraphics()
{ {
Unlock(); ToBitmap();
return Graphics.FromImage(bmp); return Graphics.FromImage(bmp);
} }
Bitmap bmp;
BitmapData bmpdata;
//TODO - lock and cache these public unsafe void ToBitmap(bool copy=true)
public unsafe int* PixelPtr { get { return (int*)bmpdata.Scan0.ToPointer(); } }
public IntPtr PixelIntPtr { get { return bmpdata.Scan0; } }
public int Stride { get { return bmpdata.Stride; } }
public int OffsetOf(int x, int y) { return y * Stride + x*4; }
public unsafe void Clear()
{ {
Lock(); if (isBitmap) return;
Util.memset32(PixelPtr, 0, Stride * Height); 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);
}
} }
/// <summary> public bool IsBitmap { get { return isBitmap; } }
/// returns a bitmap which you can use but not hold onto. bool isBitmap = false;
/// we may remove this later, as managing a Bitmap just for this may be a drag. (probably not though)
/// </summary> public unsafe void FromBitmap(bool copy=true)
public Bitmap PeekBitmap()
{ {
Unlock(); if (!isBitmap) return;
return bmp; 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) public static DisplaySurface DisplaySurfaceWrappingBitmap(Bitmap bmp)
{ {
DisplaySurface ret = new DisplaySurface(); DisplaySurface ret = new DisplaySurface();
ret.Width = bmp.Width; ret.Width = bmp.Width;
ret.Height = bmp.Height; ret.Height = bmp.Height;
ret.bmp = bmp; ret.bmp = bmp;
ret.isBitmap = true;
return ret; return ret;
} }
@ -166,8 +211,27 @@ namespace BizHawk.MultiClient
Width = width; Width = width;
Height = height; Height = height;
bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); pixels = new int[width * height];
Lock(); 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();
} }
/// <summary> /// <summary>
@ -176,23 +240,27 @@ namespace BizHawk.MultiClient
/// <param name="xpad"></param> /// <param name="xpad"></param>
/// <param name="ypad"></param> /// <param name="ypad"></param>
/// <returns></returns> /// <returns></returns>
public unsafe DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1) public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1)
{ {
Lock(); //Lock();
int new_width = Width + xpad0 + xpad1; //int new_width = Width + xpad0 + xpad1;
int new_height = Height + ypad0 + ypad1; //int new_height = Height + ypad0 + ypad1;
DisplaySurface ret = new DisplaySurface(new_width, new_height); //DisplaySurface ret = new DisplaySurface(new_width, new_height);
ret.Lock(); //ret.Lock();
int* dptr = ret.PixelPtr; //int* dptr = ret.PixelPtr;
int* sptr = PixelPtr; //int* sptr = PixelPtr;
int dstride = ret.Stride/4; //int dstride = ret.Stride/4;
int sstride = Stride/4; //int sstride = Stride/4;
for (int y = 0; y < Height; y++) //for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++) // for (int x = 0; x < Width; x++)
{ // {
dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x]; // dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x];
} // }
return ret; //return ret;
//need to reimplement this
throw new NotSupportedException();
return null;
} }
public int Width { get; private set; } public int Width { get; private set; }
@ -203,77 +271,17 @@ namespace BizHawk.MultiClient
if (bmp != null) if (bmp != null)
bmp.Dispose(); bmp.Dispose();
bmp = null; bmp = null;
UnlockPixels();
} }
/// <summary> //public unsafe int[] ToIntArray() { }
/// copies out the buffer as an int array (hopefully you can do this with a pointer instead and save some time!)
/// </summary> public void AcceptIntArray(int[] newpixels)
public unsafe int[] ToIntArray()
{ {
Lock(); FromBitmap(false);
UnlockPixels();
int w = bmp.Width; pixels = newpixels;
int h = bmp.Height; LockPixels();
var ret = new int[bmp.Width * bmp.Height];
int* pData = (int*)bmpdata.Scan0.ToPointer();
int stride = bmpdata.Stride / 4;
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
ret[i++] = pData[y * stride + x];
return ret;
}
public unsafe void SetFromIntArray(int[] pixels)
{
Lock();
if (Stride == Width * 4)
{
Marshal.Copy(pixels, 0, PixelIntPtr, Width * Height);
return;
}
int w = Width;
int h = Height;
int* pData = PixelPtr;
int stride = Stride / 4;
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
pData[y * stride + x] = pixels[i++];
}
/// <summary>
/// locks this surface so that it can be accessed by raw pointer
/// </summary>
public void Lock()
{
if (bmpdata != null) return;
var imageLockMode = ImageLockMode.ReadWrite;
bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), imageLockMode, PixelFormat.Format32bppArgb);
}
public bool IsLocked { get { return bmpdata != null; } }
public void Unlock()
{
if (bmpdata != null)
bmp.UnlockBits(bmpdata);
bmpdata = null;
}
public static unsafe DisplaySurface FromVideoProvider(IVideoProvider provider)
{
int w = provider.BufferWidth;
int h = provider.BufferHeight;
int[] buffer = provider.GetVideoBuffer();
var ret = new DisplaySurface(w,h);
int* pData = ret.PixelPtr;
int stride = ret.Stride / 4;
for (int y = 0, i=0; y < h; y++)
for (int x = 0; x < w; x++)
pData[y * stride + x] = buffer[i++];
return ret;
} }
} }
@ -588,8 +596,9 @@ namespace BizHawk.MultiClient
SwappableDisplaySurfaceSet sourceSurfaceSet = new SwappableDisplaySurfaceSet(); SwappableDisplaySurfaceSet sourceSurfaceSet = new SwappableDisplaySurfaceSet();
public void UpdateSource(IVideoProvider videoProvider) public void UpdateSource(IVideoProvider videoProvider)
{ {
//needsclear = false because we're about to clobber the data with AcceptIntArray
var newPendingSurface = sourceSurfaceSet.AllocateSurface(videoProvider.BufferWidth, videoProvider.BufferHeight, false); var newPendingSurface = sourceSurfaceSet.AllocateSurface(videoProvider.BufferWidth, videoProvider.BufferHeight, false);
newPendingSurface.SetFromIntArray(videoProvider.GetVideoBuffer()); newPendingSurface.AcceptIntArray(videoProvider.GetVideoBuffer());
sourceSurfaceSet.SetPending(newPendingSurface); sourceSurfaceSet.SetPending(newPendingSurface);
wakeupEvent.Set(); wakeupEvent.Set();
} }
@ -731,6 +740,7 @@ namespace BizHawk.MultiClient
Global.OSD.DrawScreenInfo(g); Global.OSD.DrawScreenInfo(g);
Global.OSD.DrawMessages(g); Global.OSD.DrawMessages(g);
} }
nativeBmp.FromBitmap();
Global.RenderPanel.RenderOverlay(nativeBmp); Global.RenderPanel.RenderOverlay(nativeBmp);
//release the native resolution image //release the native resolution image
nativeDisplaySurfaceSet.ReleaseSurface(nativeBmp); nativeDisplaySurfaceSet.ReleaseSurface(nativeBmp);

View File

@ -78,7 +78,6 @@ namespace BizHawk.MultiClient
} }
// Copy the image data to the texture. // Copy the image data to the texture.
surface.Lock();
using (var Data = Texture.LockRectangle(0, new Rectangle(0, 0, imageWidth, imageHeight), LockFlags.None).Data) using (var Data = Texture.LockRectangle(0, new Rectangle(0, 0, imageWidth, imageHeight), LockFlags.None).Data)
{ {
if (imageWidth == textureWidth) if (imageWidth == textureWidth)
@ -295,7 +294,7 @@ namespace BizHawk.MultiClient
Resized = false; Resized = false;
Device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0); Device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0);
Device.Present(SlimDX.Direct3D9.Present.DoNotWait); Present();
} }
public void FastRenderAndPresent(DisplaySurface surface) public void FastRenderAndPresent(DisplaySurface surface)
@ -378,7 +377,8 @@ namespace BizHawk.MultiClient
public void Present() public void Present()
{ {
Device.Present(SlimDX.Direct3D9.Present.DoNotWait); //Device.Present(SlimDX.Direct3D9.Present.DoNotWait);
Device.Present(SlimDX.Direct3D9.Present.None);
} }