|
| 1 | +#include "stdafx.h" |
| 2 | +#include "MultiD2D.h" |
| 3 | + |
| 4 | +#define SafeRelease(_Interface) if (*(_Interface) != nullptr) { (*(_Interface))->Release(); (*(_Interface)) = nullptr; } |
| 5 | + |
| 6 | +CRITICAL_SECTION ms_FactoryMutex{ 0 }; |
| 7 | +ID2D1Factory* ms_Factory{ nullptr }; |
| 8 | + |
| 9 | +void EnterFactory(void) { EnterCriticalSection(&ms_FactoryMutex); } |
| 10 | +void LeaveFactory(void) { LeaveCriticalSection(&ms_FactoryMutex); } |
| 11 | + |
| 12 | +void InitMultiD2D(void) { |
| 13 | + InitializeCriticalSection(&ms_FactoryMutex); |
| 14 | + EnterFactory(); |
| 15 | + D2D1CreateFactory(D2D1_FACTORY_TYPE::D2D1_FACTORY_TYPE_MULTI_THREADED, &ms_Factory); |
| 16 | + LeaveFactory(); |
| 17 | + |
| 18 | + printf(__FUNCTION__ ": hello!\n"); |
| 19 | + fflush(stdout); |
| 20 | +} |
| 21 | + |
| 22 | +CMultiD2D::CMultiD2D() : m_bitmap(nullptr), m_rt(nullptr), m_bitmapW(0), m_bitmapH(0), m_bitmapP(nullptr), m_mutex(new CRITICAL_SECTION()) { |
| 23 | + InitializeCriticalSection(this->m_mutex); |
| 24 | +} |
| 25 | + |
| 26 | +CMultiD2D::~CMultiD2D() { |
| 27 | + this->Discard(); |
| 28 | + |
| 29 | + this->enter(); |
| 30 | + this->m_bitmapP = nullptr; |
| 31 | + this->m_bitmapW = 0; |
| 32 | + this->m_bitmapH = 0; |
| 33 | + this->leave(); |
| 34 | + |
| 35 | + DeleteCriticalSection(this->m_mutex); |
| 36 | + delete this->m_mutex; |
| 37 | + this->m_mutex = nullptr; |
| 38 | +} |
| 39 | + |
| 40 | +void CMultiD2D::enter(void) { EnterCriticalSection(this->m_mutex); } |
| 41 | +void CMultiD2D::leave(void) { LeaveCriticalSection(this->m_mutex); } |
| 42 | + |
| 43 | +void CMultiD2D::Discard(void) { |
| 44 | + this->enter(); |
| 45 | + SafeRelease(&this->m_bitmap); |
| 46 | + SafeRelease(&this->m_rt); |
| 47 | + this->leave(); |
| 48 | +} |
| 49 | + |
| 50 | +HRESULT CMultiD2D::Create(HWND window) { |
| 51 | + HRESULT hR = S_OK; |
| 52 | + FLOAT dpiX = 0.0f, dpiY = 0.0f; |
| 53 | + |
| 54 | + this->enter(); |
| 55 | + |
| 56 | + EnterFactory(); |
| 57 | + if (this->m_rt == nullptr) { |
| 58 | + RECT rc; |
| 59 | + GetClientRect(window, &rc); |
| 60 | + D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); |
| 61 | + hR = ms_Factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(window, size), &this->m_rt); |
| 62 | + } |
| 63 | + ms_Factory->GetDesktopDpi(&dpiX, &dpiY); |
| 64 | + LeaveFactory(); |
| 65 | + |
| 66 | + if (SUCCEEDED(hR) && this->m_bitmapP != nullptr && this->m_bitmap == nullptr) { |
| 67 | + D2D1_SIZE_U bmsize = D2D1::SizeU(this->m_bitmapW, this->m_bitmapH); |
| 68 | + D2D1_BITMAP_PROPERTIES props; |
| 69 | + props.dpiX = dpiX; |
| 70 | + props.dpiY = dpiY; |
| 71 | + props.pixelFormat.alphaMode = D2D1_ALPHA_MODE::D2D1_ALPHA_MODE_IGNORE; |
| 72 | + props.pixelFormat.format = DXGI_FORMAT::DXGI_FORMAT_B8G8R8A8_UNORM; |
| 73 | + hR = this->m_rt->CreateBitmap(bmsize, this->m_bitmapP, this->m_bitmapW * 4, props, &this->m_bitmap); |
| 74 | + } |
| 75 | + |
| 76 | + this->leave(); |
| 77 | + return hR; |
| 78 | +} |
| 79 | + |
| 80 | +HRESULT CMultiD2D::OnResize(UINT w, UINT h) { |
| 81 | + HRESULT hR = S_OK; |
| 82 | + |
| 83 | + this->enter(); |
| 84 | + if (this->m_rt != nullptr) { |
| 85 | + hR = this->m_rt->Resize(D2D1::SizeU(w, h)); |
| 86 | + if (SUCCEEDED(hR)) { |
| 87 | + //printf("OnResize ok. w=%ud,h=%ud\r\n", w, h); |
| 88 | + } |
| 89 | + } |
| 90 | + this->leave(); |
| 91 | + |
| 92 | + return hR; |
| 93 | +} |
| 94 | + |
| 95 | +HRESULT CMultiD2D::OnRender(void) { |
| 96 | + HRESULT hR = S_OK; |
| 97 | + this->enter(); |
| 98 | + |
| 99 | + if (this->m_rt != nullptr && this->m_bitmap != nullptr) { |
| 100 | + this->m_rt->BeginDraw(); |
| 101 | + this->m_rt->SetTransform(D2D1::Matrix3x2F::Identity()); |
| 102 | + this->m_rt->Clear(D2D1::ColorF(D2D1::ColorF::Black)); |
| 103 | + |
| 104 | + // source rectangle, always occupy the whole bitmap, always. |
| 105 | + D2D1_SIZE_F bmsiz = this->m_bitmap->GetSize(); |
| 106 | + D2D1_RECT_F source = D2D1::RectF(0.0f, 0.0f, bmsiz.width, bmsiz.height); |
| 107 | + |
| 108 | + // change this: |
| 109 | + // right now it's just drawing bitmap in the center. |
| 110 | + D2D1_SIZE_F rtsiz = this->m_rt->GetSize(); |
| 111 | + D2D1_RECT_F dest = D2D1::RectF( |
| 112 | + rtsiz.width / 2 - source.right / 2, |
| 113 | + rtsiz.height / 2 - source.bottom / 2, |
| 114 | + rtsiz.width / 2 + source.right / 2, |
| 115 | + rtsiz.height / 2 + source.bottom / 2 |
| 116 | + ); |
| 117 | + |
| 118 | + this->m_rt->DrawBitmap(this->m_bitmap, dest, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, source); |
| 119 | + hR = this->m_rt->EndDraw(); |
| 120 | + } |
| 121 | + |
| 122 | + this->leave(); |
| 123 | + |
| 124 | + if (hR == D2DERR_RECREATE_TARGET) { |
| 125 | + hR = S_OK; // that's what MSDN docs tell me to do. |
| 126 | + this->Discard(); |
| 127 | + } |
| 128 | + |
| 129 | + return hR; |
| 130 | +} |
| 131 | + |
| 132 | +HRESULT CMultiD2D::SetBitmap(UINT w, UINT h, void* data) { |
| 133 | + this->enter(); |
| 134 | + this->m_bitmapW = w; |
| 135 | + this->m_bitmapH = h; |
| 136 | + this->m_bitmapP = data; |
| 137 | + this->leave(); |
| 138 | + this->Discard(); |
| 139 | + return S_OK; |
| 140 | +} |
0 commit comments