d3dut

annotate src/win.cc @ 1:242535442d04

added license, readme, and gpl headers
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 22 Jun 2013 10:43:12 +0300
parents ecc040281dc9
children
rev   line source
nuclear@1 1 /*
nuclear@1 2 D3DUT - Simple window creation and event handling for Direct3D 11 applications.
nuclear@1 3 Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org>
nuclear@1 4
nuclear@1 5 This program is free software: you can redistribute it and/or modify
nuclear@1 6 it under the terms of the GNU Lesser General Public License as published by
nuclear@1 7 the Free Software Foundation, either version 3 of the License, or
nuclear@1 8 (at your option) any later version.
nuclear@1 9
nuclear@1 10 This program is distributed in the hope that it will be useful,
nuclear@1 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@1 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@1 13 GNU Lesser General Public License for more details.
nuclear@1 14
nuclear@1 15 You should have received a copy of the GNU Lesser General Public License
nuclear@1 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@1 17 */
nuclear@0 18 #include <dxgi.h>
nuclear@0 19 #include "d3dut.h"
nuclear@0 20 #include "win.h"
nuclear@0 21 #include "logmsg.h"
nuclear@0 22
nuclear@0 23 std::vector<Window*> windows;
nuclear@0 24 int active_win = -1;
nuclear@0 25
nuclear@0 26 int create_window(const char *title, int xsz, int ysz, unsigned int dmflags)
nuclear@0 27 {
nuclear@0 28 IDXGIDevice *dxgidev;
nuclear@0 29 if(d3dut_dev->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgidev) != 0) {
nuclear@0 30 fatal_error("failed to get IDXGIDevice interface\n");
nuclear@0 31 return 0;
nuclear@0 32 }
nuclear@0 33 IDXGIAdapter *adapter;
nuclear@0 34 if(dxgidev->GetParent(__uuidof(IDXGIAdapter), (void**)&adapter) != 0) {
nuclear@0 35 fatal_error("failed to get IDXGIAdapter pointer\n");
nuclear@0 36 return 0;
nuclear@0 37 }
nuclear@0 38 IDXGIFactory *dxgi_factory;
nuclear@0 39 if(adapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgi_factory) != 0) {
nuclear@0 40 fatal_error("failed to get IDXGIFactory pointer\n");
nuclear@0 41 return 0;
nuclear@0 42 }
nuclear@0 43 adapter->Release();
nuclear@0 44 dxgidev->Release();
nuclear@0 45
nuclear@0 46 Window *win = new Window;
nuclear@0 47 memset(win, 0, sizeof *win);
nuclear@0 48 win->must_redisplay = true;
nuclear@0 49 win->changed_size = true;
nuclear@0 50 win->width = xsz;
nuclear@0 51 win->height = ysz;
nuclear@0 52
nuclear@0 53 int xpos = (GetSystemMetrics(SM_CXSCREEN) - xsz) / 2;
nuclear@0 54 int ypos = (GetSystemMetrics(SM_CYSCREEN) - ysz) / 2;
nuclear@0 55 win->win = CreateWindow(WINCLASSNAME, title, WS_OVERLAPPEDWINDOW, xpos, ypos, xsz, ysz, 0, 0, GetModuleHandle(0), 0);
nuclear@0 56 if(!win->win) {
nuclear@0 57 fprintf(stderr, "failed to create window: %s\n", title);
nuclear@0 58 return 0;
nuclear@0 59 }
nuclear@0 60 ShowWindow(win->win, SW_SHOW);
nuclear@0 61
nuclear@0 62 unsigned int nsamples = 1;
nuclear@0 63 unsigned int quality = 0;
nuclear@0 64 if(dmflags & D3DUT_MULTISAMPLE) {
nuclear@0 65 nsamples = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
nuclear@0 66 d3dut_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, nsamples, &quality);
nuclear@0 67 }
nuclear@0 68
nuclear@0 69 DXGI_SWAP_CHAIN_DESC sd;
nuclear@0 70 memset(&sd, 0, sizeof sd);
nuclear@0 71 sd.OutputWindow = win->win;
nuclear@0 72 sd.BufferDesc.Width = xsz;
nuclear@0 73 sd.BufferDesc.Height = ysz;
nuclear@0 74 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
nuclear@0 75 //sd.Stereo = (dmflags & D3DUT_STEREO) ? 1 : 0;
nuclear@0 76 sd.BufferDesc.RefreshRate.Numerator = 60;
nuclear@0 77 sd.BufferDesc.RefreshRate.Denominator = 1;
nuclear@0 78 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
nuclear@0 79 sd.BufferCount = (dmflags & D3DUT_DOUBLE) ? 1 : 0;
nuclear@0 80 sd.SampleDesc.Count = nsamples;
nuclear@0 81 sd.SampleDesc.Quality = quality;
nuclear@0 82 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
nuclear@0 83 sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
nuclear@0 84 sd.Windowed = 1;
nuclear@0 85
nuclear@0 86 if(dxgi_factory->CreateSwapChain(d3dut_dev, &sd, &win->swap) != 0) {
nuclear@0 87 warning("failed to create swap chain\n");
nuclear@0 88 return 0;
nuclear@0 89 }
nuclear@0 90 dxgi_factory->Release();
nuclear@0 91
nuclear@0 92 ID3D11Texture2D *rtex;
nuclear@0 93 if(win->swap->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&rtex) != 0) {
nuclear@0 94 warning("failed to get default render target texture\n");
nuclear@0 95 return 0;
nuclear@0 96 }
nuclear@0 97 if(d3dut_dev->CreateRenderTargetView(rtex, 0, &win->rtarg_view) != 0) {
nuclear@0 98 warning("failed to create render target view\n");
nuclear@0 99 rtex->Release();
nuclear@0 100 return 0;
nuclear@0 101 }
nuclear@0 102 rtex->Release();
nuclear@0 103 d3dut_ctx->OMSetRenderTargets(1, &win->rtarg_view, 0);
nuclear@0 104
nuclear@0 105 int idx = (int)windows.size();
nuclear@0 106 windows.push_back(win);
nuclear@0 107 set_active_win(idx);
nuclear@0 108 return idx;
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 void destroy_window(int idx)
nuclear@0 112 {
nuclear@0 113 if(idx < 0 || idx >= (int)windows.size()) {
nuclear@0 114 warning("destroy_window: invalid index: %d\n", idx);
nuclear@0 115 return;
nuclear@0 116 }
nuclear@0 117
nuclear@0 118 Window *win = windows[idx];
nuclear@0 119 if(win) {
nuclear@0 120 DestroyWindow(win->win);
nuclear@0 121 win->rtarg_view->Release();
nuclear@0 122 win->swap->Release();
nuclear@0 123 delete win;
nuclear@0 124 windows[idx] = 0;
nuclear@0 125 }
nuclear@0 126 }
nuclear@0 127
nuclear@0 128 void set_active_win(int idx)
nuclear@0 129 {
nuclear@0 130 if(idx < 0 || idx >= (int)windows.size()) {
nuclear@0 131 warning("set_active_win: invalid window: %d\n", idx);
nuclear@0 132 return;
nuclear@0 133 }
nuclear@0 134 d3dut_rtview = windows[idx]->rtarg_view;
nuclear@0 135 active_win = idx;
nuclear@0 136 }
nuclear@0 137
nuclear@0 138 int get_active_win()
nuclear@0 139 {
nuclear@0 140 return active_win;
nuclear@0 141 }
nuclear@0 142
nuclear@0 143 Window *get_window(int idx)
nuclear@0 144 {
nuclear@0 145 if(idx < 0) {
nuclear@0 146 idx = active_win;
nuclear@0 147 }
nuclear@0 148 if(idx < 0 || idx >= (int)windows.size()) {
nuclear@0 149 return 0;
nuclear@0 150 }
nuclear@0 151 return windows[idx];
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 static int find_window(HWND syswin)
nuclear@0 155 {
nuclear@0 156 for(size_t i=0; i<windows.size(); i++) {
nuclear@0 157 if(windows[i]->win == syswin) {
nuclear@0 158 return i;
nuclear@0 159 }
nuclear@0 160 }
nuclear@0 161 return -1;
nuclear@0 162 }
nuclear@0 163
nuclear@0 164 static void mouse_handler(Window *win, int bn, bool pressed);
nuclear@0 165
nuclear@0 166 long CALLBACK win_handle_event(HWND syswin, unsigned int msg, unsigned int wparam, long lparam)
nuclear@0 167 {
nuclear@0 168 Window *win = 0;
nuclear@0 169 int winid = find_window(syswin);
nuclear@0 170 if(winid != -1) {
nuclear@0 171 set_active_win(winid);
nuclear@0 172 win = get_window();
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 switch(msg) {
nuclear@0 176 case WM_PAINT:
nuclear@0 177 win->must_redisplay = true;
nuclear@0 178 ValidateRect(win->win, 0);
nuclear@0 179 break;
nuclear@0 180
nuclear@0 181 case WM_CLOSE:
nuclear@0 182 destroy_window(winid);
nuclear@0 183 break;
nuclear@0 184
nuclear@0 185 case WM_SIZE:
nuclear@0 186 win->width = LOWORD(lparam);
nuclear@0 187 win->height = HIWORD(lparam);
nuclear@0 188 win->changed_size = true;
nuclear@0 189 break;
nuclear@0 190
nuclear@0 191 case WM_KEYDOWN:
nuclear@0 192 if(wparam < 256) {
nuclear@0 193 if(win->keyboard_func) {
nuclear@0 194 win->keyboard_func(wparam, win->mousex, win->mousey);
nuclear@0 195 }
nuclear@0 196 } else {
nuclear@0 197 if(win->special_func) {
nuclear@0 198 win->special_func(wparam, win->mousex, win->mousey);
nuclear@0 199 }
nuclear@0 200 }
nuclear@0 201 break;
nuclear@0 202
nuclear@0 203 case WM_KEYUP:
nuclear@0 204 if(wparam < 256) {
nuclear@0 205 if(win->keyboard_up_func) {
nuclear@0 206 win->keyboard_up_func(wparam, win->mousex, win->mousey);
nuclear@0 207 }
nuclear@0 208 } else {
nuclear@0 209 if(win->special_up_func) {
nuclear@0 210 win->special_up_func(wparam, win->mousex, win->mousey);
nuclear@0 211 }
nuclear@0 212 }
nuclear@0 213 break;
nuclear@0 214
nuclear@0 215 case WM_MOUSEMOVE:
nuclear@0 216 win->mousex = LOWORD(lparam);
nuclear@0 217 win->mousey = HIWORD(lparam);
nuclear@0 218
nuclear@0 219 if(wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
nuclear@0 220 if(win->motion_func) {
nuclear@0 221 win->motion_func(win->mousex, win->mousey);
nuclear@0 222 }
nuclear@0 223 } else {
nuclear@0 224 if(win->passive_motion_func) {
nuclear@0 225 win->passive_motion_func(win->mousex, win->mousey);
nuclear@0 226 }
nuclear@0 227 }
nuclear@0 228 break;
nuclear@0 229
nuclear@0 230 case WM_LBUTTONDOWN:
nuclear@0 231 mouse_handler(win, D3DUT_LEFT_BUTTON, true);
nuclear@0 232 break;
nuclear@0 233 case WM_RBUTTONDOWN:
nuclear@0 234 mouse_handler(win, D3DUT_RIGHT_BUTTON, true);
nuclear@0 235 break;
nuclear@0 236 case WM_MBUTTONDOWN:
nuclear@0 237 mouse_handler(win, D3DUT_MIDDLE_BUTTON, true);
nuclear@0 238 break;
nuclear@0 239 case WM_LBUTTONUP:
nuclear@0 240 mouse_handler(win, D3DUT_LEFT_BUTTON, false);
nuclear@0 241 break;
nuclear@0 242 case WM_RBUTTONUP:
nuclear@0 243 mouse_handler(win, D3DUT_RIGHT_BUTTON, false);
nuclear@0 244 break;
nuclear@0 245 case WM_MBUTTONUP:
nuclear@0 246 mouse_handler(win, D3DUT_MIDDLE_BUTTON, false);
nuclear@0 247 break;
nuclear@0 248
nuclear@0 249 case WM_MOUSEWHEEL:
nuclear@0 250 {
nuclear@0 251 int delta = GET_WHEEL_DELTA_WPARAM(wparam);
nuclear@0 252 mouse_handler(win, delta < 0 ? D3DUT_WHEELDOWN_BUTTON : D3DUT_WHEELUP_BUTTON, true);
nuclear@0 253 }
nuclear@0 254 break;
nuclear@0 255
nuclear@0 256 default:
nuclear@0 257 return DefWindowProc(syswin, msg, wparam, lparam);
nuclear@0 258 }
nuclear@0 259
nuclear@0 260 return 0;
nuclear@0 261 }
nuclear@0 262
nuclear@0 263 static void mouse_handler(Window *win, int bn, bool pressed)
nuclear@0 264 {
nuclear@0 265 if(win->mouse_func) {
nuclear@0 266 win->mouse_func(bn, pressed ? D3DUT_DOWN : D3DUT_UP, win->mousex, win->mousey);
nuclear@0 267 }
nuclear@1 268 }