dev.nlited.com

>>

MyD2D: SwapChains Method

<<<< prev
next >>>>

2016-01-27 00:37:58 chip Page 1539 📢 PUBLIC

Jan 26 2016



MyD2D.cpp: /*************************************************************************/ /** MyD2D.cpp: Wrapper around Direct2D, SwapChain method. **/ /** (C)2013 nlited systems, Chip Doran **/ /*************************************************************************/ #include <Windows.h> #include <wrl.h> #include <d2d1.h> #include <d2d1_1.h> #include <d3d11.h> #include <d3d11_1.h> #include <dwrite.h> #include <wincodec.h> #include <dxgidebug.h> #include "Util.h" #include "MyD2D.h" using namespace Microsoft::WRL; //ComPtr<> using namespace D2D1; //Direct2D version 1 class MyD2D { public: static MyD2D *Ptr(HD2D hD2D); static int Create(HD2D *phD2D, HINSTANCE hModule); int Destroy(void); int CreateResourcesWnd(HWND hWnd); int ReleaseResources(HWND hWnd); int Resize(const RECT *pR); int Begin(ID2D1DeviceContext **ppDC); ID2D1DeviceContext *GetDC(void); int End(HRESULT *pWinErr); IDWriteTextFormat *GetTextFormatter(void); int BitmapCreate(struct Bitmap_s *pBitmap); //Data UINT32 Signature; private: MyD2D(void); ~MyD2D(void); int Create2(HINSTANCE hModule); int CreateSwapChain(void); int CreateSwapBitmap(); int BitmapCreateBMP(struct Bitmap_s *pBitmap); int BitmapCreateOther(struct Bitmap_s *pBitmap); //Data HINSTANCE hInst; HWND hWnd; bool IsDrawing; ID2D1Factory1 *pD2DFactory; IDWriteFactory *pDWriteFactory; IWICImagingFactory *pWICFactory; ID2D1DeviceContext *pD2DC; ComPtr<IDXGISwapChain1> pSwapChain; IDWriteTextFormat *pTextFmt; D2D1_PIXEL_FORMAT PxlFmt; UINT64 PaintTime; }; /*************************************************************************/ /** Public interface **/ /*************************************************************************/ int MyD2DCreate(HD2D *phD2D, HINSTANCE hModule) { if(IsBadPtr(phD2D,sizeof(*phD2D),BADPTR_WRITE)) return(ERR_BADPTR); return(MyD2D::Create(phD2D,hModule)); } int MyD2DDestroy(HD2D hD2D) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->Destroy()); } int MyD2DCreateResourcesWnd(HD2D hD2D, HWND hWnd) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->CreateResourcesWnd(hWnd)); } int MyD2DReleaseResources(HD2D hD2D, HWND hWnd) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->ReleaseResources(hWnd)); } int MyD2DResize(HD2D hD2D,const RECT *pR) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->Resize(pR)); } int MyD2DBegin(HD2D hD2D, ID2D1DeviceContext **ppDC) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->Begin(ppDC)); } ID2D1DeviceContext *MyD2DGetDC(HD2D hD2D) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(0); return(pD2D->GetDC()); } int MyD2DEnd(HD2D hD2D, HRESULT *pWinErr) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); return(pD2D->End(pWinErr)); } IDWriteTextFormat *MyD2DTextFormat(HD2D hD2D) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(0); return(pD2D->GetTextFormatter()); } int MyD2DBitmapCreate(HD2D hD2D, struct Bitmap_s *pBitmap) { MyD2D *pD2D= MyD2D::Ptr(hD2D); if(!pD2D) return(ERR_BADHANDLE); if(IsBadPtr(pBitmap,sizeof(*pBitmap),BADPTR_RW)) return(ERR_BADPTR); return(pD2D->BitmapCreate(pBitmap)); } /*************************************************************************/ /** Public internals **/ /*************************************************************************/ MyD2D *MyD2D::Ptr(HD2D hD2D) { MyD2D *pD2D= (MyD2D*)hD2D; if(!hD2D || IsBadPtr(pD2D,sizeof(*pD2D),BADPTR_RW) || pD2D->Signature!=SIGNATURE_MYD2D) pD2D= 0; return(pD2D); } int MyD2D::Create(HD2D *phD2D, HINSTANCE hModule) { int Err= ERR_OK; MyD2D *pD= new MyD2D; if(!pD) { Err= Error(ERR_NOMEM,__FUNCTION__": Unable to alloc %d",sizeof(*pD)); } else if(IsErr(Err= pD->Create2(hModule))) { delete pD; } else { *phD2D= (HD2D)pD; } return(Err); } static void Report(void) { #if 0 typedef HRESULT (__stdcall *fPtr)(const IID&, void **); HMODULE hDLL= GetModuleHandleW(L"dxgidebug.dll"); fPtr DXIGetDebugInterface= (fPtr)GetProcAddress(hDLL,"DXGIGetDebugInterface"); DXGIGetDebugInterface(__uuidof(IDXGIDebug),(void**)&pDXGIDebug); DXGIGetDebugInterface(__uuidof(IDXGIInfoQueue),(void**)&pIDXGIInfoQueue); const char Name[]= "pFactory"; pFactory->SetPrivateData(WKPDID_D3DDebugObjectName,sizeof(Name)-1,Name); IDXGIDebug *pDebug; if(SUCCEEDED(DXGIGetDebugInterface(__uuidof(IDXGIDebug),(void**)&pDebug))) { pDebug->ReportLiveObjects(DXGI_DEBUG_ALL,DXGI_DEBUG_RLO_ALL); } #endif } int MyD2D::Destroy(void) { int Err= ERR_OK; delete this; Report(); return(Err); } int MyD2D::CreateResourcesWnd(HWND hWnd) { int Err= ERR_OK; HRESULT WinErr; RECT rWnd; this->hWnd= hWnd; PxlFmt= PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_PREMULTIPLIED); GetClientRect(hWnd,&rWnd); //First we need a Direct2D Factory... D2D1_FACTORY_OPTIONS options; options.debugLevel= D2D1_DEBUG_LEVEL_INFORMATION; if(!pD2DFactory && !SUCCEEDED(WinErr= D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,options,&pD2DFactory))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create Direct2D factory [%d]",WinErr)); if(IsErr(Err= CreateSwapChain())) return(Error(Err,__FUNCTION__": Unable to create swap chain.")); //Then we need a text Writer Factory... if(!pDWriteFactory) { WinErr= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,__uuidof(IDWriteFactory),reinterpret_cast<IUnknown**>(&pDWriteFactory)); if(!SUCCEEDED(WinErr)) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create WriteFactory. [%d]",WinErr)); } //Then we need a Text Writer Formatter... if(!pTextFmt) { WinErr= pDWriteFactory->CreateTextFormat(L"Bitstream Vera Sans Mono",0,DWRITE_FONT_WEIGHT_NORMAL,DWRITE_FONT_STYLE_NORMAL,DWRITE_FONT_STRETCH_NORMAL,(FLOAT)12,L"en-us",&pTextFmt); if(!SUCCEEDED(WinErr)) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create TextFormat. [%d]",WinErr)); } //Create WIC Factory... if(!pWICFactory) { //Be sure to define _WIN32_WINNT_=0x0601 in the project settings for Win7 compatibility! if(!SUCCEEDED(WinErr= CoCreateInstance(CLSID_WICImagingFactory,0,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pWICFactory)))) { return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create WIC Factory. [%d]",WinErr)); } } return(ERR_OK); } int MyD2D::ReleaseResources(HWND hWnd) { int Err= ERR_OK; SafeRelease(pTextFmt); SafeRelease(pDWriteFactory); SafeRelease(pD2DC); SafeRelease(pD2DFactory); SafeRelease(pWICFactory); return(Err); } int MyD2D::Resize(const RECT *pR) { int Err= ERR_OK; HRESULT WinErr; pD2DC->SetTarget(0); if(!SUCCEEDED(WinErr= pSwapChain->ResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0))) { Err= Error(ERR_FAILED,"MyD2D:Resize: Unable to resize swap chain buffers. [%X]",WinErr); } else if(IsErr(Err= CreateSwapBitmap())) { Err= Error(Err,"MyD2D:Resize: Unable to create SwapBitmap."); } return(Err); } int MyD2D::Begin(ID2D1DeviceContext **ppDC) { int Err= ERR_OK; LARGE_INTEGER Start,End; if(!pD2DC) return(ERR_NOINIT); if(!pSwapChain.Get()) return(ERR_NOINIT); if(IsDrawing) return(ERR_BUSY); IsDrawing= true; QueryPerformanceCounter(&Start); pD2DC->BeginDraw(); QueryPerformanceCounter(&End); PaintTime= End.QuadPart - Start.QuadPart; *ppDC= pD2DC; return(Err); } ID2D1DeviceContext *MyD2D::GetDC(void) { return(pD2DC); } int MyD2D::End(HRESULT *pWinErr) { int Err= ERR_OK; HRESULT WinErr= 0; D2D1_TAG Tag1,Tag2; LARGE_INTEGER Start,End; if(!IsDrawing) { Err= ERR_NOT_READY; } else { IsDrawing= false; QueryPerformanceCounter(&Start); WinErr= pD2DC->EndDraw(&Tag1,&Tag2); if(!SUCCEEDED(WinErr)) { Err= Error(ERR_FAILED,"MyD2D:End: DrawEnd failed: (%X:%d,%d)",WinErr,Tag1,Tag2); } else if(!SUCCEEDED(WinErr= pSwapChain->Present(1,0))) { Err= Error(ERR_FAILED,"MyD2D:End: Present failed: (%X)",WinErr); } QueryPerformanceCounter(&End); PaintTime+= (End.QuadPart-Start.QuadPart); if(!IsErr(Err)) Err= (int)PaintTime; } if(pWinErr) *pWinErr= WinErr; return(Err); } IDWriteTextFormat *MyD2D::GetTextFormatter(void) { return(pTextFmt); } int MyD2D::BitmapCreate(struct Bitmap_s *pBitmap) { int Err= ERR_OK; if(IsErr(Err= BitmapCreateBMP(pBitmap))) { if(IsErr(Err= BitmapCreateOther(pBitmap))) { Err= Error(Err,__FUNCTION__": Unable to load bitmap '%S'",pBitmap->Name); } } return(Err); } /*************************************************************************/ /** Private internals **/ /*************************************************************************/ MyD2D::MyD2D(void) { memset(this,0,sizeof(*this)); Signature= SIGNATURE_MYD2D; } MyD2D::~MyD2D(void) { Signature|= SIGNATURE_INVALID; ReleaseResources(0); } int MyD2D::Create2(HINSTANCE hModule) { int Err= ERR_OK; hInst= hModule; return(Err); } int MyD2D::CreateSwapChain(void) { int Err= ERR_OK; HRESULT WinErr; ComPtr<IDXGIFactory2> pDxFactory; ComPtr<ID3D11Device> pD3Device; //Used to draw to the back buffer ComPtr<IDXGIDevice> pDxDevice; ComPtr<ID2D1Device> pD2Device; ComPtr<IDXGIAdapter> pAdapter; DXGI_SWAP_CHAIN_DESC1 SwapProp; //Create a D3D device if(!SUCCEEDED(WinErr= D3D11CreateDevice(0,D3D_DRIVER_TYPE_HARDWARE,0,D3D11_CREATE_DEVICE_BGRA_SUPPORT,0,0,D3D11_SDK_VERSION,pD3Device.GetAddressOf(),0,0))) { if(WinErr==DXGI_ERROR_UNSUPPORTED) { Warn(ERR_NOT_SUPPORTED,__FUNCTION__": D3D hardware driver not available."); WinErr= D3D11CreateDevice(0,D3D_DRIVER_TYPE_WARP,0,D3D11_CREATE_DEVICE_BGRA_SUPPORT,0,0,D3D11_SDK_VERSION,&pD3Device,0,0); } if(!SUCCEEDED(WinErr)) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create D3D devicee. [%X]",WinErr)); } pD3Device.As(&pDxDevice); if(!SUCCEEDED(WinErr= pD2DFactory->CreateDevice(pDxDevice.Get(),pD2Device.GetAddressOf()))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create D2DDevice. [%X]",WinErr)); if(!SUCCEEDED(WinErr= pD2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,&pD2DC))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create Direct2D DeviceContext. [%X]",WinErr)); if(!SUCCEEDED(WinErr= pDxDevice->GetAdapter(&pAdapter))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create DxAdapter. [%X]",WinErr)); if(!SUCCEEDED(WinErr= pAdapter->GetParent(__uuidof(pDxFactory),reinterpret_cast<void**>(pDxFactory.GetAddressOf())))) //if(!SUCCEEDED(WinErr= pAdapter->GetParent(__uuidof(IDXGIFactory2),reinterpret_cast<void**>(pDxFactory.GetAddressOf())))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to obtain DxFactory. [%X]",WinErr)); memset(&SwapProp,0,sizeof(SwapProp)); SwapProp.Format= DXGI_FORMAT_B8G8R8A8_UNORM; SwapProp.SampleDesc.Count= 1; SwapProp.BufferUsage= DXGI_USAGE_RENDER_TARGET_OUTPUT; SwapProp.BufferCount= 2; if(!SUCCEEDED(WinErr= pDxFactory->CreateSwapChainForHwnd(pDxDevice.Get(),hWnd,&SwapProp,0,0,pSwapChain.GetAddressOf()))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create swap chain. [%X]",WinErr)); if(IsErr(Err= CreateSwapBitmap())) return(Error(Err,__FUNCTION__": Unable to create SwapBitmap.")); return(Err); } int MyD2D::CreateSwapBitmap() { int Err= ERR_OK; HRESULT WinErr; ComPtr<IDXGISurface> pSurface; D2D1_BITMAP_PROPERTIES1 BmpProp; ComPtr<ID2D1Bitmap1> pBitmap; float dpiX,dpiY; //Create a surface on the back buffer... if(!SUCCEEDED(WinErr= pSwapChain->GetBuffer(0,__uuidof(pSurface),reinterpret_cast<void**>(pSurface.GetAddressOf())))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create DX surface. [%X]",WinErr)); //Create a bitmap on the surface... BmpProp= BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,PxlFmt); if(!SUCCEEDED(WinErr= pD2DC->CreateBitmapFromDxgiSurface(pSurface.Get(),BmpProp,pBitmap.GetAddressOf()))) return(Error(ERR_SYSCREATE,__FUNCTION__": Unable to create D2D Bitmap. [%X]",WinErr)); pD2DC->SetTarget(pBitmap.Get()); pD2DFactory->GetDesktopDpi(&dpiX,&dpiY); pD2DC->SetDpi(dpiX,dpiY); return(Err); } int MyD2D::BitmapCreateBMP(struct Bitmap_s *pBitmap) { int Err= ERR_OK; HRESULT WinErr; HBITMAP hBitmap= 0; IWICBitmap *pWICBitmap= 0; IWICFormatConverter *pConverter= 0; if(!pD2DC) { Err= Error(ERR_NOINIT,__FUNCTION__": No D2DC yet, unable to load '%S'",pBitmap->Name); } else if(!(hBitmap= LoadBitmap(hInst,pBitmap->Name))) { //Step 1: Load and create GDI bitmap from resource (Steps 1-4 of MSDN example) Err= Warn(ERR_NOTFOUND,__FUNCTION__": Unable to LoadBitmap(%S)!",pBitmap->Name); } else if(!SUCCEEDED(WinErr= pWICFactory->CreateBitmapFromHBITMAP(hBitmap,0,WICBitmapIgnoreAlpha,&pWICBitmap))) { //Step 2: Convert HBITMAP to WICBitmap //This upscales to 32bit+Alpha //NOTE: Ignore alpha if source doesn't have it, otherwise alpha will be zero and the bitmap will be invisible! Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create WIC bitmap for %S. [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pWICFactory->CreateFormatConverter(&pConverter))) { //Step 3: Create a WIC convert to transform bitmap to RenderTgt's native format Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create WIC Converter. [%d]",WinErr); } else if(!SUCCEEDED(WinErr= pConverter->Initialize(pWICBitmap,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,0,0,WICBitmapPaletteTypeMedianCut))) { //Step 4: Initialize converter to take 32bit PBGRA Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to initialize format converter. [%d]",WinErr); } else if(!SUCCEEDED(WinErr= pD2DC->CreateBitmapFromWicBitmap(pConverter,&pBitmap->pBitmap))) { //Step 5: Convert WIC bitmap to RenderTgt's native format Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create RenderTarget bitmap. [%d]",WinErr); } else { pBitmap->SizeDPI= pBitmap->pBitmap->GetSize(); Debug(DBG_BITMAP,__FUNCTION__": BitmapBMP(%S) loaded as %X.",pBitmap->Name,pBitmap->pBitmap); } SafeRelease(pConverter); SafeRelease(pWICBitmap); if(hBitmap) DeleteObject(hBitmap); return(Err); } int MyD2D::BitmapCreateOther(struct Bitmap_s *pBitmap) { int Err= ERR_OK; HRESULT WinErr; HRSRC hResource= 0; HGLOBAL hData; void *pData; DWORD DataSz; IWICStream *pStream= 0; IWICBitmapDecoder *pDecoder= 0; IWICBitmapFrameDecode *pSource= 0; IWICFormatConverter *pConverter= 0; if(!pD2DC) { Err= Error(ERR_NOINIT,__FUNCTION__": No D2DC yet, unable to load '%S'",pBitmap->Name); } else if(!(hResource= FindResource(hInst,pBitmap->Name,pBitmap->Type))) { //Step 1: Find the resource //NOTE: This fails for Bitmap resources (for unknown reason) Err= Error(ERR_NOTFOUND,__FUNCTION__": Bitmap '%S' not found.",pBitmap->Name); } else if(!(hData= LoadResource(hInst,hResource))) { //Step 2: Load the resource into memory Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to load resource '%S'",pBitmap->Name); } else if(!(pData= LockResource(hData))) { //Step 3: Lock the resource to process memory. Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to lock resource '%S'",pBitmap->Name); } else if(!(DataSz= SizeofResource(hInst,hResource))) { //Step 4: Determine the size of the resource in bytes (it's still memory!) Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to determine size of '%S'",pBitmap->Name); } else if(!SUCCEEDED(WinErr= pWICFactory->CreateStream(&pStream))) { //Step 5: Create the WIC stream to read the resource Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create WIC stream for '%S'",pBitmap->Name); } else if(!SUCCEEDED(WinErr= pStream->InitializeFromMemory(reinterpret_cast<BYTE*>(pData),DataSz))) { //Step 6: Initialize the stream Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to parse bitmap '%S' stream. [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pWICFactory->CreateDecoderFromStream(pStream,0,WICDecodeMetadataCacheOnLoad,&pDecoder))) { //Step 7: Create a stream decoder Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to decode '%S' [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pDecoder->GetFrame(0,&pSource))) { //Step 8: Read the first frame Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to extract frame from '%S' [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pWICFactory->CreateFormatConverter(&pConverter))) { //Step 9: Create a format converter Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create format converter for '%S' [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pConverter->Initialize(pSource,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,0,0,WICBitmapPaletteTypeMedianCut))) { //Step 10: Initialize the converter Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to convert '%S' [%d]",pBitmap->Name,WinErr); } else if(!SUCCEEDED(WinErr= pD2DC->CreateBitmapFromWicBitmap(pConverter,0,&pBitmap->pBitmap))) { //Step 11: Convert the bitmap from device-independent WIC to device-specific RenderTgt Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create RenderTgt bitmap for '%S' [%d]",pBitmap->Name,WinErr); } else { //Done! Retrieve the original size of the image. pBitmap->SizeDPI= pBitmap->pBitmap->GetSize(); Debug(DBG_BITMAP,__FUNCTION__": BitmapOther(%S) loaded as %X.",pBitmap->Name,pBitmap->pBitmap); } SafeRelease(pConverter); SafeRelease(pSource); SafeRelease(pDecoder); SafeRelease(pStream); UnlockResource(hData); return(ERR_OK); }


WebV7 (C)2018 nlited | Rendered by tikope in 33.622ms | 3.16.50.1