1
0
mirror of synced 2024-12-13 08:11:10 +01:00
OpenTaiko/FDK19/コード/01.フレームワーク/Rendering/Direct3D9Manager.cs
2021-09-21 00:16:38 +02:00

220 lines
9.3 KiB
C#

/*
* Copyright (c) 2007-2009 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using SlimDX;
using SlimDX.Direct3D9;
namespace SampleFramework
{
/// <summary>
/// Manages aspects of the graphics device unique to Direct3D9.
/// </summary>
public class Direct3D9Manager
{
GraphicsDeviceManager manager;
/// <summary>
/// Gets the graphics device.
/// </summary>
/// <value>The graphics device.</value>
#if TEST_Direct3D9Ex
public DeviceEx Device //yyagi
#else
public DeviceCache Device
#endif
{
get;
internal set;
}
/// <summary>
/// Initializes a new instance of the <see cref="Direct3D9Manager"/> class.
/// </summary>
/// <param name="manager">The parent manager.</param>
internal Direct3D9Manager(GraphicsDeviceManager manager)
{
this.manager = manager;
}
/// <summary>
/// Creates a vertex declaration using the specified vertex type.
/// </summary>
/// <param name="vertexType">Type of the vertex.</param>
/// <returns>The vertex declaration for the specified vertex type.</returns>
[EnvironmentPermission(SecurityAction.LinkDemand)]
public VertexDeclaration CreateVertexDeclaration(Type vertexType)
{
// ensure that we have a value type
if (!vertexType.IsValueType)
throw new InvalidOperationException("Vertex types must be value types.");
// grab the list of elements in the vertex
List<VertexElementAttribute> objectAttributes = new List<VertexElementAttribute>();
FieldInfo[] fields = vertexType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
// check for the custom attribute
VertexElementAttribute[] attributes = (VertexElementAttribute[])field.GetCustomAttributes(typeof(VertexElementAttribute), false);
if (field.Name.Contains("<") && field.Name.Contains(">"))
{
// look up the property matching this field to see if it has the attribute
int index1 = field.Name.IndexOf('<');
int index2 = field.Name.IndexOf('>');
// parse out the name
string propertyName = field.Name.Substring(index1 + 1, index2 - index1 - 1);
PropertyInfo property = vertexType.GetProperty(propertyName, field.FieldType);
if (property != null)
attributes = (VertexElementAttribute[])property.GetCustomAttributes(typeof(VertexElementAttribute), false);
}
if (attributes.Length == 1)
{
// add the attribute to the list
attributes[0].Offset = Marshal.OffsetOf(vertexType, field.Name).ToInt32();
objectAttributes.Add(attributes[0]);
}
}
// make sure we have at least one element
if (objectAttributes.Count < 1)
throw new InvalidOperationException("The vertex type must have at least one field or property marked with the VertexElement attribute.");
// loop through the attributes and start building vertex elements
List<VertexElement> elements = new List<VertexElement>();
Dictionary<DeclarationUsage, int> usages = new Dictionary<DeclarationUsage, int>();
foreach (VertexElementAttribute attribute in objectAttributes)
{
// check the current usage index
if (!usages.ContainsKey(attribute.Usage))
usages.Add(attribute.Usage, 0);
// advance the current usage count
int index = usages[attribute.Usage];
usages[attribute.Usage]++;
// create the element
elements.Add(new VertexElement((short)attribute.Stream, (short)attribute.Offset, attribute.Type,
attribute.Method, attribute.Usage, (byte)index));
}
elements.Add(VertexElement.VertexDeclarationEnd);
return new VertexDeclaration(Device.UnderlyingDevice, elements.ToArray());
}
/// <summary>
/// Creates a render target surface that is compatible with the current device settings.
/// </summary>
/// <param name="width">The width of the surface.</param>
/// <param name="height">The height of the surface.</param>
/// <returns>The newly created render target surface.</returns>
public Texture CreateRenderTarget(int width, int height)
{
return new Texture(Device.UnderlyingDevice, width, height, 1, Usage.RenderTarget, manager.CurrentSettings.BackBufferFormat, Pool.Default);
}
/// <summary>
/// Creates a resolve target for capturing the back buffer.
/// </summary>
/// <returns>The newly created resolve target.</returns>
public Texture CreateResolveTarget()
{
return new Texture(Device.UnderlyingDevice, manager.ScreenWidth, manager.ScreenHeight, 1, Usage.RenderTarget, manager.CurrentSettings.BackBufferFormat, Pool.Default);
}
/// <summary>
/// Resolves the current back buffer into a texture.
/// </summary>
/// <param name="target">The target texture.</param>
/// <exception cref="InvalidOperationException">Thrown when the resolve process fails.</exception>
public void ResolveBackBuffer(Texture target)
{
ResolveBackBuffer(target, 0);
}
/// <summary>
/// Resolves the current back buffer into a texture.
/// </summary>
/// <param name="target">The target texture.</param>
/// <param name="backBufferIndex">The index of the back buffer.</param>
/// <exception cref="InvalidOperationException">Thrown when the resolve process fails.</exception>
public void ResolveBackBuffer(Texture target, int backBufferIndex)
{
// disable exceptions for this method
bool storedThrow = Configuration.ThrowOnError;
Configuration.ThrowOnError = false;
Surface destination = null;
try
{
// grab the current back buffer
Surface backBuffer = Device.GetBackBuffer(0, backBufferIndex);
if (backBuffer == null || Result.Last.IsFailure)
throw new InvalidOperationException("Could not obtain back buffer surface.");
// grab the destination surface
destination = target.GetSurfaceLevel(0);
if (destination == null || Result.Last.IsFailure)
throw new InvalidOperationException("Could not obtain resolve target surface.");
// first try to copy using linear filtering
if (Device.StretchRectangle(backBuffer, destination, TextureFilter.Linear).IsFailure)
{
// that failed, so try with no filtering
if (Device.StretchRectangle(backBuffer, destination, TextureFilter.None).IsFailure)
{
// that failed as well, so the last thing we can try is a load surface call
if (Surface.FromSurface(destination, backBuffer, Filter.Default, 0).IsFailure)
throw new InvalidOperationException("Could not copy surfaces.");
}
}
}
finally
{
if (destination != null)
destination.Dispose();
Configuration.ThrowOnError = storedThrow;
}
}
/// <summary>
/// Resets the render target.
/// </summary>
public void ResetRenderTarget()
{
Surface backBuffer = Device.GetBackBuffer(0, 0);
try
{
Device.SetRenderTarget(0, backBuffer);
}
finally
{
backBuffer.Dispose();
}
}
}
}