namespace FDK
{
+ /// <summary>
+ /// テクスチャを扱うクラス。
+ /// 使用終了時は必ずDispose()してください。Finalize時の自動Disposeはありません。
+ /// Disposeを忘れた場合は、メモリリークに直結します。
+ /// Finalize時にDisposeしない代わりに、Finalize時にテクスチャのDispose漏れを検出し、
+ /// Trace.TraceWarning()でログを出力します。
+ /// see also:
+ /// https://osdn.net/projects/dtxmania/ticket/38036
+ /// https://github.com/sharpdx/SharpDX/pull/192?w=1
+ /// </summary>
public class CTexture : IDisposable
{
#region [ プロパティ ]
protected set;
}
public Vector3 vc拡大縮小倍率;
+ public string filename;
+ public string label;
#endregion
// コンストラクタ
this.szテクスチャサイズ = new Size( 0, 0 );
this._透明度 = 0xff;
this.texture = null;
+ this.bSharpDXTextureDispose完了済み = true;
this.cvPositionColoredVertexies = null;
this.b加算合成 = false;
this.fZ軸中心回転 = 0f;
this.vc拡大縮小倍率 = new Vector3( 1f, 1f, 1f );
this.bFlipY = false;
// this._txData = null;
+ this.filename = "";
+ this.label = "";
}
-
+
/// <summary>
/// <para>指定されたビットマップオブジェクトから Managed テクスチャを作成する。</para>
/// <para>テクスチャのサイズは、BITMAP画像のサイズ以上、かつ、D3D9デバイスで生成可能な最小のサイズに自動的に調節される。
/// <param name="bitmap">作成元のビットマップ。</param>
/// <param name="format">テクスチャのフォーマット。</param>
/// <exception cref="CTextureCreateFailedException">テクスチャの作成に失敗しました。</exception>
- public CTexture( Device device, Bitmap bitmap, Format format )
+ public CTexture( Device device, Bitmap bitmap, Format format, string _label="" )
: this()
{
try
{
this.Format = format;
+ this.label = _label;
this.sz画像サイズ = new Size( bitmap.Width, bitmap.Height );
this.szテクスチャサイズ = this.t指定されたサイズを超えない最適なテクスチャサイズを返す( device, this.sz画像サイズ );
this.rc全画像 = new Rectangle( 0, 0, this.sz画像サイズ.Width, this.sz画像サイズ.Height );
stream.Seek( 0L, SeekOrigin.Begin );
int colorKey = unchecked( (int) 0xFF000000 );
this.texture = Texture.FromStream( device, stream, this.szテクスチャサイズ.Width, this.szテクスチャサイズ.Height, 1, Usage.None, format, poolvar, Filter.Point, Filter.None, colorKey );
+ this.bSharpDXTextureDispose完了済み = false;
}
}
catch ( Exception e )
/// <param name="n高さ">テクスチャの高さ(希望値)。</param>
/// <param name="format">テクスチャのフォーマット。</param>
/// <exception cref="CTextureCreateFailedException">テクスチャの作成に失敗しました。</exception>
- public CTexture( Device device, int n幅, int n高さ, Format format )
- : this( device, n幅, n高さ, format, Pool.Managed )
+ public CTexture( Device device, int n幅, int n高さ, Format format, string _label = "")
+ : this( device, n幅, n高さ, format, Pool.Managed, _label)
{
}
/// <param name="format">テクスチャのフォーマット。</param>
/// <param name="b黒を透過する">画像の黒(0xFFFFFFFF)を透過させるなら true。</param>
/// <exception cref="CTextureCreateFailedException">テクスチャの作成に失敗しました。</exception>
- public CTexture( Device device, string strファイル名, Format format, bool b黒を透過する )
- : this( device, strファイル名, format, b黒を透過する, Pool.Managed )
+ public CTexture( Device device, string strファイル名, Format format, bool b黒を透過する, string _label = "")
+ : this( device, strファイル名, format, b黒を透過する, Pool.Managed, _label)
{
}
- public CTexture( Device device, byte[] txData, Format format, bool b黒を透過する )
- : this( device, txData, format, b黒を透過する, Pool.Managed )
+ public CTexture( Device device, byte[] txData, Format format, bool b黒を透過する, string _label = "")
+ : this( device, txData, format, b黒を透過する, Pool.Managed, _label)
{
}
- public CTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する )
- : this( device, bitmap, format, b黒を透過する, Pool.Managed )
+ public CTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する, string _label = "")
+ : this( device, bitmap, format, b黒を透過する, Pool.Managed, _label)
{
}
/// <param name="format">テクスチャのフォーマット。</param>
/// <param name="pool">テクスチャの管理方法。</param>
/// <exception cref="CTextureCreateFailedException">テクスチャの作成に失敗しました。</exception>
- public CTexture( Device device, int n幅, int n高さ, Format format, Pool pool )
- : this( device, n幅, n高さ, format, pool, Usage.None, false )
+ public CTexture( Device device, int n幅, int n高さ, Format format, Pool pool, string _label = "")
+ : this( device, n幅, n高さ, format, pool, Usage.None, false, _label)
{
}
- public CTexture( Device device, int n幅, int n高さ, Format format, Pool pool, Usage usage, bool b黒を透過する )
+ public CTexture( Device device, int n幅, int n高さ, Format format, Pool pool, Usage usage, bool b黒を透過する, string _label = "")
: this()
{
try
{
this.Format = format;
+ this.label = _label;
this.sz画像サイズ = new Size( n幅, n高さ );
this.szテクスチャサイズ = this.t指定されたサイズを超えない最適なテクスチャサイズを返す( device, this.sz画像サイズ );
this.rc全画像 = new Rectangle( 0, 0, this.sz画像サイズ.Width, this.sz画像サイズ.Height );
#endif
// 中で更にメモリ読み込みし直していて無駄なので、Streamを使うのは止めたいところ
this.texture = Texture.FromStream( device, stream, n幅, n高さ, 1, usage, format, pool, Filter.Point, Filter.None, colorKey );
+ this.bSharpDXTextureDispose完了済み = false;
}
}
}
/// <param name="b黒を透過する">画像の黒(0xFFFFFFFF)を透過させるなら true。</param>
/// <param name="pool">テクスチャの管理方法。</param>
/// <exception cref="CTextureCreateFailedException">テクスチャの作成に失敗しました。</exception>
- public CTexture( Device device, string strファイル名, Format format, bool b黒を透過する, Pool pool )
+ public CTexture( Device device, string strファイル名, Format format, bool b黒を透過する, Pool pool, string _label = "")
: this()
{
- MakeTexture( device, strファイル名, format, b黒を透過する, pool );
+ MakeTexture( device, strファイル名, format, b黒を透過する, pool, _label );
}
- public void MakeTexture( Device device, string strファイル名, Format format, bool b黒を透過する, Pool pool )
+ public void MakeTexture( Device device, string strファイル名, Format format, bool b黒を透過する, Pool pool, string _label = "")
{
if ( !File.Exists( strファイル名 ) ) // #27122 2012.1.13 from: ImageInformation では FileNotFound 例外は返ってこないので、ここで自分でチェックする。わかりやすいログのために。
throw new FileNotFoundException( string.Format( "ファイルが存在しません。\n[{0}]", strファイル名 ) );
Byte[] _txData = File.ReadAllBytes( strファイル名 );
- MakeTexture( device, _txData, format, b黒を透過する, pool );
+ this.filename = Path.GetFileName( strファイル名 );
+ MakeTexture( device, _txData, format, b黒を透過する, pool, _label );
}
- public CTexture( Device device, byte[] txData, Format format, bool b黒を透過する, Pool pool )
+ public CTexture( Device device, byte[] txData, Format format, bool b黒を透過する, Pool pool, string _label = "")
: this()
{
- MakeTexture( device, txData, format, b黒を透過する, pool );
+ MakeTexture( device, txData, format, b黒を透過する, pool, _label );
}
- public void MakeTexture( Device device, byte[] txData, Format format, bool b黒を透過する, Pool pool )
+ public void MakeTexture( Device device, byte[] txData, Format format, bool b黒を透過する, Pool pool, string _label = "")
{
try
{
var information = ImageInformation.FromMemory( txData );
this.Format = format;
+ this.label = _label;
this.sz画像サイズ = new Size( information.Width, information.Height );
this.rc全画像 = new Rectangle( 0, 0, this.sz画像サイズ.Width, this.sz画像サイズ.Height );
int colorKey = ( b黒を透過する ) ? unchecked( (int) 0xFF000000 ) : 0;
// {
//Trace.TraceInformation( "CTexture() start: " );
this.texture = Texture.FromMemory( device, txData, this.sz画像サイズ.Width, this.sz画像サイズ.Height, 1, Usage.None, format, pool, Filter.Point, Filter.None, colorKey );
+ this.bSharpDXTextureDispose完了済み = false;
//Trace.TraceInformation( "CTexture() end: " );
// }
}
}
}
- public CTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する, Pool pool )
+ public CTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する, Pool pool, string _label = "")
: this()
{
- MakeTexture( device, bitmap, format, b黒を透過する, pool );
+ MakeTexture( device, bitmap, format, b黒を透過する, pool, _label );
}
- public void MakeTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する, Pool pool )
+ public void MakeTexture( Device device, Bitmap bitmap, Format format, bool b黒を透過する, Pool pool, string _label = "")
{
try
{
this.Format = format;
+ this.label = _label;
this.sz画像サイズ = new Size( bitmap.Width, bitmap.Height );
this.rc全画像 = new Rectangle( 0, 0, this.sz画像サイズ.Width, this.sz画像サイズ.Height );
int colorKey = ( b黒を透過する ) ? unchecked( (int) 0xFF000000 ) : 0;
#endif
texture.UnlockRectangle( 0 );
bitmap.UnlockBits( srcBufData );
+ this.bSharpDXTextureDispose完了済み = false;
}
//Trace.TraceInformation( "CTExture() End: " );
}
device.DrawUserPrimitives( PrimitiveType.TriangleStrip, 2, this.cvPositionColoredVertexies );
}
- #region [ IDisposable 実装 ]
+
+ #region [ Dispose-Finalize パターン実装 ]
//-----------------
public void Dispose()
{
- if( !this.bDispose完了済み )
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ protected void Dispose(bool disposeManagedObjects)
+ {
+ if (this.bDispose完了済み)
+ return;
+
+ if (disposeManagedObjects)
{
- // テクスチャの破棄
- if( this.texture != null )
+ // (A) Managed リソースの解放
+ // テクスチャの破棄 (SharpDXのテクスチャは、SharpDX側で管理されるため、FDKからはmanagedリソースと見做す)
+ if (this.texture != null)
{
this.texture.Dispose();
this.texture = null;
+ this.bSharpDXTextureDispose完了済み = true;
}
+ }
+
+ // (B) Unamanaged リソースの解放
+
- this.bDispose完了済み = true;
+ this.bDispose完了済み = true;
+ }
+ ~CTexture()
+ {
+ // ファイナライザの動作時にtextureのDisposeがされていない場合は、
+ // CTextureのDispose漏れと見做して警告をログ出力する
+ if (!this.bSharpDXTextureDispose完了済み)
+ {
+ Trace.TraceWarning("CTexture: Dispose漏れを検出しました。(Size=({0}, {1}), filename={2}, label={3})", sz画像サイズ.Width, sz画像サイズ.Height, filename, label );
}
+ this.Dispose(false);
}
//-----------------
#endregion
#region [ private ]
//-----------------
protected int _透明度;
- private bool bDispose完了済み;
+ private bool bDispose完了済み, bSharpDXTextureDispose完了済み;
protected PositionColoredTexturedVertex[] cvPositionColoredVertexies;
protected TransformedColoredTexturedVertex[] cvTransformedColoredVertexies;
protected const Pool poolvar = // 2011.4.25 yyagi