📄 sdl_dx5video.c
字号:
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface::QueryInterface", result);
return(NULL);
}
result = IDirectDrawSurface_Release(dd_surface1);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface::Release", result);
return(NULL);
}
/* Get the format of the primary DirectDraw surface */
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface::Release", result);
return(NULL);
}
if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
SDL_SetError("Primary DDRAW surface is not RGB format");
return(NULL);
}
/* Free old palette and create a new one if we're in 8-bit mode */
if ( SDL_palette != NULL ) {
IDirectDrawPalette_Release(SDL_palette);
SDL_palette = NULL;
}
#if defined(NONAMELESSUNION)
if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
#else
if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
#endif
int i;
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
/* We have access to the entire palette */
for ( i=0; i<256; ++i ) {
SDL_colors[i].peFlags =
(PC_NOCOLLAPSE|PC_RESERVED);
SDL_colors[i].peRed = 0;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
} else {
/* First 10 colors are reserved by Windows */
for ( i=0; i<10; ++i ) {
SDL_colors[i].peFlags = PC_EXPLICIT;
SDL_colors[i].peRed = i;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
for ( i=10; i<(10+236); ++i ) {
SDL_colors[i].peFlags = PC_NOCOLLAPSE;
SDL_colors[i].peRed = 0;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
/* Last 10 colors are reserved by Windows */
for ( i=246; i<256; ++i ) {
SDL_colors[i].peFlags = PC_EXPLICIT;
SDL_colors[i].peRed = i;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
}
result = IDirectDraw2_CreatePalette(ddraw2,
(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
SDL_colors, &SDL_palette, NULL);
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::CreatePalette", result);
return(NULL);
}
result = IDirectDrawSurface3_SetPalette(SDL_primary,
SDL_palette);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface3::SetPalette", result);
return(NULL);
}
}
/* Create our video surface using the same pixel format */
video = current;
if ( (width != video->w) || (height != video->h)
|| (video->format->BitsPerPixel !=
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
#else
ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
#endif
SDL_FreeSurface(video);
video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
ddsd.ddpfPixelFormat.u2.dwRBitMask,
ddsd.ddpfPixelFormat.u3.dwGBitMask,
ddsd.ddpfPixelFormat.u4.dwBBitMask,
#else
ddsd.ddpfPixelFormat.dwRGBBitCount,
ddsd.ddpfPixelFormat.dwRBitMask,
ddsd.ddpfPixelFormat.dwGBitMask,
ddsd.ddpfPixelFormat.dwBBitMask,
#endif
0);
if ( video == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
video->w = width;
video->h = height;
video->pitch = 0;
}
video->flags = 0; /* Clear flags */
/* If not fullscreen, locking is possible, but it doesn't do what
the caller really expects -- if the locked surface is written to,
the appropriate portion of the entire screen is modified, not
the application window, as we would like.
Note that it is still possible to write directly to display
memory, but the application must respect the clip list of
the surface. There might be some odd timing interactions
involving clip list updates and background refreshing as
Windows moves other windows across our window.
We currently don't support this, even though it might be a
good idea since BeOS has an implementation of BDirectWindow
that does the same thing. This would be most useful for
applications that do complete screen updates every frame.
-- Fixme?
*/
if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
/* Necessary if we're going from fullscreen to window */
if ( video->pixels == NULL ) {
video->pitch = (width*video->format->BytesPerPixel);
/* Pitch needs to be QWORD (8-byte) aligned */
video->pitch = (video->pitch + 7) & ~7;
video->pixels = (void *)malloc(video->h*video->pitch);
if ( video->pixels == NULL ) {
if ( video != current ) {
SDL_FreeSurface(video);
}
SDL_OutOfMemory();
return(NULL);
}
}
dd_surface3 = NULL;
video->flags |= SDL_SWSURFACE;
if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
video->flags |= SDL_RESIZABLE;
}
if ( flags & SDL_NOFRAME ) {
video->flags |= SDL_NOFRAME;
}
} else {
/* Necessary if we're going from window to fullscreen */
if ( video->pixels != NULL ) {
free(video->pixels);
video->pixels = NULL;
}
dd_surface3 = SDL_primary;
video->flags |= SDL_HWSURFACE;
}
/* See if the primary surface has double-buffering enabled */
if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
video->flags |= SDL_DOUBLEBUF;
}
/* Allocate the SDL surface associated with the primary surface */
if ( DX5_AllocDDSurface(this, video, dd_surface3,
video->flags&SDL_HWSURFACE) < 0 ) {
if ( video != current ) {
SDL_FreeSurface(video);
}
return(NULL);
}
/* Use the appropriate blitting function */
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
video->flags |= SDL_FULLSCREEN;
if ( video->format->palette != NULL ) {
video->flags |= SDL_HWPALETTE;
}
this->UpdateRects = DX5_DirectUpdate;
} else {
this->UpdateRects = DX5_WindowUpdate;
}
/* Make our window the proper size, set the clipper, then show it */
if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
RECT bounds;
int x, y;
UINT swp_flags;
/* Create and set a clipper on our primary surface */
if ( SDL_clipper == NULL ) {
result = IDirectDraw2_CreateClipper(ddraw2,
0, &SDL_clipper, NULL);
if ( result != DD_OK ) {
if ( video != current ) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDraw2::CreateClipper",result);
return(NULL);
}
}
result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
if ( result != DD_OK ) {
if ( video != current ) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDrawClipper::SetHWnd", result);
return(NULL);
}
result = IDirectDrawSurface3_SetClipper(SDL_primary,
SDL_clipper);
if ( result != DD_OK ) {
if ( video != current ) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDrawSurface3::SetClipper", result);
return(NULL);
}
/* Set the size of the window, centering and adjusting */
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);
if ( was_visible ) {
swp_flags |= SWP_NOMOVE;
}
SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
SDL_resizing = 0;
}
ShowWindow(SDL_Window, SW_SHOW);
SetForegroundWindow(SDL_Window);
/* We're live! */
return(video);
}
struct private_hwdata {
LPDIRECTDRAWSURFACE3 dd_surface;
LPDIRECTDRAWSURFACE3 dd_writebuf;
};
static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface,
LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
{
LPDIRECTDRAWSURFACE dd_surface1;
LPDIRECTDRAWSURFACE3 dd_surface3;
DDSURFACEDESC ddsd;
HRESULT result;
/* Clear the hardware flag, in case we fail */
surface->flags &= ~flag;
/* Allocate the hardware acceleration data */
surface->hwdata = (struct private_hwdata *)
malloc(sizeof(*surface->hwdata));
if ( surface->hwdata == NULL ) {
SDL_OutOfMemory();
return(-1);
}
dd_surface3 = NULL;
/* Set up the surface description */
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
DDSD_PITCH|DDSD_PIXELFORMAT);
ddsd.dwWidth = surface->w;
ddsd.dwHeight= surface->h;
#if defined(NONAMELESSUNION)
ddsd.u1.lPitch = surface->pitch;
#else
ddsd.lPitch = surface->pitch;
#endif
if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
ddsd.ddsCaps.dwCaps =
(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
} else {
ddsd.ddsCaps.dwCaps =
(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
}
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
if ( surface->format->palette ) {
ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
}
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
#else
ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
#endif
/* Create the DirectDraw video surface */
if ( requested != NULL ) {
dd_surface3 = requested;
} else {
result = IDirectDraw2_CreateSurface(ddraw2,
&ddsd, &dd_surface1, NULL);
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::CreateSurface", result);
goto error_end;
}
result = IDirectDrawSurface_QueryInterface(dd_surface1,
&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
IDirectDrawSurface_Release(dd_surface1);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface::QueryInterface", result);
goto error_end;
}
}
if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
/* Check to see whether the surface actually ended up
in video memory, and fail if not. We expect the
surfaces we create here to actually be in hardware!
*/
result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface3::GetCaps", result);
goto error_end;
}
if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
DDSCAPS_VIDEOMEMORY ) {
SDL_SetError("No room in video memory");
goto error_end;
}
} else {
/* Try to hook our surface memory */
ddsd.dwFlags = DDSD_LPSURFACE;
ddsd.lpSurface = surface->pixels;
result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
&ddsd, 0);
if ( result != DD_OK ) {
SetDDerror("DirectDraw2::SetSurfaceDesc", result);
goto error_end;
}
}
/* Make sure the surface format was set properly */
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
&ddsd, DDLOCK_NOSYSLOCK, NULL);
if ( result != DD_OK ) {
SetDDerror("DirectDrawSurface3::Lock", result);
goto error_end;
}
IDirectDrawSurface3_Unlock(dd_surface3, NULL);
if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
if ( ddsd.lpSurface != surface->pixels ) {
SDL_SetError("DDraw didn't use SDL surface memory");
goto error_end;
}
if (
#if defined(NONAMELESSUNION)
ddsd.u1.lPitch
#else
ddsd.lPitch
#endif
!= (LONG)surface->pitch ) {
SDL_SetError("DDraw created surface with wrong pitch");
goto error_end;
}
} else {
#if defined(NONAMELESSUNION)
surface->pitch = (Uint16)ddsd.u1.lPitch;
#else
surface->pitch = (Uint16)ddsd.lPitch;
#endif
}
#if defined(NONAMELESSUNION)
if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount !=
surface->format->BitsPerPixel) ||
(ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
(ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
(ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
#else
if ( (ddsd.ddpfPixelFormat.dwRGBBitCount !=
surface->format->BitsPerPixel) ||
(ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
(ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
(ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
#endif
SDL_SetError("DDraw didn't use SDL surface description");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -