I’ve been doing some hacking about with in the win32 DIB driver and I
have a patch.
It’d be cool to get some feedback (ie check that there’s no major
breakage)…
Fixes:
- Current desktop depth now correctly detected (hopefully!) for 16bit
modes (555 and 565) - SDL_SetVideoMode() now supports both 15 bits-per-pixel (555)
and 16 bits-per-pixel (565).
(Previously, only 555 mode was supported, but you had to use a
bits-per-pixel of 16).
Unresolved issue:
- When determining which resolutions are available for fullscreen
mode, windows doesn’t distinguish between 555 and 565 modes.
The workaround I use is to just add each resolution to both the
555 and 565 lists… not ideal, but it works…
NOTE: I haven’t really tried it out on 555 hardware (my card is 565), so
I’d be interested to hear confirmation that it works…
The affected files are SDL_dibvideo.h and SDL_dibvideo.c
Attached patch is diffed from the devel_1_1_0 cvs branch.
My first attempt at producing a diff, so I might have stuffed it up
- Email me for the complete files if you want them (however I’ll be
away until next week).
Question - how can you force SDL to use the windib driver? I tried
playing with environment variables, but in the end had to force it
in the source code…
Ben.–
Ben Campbell
Programmer, Creature Labs
ben.campbell at creaturelabs.com
http://www.creaturelabs.com
-------------- next part --------------
Index: SDL_dibvideo.c
RCS file: /cvs/SDL/src/video/windib/SDL_dibvideo.c,v
retrieving revision 1.5.2.15
diff -u -r1.5.2.15 SDL_dibvideo.c
— SDL_dibvideo.c 2000/08/03 03:45:38 1.5.2.15
+++ SDL_dibvideo.c 2000/08/23 14:29:21
@@ -20,11 +20,13 @@
slouken at devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_dibvideo.c,v 1.5.2.15 2000/08/03 03:45:38 hercules Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
@@ -67,6 +69,8 @@
static void DIB_PaletteChanged(_THIS, HWND window);
static void DIB_WinPAINT(_THIS, HDC hdc);
+/* helper fn */
+static int DIB_SussScreenDepth();
/* DIB driver bootstrap functions */
@@ -183,7 +187,17 @@
if ( bpp < 8 ) { /* Not supported */
return(0);
}
- index = ((bpp+7)/8)-1;
- switch(bpp)
- {
-
case 8: index=0; break;
-
case 15: index=1; break;
-
case 16: index=2; break;
-
case 24: index=3; break;
-
case 32: index=4; break;
-
default: return 0;
- }
- /* already present? */
for ( i=0; i<SDL_nummodes[index]; ++i ) {
mode = SDL_modelist[index][i];
if ( (mode->w == w) && (mode->h == h) ) {
@@ -253,7 +267,6 @@
int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
- HDC hdc;
int i;
DEVMODE settings;
@@ -264,16 +277,18 @@
DX5_SoundFocus(SDL_Window);
/* Determine the screen depth */
- hdc = GetDC(SDL_Window);
- vformat->BitsPerPixel = GetDeviceCaps(hdc, PLANES) *
-
GetDeviceCaps(hdc, BITSPIXEL);
- vformat->BitsPerPixel = DIB_SussScreenDepth();
switch (vformat->BitsPerPixel) {
-
case 16:
-
/* GDI defined as 5-5-5 */
-
case 15: vformat->Rmask = 0x00007c00; vformat->Gmask = 0x000003e0; vformat->Bmask = 0x0000001f; break;
-
case 16:
-
vformat->Rmask = 0x0000f800;
-
vformat->Gmask = 0x000007e0;
-
vformat->Bmask = 0x0000001f;
-
break; case 24: case 32: /* GDI defined as 8-8-8 */
@@ -284,10 +299,15 @@
default:
break;
}
-
ReleaseDC(SDL_Window, hdc);
/* Query for the list of available video modes */
for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) {
-
if( settings.dmBitsPerPel == 16 ) {
-
/* NASTY HACK - assume we can do both 555 and 565 */
-
/* ...there must be a better way... */
-
DIB_AddMode(this, 15,
-
settings.dmPelsWidth, settings.dmPelsHeight);
-
}} DIB_AddMode(this, settings.dmBitsPerPel, settings.dmPelsWidth, settings.dmPelsHeight);
@@ -316,12 +336,80 @@
SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
-
return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
-
switch( format->BitsPerPixel ) {
-
case 8: return SDL_modelist[0];
-
case 15: return SDL_modelist[1];
-
case 16: return SDL_modelist[2];
-
case 24: return SDL_modelist[3];
-
case 32: return SDL_modelist[4];
-
default: return 0;
-
}
} else {
return((SDL_Rect **)-1);
}
}
+/*
- Helper fn to work out which screen depth windows is currently using.
- 15 bit mode is considered 555 format, 16 bit is 565.
- returns 0 for unknown mode.
- (Derived from code in sept 1999 Windows Developer Journal
-
http://www.wdj.com/code/archive.html)
+*/
+static int DIB_SussScreenDepth()
+{ - int dib_size;
- LPBITMAPINFOHEADER dib_hdr;
- HDC hdc;
- HBITMAP hbm;
- /* Allocate enough space for a DIB header plus palette (for
-
* 8-bit modes) or bitfields (for 16- and 32-bit modes)
-
*/
- dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
- dib_hdr = (LPBITMAPINFOHEADER) malloc(dib_size);
- memset(dib_hdr, 0, dib_size);
- dib_hdr->biSize = sizeof(BITMAPINFOHEADER);
- /* Get a device-dependent bitmap that’s compatible with the
-
screen.
-
*/
- hdc = GetDC(NULL);
- hbm = CreateCompatibleBitmap( hdc, 1, 1 );
- /* Convert the DDB to a DIB. We need to call GetDIBits twice:
-
* the first call just fills in the BITMAPINFOHEADER; the
-
* second fills in the bitfields or palette.
-
*/
- GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr,
-
DIB_RGB_COLORS);
- GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr,
-
DIB_RGB_COLORS);
- DeleteObject(hbm);
- ReleaseDC(NULL, hdc);
- switch( dib_hdr->biBitCount )
- {
- case 8: return 8;
- case 24: return 24;
- case 32: return 32;
- case 16:
-
if( dib_hdr->biCompression == BI_BITFIELDS ) {
-
/* check the red mask */
-
switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) {
-
case 0xf800: return 16; /* 565 */
-
case 0x7c00: return 15; /* 555 */
-
}
-
}
- }
- return 0; /* poo. */
+}
/* Various screen update functions available */
static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
@@ -336,6 +424,7 @@
RECT bounds;
int x, y;
BOOL was_visible;
-
Uint32 Rmask, Gmask, Bmask;
/* See whether or not we should center the window */
was_visible = IsWindowVisible(SDL_Window);
@@ -344,11 +433,16 @@
if ( bpp == current->format->BitsPerPixel ) {
video = current;
} else {
-
Uint32 Rmask, Gmask, Bmask; switch (bpp) { case 16:
-
/* GDI defined as 5-5-5 */
-
/* 5-6-5 */
-
Rmask = 0x0000f800;
-
Gmask = 0x000007e0;
-
Bmask = 0x0000001f;
-
break;
-
case 15:
-
/* 5-5-5 */ Rmask = 0x00007c00; Gmask = 0x000003e0; Bmask = 0x0000001f;
@@ -387,11 +481,14 @@
memset(&settings, 0, sizeof(DEVMODE));
settings.dmSize = sizeof(DEVMODE);
-
settings.dmBitsPerPel = bpp;
-
if( bpp==15 )
-
settings.dmBitsPerPel = 16; /* stupid crap GDI... */
-
else
-
settings.dmBitsPerPel = bpp; settings.dmPelsWidth = width; settings.dmPelsHeight = height; settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
-
if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
-
if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) { video->flags |= SDL_FULLSCREEN; if ( screen_pal != NULL ) { /* RJR: March 28, 2000
@@ -428,13 +525,28 @@
DeleteObject(screen_bmp);
}
if ( ! (flags & SDL_OPENGL) ) {
-
/* Fill in the bitmap info header */
-
if ( video->format->palette != NULL ) {
-
BOOL is16bitmode = FALSE;
-
/* (15bit (555) is considered a 16bit mode by CreateDIBSection) */
-
if( video->format->BitsPerPixel == 15 ||
-
video->format->BitsPerPixel == 16 ) {
-
is16bitmode = TRUE;
-
}
-
/* Suss out the bitmap info header */
-
if( is16bitmode ) {
-
/* for 16bit modes, the palette area is used for rgb bitmasks */ binfo = (BITMAPINFO *)malloc(sizeof(*binfo) +
-
video->format->palette->ncolors*sizeof(RGBQUAD));
-
3*sizeof(DWORD)); } else {
-
binfo = (BITMAPINFO *)malloc(sizeof(*binfo));
-
if ( video->format->palette != NULL ) {
-
binfo = (BITMAPINFO *)malloc(sizeof(*binfo) +
-
video->format->palette->ncolors*sizeof(RGBQUAD));
-
} else {
-
binfo = (BITMAPINFO *)malloc(sizeof(*binfo));
-
} }
-
if ( binfo == NULL ) { if ( video != current ) { SDL_FreeSurface(video);
@@ -442,22 +554,35 @@
SDL_OutOfMemory();
return(NULL);
}
+
binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
binfo->bmiHeader.biWidth = video->w;
-
binfo->bmiHeader.biHeight = -video->h;
-
binfo->bmiHeader.biHeight = -video->h; /* -ve for topdown bitmap */ binfo->bmiHeader.biPlanes = 1;
-
binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
-
binfo->bmiHeader.biCompression = BI_RGB; binfo->bmiHeader.biSizeImage = video->h * video->pitch; binfo->bmiHeader.biXPelsPerMeter = 0; binfo->bmiHeader.biYPelsPerMeter = 0; binfo->bmiHeader.biClrUsed = 0; binfo->bmiHeader.biClrImportant = 0;
-
if ( video->format->palette ) {
-
memset(binfo->bmiColors, 0,
-
video->format->palette->ncolors*sizeof(RGBQUAD));
-
}
-
if( is16bitmode )
-
{
-
// BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette
-
binfo->bmiHeader.biCompression = BI_BITFIELDS;
-
binfo->bmiHeader.biBitCount = 16;
-
((Uint32*)binfo->bmiColors)[0] = video->format->Rmask;
-
((Uint32*)binfo->bmiColors)[1] = video->format->Gmask;
-
((Uint32*)binfo->bmiColors)[2] = video->format->Bmask;
-
}
-
else
-
{
-
binfo->bmiHeader.biCompression = BI_RGB; //BI_BITFIELDS for 565 vs 555
-
binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
-
if ( video->format->palette ) {
-
memset(binfo->bmiColors, 0,
-
video->format->palette->ncolors*sizeof(RGBQUAD));
-
}
-
} /* Create the offscreen bitmap buffer */ hdc = GetDC(SDL_Window); screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
Index: SDL_dibvideo.h
RCS file: /cvs/SDL/src/video/windib/SDL_dibvideo.h,v
retrieving revision 1.3.2.2
diff -u -r1.3.2.2 SDL_dibvideo.h
— SDL_dibvideo.h 2000/03/16 15:20:39 1.3.2.2
+++ SDL_dibvideo.h 2000/08/23 14:29:21
@@ -35,7 +35,7 @@
HBITMAP screen_bmp;
HPALETTE screen_pal;
-#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel /
+#define NUM_MODELISTS 5 / 8, 15 (555), 16 (565), 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
};