mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 23:11:38 +00:00
[vid] Clean up windows video code a bit
It turns out the dd and dib "driver" code is very specific to the software renderer. This does not fix the segfault on changing video mode, but I do know where the problem lies: the window is being destroyed and recreated without recreating the buffers. I suspect a clean solution to this will allow for window resizing in X as well.
This commit is contained in:
parent
8ec781a434
commit
3eb28000de
5 changed files with 325 additions and 367 deletions
|
@ -35,25 +35,19 @@
|
||||||
|
|
||||||
extern HWND win_mainwindow;
|
extern HWND win_mainwindow;
|
||||||
extern HDC win_maindc;
|
extern HDC win_maindc;
|
||||||
extern HDC win_dib_section;
|
|
||||||
extern int win_using_ddraw;
|
|
||||||
extern int win_palettized;
|
extern int win_palettized;
|
||||||
extern int win_canalttab;
|
extern int win_canalttab;
|
||||||
extern DEVMODE win_gdevmode;
|
extern DEVMODE win_gdevmode;
|
||||||
extern LPDIRECTDRAWSURFACE win_dd_frontbuffer;
|
|
||||||
extern LPDIRECTDRAWSURFACE win_dd_backbuffer;
|
|
||||||
extern RECT win_src_rect;
|
|
||||||
extern RECT win_dst_rect;
|
|
||||||
extern RECT win_window_rect;
|
|
||||||
extern HDC win_gdi;
|
|
||||||
extern struct sw_ctx_s *win_sw_context;
|
extern struct sw_ctx_s *win_sw_context;
|
||||||
extern int win_minimized;
|
extern int win_minimized;
|
||||||
|
extern struct cvar_s *vid_ddraw;
|
||||||
|
extern int win_center_x, win_center_y;
|
||||||
|
extern RECT win_rect;
|
||||||
|
|
||||||
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
void Win_Activate (BOOL fActive, BOOL minimize);
|
void Win_Activate (BOOL fActive, BOOL minimize);
|
||||||
|
|
||||||
void Win_UnloadAllDrivers (void);
|
void Win_UnloadAllDrivers (void);
|
||||||
void Win_CreateDriver (void);
|
|
||||||
void Win_OpenDisplay (void);
|
void Win_OpenDisplay (void);
|
||||||
void Win_CloseDisplay (void);
|
void Win_CloseDisplay (void);
|
||||||
void Win_SetVidMode (int width, int height, const byte *palette);
|
void Win_SetVidMode (int width, int height, const byte *palette);
|
||||||
|
|
|
@ -80,9 +80,6 @@ extern qboolean WinNT;
|
||||||
|
|
||||||
extern qboolean winsock_lib_initialized;
|
extern qboolean winsock_lib_initialized;
|
||||||
|
|
||||||
extern int window_center_x, window_center_y;
|
|
||||||
extern RECT window_rect;
|
|
||||||
|
|
||||||
#ifdef SPLASH_SCREEN
|
#ifdef SPLASH_SCREEN
|
||||||
extern HWND hwnd_dialog;
|
extern HWND hwnd_dialog;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,16 +46,8 @@
|
||||||
|
|
||||||
HWND win_mainwindow;
|
HWND win_mainwindow;
|
||||||
HDC win_maindc;
|
HDC win_maindc;
|
||||||
HDC win_dib_section;
|
|
||||||
int win_using_ddraw;
|
|
||||||
int win_palettized;
|
int win_palettized;
|
||||||
int win_minimized;
|
int win_minimized;
|
||||||
LPDIRECTDRAWSURFACE win_dd_frontbuffer;
|
|
||||||
LPDIRECTDRAWSURFACE win_dd_backbuffer;
|
|
||||||
RECT win_src_rect;
|
|
||||||
RECT win_dst_rect;
|
|
||||||
RECT win_window_rect;
|
|
||||||
HDC win_gdi;
|
|
||||||
int win_canalttab = 0;
|
int win_canalttab = 0;
|
||||||
sw_ctx_t *win_sw_context;
|
sw_ctx_t *win_sw_context;
|
||||||
|
|
||||||
|
@ -64,7 +56,7 @@ sw_ctx_t *win_sw_context;
|
||||||
#define NO_MODE (MODE_WINDOWED - 1)
|
#define NO_MODE (MODE_WINDOWED - 1)
|
||||||
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3)
|
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3)
|
||||||
|
|
||||||
static cvar_t *vid_ddraw;
|
cvar_t *vid_ddraw;
|
||||||
|
|
||||||
// Note that 0 is MODE_WINDOWED
|
// Note that 0 is MODE_WINDOWED
|
||||||
static cvar_t *vid_mode;
|
static cvar_t *vid_mode;
|
||||||
|
@ -96,8 +88,8 @@ static int DIBWidth, DIBHeight;
|
||||||
static RECT WindowRect;
|
static RECT WindowRect;
|
||||||
static DWORD WindowStyle, ExWindowStyle;
|
static DWORD WindowStyle, ExWindowStyle;
|
||||||
|
|
||||||
int window_center_x, window_center_y, window_width, window_height;
|
int win_center_x, win_center_y;
|
||||||
RECT window_rect;
|
RECT win_rect;
|
||||||
|
|
||||||
DEVMODE win_gdevmode;
|
DEVMODE win_gdevmode;
|
||||||
static qboolean startwindowed = 0, windowed_mode_set;
|
static qboolean startwindowed = 0, windowed_mode_set;
|
||||||
|
@ -130,7 +122,32 @@ typedef struct {
|
||||||
char modedesc[13];
|
char modedesc[13];
|
||||||
} vmode_t;
|
} vmode_t;
|
||||||
|
|
||||||
static vmode_t modelist[MAX_MODE_LIST];
|
static vmode_t modelist[MAX_MODE_LIST] = {
|
||||||
|
{
|
||||||
|
.type = MS_WINDOWED,
|
||||||
|
.width = 320,
|
||||||
|
.height = 240,
|
||||||
|
.modedesc = "320x240",
|
||||||
|
.modenum = MODE_WINDOWED,
|
||||||
|
.fullscreen = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = MS_WINDOWED,
|
||||||
|
.width = 640,
|
||||||
|
.height = 480,
|
||||||
|
.modedesc = "640x480",
|
||||||
|
.modenum = MODE_WINDOWED + 1,
|
||||||
|
.fullscreen = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = MS_WINDOWED,
|
||||||
|
.width = 800,
|
||||||
|
.height = 600,
|
||||||
|
.modedesc = "800x600",
|
||||||
|
.modenum = MODE_WINDOWED + 2,
|
||||||
|
.fullscreen = 0,
|
||||||
|
}
|
||||||
|
};
|
||||||
static int nummodes;
|
static int nummodes;
|
||||||
|
|
||||||
int aPage; // Current active display page
|
int aPage; // Current active display page
|
||||||
|
@ -141,287 +158,6 @@ static vmode_t badmode = {
|
||||||
.modedesc = "Bad mode",
|
.modedesc = "Bad mode",
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
=============================================================================
|
|
||||||
|
|
||||||
DIRECTDRAW VIDEO DRIVER
|
|
||||||
|
|
||||||
=============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
LPDIRECTDRAW dd_Object = NULL;
|
|
||||||
HINSTANCE hInstDDraw = NULL;
|
|
||||||
|
|
||||||
LPDIRECTDRAWCLIPPER dd_Clipper = NULL;
|
|
||||||
|
|
||||||
typedef HRESULT (WINAPI *ddCreateProc_t) (GUID FAR *,
|
|
||||||
LPDIRECTDRAW FAR *,
|
|
||||||
IUnknown FAR *);
|
|
||||||
ddCreateProc_t ddCreate = NULL;
|
|
||||||
|
|
||||||
unsigned ddpal[256];
|
|
||||||
|
|
||||||
byte *vidbuf = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
int dd_window_width = 640;
|
|
||||||
int dd_window_height = 480;
|
|
||||||
|
|
||||||
static void
|
|
||||||
DD_UpdateRects (int width, int height)
|
|
||||||
{
|
|
||||||
POINT p = { .x = 0, .y = 0 };
|
|
||||||
// first we need to figure out where on the primary surface our window
|
|
||||||
// lives
|
|
||||||
ClientToScreen (win_mainwindow, &p);
|
|
||||||
GetClientRect (win_mainwindow, &win_dst_rect);
|
|
||||||
OffsetRect (&win_dst_rect, p.x, p.y);
|
|
||||||
SetRect (&win_src_rect, 0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
VID_CreateDDrawDriver (int width, int height, const byte *palette,
|
|
||||||
void **buffer, int *rowbytes)
|
|
||||||
{
|
|
||||||
DDSURFACEDESC ddsd;
|
|
||||||
|
|
||||||
win_using_ddraw = false;
|
|
||||||
dd_window_width = width;
|
|
||||||
dd_window_height = height;
|
|
||||||
|
|
||||||
vidbuf = (byte *) malloc (width * height);
|
|
||||||
buffer[0] = vidbuf;
|
|
||||||
rowbytes[0] = width;
|
|
||||||
|
|
||||||
if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(ddCreate = (ddCreateProc_t) GetProcAddress (hInstDDraw,
|
|
||||||
"DirectDrawCreate"))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED (ddCreate (NULL, &dd_Object, NULL))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (FAILED (dd_Object->lpVtbl->SetCooperativeLevel (dd_Object,
|
|
||||||
win_mainwindow,
|
|
||||||
DDSCL_NORMAL))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the primary surface in windowed mode is the full screen
|
|
||||||
memset (&ddsd, 0, sizeof (ddsd));
|
|
||||||
ddsd.dwSize = sizeof (ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
|
|
||||||
|
|
||||||
// ...and create it
|
|
||||||
if (FAILED (dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd,
|
|
||||||
&win_dd_frontbuffer, NULL))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not using a clipper will slow things down and switch aero off
|
|
||||||
if (FAILED (IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, NULL))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (FAILED (IDirectDrawClipper_SetHWnd (dd_Clipper, 0, win_mainwindow))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (FAILED (IDirectDrawSurface_SetClipper (win_dd_frontbuffer,
|
|
||||||
dd_Clipper))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the secondary surface is an offscreen surface that is the currect
|
|
||||||
// dimensions
|
|
||||||
// this will be blitted to the correct location on the primary surface
|
|
||||||
// (which is the full screen) during our draw op
|
|
||||||
memset (&ddsd, 0, sizeof (ddsd));
|
|
||||||
ddsd.dwSize = sizeof (ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
|
||||||
ddsd.dwWidth = width;
|
|
||||||
ddsd.dwHeight = height;
|
|
||||||
|
|
||||||
if (FAILED (IDirectDraw_CreateSurface (dd_Object, &ddsd,
|
|
||||||
&win_dd_backbuffer, NULL))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// direct draw is working now
|
|
||||||
win_using_ddraw = true;
|
|
||||||
|
|
||||||
// create initial rects
|
|
||||||
DD_UpdateRects (dd_window_width, dd_window_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================================================================
|
|
||||||
|
|
||||||
GDI VIDEO DRIVER
|
|
||||||
|
|
||||||
=====================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
// common bitmap definition
|
|
||||||
typedef struct dibinfo {
|
|
||||||
BITMAPINFOHEADER header;
|
|
||||||
RGBQUAD acolors[256];
|
|
||||||
} dibinfo_t;
|
|
||||||
|
|
||||||
|
|
||||||
static HGDIOBJ previously_selected_GDI_obj = NULL;
|
|
||||||
HBITMAP hDIBSection;
|
|
||||||
byte *pDIBBase = NULL;
|
|
||||||
HDC hdcDIBSection = NULL;
|
|
||||||
HDC hdcGDI = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer,
|
|
||||||
int *rowbytes)
|
|
||||||
{
|
|
||||||
dibinfo_t dibheader;
|
|
||||||
BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
hdcGDI = GetDC (win_mainwindow);
|
|
||||||
memset (&dibheader, 0, sizeof (dibheader));
|
|
||||||
|
|
||||||
// fill in the bitmap info
|
|
||||||
pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
|
||||||
pbmiDIB->bmiHeader.biWidth = width;
|
|
||||||
pbmiDIB->bmiHeader.biHeight = height;
|
|
||||||
pbmiDIB->bmiHeader.biPlanes = 1;
|
|
||||||
pbmiDIB->bmiHeader.biCompression = BI_RGB;
|
|
||||||
pbmiDIB->bmiHeader.biSizeImage = 0;
|
|
||||||
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
|
|
||||||
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
|
|
||||||
pbmiDIB->bmiHeader.biClrUsed = 256;
|
|
||||||
pbmiDIB->bmiHeader.biClrImportant = 256;
|
|
||||||
pbmiDIB->bmiHeader.biBitCount = 8;
|
|
||||||
|
|
||||||
// fill in the palette
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
// d_8to24table isn't filled in yet so this is just for testing
|
|
||||||
dibheader.acolors[i].rgbRed = palette[i * 3];
|
|
||||||
dibheader.acolors[i].rgbGreen = palette[i * 3 + 1];
|
|
||||||
dibheader.acolors[i].rgbBlue = palette[i * 3 + 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the DIB section
|
|
||||||
hDIBSection = CreateDIBSection (hdcGDI,
|
|
||||||
pbmiDIB,
|
|
||||||
DIB_RGB_COLORS,
|
|
||||||
(void **) &pDIBBase, NULL, 0);
|
|
||||||
|
|
||||||
// set video buffers
|
|
||||||
if (pbmiDIB->bmiHeader.biHeight > 0) {
|
|
||||||
// bottom up
|
|
||||||
buffer[0] = pDIBBase + (height - 1) * width;
|
|
||||||
rowbytes[0] = -width;
|
|
||||||
} else {
|
|
||||||
// top down
|
|
||||||
buffer[0] = pDIBBase;
|
|
||||||
rowbytes[0] = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear the buffer
|
|
||||||
memset (pDIBBase, 0xff, width * height);
|
|
||||||
|
|
||||||
if ((hdcDIBSection = CreateCompatibleDC (hdcGDI)) == NULL)
|
|
||||||
Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n");
|
|
||||||
|
|
||||||
if ((previously_selected_GDI_obj =
|
|
||||||
SelectObject (hdcDIBSection, hDIBSection)) == NULL)
|
|
||||||
Sys_Error ("DIB_Init() - SelectObject failed\n");
|
|
||||||
|
|
||||||
// create a palette
|
|
||||||
VID_InitGamma (palette);
|
|
||||||
viddef.vid_internal->set_palette (palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Win_CreateDriver (void)
|
|
||||||
{
|
|
||||||
if (vid_ddraw->int_val) {
|
|
||||||
VID_CreateDDrawDriver (DIBWidth, DIBHeight, viddef.palette,
|
|
||||||
&viddef.buffer, &viddef.rowbytes);
|
|
||||||
}
|
|
||||||
if (!win_using_ddraw) {
|
|
||||||
// directdraw failed or was not requested
|
|
||||||
//
|
|
||||||
// if directdraw failed, it may be partially initialized, so make sure
|
|
||||||
// the slate is clean
|
|
||||||
Win_UnloadAllDrivers ();
|
|
||||||
|
|
||||||
VID_CreateGDIDriver (DIBWidth, DIBHeight, viddef.palette,
|
|
||||||
&viddef.buffer, &viddef.rowbytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Win_UnloadAllDrivers (void)
|
|
||||||
{
|
|
||||||
// shut down ddraw
|
|
||||||
if (vidbuf) {
|
|
||||||
free (vidbuf);
|
|
||||||
vidbuf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dd_Clipper) {
|
|
||||||
IDirectDrawClipper_Release (dd_Clipper);
|
|
||||||
dd_Clipper = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (win_dd_frontbuffer) {
|
|
||||||
IDirectDrawSurface_Release (win_dd_frontbuffer);
|
|
||||||
win_dd_frontbuffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (win_dd_backbuffer) {
|
|
||||||
IDirectDrawSurface_Release (win_dd_backbuffer);
|
|
||||||
win_dd_backbuffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dd_Object) {
|
|
||||||
IDirectDraw_Release (dd_Object);
|
|
||||||
dd_Object = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hInstDDraw) {
|
|
||||||
FreeLibrary (hInstDDraw);
|
|
||||||
hInstDDraw = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ddCreate = NULL;
|
|
||||||
|
|
||||||
// shut down gdi
|
|
||||||
if (hdcDIBSection) {
|
|
||||||
SelectObject (hdcDIBSection, previously_selected_GDI_obj);
|
|
||||||
DeleteDC (hdcDIBSection);
|
|
||||||
hdcDIBSection = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hDIBSection) {
|
|
||||||
DeleteObject (hDIBSection);
|
|
||||||
hDIBSection = NULL;
|
|
||||||
pDIBBase = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdcGDI) {
|
|
||||||
// if hdcGDI exists then win_mainwindow must also be valid
|
|
||||||
ReleaseDC (win_mainwindow, hdcGDI);
|
|
||||||
hdcGDI = NULL;
|
|
||||||
}
|
|
||||||
// not using ddraw now
|
|
||||||
win_using_ddraw = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int VID_SetMode (int modenum, const byte *palette);
|
static int VID_SetMode (int modenum, const byte *palette);
|
||||||
|
|
||||||
static void __attribute__ ((used))
|
static void __attribute__ ((used))
|
||||||
|
@ -455,12 +191,12 @@ VID_CheckWindowXY (void)
|
||||||
void
|
void
|
||||||
Win_UpdateWindowStatus (int window_x, int window_y)
|
Win_UpdateWindowStatus (int window_x, int window_y)
|
||||||
{
|
{
|
||||||
window_rect.left = window_x;
|
win_rect.left = window_x;
|
||||||
window_rect.top = window_y;
|
win_rect.top = window_y;
|
||||||
window_rect.right = window_x + window_width;
|
win_rect.right = window_x + viddef.width;
|
||||||
window_rect.bottom = window_y + window_height;
|
win_rect.bottom = window_y + viddef.height;
|
||||||
window_center_x = (window_rect.left + window_rect.right) / 2;
|
win_center_x = (win_rect.left + win_rect.right) / 2;
|
||||||
window_center_y = (window_rect.top + window_rect.bottom) / 2;
|
win_center_y = (win_rect.top + win_rect.bottom) / 2;
|
||||||
IN_UpdateClipCursor ();
|
IN_UpdateClipCursor ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,27 +247,6 @@ VID_InitModes (HINSTANCE hInstance)
|
||||||
if (!RegisterClass (&wc))
|
if (!RegisterClass (&wc))
|
||||||
Sys_Error ("Couldn't register window class");
|
Sys_Error ("Couldn't register window class");
|
||||||
|
|
||||||
modelist[0].type = MS_WINDOWED;
|
|
||||||
modelist[0].width = 320;
|
|
||||||
modelist[0].height = 240;
|
|
||||||
strcpy (modelist[0].modedesc, "320x240");
|
|
||||||
modelist[0].modenum = MODE_WINDOWED;
|
|
||||||
modelist[0].fullscreen = 0;
|
|
||||||
|
|
||||||
modelist[1].type = MS_WINDOWED;
|
|
||||||
modelist[1].width = 640;
|
|
||||||
modelist[1].height = 480;
|
|
||||||
strcpy (modelist[1].modedesc, "640x480");
|
|
||||||
modelist[1].modenum = MODE_WINDOWED + 1;
|
|
||||||
modelist[1].fullscreen = 0;
|
|
||||||
|
|
||||||
modelist[2].type = MS_WINDOWED;
|
|
||||||
modelist[2].width = 800;
|
|
||||||
modelist[2].height = 600;
|
|
||||||
strcpy (modelist[2].modedesc, "800x600");
|
|
||||||
modelist[2].modenum = MODE_WINDOWED + 2;
|
|
||||||
modelist[2].fullscreen = 0;
|
|
||||||
|
|
||||||
// automatically stretch the default mode up if > 640x480 desktop
|
// automatically stretch the default mode up if > 640x480 desktop
|
||||||
// resolution
|
// resolution
|
||||||
hdc = GetDC (NULL);
|
hdc = GetDC (NULL);
|
||||||
|
@ -961,10 +676,6 @@ VID_SetMode (int modenum, const byte *palette)
|
||||||
IN_HideMouse ();
|
IN_HideMouse ();
|
||||||
}
|
}
|
||||||
|
|
||||||
window_width = viddef.width;
|
|
||||||
window_height = viddef.height;
|
|
||||||
|
|
||||||
|
|
||||||
Win_UpdateWindowStatus (0, 0); // FIXME right numbers?
|
Win_UpdateWindowStatus (0, 0); // FIXME right numbers?
|
||||||
//FIXME CDAudio_Resume ();
|
//FIXME CDAudio_Resume ();
|
||||||
//FIXME? scr_disabled_for_loading = temp;
|
//FIXME? scr_disabled_for_loading = temp;
|
||||||
|
|
|
@ -122,7 +122,7 @@ void
|
||||||
IN_UpdateClipCursor (void)
|
IN_UpdateClipCursor (void)
|
||||||
{
|
{
|
||||||
if (mouseinitialized && in_mouse_avail && !dinput) {
|
if (mouseinitialized && in_mouse_avail && !dinput) {
|
||||||
ClipCursor (&window_rect);
|
ClipCursor (&win_rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,9 +164,9 @@ IN_ActivateMouse (void)
|
||||||
restore_spi =
|
restore_spi =
|
||||||
SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
|
SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
|
||||||
|
|
||||||
SetCursorPos (window_center_x, window_center_y);
|
SetCursorPos (win_center_x, win_center_y);
|
||||||
SetCapture (win_mainwindow);
|
SetCapture (win_mainwindow);
|
||||||
ClipCursor (&window_rect);
|
ClipCursor (&win_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
in_mouse_avail = true;
|
in_mouse_avail = true;
|
||||||
|
@ -522,8 +522,8 @@ IN_LL_ProcessEvents (void)
|
||||||
mouse_oldbuttonstate = mstate_di;
|
mouse_oldbuttonstate = mstate_di;
|
||||||
} else {
|
} else {
|
||||||
GetCursorPos (¤t_pos);
|
GetCursorPos (¤t_pos);
|
||||||
mx = current_pos.x - window_center_x + mx_accum;
|
mx = current_pos.x - win_center_x + mx_accum;
|
||||||
my = current_pos.y - window_center_y + my_accum;
|
my = current_pos.y - win_center_y + my_accum;
|
||||||
mx_accum = 0;
|
mx_accum = 0;
|
||||||
my_accum = 0;
|
my_accum = 0;
|
||||||
}
|
}
|
||||||
|
@ -533,7 +533,7 @@ IN_LL_ProcessEvents (void)
|
||||||
|
|
||||||
// if the mouse has moved, force it to the center, so there's room to move
|
// if the mouse has moved, force it to the center, so there's room to move
|
||||||
if (mx || my) {
|
if (mx || my) {
|
||||||
SetCursorPos (window_center_x, window_center_y);
|
SetCursorPos (win_center_x, win_center_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,268 @@ static win_palette_t st2d_8to32table[256];
|
||||||
static byte current_palette[768];
|
static byte current_palette[768];
|
||||||
static int palette_changed;
|
static int palette_changed;
|
||||||
|
|
||||||
|
static LPDIRECTDRAW dd_Object;
|
||||||
|
static HINSTANCE hInstDDraw;
|
||||||
|
static LPDIRECTDRAWSURFACE dd_frontbuffer;
|
||||||
|
static LPDIRECTDRAWSURFACE dd_backbuffer;
|
||||||
|
static RECT src_rect;
|
||||||
|
static RECT dst_rect;
|
||||||
|
static HDC win_gdi;
|
||||||
|
static HDC dib_section;
|
||||||
|
static HBITMAP dib_bitmap;
|
||||||
|
static HGDIOBJ previous_dib;
|
||||||
|
static int using_ddraw;
|
||||||
|
|
||||||
|
static LPDIRECTDRAWCLIPPER dd_Clipper;
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *ddCreateProc_t) (GUID FAR *,
|
||||||
|
LPDIRECTDRAW FAR *,
|
||||||
|
IUnknown FAR *);
|
||||||
|
static ddCreateProc_t ddCreate;
|
||||||
|
|
||||||
|
static int dd_window_width = 640;
|
||||||
|
static int dd_window_height = 480;
|
||||||
|
|
||||||
|
static void
|
||||||
|
DD_UpdateRects (int width, int height)
|
||||||
|
{
|
||||||
|
POINT p = { .x = 0, .y = 0 };
|
||||||
|
// first we need to figure out where on the primary surface our window
|
||||||
|
// lives
|
||||||
|
ClientToScreen (win_mainwindow, &p);
|
||||||
|
GetClientRect (win_mainwindow, &dst_rect);
|
||||||
|
OffsetRect (&dst_rect, p.x, p.y);
|
||||||
|
SetRect (&src_rect, 0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
VID_CreateDDrawDriver (int width, int height)
|
||||||
|
{
|
||||||
|
DDSURFACEDESC ddsd;
|
||||||
|
|
||||||
|
using_ddraw = false;
|
||||||
|
dd_window_width = width;
|
||||||
|
dd_window_height = height;
|
||||||
|
|
||||||
|
viddef.buffer = malloc (width * height);
|
||||||
|
viddef.rowbytes = width;
|
||||||
|
|
||||||
|
if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(ddCreate = (ddCreateProc_t) GetProcAddress (hInstDDraw,
|
||||||
|
"DirectDrawCreate"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED (ddCreate (0, &dd_Object, 0))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (FAILED (dd_Object->lpVtbl->SetCooperativeLevel (dd_Object,
|
||||||
|
win_mainwindow,
|
||||||
|
DDSCL_NORMAL))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the primary surface in windowed mode is the full screen
|
||||||
|
memset (&ddsd, 0, sizeof (ddsd));
|
||||||
|
ddsd.dwSize = sizeof (ddsd);
|
||||||
|
ddsd.dwFlags = DDSD_CAPS;
|
||||||
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
|
||||||
|
|
||||||
|
// ...and create it
|
||||||
|
if (FAILED (dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd,
|
||||||
|
&dd_frontbuffer, 0))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not using a clipper will slow things down and switch aero off
|
||||||
|
if (FAILED (IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, 0))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (FAILED (IDirectDrawClipper_SetHWnd (dd_Clipper, 0, win_mainwindow))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (FAILED (IDirectDrawSurface_SetClipper (dd_frontbuffer,
|
||||||
|
dd_Clipper))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the secondary surface is an offscreen surface that is the currect
|
||||||
|
// dimensions
|
||||||
|
// this will be blitted to the correct location on the primary surface
|
||||||
|
// (which is the full screen) during our draw op
|
||||||
|
memset (&ddsd, 0, sizeof (ddsd));
|
||||||
|
ddsd.dwSize = sizeof (ddsd);
|
||||||
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
||||||
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||||
|
ddsd.dwWidth = width;
|
||||||
|
ddsd.dwHeight = height;
|
||||||
|
|
||||||
|
if (FAILED (IDirectDraw_CreateSurface (dd_Object, &ddsd,
|
||||||
|
&dd_backbuffer, 0))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// direct draw is working now
|
||||||
|
using_ddraw = true;
|
||||||
|
|
||||||
|
// create initial rects
|
||||||
|
DD_UpdateRects (dd_window_width, dd_window_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer,
|
||||||
|
int *rowbytes)
|
||||||
|
{
|
||||||
|
// common bitmap definition
|
||||||
|
typedef struct dibinfo {
|
||||||
|
BITMAPINFOHEADER header;
|
||||||
|
RGBQUAD acolors[256];
|
||||||
|
} dibinfo_t;
|
||||||
|
|
||||||
|
dibinfo_t dibheader;
|
||||||
|
BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader;
|
||||||
|
int i;
|
||||||
|
byte *dib_base = 0;
|
||||||
|
|
||||||
|
win_gdi = GetDC (win_mainwindow);
|
||||||
|
memset (&dibheader, 0, sizeof (dibheader));
|
||||||
|
|
||||||
|
// fill in the bitmap info
|
||||||
|
pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
||||||
|
pbmiDIB->bmiHeader.biWidth = width;
|
||||||
|
pbmiDIB->bmiHeader.biHeight = height;
|
||||||
|
pbmiDIB->bmiHeader.biPlanes = 1;
|
||||||
|
pbmiDIB->bmiHeader.biCompression = BI_RGB;
|
||||||
|
pbmiDIB->bmiHeader.biSizeImage = 0;
|
||||||
|
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
|
||||||
|
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
|
||||||
|
pbmiDIB->bmiHeader.biClrUsed = 256;
|
||||||
|
pbmiDIB->bmiHeader.biClrImportant = 256;
|
||||||
|
pbmiDIB->bmiHeader.biBitCount = 8;
|
||||||
|
|
||||||
|
// fill in the palette
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
// d_8to24table isn't filled in yet so this is just for testing
|
||||||
|
dibheader.acolors[i].rgbRed = palette[i * 3];
|
||||||
|
dibheader.acolors[i].rgbGreen = palette[i * 3 + 1];
|
||||||
|
dibheader.acolors[i].rgbBlue = palette[i * 3 + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the DIB section
|
||||||
|
dib_bitmap = CreateDIBSection (win_gdi,
|
||||||
|
pbmiDIB,
|
||||||
|
DIB_RGB_COLORS,
|
||||||
|
(void **) &dib_base, 0, 0);
|
||||||
|
|
||||||
|
// set video buffers
|
||||||
|
if (pbmiDIB->bmiHeader.biHeight > 0) {
|
||||||
|
// bottom up
|
||||||
|
buffer[0] = dib_base + (height - 1) * width;
|
||||||
|
rowbytes[0] = -width;
|
||||||
|
} else {
|
||||||
|
// top down
|
||||||
|
buffer[0] = dib_base;
|
||||||
|
rowbytes[0] = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the buffer
|
||||||
|
memset (dib_base, 0xff, width * height);
|
||||||
|
|
||||||
|
if ((dib_section = CreateCompatibleDC (win_gdi)) == 0)
|
||||||
|
Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n");
|
||||||
|
|
||||||
|
if ((previous_dib = SelectObject (dib_section, dib_bitmap)) == 0)
|
||||||
|
Sys_Error ("DIB_Init() - SelectObject failed\n");
|
||||||
|
|
||||||
|
// create a palette
|
||||||
|
VID_InitGamma (palette);
|
||||||
|
viddef.vid_internal->set_palette (palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Win_UnloadAllDrivers (void)
|
||||||
|
{
|
||||||
|
// shut down ddraw
|
||||||
|
if (viddef.buffer) {
|
||||||
|
free (viddef.buffer);
|
||||||
|
*(int *)0xdb = 0;
|
||||||
|
viddef.buffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dd_Clipper) {
|
||||||
|
IDirectDrawClipper_Release (dd_Clipper);
|
||||||
|
dd_Clipper = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dd_frontbuffer) {
|
||||||
|
IDirectDrawSurface_Release (dd_frontbuffer);
|
||||||
|
dd_frontbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dd_backbuffer) {
|
||||||
|
IDirectDrawSurface_Release (dd_backbuffer);
|
||||||
|
dd_backbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dd_Object) {
|
||||||
|
IDirectDraw_Release (dd_Object);
|
||||||
|
dd_Object = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hInstDDraw) {
|
||||||
|
FreeLibrary (hInstDDraw);
|
||||||
|
hInstDDraw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddCreate = 0;
|
||||||
|
|
||||||
|
// shut down gdi
|
||||||
|
if (dib_section) {
|
||||||
|
SelectObject (dib_section, previous_dib);
|
||||||
|
DeleteDC (dib_section);
|
||||||
|
dib_section = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dib_bitmap) {
|
||||||
|
DeleteObject (dib_bitmap);
|
||||||
|
dib_bitmap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win_gdi) {
|
||||||
|
// if win_gdi exists then win_mainwindow must also be valid
|
||||||
|
ReleaseDC (win_mainwindow, win_gdi);
|
||||||
|
win_gdi = 0;
|
||||||
|
}
|
||||||
|
// not using ddraw now
|
||||||
|
using_ddraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Win_CreateDriver (void)
|
||||||
|
{
|
||||||
|
if (vid_ddraw->int_val) {
|
||||||
|
VID_CreateDDrawDriver (viddef.width, viddef.height);
|
||||||
|
}
|
||||||
|
if (!using_ddraw) {
|
||||||
|
// directdraw failed or was not requested
|
||||||
|
//
|
||||||
|
// if directdraw failed, it may be partially initialized, so make sure
|
||||||
|
// the slate is clean
|
||||||
|
Win_UnloadAllDrivers ();
|
||||||
|
|
||||||
|
VID_CreateGDIDriver (viddef.width, viddef.height, viddef.palette,
|
||||||
|
&viddef.buffer, &viddef.rowbytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
win_init_bufers (void)
|
win_init_bufers (void)
|
||||||
{
|
{
|
||||||
|
Win_UnloadAllDrivers ();
|
||||||
|
Win_CreateDriver ();
|
||||||
// set the rest of the buffers we need (why not just use one single buffer
|
// set the rest of the buffers we need (why not just use one single buffer
|
||||||
// instead of all this crap? oh well, it's Quake...)
|
// instead of all this crap? oh well, it's Quake...)
|
||||||
viddef.direct = viddef.buffer;
|
viddef.direct = viddef.buffer;
|
||||||
|
@ -60,6 +319,7 @@ win_init_bufers (void)
|
||||||
|
|
||||||
// more crap for the console
|
// more crap for the console
|
||||||
viddef.conrowbytes = viddef.rowbytes;
|
viddef.conrowbytes = viddef.rowbytes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -76,7 +336,7 @@ win_set_palette (const byte *palette)
|
||||||
st2d_8to32table[i].bgra[2] = viddef.gammatable[pal[0]];
|
st2d_8to32table[i].bgra[2] = viddef.gammatable[pal[0]];
|
||||||
st2d_8to32table[i].bgra[3] = 255;
|
st2d_8to32table[i].bgra[3] = 255;
|
||||||
}
|
}
|
||||||
if (!win_minimized && !win_using_ddraw && win_dib_section) {
|
if (!win_minimized && !using_ddraw && dib_section) {
|
||||||
RGBQUAD colors[256];
|
RGBQUAD colors[256];
|
||||||
memcpy (colors, st2d_8to32table, sizeof (colors));
|
memcpy (colors, st2d_8to32table, sizeof (colors));
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
|
@ -89,7 +349,7 @@ win_set_palette (const byte *palette)
|
||||||
colors[255].rgbGreen = 0xff;
|
colors[255].rgbGreen = 0xff;
|
||||||
colors[255].rgbBlue = 0xff;
|
colors[255].rgbBlue = 0xff;
|
||||||
|
|
||||||
if (SetDIBColorTable (win_dib_section, 0, 256, colors) == 0) {
|
if (SetDIBColorTable (dib_section, 0, 256, colors) == 0) {
|
||||||
Sys_Printf ("win_set_palette() - SetDIBColorTable failed\n");
|
Sys_Printf ("win_set_palette() - SetDIBColorTable failed\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,9 +371,9 @@ dd_blit_rect (vrect_t *rect)
|
||||||
TheRect.top = rect->y;
|
TheRect.top = rect->y;
|
||||||
TheRect.bottom = rect->y + rect->height;
|
TheRect.bottom = rect->y + rect->height;
|
||||||
|
|
||||||
if (IDirectDrawSurface_Lock (win_dd_backbuffer, &TheRect, &ddsd,
|
if (IDirectDrawSurface_Lock (dd_backbuffer, &TheRect, &ddsd,
|
||||||
DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR,
|
DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR,
|
||||||
NULL) == DDERR_WASSTILLDRAWING) {
|
0) == DDERR_WASSTILLDRAWING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,23 +390,23 @@ dd_blit_rect (vrect_t *rect)
|
||||||
dst += ddsd.lPitch - rect->width;
|
dst += ddsd.lPitch - rect->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDirectDrawSurface_Unlock (win_dd_backbuffer, NULL);
|
IDirectDrawSurface_Unlock (dd_backbuffer, 0);
|
||||||
|
|
||||||
// correctly offset source
|
// correctly offset source
|
||||||
sRect.left = win_src_rect.left + rect->x;
|
sRect.left = src_rect.left + rect->x;
|
||||||
sRect.right = win_src_rect.left + rect->x + rect->width;
|
sRect.right = src_rect.left + rect->x + rect->width;
|
||||||
sRect.top = win_src_rect.top + rect->y;
|
sRect.top = src_rect.top + rect->y;
|
||||||
sRect.bottom = win_src_rect.top + rect->y + rect->height;
|
sRect.bottom = src_rect.top + rect->y + rect->height;
|
||||||
|
|
||||||
// correctly offset dest
|
// correctly offset dest
|
||||||
dRect.left = win_dst_rect.left + rect->x;
|
dRect.left = dst_rect.left + rect->x;
|
||||||
dRect.right = win_dst_rect.left + rect->x + rect->width;
|
dRect.right = dst_rect.left + rect->x + rect->width;
|
||||||
dRect.top = win_dst_rect.top + rect->y;
|
dRect.top = dst_rect.top + rect->y;
|
||||||
dRect.bottom = win_dst_rect.top + rect->y + rect->height;
|
dRect.bottom = dst_rect.top + rect->y + rect->height;
|
||||||
|
|
||||||
// copy to front buffer
|
// copy to front buffer
|
||||||
IDirectDrawSurface_Blt (win_dd_frontbuffer, &dRect, win_dd_backbuffer,
|
IDirectDrawSurface_Blt (dd_frontbuffer, &dRect, dd_backbuffer,
|
||||||
&sRect, 0, NULL);
|
&sRect, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -163,16 +423,16 @@ win_sw_update (vrect_t *rects)
|
||||||
rects = &full_rect;
|
rects = &full_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win_using_ddraw) {
|
if (using_ddraw) {
|
||||||
while (rects) {
|
while (rects) {
|
||||||
dd_blit_rect (rects);
|
dd_blit_rect (rects);
|
||||||
rects = rects->next;
|
rects = rects->next;
|
||||||
}
|
}
|
||||||
} else if (win_dib_section) {
|
} else if (dib_section) {
|
||||||
while (rects) {
|
while (rects) {
|
||||||
BitBlt (win_gdi, rects->x, rects->y,
|
BitBlt (win_gdi, rects->x, rects->y,
|
||||||
rects->x + rects->width, rects->y + rects->height,
|
rects->x + rects->width, rects->y + rects->height,
|
||||||
win_dib_section, rects->x, rects->y, SRCCOPY);
|
dib_section, rects->x, rects->y, SRCCOPY);
|
||||||
rects = rects->next;
|
rects = rects->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,14 +447,13 @@ win_choose_visual (sw_ctx_t *ctx)
|
||||||
static void
|
static void
|
||||||
win_set_background (void)
|
win_set_background (void)
|
||||||
{
|
{
|
||||||
// because we have set the background brush for the window to NULL (to
|
// because we have set the background brush for the window to 0 (to
|
||||||
// avoid flickering when re-sizing the window on the desktop), we clear
|
// avoid flickering when re-sizing the window on the desktop), we clear
|
||||||
// the window to black when created, otherwise it will be empty while
|
// the window to black when created, otherwise it will be empty while
|
||||||
// Quake starts up. This also prevents a screen flash to white when
|
// Quake starts up. This also prevents a screen flash to white when
|
||||||
// switching drivers. it still flashes, but at least it's black now
|
// switching drivers. it still flashes, but at least it's black now
|
||||||
HDC hdc = GetDC (win_mainwindow);
|
HDC hdc = GetDC (win_mainwindow);
|
||||||
PatBlt (hdc, 0, 0, win_window_rect.right, win_window_rect.bottom,
|
PatBlt (hdc, 0, 0, win_rect.right, win_rect.bottom, BLACKNESS);
|
||||||
BLACKNESS);
|
|
||||||
ReleaseDC (win_mainwindow, hdc);
|
ReleaseDC (win_mainwindow, hdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,12 +468,9 @@ win_create_context (sw_ctx_t *ctx)
|
||||||
win_set_background ();
|
win_set_background ();
|
||||||
|
|
||||||
// create the new driver
|
// create the new driver
|
||||||
win_using_ddraw = false;
|
using_ddraw = false;
|
||||||
|
|
||||||
Win_CreateDriver ();
|
|
||||||
|
|
||||||
viddef.vid_internal->init_buffers = win_init_bufers;
|
viddef.vid_internal->init_buffers = win_init_bufers;
|
||||||
VID_InitBuffers ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sw_ctx_t *
|
sw_ctx_t *
|
||||||
|
|
Loading…
Reference in a new issue