Files
bluflame/aiwaz/Backup/Aiwaz.Resources/SwapChain.cs
2026-04-18 22:31:51 +02:00

235 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using System.Runtime.InteropServices;
using Aiwaz.Core;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
[AiwazResource("SwapChain", "An output target for render operations, the output could be displayed directly into a window.")]
public class SwapChain : RenderTarget, ISwapChain
{
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[Serializable, StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left_, int top_, int right_, int bottom_)
{
Left = left_;
Top = top_;
Right = right_;
Bottom = bottom_;
}
public int Height { get { return Bottom - Top; } }
public int Width { get { return Right - Left; } }
}
private SlimDX.DXGI.SwapChainDescription swapChainDescription;
private SlimDX.DXGI.SwapChain swapChain;
public SwapChain(IntPtr windowHandle)
: this(windowHandle, 0, 0, 0, SlimDX.DXGI.Format.Unknown, 0, 0)
{
}
public SwapChain(IntPtr windowHandle, int width, int height, int refreshRate, SlimDX.DXGI.Format format)
: this (windowHandle, width, height, refreshRate, format, 0, 0)
{
}
public SwapChain(IntPtr windowHandle, int width, int height, int refreshRate, SlimDX.DXGI.Format format, int multiSampleCount, int multiSampleQuality)
: base()
{
VSync = true;
// get missing information
if (multiSampleCount <= 0)
multiSampleCount = 1;
if (width == 0 || height == 0)
{
RECT windowRect = new RECT();
GetClientRect(windowHandle, out windowRect);
if (width == 0)
width = windowRect.Right - windowRect.Left;
if (height == 0)
height = windowRect.Bottom - windowRect.Top;
}
if (refreshRate == 0)
refreshRate = 60; // 60Hz
if (format == SlimDX.DXGI.Format.Unknown)
format = SlimDX.DXGI.Format.R8G8B8A8_UNorm; // RGBA(X) 8Bit per channel -> 32Bit
swapChainDescription = new SlimDX.DXGI.SwapChainDescription()
{
BufferCount = 1,
Usage = SlimDX.DXGI.Usage.RenderTargetOutput,
OutputHandle = windowHandle,
IsWindowed = true,
ModeDescription = new SlimDX.DXGI.ModeDescription()
{
Width = width,
Height = height,
Format = (SlimDX.DXGI.Format)format,
RefreshRate = new SlimDX.Rational(refreshRate, 1)
},
SampleDescription = new SlimDX.DXGI.SampleDescription()
{
Count = multiSampleCount,
Quality = multiSampleQuality
}
};
this.multiSampleCount = multiSampleCount;
this.multiSampleQuality = multiSampleQuality;
Console.WriteLine(string.Format("Creating SwapChain ({0}x{1}x{2} {3})..", width, height, refreshRate, format.ToString()));
swapChain = new SlimDX.DXGI.SwapChain(Engine.Factory, Engine.Device, swapChainDescription);
if (swapChain == null)
throw new InitializingFailedException(this.GetType().Name, "Unable to create internal swap chain.");
this.RetriveData();
this.ViewPort = new ViewPort()
{
Width = width,
Height = height
};
}
public override int RenderTargetWidth
{
get { return swapChainDescription.ModeDescription.Width; }
}
public override int RenderTargetHeight
{
get { return swapChainDescription.ModeDescription.Height; }
}
public override SlimDX.DXGI.Format RenderTargetFormat
{
get { return swapChainDescription.ModeDescription.Format; }
}
#region ISwapChain Members
public void Resize(int width, int height)
{
if (width <= 0 || height <= 0)
{
RECT windowRect = new RECT();
GetClientRect(swapChainDescription.OutputHandle, out windowRect);
if (width <= 0)
width = windowRect.Right - windowRect.Left;
if (height <= 0)
height = windowRect.Bottom - windowRect.Top;
}
if (swapChainDescription.ModeDescription.Width == width &&
swapChainDescription.ModeDescription.Height == height)
return;
var depthStencilBuffer = this.HasDepthStencilBuffer;
Engine.Device.ClearState();
this.HasDepthStencilBuffer = false;
if (this.DX10RenderTargetView != null)
this.DX10RenderTargetView.Dispose();
this.DX10RenderTargetView = null;
swapChain.ResizeBuffers(swapChainDescription.BufferCount, width, height, swapChainDescription.ModeDescription.Format, SlimDX.DXGI.SwapChainFlags.AllowModeSwitch);
var desc = swapChainDescription.ModeDescription;
desc.Width = width;
desc.Height = height;
swapChainDescription.ModeDescription = desc;
this.RetriveData();
this.HasDepthStencilBuffer = depthStencilBuffer;
this.ViewPort = new ViewPort()
{
Width = width,
Height = height
};
}
public void Present()
{
swapChain.Present(VSync ? 1 : 0, SlimDX.DXGI.PresentFlags.None);
}
public bool Fullscreen
{
get { return !swapChainDescription.IsWindowed; }
set
{
if (swapChainDescription.IsWindowed == !value)
return;
swapChainDescription.IsWindowed = !value;
var hasDepthStencilBuffer = this.HasDepthStencilBuffer;
Engine.Device.ClearState();
this.HasDepthStencilBuffer = false;
if (this.DX10RenderTargetView != null)
this.DX10RenderTargetView.Dispose();
this.DX10RenderTargetView = null;
swapChain.SetFullScreenState(value, Engine.DeviceEnumerator.FindBestOutput(false).Output);
this.RetriveData();
this.HasDepthStencilBuffer = hasDepthStencilBuffer;
}
}
public bool VSync { get; set; }
private void RetriveData()
{
using (var backbufferTexture = SlimDX.Direct3D10.Texture2D.FromSwapChain<SlimDX.Direct3D10.Texture2D>(swapChain, 0))
{
DX10RenderTargetView = new SlimDX.Direct3D10.RenderTargetView(Engine.Device, backbufferTexture);
}
}
#endregion
#region IDisposable Members
public override void Dispose()
{
if (swapChain != null)
swapChain.Dispose();
swapChain = null;
base.Dispose();
}
#endregion
public override ICreationParams CreationParams
{
get { return null; }
}
public override ObservableCollection<IResource> Children
{
get { return null; }
}
}
}