-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathD2DRenderer.cpp
More file actions
186 lines (148 loc) · 4.42 KB
/
D2DRenderer.cpp
File metadata and controls
186 lines (148 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "D2DRenderer.h"
CD2DRenderer::CD2DRenderer(void)
: m_bitmap(0), m_d2dFactory(0), m_hWndTarget(0), m_displayMode(KeepAspectRatio)
{
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_ID2D1Factory, (void **)&m_d2dFactory);
}
CD2DRenderer::~CD2DRenderer(void)
{
SafeRelease(m_bitmap);
SafeRelease(m_hWndTarget);
SafeRelease(m_d2dFactory);
}
HRESULT CD2DRenderer::PrepareRenderTarget(BITMAPINFOHEADER& bih, HWND hWnd, bool bFlipHorizontally)
{
m_pBitmapInfo = bih;
m_hWnd = hWnd;
m_bFlipHorizontally = bFlipHorizontally;
m_pitch = m_pBitmapInfo.biWidth * 4;
DiscardResources();
return CreateResources();
}
HRESULT CD2DRenderer::CreateResources()
{
D2D1_PIXEL_FORMAT pixelFormat =
{
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_IGNORE
};
D2D1_RENDER_TARGET_PROPERTIES renderTargetProps =
{
D2D1_RENDER_TARGET_TYPE_DEFAULT,
pixelFormat,
0,
0,
D2D1_RENDER_TARGET_USAGE_NONE,
D2D1_FEATURE_LEVEL_DEFAULT
};
RECT rect;
::GetClientRect(m_hWnd, &rect);
D2D1_SIZE_U windowSize =
{
rect.right - rect.left,
rect.bottom - rect.top
};
D2D1_HWND_RENDER_TARGET_PROPERTIES hWndRenderTargetProps =
{
m_hWnd,
windowSize,
D2D1_PRESENT_OPTIONS_IMMEDIATELY
};
HR(m_d2dFactory->CreateHwndRenderTarget(renderTargetProps, hWndRenderTargetProps, &m_hWndTarget));
// (0,0) + --------> X
// |
// |
// |
// Y
if(m_bFlipHorizontally)
{
// Flip the image around the X axis
D2D1::Matrix3x2F scale = D2D1::Matrix3x2F(1, 0,
0, -1,
0, 0);
// Move it back into place
D2D1::Matrix3x2F translate = D2D1::Matrix3x2F::Translation(0, windowSize.height);
m_hWndTarget->SetTransform(scale * translate);
}
FLOAT dpiX, dpiY;
m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY);
D2D1_BITMAP_PROPERTIES bitmapProps =
{
pixelFormat,
dpiX,
dpiY
};
D2D1_SIZE_U bitmapSize =
{
m_pBitmapInfo.biWidth,
m_pBitmapInfo.biHeight
};
return m_hWndTarget->CreateBitmap(bitmapSize, bitmapProps, &m_bitmap);
}
void CD2DRenderer::DiscardResources()
{
SafeRelease(m_bitmap);
SafeRelease(m_hWndTarget);
}
static inline void ApplyLetterBoxing(D2D1_RECT_F& rendertTargetArea, D2D1_SIZE_F& frameArea)
{
const float aspectRatio = frameArea.width / frameArea.height;
const float targetW = fabs(rendertTargetArea.right - rendertTargetArea.left);
const float targetH = fabs(rendertTargetArea.bottom - rendertTargetArea.top);
float tempH = targetW / aspectRatio;
if(tempH <= targetH) // desired frame height is smaller than display height so fill black on top and bottom of display
{
float deltaH = fabs(tempH - targetH) / 2;
rendertTargetArea.top += deltaH;
rendertTargetArea.bottom -= deltaH;
}
else //desired frame height is bigger than display height so fill black on left and right of display
{
float tempW = targetH * aspectRatio;
float deltaW = fabs(tempW - targetW) / 2;
rendertTargetArea.left += deltaW;
rendertTargetArea.right -= deltaW;
}
}
HRESULT CD2DRenderer::DrawSample(const BYTE* pRgb32Buffer)
{
CheckPointer(pRgb32Buffer, E_POINTER);
if(!m_bitmap || !m_hWndTarget)
{
HR(CreateResources());
}
HR(m_bitmap->CopyFromMemory(NULL, pRgb32Buffer, m_pitch));
if (!(m_hWndTarget->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))
{
RECT rect;
::GetClientRect(m_hWnd, &rect);
D2D1_SIZE_U newSize = { rect.right, rect.bottom };
D2D1_SIZE_U size = m_hWndTarget->GetPixelSize();
if(newSize.height != size.height || newSize.width != size.width)
{
m_hWndTarget->Resize(newSize);
}
D2D1_RECT_F rectangle = D2D1::RectF(0, 0, newSize.width, newSize.height);
if(m_displayMode == KeepAspectRatio)
{
ApplyLetterBoxing(rectangle, m_bitmap->GetSize());
}
m_hWndTarget->BeginDraw();
m_hWndTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black));
m_hWndTarget->DrawBitmap(m_bitmap, rectangle);
HRESULT hr = m_hWndTarget->EndDraw();
if(hr == D2DERR_RECREATE_TARGET)
{
DiscardResources();
}
}
return S_OK;
}
void CD2DRenderer::SetDisplayMode(DisplayMode mode)
{
m_displayMode = mode;
}
DisplayMode CD2DRenderer::GetDisplayMode()
{
return m_displayMode;
}