rev |
line source |
nuclear@0
|
1 #include <dxgi.h>
|
nuclear@0
|
2 #include "d3dut.h"
|
nuclear@0
|
3 #include "win.h"
|
nuclear@0
|
4 #include "logmsg.h"
|
nuclear@0
|
5
|
nuclear@0
|
6 std::vector<Window*> windows;
|
nuclear@0
|
7 int active_win = -1;
|
nuclear@0
|
8
|
nuclear@0
|
9 int create_window(const char *title, int xsz, int ysz, unsigned int dmflags)
|
nuclear@0
|
10 {
|
nuclear@0
|
11 IDXGIDevice *dxgidev;
|
nuclear@0
|
12 if(d3dut_dev->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgidev) != 0) {
|
nuclear@0
|
13 fatal_error("failed to get IDXGIDevice interface\n");
|
nuclear@0
|
14 return 0;
|
nuclear@0
|
15 }
|
nuclear@0
|
16 IDXGIAdapter *adapter;
|
nuclear@0
|
17 if(dxgidev->GetParent(__uuidof(IDXGIAdapter), (void**)&adapter) != 0) {
|
nuclear@0
|
18 fatal_error("failed to get IDXGIAdapter pointer\n");
|
nuclear@0
|
19 return 0;
|
nuclear@0
|
20 }
|
nuclear@0
|
21 IDXGIFactory *dxgi_factory;
|
nuclear@0
|
22 if(adapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgi_factory) != 0) {
|
nuclear@0
|
23 fatal_error("failed to get IDXGIFactory pointer\n");
|
nuclear@0
|
24 return 0;
|
nuclear@0
|
25 }
|
nuclear@0
|
26 adapter->Release();
|
nuclear@0
|
27 dxgidev->Release();
|
nuclear@0
|
28
|
nuclear@0
|
29 Window *win = new Window;
|
nuclear@0
|
30 memset(win, 0, sizeof *win);
|
nuclear@0
|
31 win->must_redisplay = true;
|
nuclear@0
|
32 win->changed_size = true;
|
nuclear@0
|
33 win->width = xsz;
|
nuclear@0
|
34 win->height = ysz;
|
nuclear@0
|
35
|
nuclear@0
|
36 int xpos = (GetSystemMetrics(SM_CXSCREEN) - xsz) / 2;
|
nuclear@0
|
37 int ypos = (GetSystemMetrics(SM_CYSCREEN) - ysz) / 2;
|
nuclear@0
|
38 win->win = CreateWindow(WINCLASSNAME, title, WS_OVERLAPPEDWINDOW, xpos, ypos, xsz, ysz, 0, 0, GetModuleHandle(0), 0);
|
nuclear@0
|
39 if(!win->win) {
|
nuclear@0
|
40 fprintf(stderr, "failed to create window: %s\n", title);
|
nuclear@0
|
41 return 0;
|
nuclear@0
|
42 }
|
nuclear@0
|
43 ShowWindow(win->win, SW_SHOW);
|
nuclear@0
|
44
|
nuclear@0
|
45 unsigned int nsamples = 1;
|
nuclear@0
|
46 unsigned int quality = 0;
|
nuclear@0
|
47 if(dmflags & D3DUT_MULTISAMPLE) {
|
nuclear@0
|
48 nsamples = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
|
nuclear@0
|
49 d3dut_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, nsamples, &quality);
|
nuclear@0
|
50 }
|
nuclear@0
|
51
|
nuclear@0
|
52 DXGI_SWAP_CHAIN_DESC sd;
|
nuclear@0
|
53 memset(&sd, 0, sizeof sd);
|
nuclear@0
|
54 sd.OutputWindow = win->win;
|
nuclear@0
|
55 sd.BufferDesc.Width = xsz;
|
nuclear@0
|
56 sd.BufferDesc.Height = ysz;
|
nuclear@0
|
57 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
nuclear@0
|
58 //sd.Stereo = (dmflags & D3DUT_STEREO) ? 1 : 0;
|
nuclear@0
|
59 sd.BufferDesc.RefreshRate.Numerator = 60;
|
nuclear@0
|
60 sd.BufferDesc.RefreshRate.Denominator = 1;
|
nuclear@0
|
61 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
nuclear@0
|
62 sd.BufferCount = (dmflags & D3DUT_DOUBLE) ? 1 : 0;
|
nuclear@0
|
63 sd.SampleDesc.Count = nsamples;
|
nuclear@0
|
64 sd.SampleDesc.Quality = quality;
|
nuclear@0
|
65 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
nuclear@0
|
66 sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
nuclear@0
|
67 sd.Windowed = 1;
|
nuclear@0
|
68
|
nuclear@0
|
69 if(dxgi_factory->CreateSwapChain(d3dut_dev, &sd, &win->swap) != 0) {
|
nuclear@0
|
70 warning("failed to create swap chain\n");
|
nuclear@0
|
71 return 0;
|
nuclear@0
|
72 }
|
nuclear@0
|
73 dxgi_factory->Release();
|
nuclear@0
|
74
|
nuclear@0
|
75 ID3D11Texture2D *rtex;
|
nuclear@0
|
76 if(win->swap->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&rtex) != 0) {
|
nuclear@0
|
77 warning("failed to get default render target texture\n");
|
nuclear@0
|
78 return 0;
|
nuclear@0
|
79 }
|
nuclear@0
|
80 if(d3dut_dev->CreateRenderTargetView(rtex, 0, &win->rtarg_view) != 0) {
|
nuclear@0
|
81 warning("failed to create render target view\n");
|
nuclear@0
|
82 rtex->Release();
|
nuclear@0
|
83 return 0;
|
nuclear@0
|
84 }
|
nuclear@0
|
85 rtex->Release();
|
nuclear@0
|
86 d3dut_ctx->OMSetRenderTargets(1, &win->rtarg_view, 0);
|
nuclear@0
|
87
|
nuclear@0
|
88 int idx = (int)windows.size();
|
nuclear@0
|
89 windows.push_back(win);
|
nuclear@0
|
90 set_active_win(idx);
|
nuclear@0
|
91 return idx;
|
nuclear@0
|
92 }
|
nuclear@0
|
93
|
nuclear@0
|
94 void destroy_window(int idx)
|
nuclear@0
|
95 {
|
nuclear@0
|
96 if(idx < 0 || idx >= (int)windows.size()) {
|
nuclear@0
|
97 warning("destroy_window: invalid index: %d\n", idx);
|
nuclear@0
|
98 return;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 Window *win = windows[idx];
|
nuclear@0
|
102 if(win) {
|
nuclear@0
|
103 DestroyWindow(win->win);
|
nuclear@0
|
104 win->rtarg_view->Release();
|
nuclear@0
|
105 win->swap->Release();
|
nuclear@0
|
106 delete win;
|
nuclear@0
|
107 windows[idx] = 0;
|
nuclear@0
|
108 }
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 void set_active_win(int idx)
|
nuclear@0
|
112 {
|
nuclear@0
|
113 if(idx < 0 || idx >= (int)windows.size()) {
|
nuclear@0
|
114 warning("set_active_win: invalid window: %d\n", idx);
|
nuclear@0
|
115 return;
|
nuclear@0
|
116 }
|
nuclear@0
|
117 d3dut_rtview = windows[idx]->rtarg_view;
|
nuclear@0
|
118 active_win = idx;
|
nuclear@0
|
119 }
|
nuclear@0
|
120
|
nuclear@0
|
121 int get_active_win()
|
nuclear@0
|
122 {
|
nuclear@0
|
123 return active_win;
|
nuclear@0
|
124 }
|
nuclear@0
|
125
|
nuclear@0
|
126 Window *get_window(int idx)
|
nuclear@0
|
127 {
|
nuclear@0
|
128 if(idx < 0) {
|
nuclear@0
|
129 idx = active_win;
|
nuclear@0
|
130 }
|
nuclear@0
|
131 if(idx < 0 || idx >= (int)windows.size()) {
|
nuclear@0
|
132 return 0;
|
nuclear@0
|
133 }
|
nuclear@0
|
134 return windows[idx];
|
nuclear@0
|
135 }
|
nuclear@0
|
136
|
nuclear@0
|
137 static int find_window(HWND syswin)
|
nuclear@0
|
138 {
|
nuclear@0
|
139 for(size_t i=0; i<windows.size(); i++) {
|
nuclear@0
|
140 if(windows[i]->win == syswin) {
|
nuclear@0
|
141 return i;
|
nuclear@0
|
142 }
|
nuclear@0
|
143 }
|
nuclear@0
|
144 return -1;
|
nuclear@0
|
145 }
|
nuclear@0
|
146
|
nuclear@0
|
147 static void mouse_handler(Window *win, int bn, bool pressed);
|
nuclear@0
|
148
|
nuclear@0
|
149 long CALLBACK win_handle_event(HWND syswin, unsigned int msg, unsigned int wparam, long lparam)
|
nuclear@0
|
150 {
|
nuclear@0
|
151 Window *win = 0;
|
nuclear@0
|
152 int winid = find_window(syswin);
|
nuclear@0
|
153 if(winid != -1) {
|
nuclear@0
|
154 set_active_win(winid);
|
nuclear@0
|
155 win = get_window();
|
nuclear@0
|
156 }
|
nuclear@0
|
157
|
nuclear@0
|
158 switch(msg) {
|
nuclear@0
|
159 case WM_PAINT:
|
nuclear@0
|
160 win->must_redisplay = true;
|
nuclear@0
|
161 ValidateRect(win->win, 0);
|
nuclear@0
|
162 break;
|
nuclear@0
|
163
|
nuclear@0
|
164 case WM_CLOSE:
|
nuclear@0
|
165 destroy_window(winid);
|
nuclear@0
|
166 break;
|
nuclear@0
|
167
|
nuclear@0
|
168 case WM_SIZE:
|
nuclear@0
|
169 win->width = LOWORD(lparam);
|
nuclear@0
|
170 win->height = HIWORD(lparam);
|
nuclear@0
|
171 win->changed_size = true;
|
nuclear@0
|
172 break;
|
nuclear@0
|
173
|
nuclear@0
|
174 case WM_KEYDOWN:
|
nuclear@0
|
175 if(wparam < 256) {
|
nuclear@0
|
176 if(win->keyboard_func) {
|
nuclear@0
|
177 win->keyboard_func(wparam, win->mousex, win->mousey);
|
nuclear@0
|
178 }
|
nuclear@0
|
179 } else {
|
nuclear@0
|
180 if(win->special_func) {
|
nuclear@0
|
181 win->special_func(wparam, win->mousex, win->mousey);
|
nuclear@0
|
182 }
|
nuclear@0
|
183 }
|
nuclear@0
|
184 break;
|
nuclear@0
|
185
|
nuclear@0
|
186 case WM_KEYUP:
|
nuclear@0
|
187 if(wparam < 256) {
|
nuclear@0
|
188 if(win->keyboard_up_func) {
|
nuclear@0
|
189 win->keyboard_up_func(wparam, win->mousex, win->mousey);
|
nuclear@0
|
190 }
|
nuclear@0
|
191 } else {
|
nuclear@0
|
192 if(win->special_up_func) {
|
nuclear@0
|
193 win->special_up_func(wparam, win->mousex, win->mousey);
|
nuclear@0
|
194 }
|
nuclear@0
|
195 }
|
nuclear@0
|
196 break;
|
nuclear@0
|
197
|
nuclear@0
|
198 case WM_MOUSEMOVE:
|
nuclear@0
|
199 win->mousex = LOWORD(lparam);
|
nuclear@0
|
200 win->mousey = HIWORD(lparam);
|
nuclear@0
|
201
|
nuclear@0
|
202 if(wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
|
nuclear@0
|
203 if(win->motion_func) {
|
nuclear@0
|
204 win->motion_func(win->mousex, win->mousey);
|
nuclear@0
|
205 }
|
nuclear@0
|
206 } else {
|
nuclear@0
|
207 if(win->passive_motion_func) {
|
nuclear@0
|
208 win->passive_motion_func(win->mousex, win->mousey);
|
nuclear@0
|
209 }
|
nuclear@0
|
210 }
|
nuclear@0
|
211 break;
|
nuclear@0
|
212
|
nuclear@0
|
213 case WM_LBUTTONDOWN:
|
nuclear@0
|
214 mouse_handler(win, D3DUT_LEFT_BUTTON, true);
|
nuclear@0
|
215 break;
|
nuclear@0
|
216 case WM_RBUTTONDOWN:
|
nuclear@0
|
217 mouse_handler(win, D3DUT_RIGHT_BUTTON, true);
|
nuclear@0
|
218 break;
|
nuclear@0
|
219 case WM_MBUTTONDOWN:
|
nuclear@0
|
220 mouse_handler(win, D3DUT_MIDDLE_BUTTON, true);
|
nuclear@0
|
221 break;
|
nuclear@0
|
222 case WM_LBUTTONUP:
|
nuclear@0
|
223 mouse_handler(win, D3DUT_LEFT_BUTTON, false);
|
nuclear@0
|
224 break;
|
nuclear@0
|
225 case WM_RBUTTONUP:
|
nuclear@0
|
226 mouse_handler(win, D3DUT_RIGHT_BUTTON, false);
|
nuclear@0
|
227 break;
|
nuclear@0
|
228 case WM_MBUTTONUP:
|
nuclear@0
|
229 mouse_handler(win, D3DUT_MIDDLE_BUTTON, false);
|
nuclear@0
|
230 break;
|
nuclear@0
|
231
|
nuclear@0
|
232 case WM_MOUSEWHEEL:
|
nuclear@0
|
233 {
|
nuclear@0
|
234 int delta = GET_WHEEL_DELTA_WPARAM(wparam);
|
nuclear@0
|
235 mouse_handler(win, delta < 0 ? D3DUT_WHEELDOWN_BUTTON : D3DUT_WHEELUP_BUTTON, true);
|
nuclear@0
|
236 }
|
nuclear@0
|
237 break;
|
nuclear@0
|
238
|
nuclear@0
|
239 default:
|
nuclear@0
|
240 return DefWindowProc(syswin, msg, wparam, lparam);
|
nuclear@0
|
241 }
|
nuclear@0
|
242
|
nuclear@0
|
243 return 0;
|
nuclear@0
|
244 }
|
nuclear@0
|
245
|
nuclear@0
|
246 static void mouse_handler(Window *win, int bn, bool pressed)
|
nuclear@0
|
247 {
|
nuclear@0
|
248 if(win->mouse_func) {
|
nuclear@0
|
249 win->mouse_func(bn, pressed ? D3DUT_DOWN : D3DUT_UP, win->mousex, win->mousey);
|
nuclear@0
|
250 }
|
nuclear@0
|
251 } |