/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/11/29
/// 
/// @brief  基底となるとこらへん。
/// 
/// ****************************************************************************

#pragma once

//#define CPL_USE_DX9
//#define CPL_USE_DX10
//#define CPL_USE_DX11
//#define CPL_USE_DX11_1


#include <winsdkver.h>


// 必要なライブラリの読み込み
#ifdef _MSC_VER

#if defined CPL_USE_DX12

  #   pragma comment(lib, "d3d12.lib")

#elif defined CPL_USE_DX11_1

  #   define CPL_USE_DX11ex
  #   pragma comment(lib, "d3d11.lib")

# elif defined CPL_USE_DX11

#if WINVER_MAXVER >= 0x0602 // Win8以上
  #   define CPL_USE_DX11ex
  #   pragma comment(lib, "d3d11.lib")
  #   pragma comment(lib, "DXGI.lib")
  #   pragma comment(lib, "d3dcompiler.lib")
  #   pragma comment(lib, "dxguid.lib")
#else
  #   pragma comment(lib, "d3d11.lib")
  #   pragma comment(lib, "d3dx11.lib")
  #   pragma comment(lib, "d3dxof.lib")
  #   pragma comment(lib, "dxguid.lib")
  #   pragma comment(lib, "DXGI.lib")
#endif

  #   pragma comment(lib, "dinput8.lib")

  #   ifndef CPL_USE_DX11ex
  #   ifdef CPL_DEBUG
  #     pragma comment(lib, "d3dx11d.lib")
  #     pragma comment(lib, "DxErr.lib")
  #   else
  #     pragma comment(lib, "d3dx11.lib")
  #     pragma comment(lib, "d3dx10.lib")
  #     pragma comment(lib, "d3dx9.lib")
  #   endif
  #   endif

# elif defined CPL_USE_DX10
  #   pragma comment(lib, "d3d10.lib")
  #   pragma comment(lib, "d3d10.lib")
  #   pragma comment(lib, "d3dxof.lib")
  #   pragma comment(lib, "dxguid.lib")
  #   pragma comment(lib, "DXGI.lib")

  #   pragma comment(lib, "dinput8.lib")

  #   ifdef CPL_DEBUG
  #     pragma comment(lib, "d3dx10d.lib")
  #     pragma comment(lib, "DxErr.lib")
  #   else
  #     pragma comment(lib, "d3dx10.lib")
  #     pragma comment(lib, "d3dx9.lib")
  #   endif

//# else // ver9
//#   pragma comment(lib, "d3d9.lib")
//#   pragma comment(lib, "d3d9.lib")
//#   pragma comment(lib, "d3dxof.lib")
//#   pragma comment(lib, "dxguid.lib")
//
//#   pragma comment(lib, "dinput8.lib")
//
//#   ifdef CPL_DEBUG
//#     pragma comment(lib, "d3dx9d.lib")
////#     pragma comment(lib, "dxerr9.lib")
//#     pragma comment(lib, "DxErr.lib")
//#   else
//#     pragma comment(lib, "d3dx9.lib")
//#   endif
# endif
#endif


#ifndef NOMINMAX
#define NOMINMAX // min/max定義すんな！
#endif

//#include "../Core/Pointer/CPL_Core_PointerCom.h"
//#include "../Core/Container/Array/CPL_Core_DynamicArray.h"
#include "../Core/CPL_Core.h"
#include "../Math/CPL_Math.h"
#include "../Win/CPL_WINDOWS.h"


#ifdef CPL_USE_DX11_1

  #include "DDSTextureLoader/DDSTextureLoader.h"
  #include "WICTextureLoader/WICTextureLoader.h"

#elif defined CPL_USE_DX11

#ifdef CPL_USE_DX11ex
  #include "DDSTextureLoader/DDSTextureLoader.h"
  #include "WICTextureLoader/WICTextureLoader.h"
#else
  #include <d3dx11.h>
  #include <d3dx11core.h>
  #include <D3DX10math.h>
  #include <DxErr.h>
  #include <dxfile.h>
#endif

#elif defined CPL_USE_DX10
  #include <d3d10.h>
  #include <d3dx10.h>
  #include <d3dx10core.h>
  #include <DxErr.h>
  #include <dxfile.h>
  //#include <dxsdkver.h>

//#else
//# include <d3d9.h>
//# include <d3dx9.h>
//# include <d3dx9core.h>
////# include <dxerr9.h>
//# include <DxErr.h>
#endif


//#include "CPL_DirectX.h"

namespace CPL {

/// DirectX関連が含まれます。
namespace DX {



//#define CPL_DX_MSG_NOT_CREATE_D3D    "Direct3Dインターフェイスの作成に失敗\n"
#define CPL_DX_MSG_NOT_CREATE_DEVICE "DirectXデバイス作成に失敗\n"
#define CPL_DX_MSG_NOT_DEVICE        "DirectXデバイスが無効です\n"
#define CPL_DX_MSG_NOT_DEFAULT_FONT  "デフォルトのフォントが設定されていません\n"

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

using td_Coord2 = CPL::WIN::td_Coord2;

typedef U8                       TYPE_SLOT_INDEX;
typedef U32                      TYPE_INDEX;
typedef Core::Point3<TYPE_INDEX> TYPE_INDEX3;
//typedef float4                   ColorType;

struct ColorType : public float4
{
private:
  typedef ColorType type_this;
public:
  ColorType(){}
  ColorType( _in<float4> in_color )
    : float4( in_color )
  {}
  ColorType( _in<ColorType> in_color )
    : float4( (float4 const&)in_color )
  {}
  ColorType( U32 in_color )
  {
    a = (((U8*)&in_color)[0]) / 255.0f;
    b = (((U8*)&in_color)[1]) / 255.0f;
    g = (((U8*)&in_color)[2]) / 255.0f;
    r = (((U8*)&in_color)[3]) / 255.0f;
  }

  ColorType( float in_val_ )
    : float4( in_val_ )
  {}

  template<class T>
  ColorType( T const& rgb, float a_ )
    : float4( rgb, a_ )
  {}

  template<class T0, class T1>
  ColorType( T0 const& c0, T1 const& c1, float a_ )
    : float4( c0, c1, a_ )
  {}

  ColorType( float r_, float g_, float b_, float a_ )
    : float4( r_, g_, b_, a_ )
  {}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( +=, zzf_add_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( -=, zzf_sub_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( *=, zzf_multiply_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( /=, zzf_division_eq )
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  ColorType const operator + ( T const& rhs ) const
  {
    return ColorType( *this ) += rhs;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  ColorType const operator - ( T const& rhs ) const
  {
    return ColorType( *this ) -= rhs;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  ColorType const operator * ( T const& rhs ) const
  {
    return ColorType( *this ) *= rhs;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  ColorType const operator / ( T const& rhs ) const
  {
    return ColorType( *this ) /= rhs;
  }

  // _____________________________________________________________________________
  /// @brief U32形式に変換した値を取得
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  U32 GetColor_by_Convert_to_U32() const
  {
    U8x4 color
      ( (U8)Clamp((int)(r * 255.0f), 0, 255)
      , (U8)Clamp((int)(g * 255.0f), 0, 255)
      , (U8)Clamp((int)(b * 255.0f), 0, 255)
      , (U8)Clamp((int)(a * 255.0f), 0, 255)
      );
    return *(U32*)&color;
  }

  // _____________________________________________________________________________
  /// @brief 指定した色の反対色を求める
  /// 
  /// @param[out] out_color
  ///   : 変換した色を格納するColorTypeオブジェクトへを指定します。
  /// @param[in] in_color
  ///   : 変換元のColorTypeオブジェクトを指定します。
  /// 
  /// @return out_colorを指すアドレスを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  static ColorType*
    ConvertColor_to_Opposite
      ( rout<ColorType> out_color
      , _in<ColorType > in_color
      )
  {
    out_color.r = 1.0f - Clamp( in_color.r, 0.0f, 1.0f );
    out_color.g = 1.0f - Clamp( in_color.g, 0.0f, 1.0f );
    out_color.b = 1.0f - Clamp( in_color.b, 0.0f, 1.0f );
    out_color.a = 1.0f - Clamp( in_color.a, 0.0f, 1.0f );
    return &out_color;
  }

  // _____________________________________________________________________________
  /// @brief 指定した色の反対色を求める
  /// 
  /// @param[in] in_color
  ///   : 変換元のColorTypeオブジェクトを指定します。
  /// 
  /// @return 変換された色を返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  static ColorType
    ConvertColor_to_Opposite( _in<ColorType> in_color )
  {
    return ColorType
    { 1.0f - Clamp( in_color.r, 0.0f, 1.0f )
    , 1.0f - Clamp( in_color.g, 0.0f, 1.0f )
    , 1.0f - Clamp( in_color.b, 0.0f, 1.0f )
    , 1.0f - Clamp( in_color.a, 0.0f, 1.0f )
    };
  }

  // _____________________________________________________________________________
  /// @brief 反対色に変換した値を取得
  /// 
  /// @param[out] out_color
  ///   : 変換した値を格納するColorTypeオブジェクトへの参照を指定します。
  /// @return
  /// out_colorのアドレスを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ColorType* GetColor_by_Convert_to_Opposite( rout<ColorType> out_color ) const
  {
    return ConvertColor_to_Opposite( out_color, *this );
  }
  // _____________________________________________________________________________
  /// @brief 反対色に変換した値を取得
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ColorType GetColor_by_Convert_to_Opposite() const
  {
    return ConvertColor_to_Opposite( *this );
  }
};

const int SLOT_MAX = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT;
const int SHADER_CONSTANT_BUF_MAX = D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
const int VERTEX_SIZE_MAX = 256;


//#define CPL_DX_DEF_PARAM(type_,name_) typedef type_ name_

#if defined CPL_USE_DX11  ||  defined CPL_USE_DX11_1
# define CPL_DX_RETYPE(name, dx_type)\
    using name = dx_type;\
    using Cp##name = CPL::Core::ComPtr<name>;

# define CPL_DX_RETYPE_SW(name, dx11type, dx10type)\
    using name = dx11type;

# define CPL_DX_RETYPE_SW2(name, dx11type, dx10type)\
    using name = dx11type;\
    using Cp##name = CPL::Core::ComPtr<name>;
//# define CPL_DX_RETYPE_SW(name, dx11type, dx10type) \
//  struct name : public dx11type {\
//    name( name const& d ) : dx11type( d ){}\
//    name( dx11type const& d ) : dx11type( d ) {}\
//    name(){}\
//    CPL_TYPE_PTR_REF2_MEM(name);\
//  };

#elif defined CPL_USE_DX10
# define CPL_DX_REDEF_SW(name, dx11type, dx10type) typedef dx10type name;// CPL_TYPE_PTR_REF1_(name)
//#elif defined CPL_USE_DX9
//# define CPL_DX_REDEF_SW(name, dx11type, dx10type, dx9type) typedef dx9type name; CPL_TYPE_PTR_REF1_(name)
//  typedef IDirect3D9         D3DObject;
//
//  typedef ID3DXConstantTable D3DConstantTable;
//  CPL_TYPE_PTR_REF1_(D3DConstantTable);
//  
//  CPL_TYPE_PTR_REF1_( D3DObject );
#endif


CPL_DX_RETYPE_SW2( DXDevice,             ID3D11Device,             ID3D10Device        );
CPL_DX_RETYPE_SW2( DXDeviceContext,      ID3D11DeviceContext,      ID3D10DeviceContext );
CPL_DX_RETYPE_SW2( DXResource,           ID3D11Resource,           ID3D10Resource      );
CPL_DX_RETYPE_SW2( DXInputLayout,        ID3D11InputLayout,        ID3D10InputLayout   );
CPL_DX_RETYPE_SW2( DXBuffer,             ID3D11Buffer,             ID3D10Buffer        );
CPL_DX_RETYPE_SW2( DXVertexShader,       ID3D11VertexShader,       ID3D10VertexShader  );
CPL_DX_RETYPE_SW2( DXPixelShader,        ID3D11PixelShader,        ID3D10PixelShader   );
CPL_DX_RETYPE_SW2( DXBlob,               ID3DBlob,                 ID3D10Blob      );
CPL_DX_RETYPE_SW2( DXTexture1D,          ID3D11Texture1D,          ID3D10Texture1D );
CPL_DX_RETYPE_SW2( DXTexture2D,          ID3D11Texture2D,          ID3D10Texture2D );
CPL_DX_RETYPE_SW2( DXTexture3D,          ID3D11Texture3D,          ID3D10Texture3D );
CPL_DX_RETYPE_SW2( DXRasterizerState,    ID3D11RasterizerState,    ID3D10RasterizerState );
CPL_DX_RETYPE_SW2( DXBlendState,         ID3D11BlendState,         ID3D10BlendState );
CPL_DX_RETYPE_SW2( DXSamplerState,       ID3D11SamplerState,       ID3D10SamplerState );
CPL_DX_RETYPE_SW2( DXDepthStencilState,  ID3D11DepthStencilState,  ID3D10DepthStencilState );
CPL_DX_RETYPE_SW2( DXRenderTargetView,   ID3D11RenderTargetView,   ID3D10RenderTargetView );
CPL_DX_RETYPE_SW2( DXDepthStencilView,   ID3D11DepthStencilView,   ID3D10DepthStencilView );
CPL_DX_RETYPE_SW2( DXShaderResourceView, ID3D11ShaderResourceView, ID3D10ShaderResourceView );

//CPL_DX_RETYPE( Unknown_i,         IUnknown );
CPL_DX_RETYPE( GIObject,          IDXGIObject );
CPL_DX_RETYPE( GIAdapter,         IDXGIAdapter );
CPL_DX_RETYPE( GIAdapter1,        IDXGIAdapter1 );
CPL_DX_RETYPE( GIDevice,          IDXGIDevice );
CPL_DX_RETYPE( GIDevice1,         IDXGIDevice1 );
CPL_DX_RETYPE( GIFactory,         IDXGIFactory );
CPL_DX_RETYPE( GIFactory1,        IDXGIFactory1 );
CPL_DX_RETYPE( GIKeyedMutex,      IDXGIKeyedMutex );
CPL_DX_RETYPE( GIOutput,          IDXGIOutput );
CPL_DX_RETYPE( GIDEviceSubObject, IDXGIDeviceSubObject );
CPL_DX_RETYPE( GIResource,        IDXGIResource );
CPL_DX_RETYPE( GISurface,         IDXGISurface );
CPL_DX_RETYPE( GISurface1,        IDXGISurface1 );
CPL_DX_RETYPE( GISwapChain,       IDXGISwapChain );

CPL_DX_RETYPE_SW( DX_IN_ELEMENT_DESC,           D3D11_INPUT_ELEMENT_DESC,        D3D10_INPUT_ELEMENT_DESC );
CPL_DX_RETYPE_SW( DX_BUFFER_DESC,               CD3D11_BUFFER_DESC,              CD3D10_BUFFER_DESC );
CPL_DX_RETYPE_SW( DX_SUBRESOURCE_DATA,          D3D11_SUBRESOURCE_DATA,          D3D10_SUBRESOURCE_DATA );
CPL_DX_RETYPE_SW( DX_MAPPED_SUBRESOURCE,        D3D11_MAPPED_SUBRESOURCE,        D3D11_MAPPED_SUBRESOURCE );
CPL_DX_RETYPE_SW( DX_VIEWPORT,                  D3D11_VIEWPORT,                  D3D10_VIEWPORT );
CPL_DX_RETYPE_SW( DX_RASTERIZER_DESC,           D3D11_RASTERIZER_DESC,           D3D10_RASTERIZER_DESC );
CPL_DX_RETYPE_SW( DX_SAMPLER_DESC,              D3D11_SAMPLER_DESC,              D3D10_SAMPLER_DESC );
CPL_DX_RETYPE_SW( DX_BLEND_DESC,                D3D11_BLEND_DESC,                D3D10_BLEND_DESC );
CPL_DX_RETYPE_SW( DX_DEPTH_STENCIL_DESC,        D3D11_DEPTH_STENCIL_DESC,        D3D10_DEPTH_STENCIL_DESC );
CPL_DX_RETYPE_SW( DX_DEPTH_STENCIL_VIEW_DESC,   D3D11_DEPTH_STENCIL_VIEW_DESC,   D3D10_DEPTH_STENCIL_VIEW_DESC );
CPL_DX_RETYPE_SW( DX_RENDER_TARGET_VIEW_DESC,   D3D11_RENDER_TARGET_VIEW_DESC,   D3D10_RENDER_TARGET_VIEW_DESC );
CPL_DX_RETYPE_SW( DX_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC, D3D10_SHADER_RESOURCE_VIEW_DESC );
CPL_DX_RETYPE_SW( DX_TEXTURE1D_DESC,            D3D11_TEXTURE1D_DESC,            D3D10_TEXTURE1D_DESC );
CPL_DX_RETYPE_SW( DX_TEXTURE2D_DESC,            D3D11_TEXTURE2D_DESC,            D3D10_TEXTURE2D_DESC );
CPL_DX_RETYPE_SW( DX_TEXTURE3D_DESC,            D3D11_TEXTURE3D_DESC,            D3D10_TEXTURE3D_DESC );

CPL_DX_RETYPE_SW( DX_PRIMITIVE_TOPOLOGY, D3D11_PRIMITIVE_TOPOLOGY, D3D10_PRIMITIVE_TOPOLOGY );
CPL_DX_RETYPE_SW( DX_BIND_FLAG,          D3D11_BIND_FLAG,          D3D10_BIND_FLAG );


//
//typedef Core::SmartPtr<D3DDevice>::Com          CpDXDevice;
//typedef Core::SmartPtr<D3DDeviceContext>::Com   CpDXDeviceContext;
//typedef Core::SmartPtr<D3DResource>::Com        SpDxResource;
//typedef Core::SmartPtr<D3DInputLayout>::Com     SpDXInputLayout;
//typedef Core::SmartPtr<DXBuffer>::Com          SpDxBuffer;
//typedef Core::SmartPtr<DXVertexShader>::Com    SpDxVertexShader;
//typedef Core::SmartPtr<DXPixelShader>::Com     SpDxPixelShader;
//typedef Core::SmartPtr<GISwapChain>::Com       SpGISwapChain;
//typedef Core::SmartPtr<DXBlob>::Com            SpDxBlob;
//typedef Core::SmartPtr<DXTexture1D>::Com       SpDxTexture1D;
//typedef Core::SmartPtr<DXTexture2D>::Com       SpDXTexture2D;
//typedef Core::SmartPtr<DXTexture3D>::Com       SpDxTexture3D;
//typedef Core::SmartPtr<DXRasterizerState>::Com SpDxRasterizerState;
//typedef Core::SmartPtr<IDXGIFactory>::Com       SpDxFactory;
//typedef Core::SmartPtr<IDXGIAdapter>::Com       SpGIAdapter;


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DirectX用HRESULTに対応するエラーメッセージ取得関数
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char_cptr GetErrorMessage( HRESULT hr );
void   OutputErrorMessage( HRESULT hr );



/// @cond
namespace zzz_ {


  // _____________________________________________________________________________
  /// @brief DXGIクラスラッパー基底クラス
  ///
  // *****************************************************************************
  class DXGIClassWrapperBase
  {
  protected:
    IDXGIObject* m_ptr_dx_object;
  public:
    DXGIClassWrapperBase() : m_ptr_dx_object(nullptr) {}
    ~DXGIClassWrapperBase()
    {
      RELEASE( m_ptr_dx_object );
    }
  };


  // _____________________________________________________________________________
  /// @brief DirectXクラス用ラッパー
  ///
  // *****************************************************************************
  template< class T_DX_Object >
  class DXGIClassWrapper
    : public DXGIClassWrapperBase
  {
    typedef DXGIClassWrapper< T_DX_Object > type_this;
    typedef T_DX_Object* PDXObject;
  protected:
  public:
    PDXObject operator ->() const
      {
        return static_cast<PDXObject>(m_ptr_dx_object);
      }
      
    template<class T>
    operator T() const { return this->m_sp_dx_object; }
  };

} // namespace zzz_
/// @endcond


using Vector3  = CPL::Math::D3<float>::Vector;
using Vector2  = CPL::Math::D2<float>::Vector;
using Matrix   = CPL::Math::D3<float>::Matrix;
using Matrix2D = CPL::Math::D2<float>::Matrix;

//namespace Core {

// _____________________________________________________________________________
/// @brief DirectXコンポーネント用デリータ
///
// *****************************************************************************
template<class T_Type>
struct DX_DELETER {
  void operator()( T_Type* ptr )
  {
    if( ptr )
    {
      ptr->Release();
    }
  }
};


// 前方宣言
class Window; // CPL::DX::Window

// _____________________________________________________________________________
/// @brief Graphicsインターフェイス
///
// *****************************************************************************
class Graphics_i_
  : public Core::BaseObject
{
  friend class Graphics;
  
public:
  // デバイス作成用パラメータ
  struct CreateDeviceInfo {
    DX::Window*               in_ptr_dx_window; // ウィンドウポインタ
    BOOL                      in_flag_win_mode; // ウィンドウモード
    float                     in_vs_version;    // チェックする頂点シェーダのバージョン
    float                     in_ps_version;    // チェックするピクセルシェーダのバージョン
    UINT                      in_create_device_flags;
    HMODULE                   in_hdl_software_rasterrizer;
    mutable D3D_FEATURE_LEVEL out_feature_levels; // 実際に適用されたフューチャーレベル

    CreateDeviceInfo();
  };
protected:
  struct CreateDeviceInfo2 {
    D3D_DRIVER_TYPE const*   in_driver_types; // ドライバータイプリスト
    UINT                     in_driver_types_num;
    D3D_FEATURE_LEVEL const* in_ptr_feature_levels; // フューチャーレベルリスト
    UINT                     in_feature_levels_num; // フューチャーレベル数
  };

  // DirectX Graphics デバイスポインタ
  CPL_SINGLETON( CpDXDevice, sm_sp_d3d_dev )
  CPL_SINGLETON( CpDXDeviceContext, sm_sp_d3d_IC )

public:
  typedef Core::Array::Dynamic< CpGIAdapter > AdapterTable;

  static CpDXDevice const&
    GetDevice()
    {
      return sm_sp_d3d_dev();
    }
  static CpDXDeviceContext const&
    GetImmediateContext()
    {
      return sm_sp_d3d_IC();
    }
  static void
    SetDevice
      ( DXDevice*        in_sp_d3d_dev
      , DXDeviceContext* in_sp_d3d_dev_IC
      );
  //static void         StaticRelease();
  
  Graphics_i_
  ( DXDevice*        in_ptr_d3d_dev
  , DXDeviceContext* in_ptr_d3d_IC
  );
  
protected:
  Graphics_i_();
  Graphics_i_( InitializeVT_ const& ivt ){}
  
  virtual ~Graphics_i_()
  {
    //StaticRelease();
  }
  
  //virtual bool CallCreateDevice( CreateDeviceInfo const& in_ptr_create_info ) = 0;
  //virtual bool CallCreateRenderTarget() = 0;

public:
  virtual DX::Window const* GetWindow( _in<int> in_index ) const = 0;
  //virtual DX::Window*       GetWindow( _in<int> in_index ) = 0;
  virtual bool              Create( _in<CreateDeviceInfo> io_create_info ) = 0;
  virtual void              Release() = 0;
  virtual HRESULT           AddWindow( DX::Window* in_ptr_dx_window ) = 0;
  virtual size_t            GetWindowNum() const = 0;
  virtual void              SendDestroyWindow( DX::Window* in_ptr_dx_window ) = 0;
  //virtual short2            GetMaxViewSize() const = 0;
  //virtual int               GetDepthBufferSize( pout<u_int2> out_ptr_size, _in<int> in_window_idx = 0 ) const = 0;
  virtual int               EnumAdapters( rout<AdapterTable> out_adapter_table ) const = 0;
  //virtual int               CompDepthBufferSize( _in<u_int2> in_size, pin<u_int2> in_ptr_need_size ) const = 0;
  //virtual HRESULT           SetDepthBufferSize( _in<u_int2> in_size ) = 0;
  //virtual int               ExtendDepthBufferSize( _in<u_int2> in_size ) = 0;
};

} // namespace DX


// _____________________________________________________________________________
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TBTag ToTag( _in<DX::ColorType> in_color );
TBTag& operator << ( rio<TBTag> io_tag, _in<DX::ColorType> in_color );
DX::ColorType& operator << ( rout<DX::ColorType> out_color, _in<TBTag> in_tag );
CPL_DEF_CORE_TAG_RSHIFT_INOUT( DX::ColorType )


} // namespace CPL
