154 lines
3.1 KiB
C#
154 lines
3.1 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Runtime.InteropServices;
|
|
using BizHawk.Common;
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
|
{
|
|
/// <summary>
|
|
/// This is a wrapper for a Bitmap, basically, which can also be a int[].
|
|
/// It should be phased out, in favor of BitmapBuffer and Texture2d's
|
|
/// </summary>
|
|
public unsafe class DisplaySurface : IDisposable
|
|
{
|
|
private Bitmap _bmp;
|
|
private BitmapData _bmpData;
|
|
private readonly int[] _pixels;
|
|
|
|
public unsafe void Clear()
|
|
{
|
|
FromBitmap(false);
|
|
Util.Memset(PixelPtr, 0, Stride * Height);
|
|
}
|
|
|
|
public Bitmap PeekBitmap()
|
|
{
|
|
ToBitmap();
|
|
return _bmp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// returns a Graphics object used to render to this surface. be sure to dispose it!
|
|
/// </summary>
|
|
public Graphics GetGraphics()
|
|
{
|
|
ToBitmap();
|
|
return Graphics.FromImage(_bmp);
|
|
}
|
|
|
|
public unsafe void ToBitmap(bool copy=true)
|
|
{
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
private bool _isBitmap;
|
|
|
|
public unsafe void FromBitmap(bool copy = true)
|
|
{
|
|
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 DisplaySurface(int width, int height)
|
|
{
|
|
// can't create a bitmap with zero dimensions, so for now, just bump it up to one
|
|
if (width == 0)
|
|
{
|
|
width = 1;
|
|
}
|
|
|
|
if (height == 0)
|
|
{
|
|
height = 1;
|
|
}
|
|
|
|
Width = width;
|
|
Height = height;
|
|
|
|
_pixels = new int[width * height];
|
|
LockPixels();
|
|
}
|
|
|
|
public int* PixelPtr => (int*)_ptr;
|
|
public int Stride => Width * 4;
|
|
|
|
private void* _ptr;
|
|
private GCHandle _handle;
|
|
private void LockPixels()
|
|
{
|
|
UnlockPixels();
|
|
_handle = GCHandle.Alloc(_pixels, GCHandleType.Pinned);
|
|
_ptr = _handle.AddrOfPinnedObject().ToPointer();
|
|
}
|
|
|
|
private void UnlockPixels()
|
|
{
|
|
if (_handle.IsAllocated)
|
|
{
|
|
_handle.Free();
|
|
}
|
|
}
|
|
|
|
public int Width { get; }
|
|
public int Height { get; }
|
|
|
|
public void Dispose()
|
|
{
|
|
_bmp?.Dispose();
|
|
_bmp = null;
|
|
UnlockPixels();
|
|
}
|
|
}
|
|
|
|
}
|