dev.nlited.com

>>

D3Text Code

<<<< prev

2017-11-25 19:52:44 chip Page 2065 📢 PUBLIC

Nov 25 2017

D3Text code. The details are described here: Direct2D in Direct3D


WARNING!

This code may have a bug that causes ~D3Text() to kick out a _com_error exception when the D3Text object is destroyed. It seems to work fine otherwise. I am currently investigating...

It may be a problem with the VMware graphics driver or some other local thing. I can run the release build natively (outside the VM) without any apparent problems. I need to try running it natively on a system with Visual Studio installed.



Example Usage: void Game::RenderText(void) { D3Text text(d3dDevice.Get(),d3dContext.Get(),swapChain.Get()); // Print frame status text. text.SetColor(D2D1::ColorF(D2D1::ColorF::Black)); text.Write(L"Frame %06llu %ufps (%6.2f,%6.2f,%6.2f) %3.1f %3.1f" ,frameCt,frameRate ,viewPt.x,viewPt.y,viewPt.z ,XMConvertToDegrees(viewVec.y),XMConvertToDegrees(viewVec.z) ); // Draw frame rate graph. text.Rectangle(D2D1::Point2F(10.0f,40.0f),D2D1::Point2F(210.0f,60.0f)); D2D1_POINT_2F pt0,pt1; pt0= { 10.0f,60.0f-std::min((INT16)120,vecFrameRate[0])*(20.0f/120.0f) }; text.SetColor(D2D1::ColorF(D2D1::ColorF::Yellow)); for(UINT n1=1;n1<vecFrameRate.size();n1++) { pt1= { 10.0f+n1,60.0f-std::min((INT16)120,vecFrameRate[n1])*(20.0f/120.0f) }; text.Line(pt0,pt1); pt0= pt1; } }
D3Text.h: #define D3TEXT_OBJ_SIZE 616 class D3Text { public: D3Text(void); D3Text(ID3D11Device *pDevice, ID3D11DeviceContext *pContext, IDXGISwapChain1 *pSwap); ~D3Text(void); HRESULT Create(ID3D11Device *pDevice, ID3D11DeviceContext *pContext); void Begin(IDXGISwapChain1 *pSwap); void End(void); void Reset(void); void SetColor(D2D1::ColorF &clr); UINT Write(const WCHAR *Fmt,...); void Line(D2D1_POINT_2F &pt0, D2D1_POINT_2F &pt1); void Rectangle(D2D1_POINT_2F &pt0, D2D1_POINT_2F &pt1); private: class nD3Text *pObj; BYTE Obj[D3TEXT_OBJ_SIZE]; };
D3Text.cpp: /*************************************************************************/ /** D3Text.cpp: Use Direct2D and DirectWrite in a Direct3D environment. **/ /** (C)2017 nlited systems inc. **/ /*************************************************************************/ #include "pch.h" #include <new> #include <stdio.h> #include <windows.h> #include <d2d1_2.h> #include <d2d1_1helper.h> #include <dwrite_1.h> #include <wrl/client.h> #include "Game.h" #pragma message(__FILE__": Optimizer disabled.") #pragma optimize("",off) #pragma comment(lib,"d2d1.lib") #pragma comment(lib,"dwrite.lib") using namespace D2D1; #define Zero(O) memset(&O,0,sizeof(O)) #define STRSIZE(S) (sizeof(S)/sizeof(S[0]) - 1) #define CHECK_OBJ_SIZE(name,size) \ template<int N> struct name##_CheckSizeT { short operator()() { return((N+0x7FFF)-size); } }; \ static void name##_CheckSize(void) { name##_CheckSizeT<sizeof(name)>()(); } #define SafeRelease(pObj) { if(pObj) pObj->Release(); pObj= 0; } /*************************************************************************/ /** nD3Text: Internal class. **/ /*************************************************************************/ #define TEXT_MAX 200 class nD3Text { public: nD3Text(D3Text *pD3Text); ~nD3Text(void); HRESULT Create(void); HRESULT Create(ID3D11Device *pDevice, ID3D11DeviceContext *pContext); void Reset(void); HRESULT Begin(IDXGISwapChain1 *pSwap); HRESULT End(void); void SetColor(ColorF &clr); UINT Write(const WCHAR *Fmt, va_list ArgList); void Line(D2D1_POINT_2F &pt0, D2D1_POINT_2F &pt1); void Rectangle(D2D1_POINT_2F &pt0,D2D1_POINT_2F &pt1); private: D3Text *pText; //Parent D3Text interface object. bool isCreated; //Was everything created successfully? bool isBegun; //Was Begin() called? WCHAR Text[TEXT_MAX]; //Final output text. UINT ChrCt; //Valid characters in Text[] WCHAR FontName[40]; //Font face DWRITE_FONT_WEIGHT FontWgt; //Font weight DWRITE_FONT_WEIGHT_REGULAR DWRITE_FONT_STYLE FontStyle; //Font style DWRITE_FONT_STYLE_NORMAL float FontHgt; //Font height (points) ID2D1SolidColorBrush *pbrText; //Text color IDWriteTextFormat *pFormat; //DWrite text formatter ID3D11Device *p3dDevice; //Direct3D 11.1 device ID3D11DeviceContext *p3dContext; //Direct3D 11.1 device context IDXGIDevice *pdxDevice; //Common DirectX device IDXGISurface *pdxSurface; //Common DirectX surface, derived from the 3D swap chain. ID2D1Device1 *p2dDevice; //Direct2D device ID2D1DeviceContext1 *p2dContext; //Direct2D device context ID2D1Bitmap1 *p2dBitmap; //Direct2D target bitmap D2D1_SIZE_F szLayout; //Size (pixels) of p2dBitmap D2D1_RECT_F rLayout; //Layout rectangle }; // If this generates a compiler warning, DBTEXT_OBJ_SIZE needs to be updated. CHECK_OBJ_SIZE(nD3Text,D3TEXT_OBJ_SIZE); /*************************************************************************/ /** Public interface **/ /*************************************************************************/ D3Text::D3Text(void) { Zero(Obj); pObj= new(Obj) nD3Text(this); } D3Text::D3Text(ID3D11Device *pDevice, ID3D11DeviceContext *pContext, IDXGISwapChain1 *pSwap) { Zero(Obj); if(pObj= new(Obj) nD3Text(this)) { if(SUCCEEDED(pObj->Create(pDevice,pContext))) pObj->Begin(pSwap); } } D3Text::~D3Text(void) { if(pObj) { pObj->~nD3Text(); pObj= 0; } } HRESULT D3Text::Create(ID3D11Device *pDevice, ID3D11DeviceContext *pContext) { return(pObj ? pObj->Create(pDevice,pContext):ERROR_INVALID_HANDLE); } void D3Text::Begin(IDXGISwapChain1 *pSwap) { if(pObj) pObj->Begin(pSwap); } void D3Text::End(void) { if(pObj) pObj->End(); } void D3Text::Reset(void) { if(pObj) pObj->Reset(); } void D3Text::SetColor(ColorF &clr) { if(pObj) pObj->SetColor(clr); } UINT D3Text::Write(const WCHAR *Fmt, ...) { va_list ArgList; va_start(ArgList,Fmt); UINT ChrCt= pObj ? pObj->Write(Fmt,ArgList):0; va_end(ArgList); return(ChrCt); } void D3Text::Line(D2D1_POINT_2F &pt0, D2D1_POINT_2F &pt1) { if(pObj) pObj->Line(pt0,pt1); } void D3Text::Rectangle(D2D1_POINT_2F &pt0,D2D1_POINT_2F &pt1) { if(pObj) pObj->Rectangle(pt0,pt1); } /*************************************************************************/ /** nText **/ /*************************************************************************/ static ComPtr<ID2D1Factory2> gD2DFactory; static ComPtr<IDWriteFactory1> gDWriteFactory; nD3Text::nD3Text(D3Text *pD3Text) { pText= pD3Text; wcsncpy(FontName,L"Arial",STRSIZE(FontName)); FontWgt= DWRITE_FONT_WEIGHT_BOLD; FontStyle= DWRITE_FONT_STYLE_NORMAL; FontHgt= 18.0f; } nD3Text::~nD3Text(void) { if(isBegun) End(); isCreated= false; SafeRelease(pbrText); SafeRelease(p2dBitmap); SafeRelease(pdxSurface); SafeRelease(p2dDevice); SafeRelease(pdxDevice); SafeRelease(p3dContext); SafeRelease(p3dDevice); SafeRelease(pFormat); SafeRelease(p2dContext); //This triggers _com_error exception (debug and/or vmware only?) } HRESULT nD3Text::Create(void) { HRESULT Err= 0; D2D1_FACTORY_OPTIONS d2dOptions; Zero(d2dOptions); d2dOptions.debugLevel= D2D1_DEBUG_LEVEL_INFORMATION; auto uuidD2D= __uuidof(ID2D1Factory2); auto uuidDWrite= __uuidof(IDWriteFactory1); auto pDWF= reinterpret_cast<IUnknown**>(gDWriteFactory.ReleaseAndGetAddressOf()); if(!gD2DFactory.Get() && FAILED(Err= D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,uuidD2D,&d2dOptions,(void**)gD2DFactory.ReleaseAndGetAddressOf()))) { //Failed to create Direct2D factory. } else if(!gDWriteFactory.Get() && FAILED(Err= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,uuidDWrite,pDWF))) { //Failed to create DirectWrite factory. } else if(FAILED(Err= gDWriteFactory->CreateTextFormat(FontName,0,FontWgt,FontStyle,DWRITE_FONT_STRETCH_NORMAL,FontHgt,L"en-us",&pFormat))) { //Failed to create the font. } else { pFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); pFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR); } return(Err); } HRESULT nD3Text::Create(ID3D11Device *pDevice, ID3D11DeviceContext *pContext) { HRESULT Err= 0; // I need to re-query the DirectX 11.1 interface in case the caller is using an older one. if(FAILED(Create())) { //Failed to create factories. } else if(FAILED(Err= pDevice->QueryInterface(__uuidof(ID3D11Device1),(void**)&p3dDevice))) { //Device is invalid or not DX11.1 } else if(FAILED(Err= pContext->QueryInterface(__uuidof(ID3D11DeviceContext1),(void**)&p3dContext))) { //Context is invalid or not DX11.1 } else if(FAILED(Err= pDevice->QueryInterface(__uuidof(IDXGIDevice1),(void**)&pdxDevice))) { //Device does not support IDXGI } else if(FAILED(Err= gD2DFactory->CreateDevice(pdxDevice,&p2dDevice))) { //Failed to create D2D Device from DXGI. //Err= Error(Err,L"D3Text:Create: Failed to create D2D device from DXGI device."); } else if(FAILED(Err= p2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,&p2dContext))) { //Failed to create D2D device context. } else { p2dContext->CreateSolidColorBrush(ColorF(ColorF::Black),&pbrText); isCreated= true; } SafeRelease(p3dDevice); SafeRelease(p3dContext); SafeRelease(pdxDevice); SafeRelease(p2dDevice); return(Err); } HRESULT nD3Text::Begin(IDXGISwapChain1 *pSwap) { HRESULT Err= 0; ChrCt= 0; if(!isCreated) return(ERROR_NOT_READY); if(FAILED(Err= pSwap->GetBuffer(0,__uuidof(pdxSurface),(void**)&pdxSurface))) { //Failed to create DXGI surface } else { auto pPixelFmt= PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_IGNORE); auto pProp= BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET|D2D1_BITMAP_OPTIONS_CANNOT_DRAW,pPixelFmt); if(FAILED(Err= p2dContext->CreateBitmapFromDxgiSurface(pdxSurface,pProp,&p2dBitmap))) { //Failed to create D2D bitmap. } else { p2dContext->SetTarget(p2dBitmap); FLOAT dpiX,dpiY; szLayout= p2dBitmap->GetSize(); rLayout={ 0,0,szLayout.width,szLayout.height }; gD2DFactory->GetDesktopDpi(&dpiX,&dpiY); p2dContext->SetDpi(dpiX,dpiY); p2dContext->BeginDraw(); isBegun= true; } } return(Err); } HRESULT nD3Text::End(void) { HRESULT Err= 0; if(isBegun) { p2dContext->EndDraw(); p2dContext->SetTarget(0); SafeRelease(p2dBitmap); SafeRelease(pdxSurface); } isBegun= false; return(Err); } void nD3Text::Reset(void) { //TODO: Release everything. isBegun= false; } void nD3Text::SetColor(ColorF &clr) { if(isCreated) { SafeRelease(pbrText); p2dContext->CreateSolidColorBrush(clr,&pbrText); } } UINT nD3Text::Write(const WCHAR *Fmt, va_list ArgList) { int ct= 0; if(!isBegun) return(0); ct+= _vsnwprintf(Text+ChrCt,STRSIZE(Text)-ChrCt,Fmt,ArgList); if(ct<0) ct= STRSIZE(Text)-ChrCt; ChrCt+= ct; if(ChrCt) p2dContext->DrawTextW(Text,ChrCt,pFormat,rLayout,pbrText); return(ChrCt); } void nD3Text::Line(D2D1_POINT_2F &pt0, D2D1_POINT_2F &pt1) { if(isBegun) p2dContext->DrawLine(pt0,pt1,pbrText); } void nD3Text::Rectangle(D2D1_POINT_2F &pt0,D2D1_POINT_2F &pt1) { if(isBegun) { D2D1_RECT_F rect= { pt0.x,pt0.y,pt1.x,pt1.y }; p2dContext->DrawRectangle(rect,pbrText); } } //EOF: TEXT.CPP


WebV7 (C)2018 nlited | Rendered by tikope in 31.258ms | 3.133.129.8