// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
// 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.Runtime.InteropServices;
namespace SharpDX.Direct3D9
{
///
/// EffectHandle used to identify a shader parameter.
///
public class EffectHandle : DisposeBase
{
#region Constants and Fields
///
/// Defines the behavior for caching strings. True by default.
///
private const bool UseCacheStrings = true;
///
/// Cache of allocated strings.
///
private static readonly Dictionary AllocatedStrings = new Dictionary();
///
/// Pointer to the handle or the allocated string.
///
private IntPtr pointer;
///
/// If the is a custom string not cached that needs to be released by this instance.
///
private bool isStringToRelease;
#endregion
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
public EffectHandle()
{
}
///
/// Initializes a new instance of the class.
///
///
/// The pointer.
///
public EffectHandle(IntPtr pointer)
{
this.pointer = pointer;
}
///
/// Initializes a new instance of the class.
///
///
/// The pointer.
///
public unsafe EffectHandle(void* pointer)
{
this.pointer = new IntPtr(pointer);
}
///
/// Initializes a new instance of the class.
///
///
/// The name.
///
public EffectHandle(string name)
{
pointer = AllocateString(name);
isStringToRelease = !UseCacheStrings;
}
#endregion
#region Public Methods
///
/// Clears the cache.
///
///
/// By default, this class is caching all strings that are implicitly used as an effect handle.
/// Use this method in order to deallocate all strings that were previously cached.
///
public static void ClearCache()
{
lock (AllocatedStrings)
{
foreach (var value in AllocatedStrings.Values)
Marshal.FreeHGlobal(value);
AllocatedStrings.Clear();
}
}
#endregion
#region Methods
///
/// marshal free.
///
/// The __from.
/// The @ref.
internal static void __MarshalFree(ref EffectHandle __from, ref __Native @ref)
{
}
///
/// Method to marshal from native to managed struct
///
/// The __from.
/// The @ref.
internal static void __MarshalFrom(ref EffectHandle __from, ref __Native @ref)
{
if (@ref.Pointer == IntPtr.Zero)
__from = null;
else
__from.pointer = @ref.Pointer;
}
///
/// Method to marshal from managed struct tot native
///
/// The __from.
/// The @ref.
internal static void __MarshalTo(ref EffectHandle __from, ref __Native @ref)
{
if (__from == null)
@ref.Pointer = IntPtr.Zero;
else
@ref.Pointer = __from.pointer;
}
///
protected override void Dispose(bool disposing)
{
if (isStringToRelease)
{
Marshal.FreeHGlobal(pointer);
pointer = IntPtr.Zero;
isStringToRelease = false;
}
}
///
/// Allocates a string.
///
///
/// The name.
///
///
/// Pointer to the allocated string
///
private static IntPtr AllocateString(string name)
{
IntPtr value;
if (UseCacheStrings)
{
lock (AllocatedStrings)
{
if (!AllocatedStrings.TryGetValue(name, out value))
{
value = Marshal.StringToHGlobalAnsi(name);
AllocatedStrings.Add(name, value);
}
}
}
else
{
value = Marshal.StringToHGlobalAnsi(name);
}
return value;
}
#endregion
#region Operators
///
/// Performs an implicit conversion from to .
///
/// The value.
///
/// The result of the conversion.
///
public static implicit operator IntPtr(EffectHandle value)
{
return value.pointer;
}
///
/// Performs an implicit conversion from to .
///
/// The value.
///
/// The result of the conversion.
///
public static implicit operator EffectHandle(IntPtr value)
{
return new EffectHandle(value);
}
///
/// Performs an implicit conversion from to raw pointer"/>.
///
/// The value.
///
/// The result of the conversion.
///
public static unsafe implicit operator void*(EffectHandle value)
{
return (void*)value.pointer;
}
///
/// Performs an implicit conversion from raw pointer to .
///
/// The value.
///
/// The result of the conversion.
///
public static unsafe implicit operator EffectHandle(void* value)
{
return new EffectHandle(value);
}
///
/// Performs an implicit conversion from to .
///
/// The name.
///
/// The result of the conversion.
///
public static implicit operator EffectHandle(string name)
{
return new EffectHandle(name);
}
#endregion
[StructLayout(LayoutKind.Sequential)]
internal struct __Native
{
public IntPtr Pointer;
internal void __MarshalFree()
{
}
public static implicit operator IntPtr(__Native value)
{
return value.Pointer;
}
public static implicit operator __Native(IntPtr value)
{
return new __Native() { Pointer = value };
}
public static unsafe implicit operator void*(__Native value)
{
return (void*)value.Pointer;
}
public static unsafe implicit operator __Native(void* value)
{
return new __Native() { Pointer = (IntPtr)value };
}
}
}
}