Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ■D3DD2DInteropMutex.cpp
- // Direct3D 11.0とDirect2Dを連携するサンプル(IDXGIKeyedMutexを使う方法)
- // ver 1.0 2012/11/16
- //
- // ■必須環境
- // Windows 7+ or ( Windows Vista SP2 + KB 971644 )
- // 注意 : Direct2Dが必要になるため、Windows VistaではWindows Updateを行う必要あり。
- // VisualStudio 2012+ or ( VisualStudio 2008 Express以降 + DirectX SDK )
- #define _WIN32_WINNT 0x0601
- #include <Windows.h>
- #include <tchar.h>
- #include <d3d11.h>
- #include <d3d10_1.h>
- #include <d2d1.h>
- #include <dwrite.h>
- #include <exception>
- #include <cstring>
- #pragma comment( lib, "d3d11.lib" )
- #pragma comment( lib, "d3d10_1.lib" )
- #pragma comment( lib, "d2d1.lib" )
- #pragma comment( lib, "dwrite.lib" )
- // ウィンドウのサイズ
- static const int WINDOW_WIDTH = 800;
- static const int WINDOW_HEIGHT = 600;
- // ウィンドウのハンドル
- static HWND g_mainWindowHandle = 0;
- // フォントの基本サイズ
- static const float FONT_DEFAULT_SIZE = 48.0f;
- // Win32APIに関する問題が発生したときに投げる例外
- class win32_exception : public std::exception
- {
- public:
- win32_exception( const char *const msg ) : std::exception( msg ) {}
- };
- // Direct3D/2Dに関する問題が発生したときに投げる例外
- class d3d_exception : public std::exception
- {
- public:
- d3d_exception( const char *const msg ) : std::exception( msg ) {}
- };
- class MyD3D
- {
- public:
- IDXGISwapChain *swapChain_;
- IDXGIDevice1 *dxgiDev_;
- ID3D11Device *dev_;
- ID3D11DeviceContext *cont_;
- ID3D10Device1 *dev101_;
- D3D_FEATURE_LEVEL featureLevel_;
- ID3D11Texture2D *backBufferTex_;
- ID3D11RenderTargetView *backBufferRTV_;
- ID2D1RenderTarget *d2dRenderTarget_;
- IDWriteTextFormat *dwriteTextFormat_;
- ID3D11Texture2D *sharedSurfTex_;
- ID3D11ShaderResourceView *sharedSurfSRV_;
- IDXGIKeyedMutex *mutex11_, *mutex101_;
- IDXGISurface1 *dxgiBackBuffer_;
- public:
- void Release()
- {
- #define SAFE_RELEASE( i ) if( (i) ) { (i)->Release(); (i) = nullptr; }
- SAFE_RELEASE( swapChain_ );
- SAFE_RELEASE( dxgiDev_ );
- SAFE_RELEASE( dev_ );
- SAFE_RELEASE( cont_ );
- SAFE_RELEASE( dev101_ );
- SAFE_RELEASE( backBufferTex_ );
- SAFE_RELEASE( backBufferRTV_ );
- SAFE_RELEASE( d2dRenderTarget_ );
- SAFE_RELEASE( dwriteTextFormat_ );
- SAFE_RELEASE( sharedSurfTex_ );
- SAFE_RELEASE( sharedSurfSRV_ );
- SAFE_RELEASE( mutex11_ );
- SAFE_RELEASE( mutex101_ );
- SAFE_RELEASE( dxgiBackBuffer_ );
- #undef SAFE_RELEASE
- }
- void Init()
- {
- HRESULT hr;
- float dpiX, dpiY;
- // スワップチェインの記述
- DXGI_SWAP_CHAIN_DESC sc;
- // 解像度
- sc.BufferDesc.Width = WINDOW_WIDTH;
- sc.BufferDesc.Height = WINDOW_HEIGHT;
- // バックバッファのテクスチャフォーマット
- sc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
- // フレームレート
- sc.BufferDesc.RefreshRate.Denominator = 1;
- sc.BufferDesc.RefreshRate.Numerator = 60;
- // スケール方法
- sc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
- // インタレース方法
- sc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
- // ウィンドウハンドル
- sc.OutputWindow = g_mainWindowHandle;
- // 全画面表示か否か
- sc.Windowed = TRUE;
- // 使用方法
- sc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- // バックバッファの数
- sc.BufferCount = 2;
- // 描画後のバッファの扱い
- sc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
- // MSAA
- sc.SampleDesc.Count = 1;
- sc.SampleDesc.Quality = 0;
- // フラグ
- sc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // 解像度変更が有効
- // 下位互換API
- D3D_FEATURE_LEVEL features[] = {
- D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0
- };
- // フラグ
- UINT d3dFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; // BGRA テクスチャ有効
- #ifndef NDEBUG
- d3dFlags |= D3D11_CREATE_DEVICE_DEBUG; // Debug ビルドならエラー報告を有効
- #endif
- // Direct3Dの作成
- hr = D3D11CreateDeviceAndSwapChain(
- nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, d3dFlags,
- features, ARRAYSIZE( features ), D3D11_SDK_VERSION,
- &sc, &swapChain_,
- &dev_, &featureLevel_, &cont_ );
- if( FAILED( hr ) )
- throw d3d_exception( "D3D11CreateDevice()" );
- // DXGIデバイスの作成
- hr = dev_->QueryInterface<IDXGIDevice1>( &dxgiDev_ );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Device#QueryInterface()" );
- // キューに格納されていく描画コマンドをスワップ時に全てフラッシュする
- dxgiDev_->SetMaximumFrameLatency( 1 );
- // DXGIアダプタ(GPU)の取得
- IDXGIAdapter *adapter;
- hr = dxgiDev_->GetAdapter( &adapter );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIDevice#GetAdapter()" );
- // Direct3D 10.1に関連するパラメータ
- UINT d3d101Flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; // BGRA テクスチャ有効
- #ifndef NDEBUG
- d3d101Flags |= D3D11_CREATE_DEVICE_DEBUG; // Debug ビルドならエラー報告を有効
- #endif
- D3D10_FEATURE_LEVEL1 feature101;
- switch( featureLevel_ ) {
- case D3D_FEATURE_LEVEL_9_1: feature101 = D3D10_FEATURE_LEVEL_9_1; break;
- case D3D_FEATURE_LEVEL_9_2: feature101 = D3D10_FEATURE_LEVEL_9_2; break;
- case D3D_FEATURE_LEVEL_9_3: feature101 = D3D10_FEATURE_LEVEL_9_3; break;
- case D3D_FEATURE_LEVEL_10_0: feature101 = D3D10_FEATURE_LEVEL_10_0; break;
- default: feature101 = D3D10_FEATURE_LEVEL_10_1; break;
- }
- // Direct3D 10.1の作成
- hr = D3D10CreateDevice1(
- adapter, D3D10_DRIVER_TYPE_HARDWARE, 0, d3d101Flags,
- feature101, D3D10_1_SDK_VERSION, &dev101_ );
- if( FAILED( hr ) )
- throw d3d_exception( "D3D10CreateDevice1()" );
- // バックバッファの取得
- hr = swapChain_->GetBuffer( 0, IID_PPV_ARGS( &backBufferTex_ ) );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGISwapChain#GetBuffer()" );
- // バックバッファのレンダーターゲットビューの作成
- hr = dev_->CreateRenderTargetView( backBufferTex_, nullptr, &backBufferRTV_ );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Device#CreateRenderTargetView()" );
- // 共有するテクスチャの作成
- D3D11_TEXTURE2D_DESC texDesc;
- ZeroMemory( &texDesc, sizeof( texDesc ) );
- texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
- texDesc.Width = sc.BufferDesc.Width;
- texDesc.Height = sc.BufferDesc.Height;
- texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
- texDesc.Usage = D3D11_USAGE_DEFAULT;
- texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
- texDesc.SampleDesc.Count = 1;
- texDesc.ArraySize = 1;
- texDesc.MipLevels = 1;
- hr = dev_->CreateTexture2D( &texDesc, nullptr, &sharedSurfTex_ );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Device#CreateTexture2D()" );
- hr = dev_->CreateShaderResourceView(
- sharedSurfTex_, nullptr, &sharedSurfSRV_ );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Device#CreateShaderResourceView()" );
- //
- hr = sharedSurfTex_->QueryInterface( IID_PPV_ARGS( &mutex11_ ) );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Texture2D#QueryInterface()" );
- IDXGIResource *dxgiRes;
- hr = sharedSurfTex_->QueryInterface( IID_PPV_ARGS( &dxgiRes ) );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D11Texture2D#QueryInterface()" );
- HANDLE hShared;
- hr = dxgiRes->GetSharedHandle( &hShared );
- dxgiRes->Release();
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIResource#GetSharedHandle()" );
- hr = dev101_->OpenSharedResource( hShared, IID_PPV_ARGS( &dxgiBackBuffer_ ) );
- if( FAILED( hr ) )
- throw d3d_exception( "ID3D10Device1#OpenSharedResource()" );
- hr = dxgiBackBuffer_->QueryInterface( IID_PPV_ARGS( &mutex101_ ) );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGISurface1#QueryInterface()" );
- // Direct2Dのファクトリーの作成
- D2D1_FACTORY_OPTIONS d2dOpt;
- ZeroMemory( &d2dOpt, sizeof d2dOpt );
- ID2D1Factory *d2dFactory;
- hr = D2D1CreateFactory(
- D2D1_FACTORY_TYPE_SINGLE_THREADED,
- __uuidof( ID2D1Factory ),
- &d2dOpt,
- reinterpret_cast<void**>( &d2dFactory ) );
- if( FAILED( hr ) )
- throw d3d_exception( "D2D1CreateFactory()" );
- // DPIの取得
- d2dFactory->GetDesktopDpi( &dpiX, &dpiY );
- // Direct2Dの描画先となるレンダーターゲットを作成
- D2D1_RENDER_TARGET_PROPERTIES d2dProp =
- D2D1::RenderTargetProperties(
- D2D1_RENDER_TARGET_TYPE_HARDWARE,
- D2D1::PixelFormat( DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED ),
- dpiX,
- dpiY );
- hr = d2dFactory->CreateDxgiSurfaceRenderTarget(
- dxgiBackBuffer_, &d2dProp, &d2dRenderTarget_ );
- if( FAILED( hr ) )
- throw d3d_exception( "ID2D1Factory#CreateDxgiSurfaceRenderTarget()" );
- // DirectWriteのファクトリの作成
- IDWriteFactory *dwriteFactory;
- hr = DWriteCreateFactory(
- DWRITE_FACTORY_TYPE_SHARED,
- __uuidof( dwriteFactory ),
- reinterpret_cast<IUnknown**>( &dwriteFactory ) );
- if( FAILED( hr ) )
- throw d3d_exception( "DWriteCreateFactory()" );
- // テキストフォーマットの作成
- hr = dwriteFactory->CreateTextFormat(
- L"Meiryo UI", nullptr,
- DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
- FONT_DEFAULT_SIZE, L"", &dwriteTextFormat_ );
- dwriteFactory->Release();
- if( FAILED( hr ) )
- throw d3d_exception( "IDWriteFactory#CreateTextFormat()" );
- // 文字の位置の設定
- hr = dwriteTextFormat_->SetTextAlignment( DWRITE_TEXT_ALIGNMENT_CENTER );
- if( FAILED( hr ) )
- throw d3d_exception( "IDWriteTextFormat#SetTextAlignment()" );
- // パラグラフの指定
- hr = dwriteTextFormat_->SetParagraphAlignment( DWRITE_PARAGRAPH_ALIGNMENT_NEAR );
- if( FAILED( hr ) )
- throw d3d_exception( "IDWriteTextFormat#SetParagraphAlignment()" );
- }
- };
- static MyD3D g_d3d;
- // 描画
- void draw()
- {
- HRESULT hr;
- static float el = 0.0f;
- el += 1.0f;
- if( el > 360.0f ) el = 0.0f;
- // Direct3D
- hr = g_d3d.mutex11_->AcquireSync( 0, INFINITE );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#AcquireSync()" );
- float clearColor[] = { 0.1f, 0.2f, 0.4f, 1.0f };
- g_d3d.cont_->ClearRenderTargetView( g_d3d.backBufferRTV_, clearColor );
- hr = g_d3d.mutex11_->ReleaseSync( 1 );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#ReleaseSync()" );
- // Direct2D
- hr = g_d3d.mutex101_->AcquireSync( 1, INFINITE );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#AcquireSync()" );
- D2D1_COLOR_F color;
- color = D2D1::ColorF(
- min( 120.0f, max( 0, 120.0f - el ) ) / 120.0f,
- min( 120.0f, max( 0, el - 120.0f ) ) / 120.0f,
- min( 120.0f, max( 0, 240.0f - el ) ) / 120.0f,
- 1.0f );
- ID2D1SolidColorBrush *brush;
- hr = g_d3d.d2dRenderTarget_->CreateSolidColorBrush( color, &brush );
- if( FAILED( hr ) )
- throw d3d_exception( "ID2D1DeviceContext#CreateSolidColorBrush()" );
- D2D1_RECT_F rect;
- rect = D2D1::RectF( 0 + el, 500, 440 + el, 550 );
- g_d3d.d2dRenderTarget_->BeginDraw();
- g_d3d.d2dRenderTarget_->Clear( D2D1::ColorF( 0.0f, 0.5f, 0.0f, 0.0f ) );
- g_d3d.d2dRenderTarget_->FillRectangle( &rect, brush );
- // DirectWrite
- rect = D2D1::RectF( 0 + el, 200, 450 + el, 201 );
- TCHAR *drawText = _T( "Hello HELL World!!!\n地球の未来にご奉仕するにゃん!" );
- g_d3d.d2dRenderTarget_->DrawText(
- drawText, _tcslen( drawText ), g_d3d.dwriteTextFormat_, &rect, brush );
- g_d3d.d2dRenderTarget_->EndDraw();
- brush->Release();
- hr = g_d3d.mutex101_->ReleaseSync( 2 );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#ReleaseSync()" );
- // Direct3D
- hr = g_d3d.mutex11_->AcquireSync( 2, INFINITE );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#AcquireSync()" );
- g_d3d.cont_->CopyResource( g_d3d.backBufferTex_, g_d3d.sharedSurfTex_ );
- hr = g_d3d.mutex11_->ReleaseSync( 0 );
- if( FAILED( hr ) )
- throw d3d_exception( "IDXGIKeyedMutex#ReleaseSync()" );
- // DXGI
- g_d3d.swapChain_->Present( 1, 0 );
- }
- // ウィンドウプロシージャ
- LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
- {
- PAINTSTRUCT ps;
- HDC hdc;
- switch( message ) {
- case WM_KEYDOWN:
- if( wParam == VK_ESCAPE ) {
- PostMessage( hWnd, WM_DESTROY, 0, 0 );
- return 0;
- }
- break;
- case WM_PAINT:
- hdc = BeginPaint( hWnd, &ps );
- EndPaint( hWnd, &ps );
- break;
- case WM_DESTROY:
- PostQuitMessage( 0 );
- break;
- default:
- return DefWindowProc( hWnd, message, wParam, lParam );
- }
- return 0;
- }
- // ウィンドウを作成する
- static HWND setupWindow( int width, int height )
- {
- WNDCLASSEX wcex;
- wcex.cbSize = sizeof( WNDCLASSEX );
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = (HMODULE)GetModuleHandle( 0 );
- wcex.hIcon = nullptr;
- wcex.hCursor = LoadCursor( nullptr, IDC_ARROW );
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = nullptr;
- wcex.lpszClassName = _T( "WindowClass" );
- wcex.hIconSm = nullptr;
- if( !RegisterClassEx( &wcex ) ) {
- throw win32_exception( "RegisterClassEx()" );
- }
- RECT rect = { 0, 0, width, height };
- AdjustWindowRect( &rect, WS_OVERLAPPEDWINDOW, FALSE );
- const int windowWidth = ( rect.right - rect.left );
- const int windowHeight = ( rect.bottom - rect.top );
- HWND hWnd = CreateWindow( _T("WindowClass"), _T("D3DD2DInterop"),
- WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, windowWidth, windowHeight,
- nullptr, nullptr, nullptr, nullptr );
- if( !hWnd ) {
- throw win32_exception( "CreateWindow()" );
- }
- return hWnd;
- }
- // エントリーポイント
- int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
- {
- MSG msg;
- ZeroMemory( &msg, sizeof msg );
- // Debugでは例外を開発環境が受け取り,Releaseではメッセージを表示して強制的に終了する
- #ifdef NDEBUG
- try {
- #endif
- g_mainWindowHandle = setupWindow( WINDOW_WIDTH, WINDOW_HEIGHT );
- ShowWindow( g_mainWindowHandle, SW_SHOW );
- UpdateWindow( g_mainWindowHandle );
- g_d3d.Init();
- while( msg.message != WM_QUIT ) {
- BOOL r = PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE );
- if( r == 0 ) {
- draw();
- }
- else {
- DispatchMessage( &msg );
- }
- }
- #ifdef NDEBUG
- } catch( std::exception &e ) {
- MessageBoxA( g_mainWindowHandle, e.what(), "D3DD2DInterop - 問題が発生しました", MB_ICONSTOP ); }
- #endif
- g_d3d.Release();
- return static_cast<int>( msg.wParam );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement