vkQuake2 doxygen  1.0 dev
vk_imp.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 Copyright (C) 2018-2019 Krzysztof Kondrak
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14 See the GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 */
21 /*
22 ** VK_IMP.C
23 **
24 ** This file contains ALL Win32 specific stuff having to do with the
25 ** Vulkan refresh. When a port is being made the following functions
26 ** must be implemented by the port:
27 **
28 ** Vkimp_EndFrame
29 ** Vkimp_Init
30 ** Vkimp_Shutdown
31 **
32 */
33 #include <assert.h>
34 #include <windows.h>
35 #include "../ref_vk/vk_local.h"
36 #include "vk_win.h"
37 #include "winquake.h"
38 
40 
41 extern cvar_t *vid_fullscreen;
42 extern cvar_t *vid_ref;
43 
44 /*
45 ** VID_CreateWindow
46 */
47 #define WINDOW_CLASS_NAME "Quake 2"
48 
50 {
51  WNDCLASS wc;
52  RECT r;
54  int stylebits;
55  int x, y, w, h;
56  int exstyle;
57 
58  /* Register the frame class */
59  wc.style = 0;
60  wc.lpfnWndProc = (WNDPROC)vkw_state.wndproc;
61  wc.cbClsExtra = 0;
62  wc.cbWndExtra = 0;
63  wc.hInstance = vkw_state.hInstance;
64  wc.hIcon = 0;
65  wc.hCursor = LoadCursor (NULL,IDC_ARROW);
66  wc.hbrBackground = (void *)COLOR_GRAYTEXT;
67  wc.lpszMenuName = 0;
68  wc.lpszClassName = WINDOW_CLASS_NAME;
69 
70  if (!RegisterClass (&wc) )
71  ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
72 
73  if (fullscreen)
74  {
75  exstyle = WS_EX_TOPMOST;
76  stylebits = WS_POPUP|WS_VISIBLE;
77  }
78  else
79  {
80  exstyle = 0;
81  stylebits = WINDOW_STYLE;
82  }
83 
84  r.left = 0;
85  r.top = 0;
86  r.right = width;
87  r.bottom = height;
88 
89  AdjustWindowRect (&r, stylebits, FALSE);
90 
91  w = r.right - r.left;
92  h = r.bottom - r.top;
93 
94  vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
95  vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
96  x = vid_xpos->value;
97  y = vid_ypos->value;
98 
99  vkw_state.hWnd = CreateWindowEx (
100  exstyle,
102  "Quake 2 (Vulkan) "CPUSTRING,
103  stylebits,
104  x, y, w, h,
105  NULL,
106  NULL,
108  NULL);
109 
110  if (!vkw_state.hWnd)
111  ri.Sys_Error (ERR_FATAL, "Couldn't create window");
112 
113  memset( &vkw_state.monInfo, 0, sizeof(MONITORINFOEX) );
114  vkw_state.monInfo.cbSize = sizeof(MONITORINFOEX);
115  GetMonitorInfo( MonitorFromWindow(vkw_state.hWnd, MONITOR_DEFAULTTOPRIMARY), (LPMONITORINFO)&vkw_state.monInfo );
116 
117  if (fullscreen)
118  {
119  DEVMODE dm;
120  memset(&dm, 0, sizeof(dm));
121 
122  dm.dmSize = sizeof(dm);
123  dm.dmPelsWidth = width;
124  dm.dmPelsHeight = height;
125  dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
126 
127  if (vk_bitdepth->value != 0)
128  {
129  dm.dmBitsPerPel = vk_bitdepth->value;
130  dm.dmFields |= DM_BITSPERPEL;
131  }
132 
133  if ( ChangeDisplaySettingsEx( vkw_state.monInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL ) != DISP_CHANGE_SUCCESSFUL )
134  {
135  return false;
136  }
137 
138  GetMonitorInfo( MonitorFromWindow(vkw_state.hWnd, MONITOR_DEFAULTTOPRIMARY), (LPMONITORINFO)&vkw_state.monInfo );
139  SetWindowPos( vkw_state.hWnd, NULL, vkw_state.monInfo.rcMonitor.left, vkw_state.monInfo.rcMonitor.top, width, height,
140  SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER );
141  }
142  else
143  {
144  ChangeDisplaySettingsEx( vkw_state.monInfo.szDevice, NULL, NULL, 0, NULL );
145  }
146 
147  ShowWindow( vkw_state.hWnd, SW_SHOW );
148  UpdateWindow( vkw_state.hWnd );
149  SetForegroundWindow( vkw_state.hWnd );
150  SetFocus( vkw_state.hWnd );
151 
152  // let the sound and input subsystems know about the new window
154 
155  return true;
156 }
157 
158 void Vkimp_GetSurfaceExtensions(char **extensions, uint32_t *extCount)
159 {
160  if (extensions)
161  {
162  extensions[0] = VK_KHR_SURFACE_EXTENSION_NAME;
163  extensions[1] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
164  }
165 
166  if (extCount)
167  *extCount = 2;
168 }
169 
171 {
172  VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {
173  .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
174  .pNext = NULL,
175  .flags = 0,
176  .hinstance = GetModuleHandle(NULL),
177  .hwnd = vkw_state.hWnd,
178  };
179 
180  return vkCreateWin32SurfaceKHR(vk_instance, &surfaceCreateInfo, NULL, &vk_surface);
181 }
182 
183 /*
184 ** Vkimp_SetMode
185 */
186 rserr_t Vkimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
187 {
188  int width, height;
189  const char *win_fs[] = { "W", "FS" };
190 
191  ri.Con_Printf( PRINT_ALL, "Initializing Vulkan display\n");
192 
193  ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode );
194 
195  if ( !ri.Vid_GetModeInfo( &width, &height, mode ) )
196  {
197  ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
198  return rserr_invalid_mode;
199  }
200 
201  ri.Con_Printf( PRINT_ALL, " %d %d %s\n", width, height, win_fs[fullscreen] );
202 
203  // destroy the existing window
204  if (vkw_state.hWnd)
205  {
206  Vkimp_Shutdown ();
207  }
208 
209  // do a CDS if needed
210  if ( fullscreen )
211  {
212  ri.Con_Printf( PRINT_ALL, "...attempting fullscreen\n" );
213 
214  if ( vk_bitdepth->value != 0 )
215  {
216  ri.Con_Printf( PRINT_ALL, "...using vk_bitdepth of %d\n", ( int ) vk_bitdepth->value );
217  }
218  else
219  {
220  HDC hdc = GetDC( NULL );
221  int bitspixel = GetDeviceCaps( hdc, BITSPIXEL );
222 
223  ri.Con_Printf( PRINT_ALL, "...using desktop display depth of %d\n", bitspixel );
224 
225  ReleaseDC( 0, hdc );
226  }
227 
228  ri.Con_Printf( PRINT_ALL, "...calling CDS: " );
229  if ( VID_CreateWindow(width, height, true) )
230  {
231  *pwidth = width;
232  *pheight = height;
233 
234  vk_state.fullscreen = true;
235 
236  ri.Con_Printf( PRINT_ALL, "ok\n" );
237  return rserr_ok;
238  }
239  else
240  {
241  ri.Con_Printf( PRINT_ALL, " failed\n" );
242  ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
243 
244  DestroyWindow(vkw_state.hWnd);
245  UnregisterClass(WINDOW_CLASS_NAME, vkw_state.hInstance);
246  VID_CreateWindow(width, height, false);
247 
248  *pwidth = width;
249  *pheight = height;
250  vk_state.fullscreen = false;
252  }
253  }
254  else
255  {
256  ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
257 
258  *pwidth = width;
259  *pheight = height;
260  vk_state.fullscreen = false;
261  if ( !VID_CreateWindow (width, height, false) )
262  return rserr_invalid_mode;
263  }
264 
265  return rserr_ok;
266 }
267 
268 /*
269 ** Vkimp_Shutdown
270 **
271 ** For Vulkan, the OS-specific part here is only destroying the window.
272 **
273 */
274 void Vkimp_Shutdown( void )
275 {
276  if (vkw_state.hWnd)
277  {
278  DestroyWindow(vkw_state.hWnd);
279  vkw_state.hWnd = NULL;
280  }
281 
282  if (vkw_state.log_fp)
283  {
284  fclose(vkw_state.log_fp);
285  vkw_state.log_fp = 0;
286  }
287 
288  UnregisterClass(WINDOW_CLASS_NAME, vkw_state.hInstance);
289 
290  if (vk_state.fullscreen)
291  {
292  ChangeDisplaySettingsEx( vkw_state.monInfo.szDevice, NULL, NULL, 0, NULL );
293  vk_state.fullscreen = false;
294  }
295 }
296 
297 
298 /*
299 ** Vkimp_Init
300 **
301 ** This routine is responsible for initializing the OS specific portions
302 ** of Vulkan.
303 */
304 qboolean Vkimp_Init( void *hinstance, void *wndproc )
305 {
306 #define OSR2_BUILD_NUMBER 1111
307 
308  OSVERSIONINFO vinfo;
309 
310  vinfo.dwOSVersionInfoSize = sizeof(vinfo);
311 
313 
314  if ( GetVersionEx( &vinfo) )
315  {
316  if ( vinfo.dwMajorVersion > 4 )
317  {
319  }
320  else if ( vinfo.dwMajorVersion == 4 )
321  {
322  if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
323  {
325  }
326  else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
327  {
328  if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
329  {
331  }
332  }
333  }
334  }
335  else
336  {
337  ri.Con_Printf( PRINT_ALL, "Vkimp_Init() - GetVersionEx failed\n" );
338  return false;
339  }
340 
341  vkw_state.hInstance = ( HINSTANCE ) hinstance;
342  vkw_state.wndproc = wndproc;
343 
344  return true;
345 }
346 
347 /*
348 ** Vkimp_BeginFrame
349 */
350 void Vkimp_BeginFrame( float camera_separation )
351 {
352  if (vk_bitdepth->modified)
353  {
355  {
356  ri.Cvar_SetValue("vk_bitdepth", 0);
357  ri.Con_Printf(PRINT_ALL, "vk_bitdepth requires Win95 OSR2.x or WinNT 4.x\n");
358  }
359  vk_bitdepth->modified = false;
360  }
361 }
362 
363 /*
364 ** Vkimp_EndFrame
365 **
366 ** Responsible for doing a swapbuffers and possibly for other stuff
367 ** as yet to be determined.
368 */
369 void Vkimp_EndFrame (void)
370 {
371 }
372 
373 /*
374 ** Vkimp_AppActivate
375 */
377 {
378  if ( active )
379  {
380  SetForegroundWindow( vkw_state.hWnd );
381  ShowWindow( vkw_state.hWnd, SW_RESTORE );
382  }
383  else
384  {
385  if ( vid_fullscreen->value )
386  ShowWindow( vkw_state.hWnd, SW_MINIMIZE );
387  }
388 }
rserr_t
rserr_t
Definition: r_local.h:103
height
GLsizei height
Definition: qgl_win.c:69
OSR2_BUILD_NUMBER
#define OSR2_BUILD_NUMBER
vk_instance
VkInstance vk_instance
Definition: vk_common.c:46
ri
refimport_t ri
Definition: r_main.c:25
refimport_t::Vid_NewWindow
void(* Vid_NewWindow)(int width, int height)
Definition: ref.h:222
vk_win.h
cvar_s::modified
qboolean modified
Definition: q_shared.h:330
VID_CreateWindow
qboolean VID_CreateWindow(int width, int height, qboolean fullscreen)
Definition: vk_imp.c:49
vid_fullscreen
cvar_t * vid_fullscreen
Definition: vid_dll.c:47
refimport_t::Cvar_Get
cvar_t *(* Cvar_Get)(char *name, char *value, int flags)
Definition: ref.h:216
Vkimp_Shutdown
void Vkimp_Shutdown(void)
Definition: vk_imp.c:274
qboolean
qboolean
Definition: q_shared.h:63
x
GLint GLenum GLint x
Definition: qgl_win.c:116
winquake.h
vkwstate_t::wndproc
void * wndproc
Definition: vk_win.h:31
vkw_state
vkwstate_t vkw_state
Definition: vk_imp.c:39
width
GLint GLsizei width
Definition: qgl_win.c:115
vkwstate_t
Definition: vk_win.h:28
cvar_s
Definition: q_shared.h:324
Vkimp_BeginFrame
void Vkimp_BeginFrame(float camera_separation)
Definition: vk_imp.c:350
refimport_t::Vid_GetModeInfo
qboolean(* Vid_GetModeInfo)(int *width, int *height, int mode)
Definition: ref.h:220
vkwstate_t::monInfo
MONITORINFOEX monInfo
Definition: vk_win.h:33
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:202
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:751
WINDOW_CLASS_NAME
#define WINDOW_CLASS_NAME
Definition: vk_imp.c:47
Vkimp_GetSurfaceExtensions
void Vkimp_GetSurfaceExtensions(char **extensions, uint32_t *extCount)
Definition: vk_imp.c:158
r
GLdouble GLdouble r
Definition: qgl_win.c:336
HDC
HDC(WINAPI *qwglGetCurrentDC)(VOID)
Vkimp_EndFrame
void Vkimp_EndFrame(void)
Definition: vk_imp.c:369
Vkimp_SetMode
rserr_t Vkimp_SetMode(int *pwidth, int *pheight, int mode, qboolean fullscreen)
Definition: vk_imp.c:186
rserr_invalid_mode
@ rserr_invalid_mode
Definition: r_local.h:108
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:194
cvar_s::value
float value
Definition: q_shared.h:331
vk_state
vkstate_t vk_state
Definition: vk_rmain.c:31
vkwstate_t::allowdisplaydepthchange
qboolean allowdisplaydepthchange
Definition: vk_win.h:35
NULL
#define NULL
Definition: q_shared.h:67
Vkimp_CreateSurface
VkResult Vkimp_CreateSurface()
Definition: vk_imp.c:170
ERR_FATAL
#define ERR_FATAL
Definition: qcommon.h:743
y
GLint y
Definition: qgl_win.c:115
WINDOW_STYLE
#define WINDOW_STYLE
Definition: winquake.h:28
vid_ref
cvar_t * vid_ref
Definition: vid_dll.c:44
Vkimp_AppActivate
void Vkimp_AppActivate(qboolean active)
Definition: vk_imp.c:376
rserr_ok
@ rserr_ok
Definition: r_local.h:105
vk_bitdepth
cvar_t * vk_bitdepth
Definition: vk_rmain.c:92
vkwstate_t::hWnd
HWND hWnd
Definition: vk_win.h:32
vid_xpos
cvar_t * vid_xpos
Definition: vid_dll.c:45
vkwstate_t::log_fp
FILE * log_fp
Definition: vk_win.h:36
vk_surface
VkSurfaceKHR vk_surface
Definition: vk_common.c:47
w
GLdouble GLdouble GLdouble w
Definition: qgl_win.c:291
FALSE
#define FALSE
Definition: stb_vorbis.c:618
refimport_t::Cvar_SetValue
void(* Cvar_SetValue)(char *name, float value)
Definition: ref.h:218
mode
GLenum mode
Definition: qgl_win.c:113
Vkimp_Init
qboolean Vkimp_Init(void *hinstance, void *wndproc)
Definition: vk_imp.c:304
vid_ypos
cvar_t * vid_ypos
Definition: vid_dll.c:46
vkwstate_t::hInstance
HINSTANCE hInstance
Definition: vk_win.h:30
CPUSTRING
#define CPUSTRING
Definition: qcommon.h:86
vkstate_t::fullscreen
qboolean fullscreen
Definition: vk_local.h:333
rserr_invalid_fullscreen
@ rserr_invalid_fullscreen
Definition: r_local.h:107