xref: /oneTBB/examples/common/gui/d2dvideo.cpp (revision c21e688a)
1d86ed7fbStbbdev /*
2*c21e688aSSergey Zheltov     Copyright (c) 2005-2022 Intel Corporation
3d86ed7fbStbbdev 
4d86ed7fbStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5d86ed7fbStbbdev     you may not use this file except in compliance with the License.
6d86ed7fbStbbdev     You may obtain a copy of the License at
7d86ed7fbStbbdev 
8d86ed7fbStbbdev         http://www.apache.org/licenses/LICENSE-2.0
9d86ed7fbStbbdev 
10d86ed7fbStbbdev     Unless required by applicable law or agreed to in writing, software
11d86ed7fbStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12d86ed7fbStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86ed7fbStbbdev     See the License for the specific language governing permissions and
14d86ed7fbStbbdev     limitations under the License.
15d86ed7fbStbbdev */
16d86ed7fbStbbdev 
17d86ed7fbStbbdev // common Windows parts
18d86ed7fbStbbdev #include "winvideo.hpp"
19d86ed7fbStbbdev 
20d86ed7fbStbbdev // and another headers
21d86ed7fbStbbdev #include <cassert>
22d86ed7fbStbbdev #include <stdio.h>
23d86ed7fbStbbdev #include <dxsdkver.h>
24d86ed7fbStbbdev #if _DXSDK_PRODUCT_MAJOR < 9
25d86ed7fbStbbdev #error DXSDK Version 9 and above required.
26d86ed7fbStbbdev #endif
27d86ed7fbStbbdev #include <d2d1.h>
28d86ed7fbStbbdev #include <d2d1helper.h>
29d86ed7fbStbbdev #pragma comment(lib, "d2d1.lib")
30d86ed7fbStbbdev 
31d86ed7fbStbbdev ID2D1Factory *m_pD2DFactory;
32d86ed7fbStbbdev ID2D1HwndRenderTarget *m_pRenderTarget;
33d86ed7fbStbbdev ID2D1Bitmap *m_pBitmap;
34d86ed7fbStbbdev D2D1_SIZE_U bitmapSize;
35d86ed7fbStbbdev 
36d86ed7fbStbbdev HANDLE g_hVSync;
37d86ed7fbStbbdev 
38d86ed7fbStbbdev #include <DXErr.h>
39d86ed7fbStbbdev #pragma comment(lib, "DxErr.lib")
40d86ed7fbStbbdev 
41d86ed7fbStbbdev //! Create a dialog box and tell the user what went wrong
DisplayError(LPSTR lpstrErr,HRESULT hres)42d86ed7fbStbbdev bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
43d86ed7fbStbbdev     if (hres != S_OK) {
44d86ed7fbStbbdev         static bool InError = false;
45d86ed7fbStbbdev         int retval = 0;
46d86ed7fbStbbdev         if (!InError) {
47d86ed7fbStbbdev             InError = true;
48d86ed7fbStbbdev             const char *message = hres ? DXGetErrorString(hres) : 0;
49d86ed7fbStbbdev             retval =
50d86ed7fbStbbdev                 MessageBoxA(g_hAppWnd, lpstrErr, hres ? message : "Error!", MB_OK | MB_ICONERROR);
51d86ed7fbStbbdev             InError = false;
52d86ed7fbStbbdev         }
53d86ed7fbStbbdev     }
54d86ed7fbStbbdev     return false;
55d86ed7fbStbbdev }
56d86ed7fbStbbdev 
DrawBitmap()57d86ed7fbStbbdev void DrawBitmap() {
58d86ed7fbStbbdev     HRESULT hr = S_OK;
59d86ed7fbStbbdev     if (m_pRenderTarget) {
60d86ed7fbStbbdev         m_pRenderTarget->BeginDraw();
61d86ed7fbStbbdev         if (m_pBitmap)
6257f524caSIlya Isaev             hr = m_pBitmap->CopyFromMemory(nullptr, (BYTE *)g_pImg, 4 * g_sizex);
63d86ed7fbStbbdev         DisplayError("DrawBitmap error", hr);
64d86ed7fbStbbdev         m_pRenderTarget->DrawBitmap(m_pBitmap);
65d86ed7fbStbbdev         m_pRenderTarget->EndDraw();
66d86ed7fbStbbdev     }
67d86ed7fbStbbdev     return;
68d86ed7fbStbbdev }
69d86ed7fbStbbdev 
mouse(int k,LPARAM lParam)70d86ed7fbStbbdev inline void mouse(int k, LPARAM lParam) {
71d86ed7fbStbbdev     int x = (int)LOWORD(lParam);
72d86ed7fbStbbdev     int y = (int)HIWORD(lParam);
73d86ed7fbStbbdev     RECT rc;
74d86ed7fbStbbdev     GetClientRect(g_hAppWnd, &rc);
75d86ed7fbStbbdev     g_video->on_mouse(x * g_sizex / (rc.right - rc.left), y * g_sizey / (rc.bottom - rc.top), k);
76d86ed7fbStbbdev }
77d86ed7fbStbbdev 
78d86ed7fbStbbdev //! Win event processing function
InternalWndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)79d86ed7fbStbbdev LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
80d86ed7fbStbbdev     switch (iMsg) {
81d86ed7fbStbbdev         case WM_MOVE:
82d86ed7fbStbbdev             // Check to make sure our window exists before we tell it to repaint.
83d86ed7fbStbbdev             // This will fail the first time (while the window is being created).
84d86ed7fbStbbdev             if (hwnd) {
8557f524caSIlya Isaev                 InvalidateRect(hwnd, nullptr, FALSE);
86d86ed7fbStbbdev                 UpdateWindow(hwnd);
87d86ed7fbStbbdev             }
88d86ed7fbStbbdev             return 0L;
89d86ed7fbStbbdev 
90d86ed7fbStbbdev         case WM_SIZE:
91d86ed7fbStbbdev         case WM_PAINT:
92d86ed7fbStbbdev             if (g_video->running && g_video->updating) {
93d86ed7fbStbbdev                 DrawBitmap();
94d86ed7fbStbbdev                 Sleep(0);
95d86ed7fbStbbdev             }
96d86ed7fbStbbdev             break;
97d86ed7fbStbbdev         // Process all mouse and keyboard events
98d86ed7fbStbbdev         case WM_LBUTTONDOWN: mouse(1, lParam); break;
99d86ed7fbStbbdev         case WM_LBUTTONUP: mouse(-1, lParam); break;
100d86ed7fbStbbdev         case WM_RBUTTONDOWN: mouse(2, lParam); break;
101d86ed7fbStbbdev         case WM_RBUTTONUP: mouse(-2, lParam); break;
102d86ed7fbStbbdev         case WM_MBUTTONDOWN: mouse(3, lParam); break;
103d86ed7fbStbbdev         case WM_MBUTTONUP: mouse(-3, lParam); break;
104d86ed7fbStbbdev         case WM_CHAR: g_video->on_key((int)wParam); break;
105d86ed7fbStbbdev 
106d86ed7fbStbbdev         // some useless stuff
107d86ed7fbStbbdev         case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
108d86ed7fbStbbdev         case WM_DISPLAYCHANGE: return 0;
109d86ed7fbStbbdev 
110d86ed7fbStbbdev         // Now, shut down the window...
111d86ed7fbStbbdev         case WM_DESTROY: PostQuitMessage(0); return 0;
112d86ed7fbStbbdev     }
113d86ed7fbStbbdev     // call user defined proc, if exists
114d86ed7fbStbbdev     return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
115d86ed7fbStbbdev                        : DefWindowProc(hwnd, iMsg, wParam, lParam);
116d86ed7fbStbbdev }
117d86ed7fbStbbdev 
init_window(int sizex,int sizey)118d86ed7fbStbbdev bool video::init_window(int sizex, int sizey) {
119d86ed7fbStbbdev     assert(win_hInstance != 0);
120d86ed7fbStbbdev     g_sizex = sizex;
121d86ed7fbStbbdev     g_sizey = sizey;
122d86ed7fbStbbdev     if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false)) {
123d86ed7fbStbbdev         DisplayError("Unable to initialize the program's window.");
124d86ed7fbStbbdev         return false;
125d86ed7fbStbbdev     }
126d86ed7fbStbbdev     ShowWindow(g_hAppWnd, SW_SHOW);
127d86ed7fbStbbdev     g_pImg = new unsigned int[sizex * sizey];
128d86ed7fbStbbdev 
129d86ed7fbStbbdev     HRESULT hr = S_OK;
130d86ed7fbStbbdev 
131d86ed7fbStbbdev     hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
132d86ed7fbStbbdev     // Create a Direct2D render target.
133d86ed7fbStbbdev     if (SUCCEEDED(hr) && !m_pRenderTarget) {
134d86ed7fbStbbdev         RECT rc;
135d86ed7fbStbbdev         GetClientRect(g_hAppWnd, &rc);
136d86ed7fbStbbdev 
137d86ed7fbStbbdev         bitmapSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
138d86ed7fbStbbdev 
139d86ed7fbStbbdev         hr = m_pD2DFactory->CreateHwndRenderTarget(
140d86ed7fbStbbdev             D2D1::RenderTargetProperties(),
141d86ed7fbStbbdev             D2D1::HwndRenderTargetProperties(g_hAppWnd, bitmapSize),
142d86ed7fbStbbdev             &m_pRenderTarget);
143d86ed7fbStbbdev         if (SUCCEEDED(hr) && !m_pBitmap) {
144d86ed7fbStbbdev             D2D1_PIXEL_FORMAT pixelFormat =
145d86ed7fbStbbdev                 D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
146d86ed7fbStbbdev             D2D1_BITMAP_PROPERTIES bitmapProperties;
147d86ed7fbStbbdev             bitmapProperties.pixelFormat = pixelFormat;
148d86ed7fbStbbdev             m_pRenderTarget->GetDpi(&bitmapProperties.dpiX, &bitmapProperties.dpiY);
149d86ed7fbStbbdev             m_pRenderTarget->CreateBitmap(bitmapSize, bitmapProperties, &m_pBitmap);
150d86ed7fbStbbdev             m_pRenderTarget->DrawBitmap(m_pBitmap);
151d86ed7fbStbbdev         }
152d86ed7fbStbbdev     }
153d86ed7fbStbbdev 
154d86ed7fbStbbdev     running = true;
155d86ed7fbStbbdev     return true;
156d86ed7fbStbbdev }
157d86ed7fbStbbdev 
terminate()158d86ed7fbStbbdev void video::terminate() {
159d86ed7fbStbbdev     if (m_pBitmap)
160d86ed7fbStbbdev         m_pBitmap->Release();
161d86ed7fbStbbdev     if (m_pRenderTarget)
162d86ed7fbStbbdev         m_pRenderTarget->Release();
163d86ed7fbStbbdev     if (m_pD2DFactory)
164d86ed7fbStbbdev         m_pD2DFactory->Release();
16557f524caSIlya Isaev     g_video = nullptr;
166d86ed7fbStbbdev     running = false;
167ba947f18SIlya Isaev 
168d86ed7fbStbbdev     delete[] g_pImg;
16957f524caSIlya Isaev     g_pImg = nullptr;
170d86ed7fbStbbdev }
171d86ed7fbStbbdev 
172d86ed7fbStbbdev //////////// drawing area constructor & destructor /////////////
173d86ed7fbStbbdev 
drawing_area(int x,int y,int sizex,int sizey)174d86ed7fbStbbdev drawing_area::drawing_area(int x, int y, int sizex, int sizey)
175d86ed7fbStbbdev         : base_index(y * g_sizex + x),
176d86ed7fbStbbdev           max_index(g_sizex * g_sizey),
177d86ed7fbStbbdev           index_stride(g_sizex),
178d86ed7fbStbbdev           pixel_depth(24),
179d86ed7fbStbbdev           ptr32(g_pImg),
180d86ed7fbStbbdev           start_x(x),
181d86ed7fbStbbdev           start_y(y),
182d86ed7fbStbbdev           size_x(sizex),
183d86ed7fbStbbdev           size_y(sizey) {
184d86ed7fbStbbdev     assert(x < g_sizex);
185d86ed7fbStbbdev     assert(y < g_sizey);
186d86ed7fbStbbdev     assert(x + sizex <= g_sizex);
187d86ed7fbStbbdev     assert(y + sizey <= g_sizey);
188d86ed7fbStbbdev 
189d86ed7fbStbbdev     index = base_index; // current index
190d86ed7fbStbbdev }
191d86ed7fbStbbdev 
update()192d86ed7fbStbbdev void drawing_area::update() {
193d86ed7fbStbbdev     if (g_video->updating) {
194d86ed7fbStbbdev         RECT r;
195d86ed7fbStbbdev         r.left = start_x;
196d86ed7fbStbbdev         r.right = start_x + size_x;
197d86ed7fbStbbdev         r.top = start_y;
198d86ed7fbStbbdev         r.bottom = start_y + size_y;
199d86ed7fbStbbdev         InvalidateRect(g_hAppWnd, &r, false);
200d86ed7fbStbbdev     }
201d86ed7fbStbbdev }
202