Windib fix

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 :slight_smile:

  • 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];
};