test/graywin.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 945 d33645c36072
child 1662 782fd950bd46
child 1895 c121d94672cb
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

In my example, 384x240 has 92160 pixels, and 320x400 has 128000 pixels. So now
SDL will choose 384x240 for the asked 320x240 mode.
     1 
     2 /* Simple program:  Fill a colormap with gray and stripe it down the screen */
     3 
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <string.h>
     7 #include <time.h>
     8 
     9 #include "SDL.h"
    10 
    11 #ifdef TEST_VGA16 /* Define this if you want to test VGA 16-color video modes */
    12 #define NUM_COLORS	16
    13 #else
    14 #define NUM_COLORS	256
    15 #endif
    16 
    17 /* Draw a randomly sized and colored box centered about (X,Y) */
    18 void DrawBox(SDL_Surface *screen, int X, int Y, int width, int height)
    19 {
    20 	static unsigned int seeded = 0;
    21 	SDL_Rect area;
    22 	Uint32 color;
    23         Uint32 randc;
    24 
    25 	/* Seed the random number generator */
    26 	if ( seeded == 0 ) {
    27 		srand(time(NULL));
    28 		seeded = 1;
    29 	}
    30 
    31 	/* Get the bounds of the rectangle */
    32 	area.w = (rand()%width);
    33 	area.h = (rand()%height);
    34 	area.x = X-(area.w/2);
    35 	area.y = Y-(area.h/2);
    36         randc = (rand()%NUM_COLORS);
    37 
    38         if (screen->format->BytesPerPixel==1)
    39         {
    40             color = randc;
    41         }
    42         else
    43         {
    44             color = SDL_MapRGB(screen->format, randc, randc, randc);
    45         }
    46 
    47 	/* Do it! */
    48 	SDL_FillRect(screen, &area, color);
    49 	if ( screen->flags & SDL_DOUBLEBUF ) {
    50 		SDL_Flip(screen);
    51 	} else {
    52 		SDL_UpdateRects(screen, 1, &area);
    53 	}
    54 }
    55 
    56 void DrawBackground(SDL_Surface *screen)
    57 {
    58 	int i, j, k;
    59 	Uint8  *buffer;
    60 	Uint16 *buffer16;
    61         Uint16 color;
    62         Uint8  gradient;
    63 
    64 	/* Set the surface pixels and refresh! */
    65 	/* Use two loops in case the surface is double-buffered (both sides) */
    66 
    67 	for ( j=0; j<2; ++j ) {
    68 		if ( SDL_LockSurface(screen) < 0 ) {
    69 			fprintf(stderr, "Couldn't lock display surface: %s\n",
    70 								SDL_GetError());
    71 			return;
    72 		}
    73 		buffer = (Uint8 *)screen->pixels;
    74 
    75 		if (screen->format->BytesPerPixel!=2) {
    76 			for ( i=0; i<screen->h; ++i ) {
    77 				memset(buffer,(i*(NUM_COLORS-1))/screen->h, screen->w * screen->format->BytesPerPixel);
    78 				buffer += screen->pitch;
    79 			}
    80 		}
    81                 else
    82                 {
    83 			for ( i=0; i<screen->h; ++i ) {
    84 				gradient=((i*(NUM_COLORS-1))/screen->h);
    85                                 color = SDL_MapRGB(screen->format, gradient, gradient, gradient);
    86                                 buffer16=(Uint16*)buffer;
    87                                 for (k=0; k<screen->w; k++)
    88                                 {
    89                                    *(buffer16+k)=color;
    90                                 }
    91 				buffer += screen->pitch;
    92 			}
    93                 }
    94 
    95 		SDL_UnlockSurface(screen);
    96 		if ( screen->flags & SDL_DOUBLEBUF ) {
    97 			SDL_Flip(screen);
    98 		} else {
    99 			SDL_UpdateRect(screen, 0, 0, 0, 0);
   100                         break;
   101 		}
   102 	}
   103 }
   104 
   105 SDL_Surface *CreateScreen(Uint16 w, Uint16 h, Uint8 bpp, Uint32 flags)
   106 {
   107 	SDL_Surface *screen;
   108 	int i;
   109 	SDL_Color palette[NUM_COLORS];
   110 
   111 	/* Set the video mode */
   112 	screen = SDL_SetVideoMode(w, h, bpp, flags);
   113 	if ( screen == NULL ) {
   114 		fprintf(stderr, "Couldn't set display mode: %s\n",
   115 							SDL_GetError());
   116 		return(NULL);
   117 	}
   118 	fprintf(stderr, "Screen is in %s mode\n",
   119 		(screen->flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed");
   120 
   121 	if (bpp==8) {
   122 		/* Set a gray colormap, reverse order from white to black */
   123 		for ( i=0; i<NUM_COLORS; ++i ) {
   124 			palette[i].r = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
   125 			palette[i].g = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
   126 			palette[i].b = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
   127 		}
   128 		SDL_SetColors(screen, palette, 0, NUM_COLORS);
   129 	}
   130 
   131 	return(screen);
   132 }
   133 
   134 int main(int argc, char *argv[])
   135 {
   136 	SDL_Surface *screen;
   137 	Uint32 videoflags;
   138 	int    done;
   139 	SDL_Event event;
   140 	int width, height, bpp;
   141 
   142 	/* Initialize SDL */
   143 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
   144 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
   145 		exit(1);
   146 	}
   147 
   148 	/* See if we try to get a hardware colormap */
   149 	width = 640;
   150 	height = 480;
   151 	bpp = 8;
   152 	videoflags = SDL_SWSURFACE;
   153 	while ( argc > 1 ) {
   154 		--argc;
   155 		if ( argv[argc-1] && (strcmp(argv[argc-1], "-width") == 0) ) {
   156 			width = atoi(argv[argc]);
   157 			--argc;
   158 		} else
   159 		if ( argv[argc-1] && (strcmp(argv[argc-1], "-height") == 0) ) {
   160 			height = atoi(argv[argc]);
   161 			--argc;
   162 		} else
   163 		if ( argv[argc-1] && (strcmp(argv[argc-1], "-bpp") == 0) ) {
   164 			bpp = atoi(argv[argc]);
   165 			--argc;
   166 		} else
   167 		if ( argv[argc] && (strcmp(argv[argc], "-hw") == 0) ) {
   168 			videoflags |= SDL_HWSURFACE;
   169 		} else
   170 		if ( argv[argc] && (strcmp(argv[argc], "-hwpalette") == 0) ) {
   171 			videoflags |= SDL_HWPALETTE;
   172 		} else
   173 		if ( argv[argc] && (strcmp(argv[argc], "-flip") == 0) ) {
   174 			videoflags |= SDL_DOUBLEBUF;
   175 		} else
   176 		if ( argv[argc] && (strcmp(argv[argc], "-noframe") == 0) ) {
   177 			videoflags |= SDL_NOFRAME;
   178 		} else
   179 		if ( argv[argc] && (strcmp(argv[argc], "-resize") == 0) ) {
   180 			videoflags |= SDL_RESIZABLE;
   181 		} else
   182 		if ( argv[argc] && (strcmp(argv[argc], "-fullscreen") == 0) ) {
   183 			videoflags |= SDL_FULLSCREEN;
   184 		} else {
   185 			fprintf(stderr, "Usage: %s [-width] [-height] [-bpp] [-hw] [-hwpalette] [-flip] [-noframe] [-fullscreen] [-resize]\n",
   186 								argv[0]);
   187 			exit(1);
   188 		}
   189 	}
   190 
   191 	/* Set a video mode */
   192 	screen = CreateScreen(width, height, bpp, videoflags);
   193 	if ( screen == NULL ) {
   194 		exit(2);
   195 	}
   196         
   197         DrawBackground(screen);
   198 		
   199 	/* Wait for a keystroke */
   200 	done = 0;
   201 	while ( !done && SDL_WaitEvent(&event) ) {
   202 		switch (event.type) {
   203 			case SDL_MOUSEBUTTONDOWN:
   204 				DrawBox(screen, event.button.x, event.button.y, width, height);
   205 				break;
   206 			case SDL_KEYDOWN:
   207 				/* Ignore ALT-TAB for windows */
   208 				if ( (event.key.keysym.sym == SDLK_LALT) ||
   209 				     (event.key.keysym.sym == SDLK_TAB) ) {
   210 					break;
   211 				}
   212 				/* Center the mouse on <SPACE> */
   213 				if ( event.key.keysym.sym == SDLK_SPACE ) {
   214 					SDL_WarpMouse(width/2, height/2);
   215 					break;
   216 				}
   217 				/* Toggle fullscreen mode on <RETURN> */
   218 				if ( event.key.keysym.sym == SDLK_RETURN ) {
   219 					videoflags ^= SDL_FULLSCREEN;
   220 					screen = CreateScreen(
   221 						screen->w, screen->h,
   222 						screen->format->BitsPerPixel,
   223 								videoflags);
   224 					if ( screen == NULL ) {
   225 						fprintf(stderr,
   226 					"Couldn't toggle fullscreen mode\n");
   227 						done = 1;
   228 					}
   229                                         DrawBackground(screen);
   230 					break;
   231 				}
   232 				/* Any other key quits the application... */
   233 			case SDL_QUIT:
   234 				done = 1;
   235 				break;
   236 			case SDL_VIDEOEXPOSE:
   237 				DrawBackground(screen);
   238 				break;
   239 			case SDL_VIDEORESIZE:
   240 					screen = CreateScreen(
   241 						event.resize.w, event.resize.h,
   242 						screen->format->BitsPerPixel,
   243 								videoflags);
   244 					if ( screen == NULL ) {
   245 						fprintf(stderr,
   246 					"Couldn't resize video mode\n");
   247 						done = 1;
   248 					}
   249 					DrawBackground(screen);
   250 				break;
   251 			default:
   252 				break;
   253 		}
   254 	}
   255 	SDL_Quit();
   256 	return(0);
   257 }