Skip to content

Commit 93b4948

Browse files
committed
Make Direct2DContext draw to an offscreen bitmap instead of an onscreen hwnd.
1 parent 6bb7d21 commit 93b4948

File tree

4 files changed

+67
-43
lines changed

4 files changed

+67
-43
lines changed

Sources/WindowsAppSupport/WAS_BitmapContextGdi.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ void BitmapContextGdi::Init (void* nativeHandle)
6565
width = clientRect.right - clientRect.left;
6666
height = clientRect.bottom - clientRect.top;
6767

68-
HDC hdc = GetDC (NULL);
69-
memoryDC = CreateCompatibleDC (hdc);
70-
memoryBitmap = CreateCompatibleBitmap (hdc, width, height);
68+
CreateOffscreenContext ();
7169
}
7270

7371
void BitmapContextGdi::BlitToWindow (void* nativeHandle)
@@ -91,13 +89,7 @@ void BitmapContextGdi::Resize (int newWidth, int newHeight)
9189
{
9290
width = newWidth;
9391
height = newHeight;
94-
95-
DeleteObject (memoryBitmap);
96-
DeleteDC (memoryDC);
97-
98-
HDC hdc = GetDC (NULL);
99-
memoryDC = CreateCompatibleDC (hdc);
100-
memoryBitmap = CreateCompatibleBitmap (hdc, width, height);
92+
CreateOffscreenContext ();
10193
}
10294

10395
double BitmapContextGdi::GetWidth () const
@@ -138,13 +130,13 @@ void BitmapContextGdi::DrawLine (const NUIE::Point& beg, const NUIE::Point& end,
138130

139131
void BitmapContextGdi::DrawBezier (const NUIE::Point& p1, const NUIE::Point& p2, const NUIE::Point& p3, const NUIE::Point& p4, const NUIE::Pen& pen)
140132
{
133+
SelectObjectGuard selectGuard (memoryDC, memoryBitmap);
141134
POINT points[4] = {
142135
CreatePoint (p1),
143136
CreatePoint (p2),
144137
CreatePoint (p3),
145138
CreatePoint (p4)
146139
};
147-
SelectObjectGuard selectGuard (memoryDC, memoryBitmap);
148140
SelectObject (memoryDC, GetStockObject (NULL_BRUSH));
149141
SelectObject (memoryDC, penCache.Get (pen));
150142
::PolyBezier (memoryDC, points, 4);
@@ -239,6 +231,16 @@ void BitmapContextGdi::DrawIcon (const NUIE::Rect&, const NUIE::IconId&)
239231
DBGBREAK ();
240232
}
241233

234+
void BitmapContextGdi::CreateOffscreenContext ()
235+
{
236+
DeleteObject (memoryBitmap);
237+
DeleteDC (memoryDC);
238+
239+
HDC hdc = GetDC (NULL);
240+
memoryDC = CreateCompatibleDC (hdc);
241+
memoryBitmap = CreateCompatibleBitmap (hdc, width, height);
242+
}
243+
242244
POINT BitmapContextGdi::CreatePoint (const NUIE::Point& point) const
243245
{
244246
POINT gdiPoint;

Sources/WindowsAppSupport/WAS_BitmapContextGdi.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class BitmapContextGdi : public NUIE::NativeDrawingContext
8383
virtual void DrawIcon (const NUIE::Rect& rect, const NUIE::IconId& iconId) override;
8484

8585
private:
86+
void CreateOffscreenContext ();
8687
POINT CreatePoint (const NUIE::Point& point) const;
8788
RECT CreateRect (const NUIE::Rect& rect) const;
8889
RECT CreateRect (const NUIE::Rect& rect, const NUIE::Pen& pen) const;

Sources/WindowsAppSupport/WAS_Direct2DContext.cpp

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -108,55 +108,61 @@ static float GetPenThickness (const NUIE::Pen& pen)
108108
Direct2DContext::Direct2DContext (const Direct2DImageLoaderPtr& imageLoader) :
109109
NUIE::NativeDrawingContext (),
110110
direct2DHandler (),
111-
hwnd (NULL),
112111
width (0),
113112
height (0),
114113
imageLoader (imageLoader),
115-
renderTarget (nullptr)
114+
renderTarget (nullptr),
115+
memoryDC (NULL),
116+
memoryBitmap (NULL)
116117
{
117118

118119
}
119120

120121
Direct2DContext::~Direct2DContext ()
121122
{
123+
DeleteObject (memoryBitmap);
124+
DeleteDC (memoryDC);
122125
SafeRelease (&renderTarget);
123126
}
124127

125128
void Direct2DContext::Init (void* nativeHandle)
126129
{
127-
hwnd = (HWND) nativeHandle;
130+
HWND hwnd = (HWND) nativeHandle;
131+
132+
RECT clientRect;
133+
GetClientRect (hwnd, &clientRect);
134+
width = clientRect.right - clientRect.left;
135+
height = clientRect.bottom - clientRect.top;
136+
128137
CreateRenderTarget ();
138+
CreateOffscreenContext ();
129139
}
130140

131141
void Direct2DContext::BlitToWindow (void* nativeHandle)
132142
{
133-
HWND targetHwnd = (HWND) nativeHandle;
134-
if (hwnd == targetHwnd) {
135-
return;
136-
}
143+
HWND hwnd = (HWND) nativeHandle;
144+
137145
PAINTSTRUCT ps;
138-
HDC targetHdc = BeginPaint (targetHwnd, &ps);
139-
BlitToContext (targetHdc);
140-
EndPaint (targetHwnd, &ps);
146+
HDC hdc = BeginPaint (hwnd, &ps);
147+
BlitToContext (hdc);
148+
EndPaint (hwnd, &ps);
141149
}
142150

143151
void Direct2DContext::BlitToContext (void* nativeContext)
144152
{
145-
HDC targetHdc = (HDC) nativeContext;
146-
if (hwnd == WindowFromDC (targetHdc)) {
147-
return;
148-
}
149-
BitBlt (targetHdc, 0, 0, width, height, GetDC (renderTarget->GetHwnd ()), 0, 0, SRCCOPY);
153+
HDC hdc = (HDC) nativeContext;
154+
BitBlt (hdc, 0, 0, width, height, memoryDC, 0, 0, SRCCOPY);
150155
}
151156

152157
void Direct2DContext::Resize (int newWidth, int newHeight)
153158
{
159+
if (newWidth == 0 || newHeight == 0 || renderTarget == nullptr) {
160+
return;
161+
}
162+
154163
width = newWidth;
155164
height = newHeight;
156-
if (width > 0 && height > 0) {
157-
D2D1_SIZE_U size = D2D1::SizeU (width, height);
158-
renderTarget->Resize (size);
159-
}
165+
CreateOffscreenContext ();
160166
}
161167

162168
double Direct2DContext::GetWidth () const
@@ -326,23 +332,34 @@ void Direct2DContext::DrawIcon (const NUIE::Rect& rect, const NUIE::IconId& icon
326332

327333
void Direct2DContext::CreateRenderTarget ()
328334
{
329-
RECT clientRect;
330-
GetClientRect (hwnd, &clientRect);
331-
width = clientRect.right - clientRect.left;
332-
height = clientRect.bottom - clientRect.top;
333-
334-
D2D1_SIZE_U size = D2D1::SizeU (width, height);
335-
D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties ();
336-
D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties (hwnd, size);
337-
338335
SafeRelease (&renderTarget);
339336
if (imageLoader != nullptr) {
340337
imageLoader->ClearCache ();
341338
}
342339

343-
direct2DHandler.direct2DFactory->CreateHwndRenderTarget (renderTargetProperties, hwndRenderTargetProperties, &renderTarget);
344-
renderTarget->SetDpi (96.0f, 96.0f);
340+
D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties (
341+
D2D1_RENDER_TARGET_TYPE_DEFAULT,
342+
D2D1::PixelFormat (DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
343+
96.0f, 96.0f,
344+
D2D1_RENDER_TARGET_USAGE_NONE,
345+
D2D1_FEATURE_LEVEL_DEFAULT
346+
);
347+
direct2DHandler.direct2DFactory->CreateDCRenderTarget (&renderTargetProperties, &renderTarget);
345348
DBGASSERT (renderTarget != nullptr);
346349
}
347350

351+
void Direct2DContext::CreateOffscreenContext ()
352+
{
353+
DeleteObject (memoryBitmap);
354+
DeleteDC (memoryDC);
355+
356+
HDC hdc = GetDC (NULL);
357+
memoryDC = CreateCompatibleDC (hdc);
358+
memoryBitmap = CreateCompatibleBitmap (hdc, width, height);
359+
SelectObject (memoryDC, memoryBitmap);
360+
361+
RECT clientRect = { 0, 0, width, height };
362+
renderTarget->BindDC (memoryDC, &clientRect);
363+
}
364+
348365
}

Sources/WindowsAppSupport/WAS_Direct2DContext.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,17 @@ class Direct2DContext : public NUIE::NativeDrawingContext
6161

6262
private:
6363
void CreateRenderTarget ();
64+
void CreateOffscreenContext ();
6465

65-
HWND hwnd;
6666
int width;
6767
int height;
68+
6869
Direct2DHandler direct2DHandler;
6970
Direct2DImageLoaderPtr imageLoader;
70-
ID2D1HwndRenderTarget* renderTarget;
71+
ID2D1DCRenderTarget* renderTarget;
72+
73+
HDC memoryDC;
74+
HBITMAP memoryBitmap;
7175
};
7276

7377
}

0 commit comments

Comments
 (0)