// 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 }; } } } }