From 2b5fd9e8d9d82a2ffd266cdc5aed68c8aa04c2c7 Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 10 Jun 2012 19:52:54 +0000 Subject: [PATCH] display manager speedup-dont use any gdi+ unless absolutely necessary (d3d renderer less sensitive to window size) --- .../DisplayManager/DisplayManager.cs | 224 +++++++++--------- BizHawk.MultiClient/RenderPanel.cs | 6 +- 2 files changed, 120 insertions(+), 110 deletions(-) diff --git a/BizHawk.MultiClient/DisplayManager/DisplayManager.cs b/BizHawk.MultiClient/DisplayManager/DisplayManager.cs index 8f3a6e3a98..6cfeb02ae0 100644 --- a/BizHawk.MultiClient/DisplayManager/DisplayManager.cs +++ b/BizHawk.MultiClient/DisplayManager/DisplayManager.cs @@ -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; + } + /// /// returns a Graphics object used to render to this surface. be sure to dispose it! /// public Graphics GetGraphics() { - Unlock(); + ToBitmap(); return Graphics.FromImage(bmp); } - Bitmap bmp; - BitmapData bmpdata; - //TODO - lock and cache these - 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() + public unsafe void ToBitmap(bool copy=true) { - Lock(); - Util.memset32(PixelPtr, 0, Stride * Height); + if (isBitmap) return; + 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); + } + } - /// - /// returns a bitmap which you can use but not hold onto. - /// we may remove this later, as managing a Bitmap just for this may be a drag. (probably not though) - /// - public Bitmap PeekBitmap() + public bool IsBitmap { get { return isBitmap; } } + bool isBitmap = false; + + public unsafe void FromBitmap(bool copy=true) { - Unlock(); - return bmp; + if (!isBitmap) return; + 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) { DisplaySurface ret = new DisplaySurface(); ret.Width = bmp.Width; ret.Height = bmp.Height; ret.bmp = bmp; + ret.isBitmap = true; return ret; } @@ -166,8 +211,27 @@ namespace BizHawk.MultiClient Width = width; Height = height; - bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); - Lock(); + pixels = new int[width * height]; + 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(); } /// @@ -176,23 +240,27 @@ namespace BizHawk.MultiClient /// /// /// - public unsafe DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1) + public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1) { - Lock(); - int new_width = Width + xpad0 + xpad1; - int new_height = Height + ypad0 + ypad1; - DisplaySurface ret = new DisplaySurface(new_width, new_height); - ret.Lock(); - int* dptr = ret.PixelPtr; - int* sptr = PixelPtr; - int dstride = ret.Stride/4; - int sstride = Stride/4; - for (int y = 0; y < Height; y++) - for (int x = 0; x < Width; x++) - { - dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x]; - } - return ret; + //Lock(); + //int new_width = Width + xpad0 + xpad1; + //int new_height = Height + ypad0 + ypad1; + //DisplaySurface ret = new DisplaySurface(new_width, new_height); + //ret.Lock(); + //int* dptr = ret.PixelPtr; + //int* sptr = PixelPtr; + //int dstride = ret.Stride/4; + //int sstride = Stride/4; + //for (int y = 0; y < Height; y++) + // for (int x = 0; x < Width; x++) + // { + // dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x]; + // } + //return ret; + + //need to reimplement this + throw new NotSupportedException(); + return null; } public int Width { get; private set; } @@ -203,77 +271,17 @@ namespace BizHawk.MultiClient if (bmp != null) bmp.Dispose(); bmp = null; + UnlockPixels(); } - /// - /// copies out the buffer as an int array (hopefully you can do this with a pointer instead and save some time!) - /// - public unsafe int[] ToIntArray() + //public unsafe int[] ToIntArray() { } + + public void AcceptIntArray(int[] newpixels) { - Lock(); - - int w = bmp.Width; - int h = bmp.Height; - 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++]; - } - - /// - /// locks this surface so that it can be accessed by raw pointer - /// - 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; + FromBitmap(false); + UnlockPixels(); + pixels = newpixels; + LockPixels(); } } @@ -588,8 +596,9 @@ namespace BizHawk.MultiClient SwappableDisplaySurfaceSet sourceSurfaceSet = new SwappableDisplaySurfaceSet(); 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); - newPendingSurface.SetFromIntArray(videoProvider.GetVideoBuffer()); + newPendingSurface.AcceptIntArray(videoProvider.GetVideoBuffer()); sourceSurfaceSet.SetPending(newPendingSurface); wakeupEvent.Set(); } @@ -731,6 +740,7 @@ namespace BizHawk.MultiClient Global.OSD.DrawScreenInfo(g); Global.OSD.DrawMessages(g); } + nativeBmp.FromBitmap(); Global.RenderPanel.RenderOverlay(nativeBmp); //release the native resolution image nativeDisplaySurfaceSet.ReleaseSurface(nativeBmp); diff --git a/BizHawk.MultiClient/RenderPanel.cs b/BizHawk.MultiClient/RenderPanel.cs index 82460584a9..f14aa145a7 100644 --- a/BizHawk.MultiClient/RenderPanel.cs +++ b/BizHawk.MultiClient/RenderPanel.cs @@ -78,7 +78,6 @@ namespace BizHawk.MultiClient } // Copy the image data to the texture. - surface.Lock(); using (var Data = Texture.LockRectangle(0, new Rectangle(0, 0, imageWidth, imageHeight), LockFlags.None).Data) { if (imageWidth == textureWidth) @@ -295,7 +294,7 @@ namespace BizHawk.MultiClient Resized = false; Device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0); - Device.Present(SlimDX.Direct3D9.Present.DoNotWait); + Present(); } public void FastRenderAndPresent(DisplaySurface surface) @@ -378,7 +377,8 @@ namespace BizHawk.MultiClient public void Present() { - Device.Present(SlimDX.Direct3D9.Present.DoNotWait); + //Device.Present(SlimDX.Direct3D9.Present.DoNotWait); + Device.Present(SlimDX.Direct3D9.Present.None); }