--- /dev/null
+/*
+* 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 SharpDX;
+using SharpDX.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 Device 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, 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, 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, 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.GetResultFromWin32Error( Marshal.GetLastWin32Error() ).Failure)
+ throw new InvalidOperationException("Could not obtain back buffer surface.");
+
+ // grab the destination surface
+ destination = target.GetSurfaceLevel(0);
+ if (destination == null || Result.GetResultFromWin32Error( Marshal.GetLastWin32Error() ).Failure)
+ throw new InvalidOperationException("Could not obtain resolve target surface.");
+
+ // first try to copy using linear filtering
+ Device.StretchRectangle( backBuffer, destination, TextureFilter.Linear );
+ if ( Result.GetResultFromWin32Error( Marshal.GetLastWin32Error() ).Failure )
+ {
+ // that failed, so try with no filtering
+ Device.StretchRectangle( backBuffer, destination, TextureFilter.None );
+ if( Result.GetResultFromWin32Error( Marshal.GetLastWin32Error() ).Failure )
+ {
+ // that failed as well, so the last thing we can try is a load surface call
+ Surface.FromSurface( destination, backBuffer, Filter.Default, 0 );
+ if( Result.GetResultFromWin32Error( Marshal.GetLastWin32Error() ).Failure )
+ 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();
+ }
+ }
+ }
+}