📄 sdl_dx5video.c
字号:
}
if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
this->info.blit_hw_CC = 1;
}
if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
/* This is only for alpha channel, and DirectX 6
doesn't support 2D alpha blits yet, so set it 0
*/
this->info.blit_hw_A = 0;
}
if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
this->info.blit_sw = 1;
/* This isn't necessarily true, but the HEL will cover us */
this->info.blit_sw_CC = this->info.blit_hw_CC;
this->info.blit_sw_A = this->info.blit_hw_A;
}
if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
this->info.blit_fill = 1;
}
/* Find out how much video memory is available */
{ DDSCAPS ddsCaps;
DWORD total_mem;
ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
result = IDirectDraw2_GetAvailableVidMem(ddraw2,
&ddsCaps, &total_mem, NULL);
if ( result != DD_OK ) {
total_mem = DDCaps.dwVidMemTotal;
}
this->info.video_mem = total_mem/1024;
}
return(0);
}
int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
HRESULT result;
LPDIRECTDRAW ddraw;
int i, j;
HDC hdc;
/* Intialize everything */
ddraw2 = NULL;
SDL_primary = NULL;
SDL_clipper = NULL;
SDL_palette = NULL;
for ( i=0; i<NUM_MODELISTS; ++i ) {
SDL_nummodes[i] = 0;
SDL_modelist[i] = NULL;
SDL_modeindex[i] = 0;
}
colorchange_expected = 0;
/* Create the window */
if ( DX5_CreateWindow(this) < 0 ) {
return(-1);
}
#ifndef DISABLE_AUDIO
DX5_SoundFocus(SDL_Window);
#endif
/* Create the DirectDraw object */
result = DDrawCreate(NULL, &ddraw, NULL);
if ( result != DD_OK ) {
SetDDerror("DirectDrawCreate", result);
return(-1);
}
result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
(LPVOID *)&ddraw2);
IDirectDraw_Release(ddraw);
if ( result != DD_OK ) {
SetDDerror("DirectDraw::QueryInterface", result);
return(-1);
}
/* Determine the screen depth */
hdc = GetDC(SDL_Window);
vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
GetDeviceCaps(hdc,BITSPIXEL);
ReleaseDC(SDL_Window, hdc);
/* Enumerate the available fullscreen modes */
for ( i=0; i<NUM_MODELISTS; ++i )
enumlists[i] = NULL;
result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::EnumDisplayModes", result);
return(-1);
}
for ( i=0; i<NUM_MODELISTS; ++i ) {
struct DX5EnumRect *rect;
SDL_modelist[i] = (SDL_Rect **)
malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
if ( SDL_modelist[i] == NULL ) {
SDL_OutOfMemory();
return(-1);
}
for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
SDL_modelist[i][j]=(SDL_Rect *)rect;
}
SDL_modelist[i][j] = NULL;
}
/* Fill in some window manager capabilities */
this->info.wm_available = 1;
/* Fill in the video hardware capabilities */
DX5_UpdateVideoInfo(this);
return(0);
}
SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
int bpp;
bpp = format->BitsPerPixel;
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
/* FIXME: No support for 1 bpp or 4 bpp formats */
switch (bpp) { /* Does windows support other BPP? */
case 8:
case 16:
case 24:
case 32:
bpp = (bpp/8)-1;
if ( SDL_nummodes[bpp] > 0 )
return(SDL_modelist[bpp]);
/* Fall through */
default:
return((SDL_Rect **)0);
}
} else {
if ( this->screen->format->BitsPerPixel == bpp ) {
return((SDL_Rect **)-1);
} else {
return((SDL_Rect **)0);
}
}
}
/* Various screen update functions available */
static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
SDL_Surface *video;
HRESULT result;
DWORD sharemode;
DWORD style;
const DWORD directstyle =
(WS_POPUP);
const DWORD windowstyle =
(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
const DWORD resizestyle =
(WS_THICKFRAME|WS_MAXIMIZEBOX);
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE dd_surface1;
LPDIRECTDRAWSURFACE3 dd_surface3;
BOOL was_visible;
#ifdef DDRAW_DEBUG
fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
#endif
/* See whether or not we should center the window */
was_visible = IsWindowVisible(SDL_Window);
/* Clean up any previous DirectDraw surfaces */
if ( current->hwdata ) {
this->FreeHWSurface(this, current);
current->hwdata = NULL;
}
if ( SDL_primary != NULL ) {
IDirectDrawSurface3_Release(SDL_primary);
SDL_primary = NULL;
}
/* Unset any previous OpenGL fullscreen mode */
if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
(SDL_OPENGL|SDL_FULLSCREEN) ) {
ChangeDisplaySettings(NULL, 0);
}
/* Clean up any GL context that may be hanging around */
if ( current->flags & SDL_OPENGL ) {
WIN_GL_ShutDown(this);
}
/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
if ( flags & SDL_OPENGL ) {
RECT bounds;
int x, y;
Uint32 Rmask, Gmask, Bmask;
/* Recalculate the bitmasks if necessary */
if ( bpp == current->format->BitsPerPixel ) {
video = current;
} else {
switch (bpp) {
case 15:
case 16:
if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
/* 5-5-5 */
Rmask = 0x00007c00;
Gmask = 0x000003e0;
Bmask = 0x0000001f;
} else {
/* 5-6-5 */
Rmask = 0x0000f800;
Gmask = 0x000007e0;
Bmask = 0x0000001f;
}
break;
case 24:
case 32:
/* GDI defined as 8-8-8 */
Rmask = 0x00ff0000;
Gmask = 0x0000ff00;
Bmask = 0x000000ff;
break;
default:
Rmask = 0x00000000;
Gmask = 0x00000000;
Bmask = 0x00000000;
break;
}
video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
Rmask, Gmask, Bmask, 0);
if ( video == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
}
/* Fill in part of the video surface */
video->flags = 0; /* Clear flags */
video->w = width;
video->h = height;
video->pitch = SDL_CalculatePitch(video);
/* Set fullscreen mode if appropriate.
Ugh, since our list of valid video modes comes from
the DirectX driver, we may not actually be able to
change to the desired resolution here.
FIXME: Should we do a closest match?
*/
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
DEVMODE settings;
memset(&settings, 0, sizeof(DEVMODE));
settings.dmSize = sizeof(DEVMODE);
settings.dmBitsPerPel = video->format->BitsPerPixel;
settings.dmPelsWidth = width;
settings.dmPelsHeight = height;
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
video->flags |= SDL_FULLSCREEN;
SDL_fullscreen_mode = settings;
}
}
style = GetWindowLong(SDL_Window, GWL_STYLE);
style &= ~(resizestyle|WS_MAXIMIZE);
if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
style &= ~windowstyle;
style |= directstyle;
} else {
if ( flags & SDL_NOFRAME ) {
style &= ~windowstyle;
style |= directstyle;
video->flags |= SDL_NOFRAME;
} else {
style &= ~directstyle;
style |= windowstyle;
if ( flags & SDL_RESIZABLE ) {
style |= resizestyle;
video->flags |= SDL_RESIZABLE;
}
}
if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
}
SetWindowLong(SDL_Window, GWL_STYLE, style);
/* Resize the window (copied from SDL WinDIB driver) */
if ( SDL_windowid == NULL ) {
UINT swp_flags;
SDL_resizing = 1;
bounds.left = 0;
bounds.top = 0;
bounds.right = video->w;
bounds.bottom = video->h;
AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE);
width = bounds.right-bounds.left;
height = bounds.bottom-bounds.top;
x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
if ( y < 0 ) { /* Cover up title bar for more client area */
y -= GetSystemMetrics(SM_CYCAPTION)/2;
}
swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW);
if ( was_visible && !(flags & SDL_FULLSCREEN) ) {
swp_flags |= SWP_NOMOVE;
}
SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
SDL_resizing = 0;
SetForegroundWindow(SDL_Window);
}
/* Set up for OpenGL */
if ( WIN_GL_SetupWindow(this) < 0 ) {
return(NULL);
}
video->flags |= SDL_OPENGL;
return(video);
}
/* Set the appropriate window style */
style = GetWindowLong(SDL_Window, GWL_STYLE);
style &= ~(resizestyle|WS_MAXIMIZE);
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
style &= ~windowstyle;
style |= directstyle;
} else {
if ( flags & SDL_NOFRAME ) {
style &= ~windowstyle;
style |= directstyle;
} else {
style &= ~directstyle;
style |= windowstyle;
if ( flags & SDL_RESIZABLE ) {
style |= resizestyle;
}
}
if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
}
SetWindowLong(SDL_Window, GWL_STYLE, style);
/* Set DirectDraw sharing mode.. exclusive when fullscreen */
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
} else {
sharemode = DDSCL_NORMAL;
}
result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::SetCooperativeLevel", result);
return(NULL);
}
/* Set the display mode, if we are in fullscreen mode */
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
/* Cover up desktop during mode change */
SDL_resizing = 1;
SetWindowPos(SDL_Window, NULL, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
(SWP_NOCOPYBITS | SWP_NOZORDER));
SDL_resizing = 0;
ShowWindow(SDL_Window, SW_SHOW);
while ( GetForegroundWindow() != SDL_Window ) {
SetForegroundWindow(SDL_Window);
SDL_Delay(100);
}
result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
bpp, 0, 0);
if ( result != DD_OK ) {
/* We couldn't set fullscreen mode, try window */
return(DX5_SetVideoMode(this, current,
width, height, bpp, flags & ~SDL_FULLSCREEN));
}
DX5_DInputReset(this, 1);
} else {
DX5_DInputReset(this, 0);
}
DX5_UpdateVideoInfo(this);
/* Create a primary DirectDraw surface */
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
/* There's no windowed double-buffering */
flags &= ~SDL_DOUBLEBUF;
}
if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
ddsd.dwBackBufferCount = 1;
}
result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL);
if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
ddsd.dwBackBufferCount = 0;
result = IDirectDraw2_CreateSurface(ddraw2,
&ddsd, &dd_surface1, NULL);
}
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
return(NULL);
}
result = IDirectDrawSurface_QueryInterface(dd_surface1,
&IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -