test/testwin.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1152 51a8702d8ecd
child 1659 14717b52abc0
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 /* Bring up a window and play with it */
     3 
     4 #include <stdlib.h>
     5 #include <stdio.h>
     6 #include <string.h>
     7 
     8 #define BENCHMARK_SDL
     9 
    10 #define NOTICE(X)	printf("%s", X);
    11 
    12 #include "SDL.h"
    13 
    14 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    15 static void quit(int rc)
    16 {
    17 	SDL_Quit();
    18 	exit(rc);
    19 }
    20 
    21 void DrawPict(SDL_Surface *screen, char *bmpfile,
    22 					int speedy, int flip, int nofade)
    23 {
    24 	SDL_Surface *picture;
    25 	SDL_Rect dest, update;
    26 	int i, centered;
    27 	int ncolors;
    28 	SDL_Color *colors, *cmap;
    29 
    30 	/* Load the image into a surface */
    31 	if ( bmpfile == NULL ) {
    32 		bmpfile = "sample.bmp";		/* Sample image */
    33 	}
    34 fprintf(stderr, "Loading picture: %s\n", bmpfile);
    35 	picture = SDL_LoadBMP(bmpfile);
    36 	if ( picture == NULL ) {
    37 		fprintf(stderr, "Couldn't load %s: %s\n", bmpfile,
    38 							SDL_GetError());
    39 		return;
    40 	}
    41 
    42 	/* Set the display colors -- on a hicolor display this is a no-op */
    43 	if ( picture->format->palette ) {
    44 		ncolors = picture->format->palette->ncolors;
    45 		colors  = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));
    46 		cmap    = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));
    47 		memcpy(colors, picture->format->palette->colors,
    48 						ncolors*sizeof(SDL_Color));
    49 	} else {
    50 		int       r, g, b;
    51 
    52 		/* Allocate 256 color palette */
    53 		ncolors = 256;
    54 		colors  = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));
    55 		cmap    = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));
    56 
    57 		/* Set a 3,3,2 color cube */
    58 		for ( r=0; r<8; ++r ) {
    59 			for ( g=0; g<8; ++g ) {
    60 				for ( b=0; b<4; ++b ) {
    61 					i = ((r<<5)|(g<<2)|b);
    62 					colors[i].r = r<<5;
    63 					colors[i].g = g<<5;
    64 					colors[i].b = b<<6;
    65 				}
    66 			}
    67 		}
    68 	}
    69 NOTICE("testwin: setting colors\n");
    70 	if ( ! SDL_SetColors(screen, colors, 0, ncolors) &&
    71 				(screen->format->palette != NULL) ) {
    72 		fprintf(stderr,
    73 "Warning: Couldn't set all of the colors, but SDL will map the image\n"
    74 "         (colormap fading will suffer - try the -warp option)\n"
    75 		);
    76 	}
    77 
    78 	/* Set the screen to black (not really necessary) */
    79 	if ( SDL_LockSurface(screen) == 0 ) {
    80 		Uint32 black;
    81 		Uint8 *pixels;
    82 
    83 		black = SDL_MapRGB(screen->format, 0, 0, 0);
    84 		pixels = (Uint8 *)screen->pixels;
    85 		for ( i=0; i<screen->h; ++i ) {
    86 			memset(pixels, black,
    87 				screen->w*screen->format->BytesPerPixel);
    88 			pixels += screen->pitch;
    89 		}
    90 		SDL_UnlockSurface(screen);
    91 		SDL_UpdateRect(screen, 0, 0, 0, 0);
    92 	}
    93 	
    94 	/* Display the picture */
    95 	if ( speedy ) {
    96 		SDL_Surface *displayfmt;
    97 
    98 fprintf(stderr, "Converting picture\n");
    99 		displayfmt = SDL_DisplayFormat(picture);
   100 		if ( displayfmt == NULL ) {
   101 			fprintf(stderr,
   102 				"Couldn't convert image: %s\n", SDL_GetError());
   103 			goto done;
   104 		}
   105 		SDL_FreeSurface(picture);
   106 		picture = displayfmt;
   107 	}
   108 	printf("(image surface located in %s memory)\n", 
   109 			(picture->flags&SDL_HWSURFACE) ? "video" : "system");
   110 	centered = (screen->w - picture->w)/2;
   111 	if ( centered < 0 ) {
   112 		centered = 0;
   113 	}
   114 	dest.y = (screen->h - picture->h)/2;
   115 	dest.w = picture->w;
   116 	dest.h = picture->h;
   117 NOTICE("testwin: moving image\n");
   118 	for ( i=0; i<=centered; ++i ) {
   119 		dest.x = i;
   120 		update = dest;
   121 		if ( SDL_BlitSurface(picture, NULL, screen, &update) < 0 ) {
   122 			fprintf(stderr, "Blit failed: %s\n", SDL_GetError());
   123 			break;
   124 		}
   125 		if ( flip ) {
   126 			SDL_Flip(screen);
   127 		} else {
   128 			SDL_UpdateRects(screen, 1, &update);
   129 		}
   130 	}
   131 
   132 #ifdef SCREENSHOT
   133 	if ( SDL_SaveBMP(screen, "screen.bmp") < 0 )
   134 		printf("Couldn't save screen: %s\n", SDL_GetError());
   135 #endif
   136 
   137 #ifndef BENCHMARK_SDL
   138 	/* Let it sit there for a while */
   139 	SDL_Delay(5*1000);
   140 #endif
   141 	/* Fade the colormap */
   142 	if ( ! nofade ) {
   143 		int maxstep;
   144 		SDL_Color final;
   145 		SDL_Color palcolors[256];
   146 		struct {
   147 			Sint16 r, g, b;
   148 		} cdist[256];
   149 
   150 NOTICE("testwin: fading out...\n");
   151 		memcpy(cmap, colors, ncolors*sizeof(SDL_Color));
   152 		maxstep = 32-1;
   153 		final.r = 0xFF;
   154 		final.g = 0x00;
   155 		final.b = 0x00;
   156 		memcpy(palcolors, colors, ncolors*sizeof(SDL_Color));
   157 		for ( i=0; i<ncolors; ++i ) {
   158 			cdist[i].r = final.r-palcolors[i].r;
   159 			cdist[i].g = final.g-palcolors[i].g;
   160 			cdist[i].b = final.b-palcolors[i].b;
   161 		}
   162 		for ( i=0; i<=maxstep/2; ++i ) {	/* halfway fade */
   163 			int c;
   164 			for ( c=0; c<ncolors; ++c ) {
   165 				colors[c].r =
   166 					palcolors[c].r+((cdist[c].r*i))/maxstep;
   167 				colors[c].g =
   168 					palcolors[c].g+((cdist[c].g*i))/maxstep;
   169 				colors[c].b =
   170 					palcolors[c].b+((cdist[c].b*i))/maxstep;
   171 			}
   172 			SDL_SetColors(screen, colors, 0, ncolors);
   173 			SDL_Delay(1);
   174 		}
   175 		final.r = 0x00;
   176 		final.g = 0x00;
   177 		final.b = 0x00;
   178 		memcpy(palcolors, colors, ncolors*sizeof(SDL_Color));
   179 		for ( i=0; i<ncolors; ++i ) {
   180 			cdist[i].r = final.r-palcolors[i].r;
   181 			cdist[i].g = final.g-palcolors[i].g;
   182 			cdist[i].b = final.b-palcolors[i].b;
   183 		}
   184 		maxstep /= 2;
   185 		for ( i=0; i<=maxstep; ++i ) {		/* finish fade out */
   186 			int c;
   187 			for ( c=0; c<ncolors; ++c ) {
   188 				colors[c].r =
   189 					palcolors[c].r+((cdist[c].r*i))/maxstep;
   190 				colors[c].g =
   191 					palcolors[c].g+((cdist[c].g*i))/maxstep;
   192 				colors[c].b =
   193 					palcolors[c].b+((cdist[c].b*i))/maxstep;
   194 			}
   195 			SDL_SetColors(screen, colors, 0, ncolors);
   196 			SDL_Delay(1);
   197 		}
   198 		for ( i=0; i<ncolors; ++i ) {
   199 			colors[i].r = final.r;
   200 			colors[i].g = final.g;
   201 			colors[i].b = final.b;
   202 		}
   203 		SDL_SetColors(screen, colors, 0, ncolors);
   204 NOTICE("testwin: fading in...\n");
   205 		memcpy(palcolors, colors, ncolors*sizeof(SDL_Color));
   206 		for ( i=0; i<ncolors; ++i ) {
   207 			cdist[i].r = cmap[i].r-palcolors[i].r;
   208 			cdist[i].g = cmap[i].g-palcolors[i].g;
   209 			cdist[i].b = cmap[i].b-palcolors[i].b;
   210 		}
   211 		for ( i=0; i<=maxstep; ++i ) {	/* 32 step fade in */
   212 			int c;
   213 			for ( c=0; c<ncolors; ++c ) {
   214 				colors[c].r =
   215 					palcolors[c].r+((cdist[c].r*i))/maxstep;
   216 				colors[c].g =
   217 					palcolors[c].g+((cdist[c].g*i))/maxstep;
   218 				colors[c].b =
   219 					palcolors[c].b+((cdist[c].b*i))/maxstep;
   220 			}
   221 			SDL_SetColors(screen, colors, 0, ncolors);
   222 			SDL_Delay(1);
   223 		}
   224 NOTICE("testwin: fading over\n");
   225 	}
   226 	
   227 done:
   228 	/* Free the picture and return */
   229 	SDL_FreeSurface(picture);
   230 	free(colors); free(cmap);
   231 	return;
   232 }
   233 
   234 int main(int argc, char *argv[])
   235 {
   236 	SDL_Surface *screen;
   237 	/* Options */
   238 	int speedy, flip, nofade;
   239 	int delay;
   240 	int w, h;
   241 	int desired_bpp;
   242 	Uint32 video_flags;
   243 #ifdef BENCHMARK_SDL
   244 	Uint32 then, now;
   245 #endif
   246 	/* Set default options and check command-line */
   247 	speedy = 0;
   248 	flip = 0;
   249 	nofade = 0;
   250 	delay = 1;
   251 
   252 #ifdef _WIN32_WCE
   253 	w = 640;
   254 	h = 320;
   255 	desired_bpp = 0;
   256 	video_flags = SDL_FULLSCREEN;
   257 #else
   258 	w = 640;
   259 	h = 480;
   260 	desired_bpp = 0;
   261 	video_flags = 0;
   262 #endif
   263 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
   264 		fprintf(stderr,
   265 			"Couldn't initialize SDL: %s\n", SDL_GetError());
   266 		return(1);
   267 	}
   268 
   269 	while ( argc > 1 ) {
   270 		if ( strcmp(argv[1], "-speedy") == 0 ) {
   271 			speedy = 1;
   272 			argv += 1;
   273 			argc -= 1;
   274 		} else
   275 		if ( strcmp(argv[1], "-nofade") == 0 ) {
   276 			nofade = 1;
   277 			argv += 1;
   278 			argc -= 1;
   279 		} else
   280 		if ( strcmp(argv[1], "-delay") == 0 ) {
   281 			if ( argv[2] ) {
   282 				delay = atoi(argv[2]);
   283 				argv += 2;
   284 				argc -= 2;
   285 			} else {
   286 				fprintf(stderr,
   287 				"The -delay option requires an argument\n");
   288 				quit(1);
   289 			}
   290 		} else
   291 		if ( strcmp(argv[1], "-width") == 0 ) {
   292 			if ( argv[2] && ((w = atoi(argv[2])) > 0) ) {
   293 				argv += 2;
   294 				argc -= 2;
   295 			} else {
   296 				fprintf(stderr,
   297 				"The -width option requires an argument\n");
   298 				quit(1);
   299 			}
   300 		} else
   301 		if ( strcmp(argv[1], "-height") == 0 ) {
   302 			if ( argv[2] && ((h = atoi(argv[2])) > 0) ) {
   303 				argv += 2;
   304 				argc -= 2;
   305 			} else {
   306 				fprintf(stderr,
   307 				"The -height option requires an argument\n");
   308 				quit(1);
   309 			}
   310 		} else
   311 		if ( strcmp(argv[1], "-bpp") == 0 ) {
   312 			if ( argv[2] ) {
   313 				desired_bpp = atoi(argv[2]);
   314 				argv += 2;
   315 				argc -= 2;
   316 			} else {
   317 				fprintf(stderr,
   318 				"The -bpp option requires an argument\n");
   319 				quit(1);
   320 			}
   321 		} else
   322 		if ( strcmp(argv[1], "-warp") == 0 ) {
   323 			video_flags |= SDL_HWPALETTE;
   324 			argv += 1;
   325 			argc -= 1;
   326 		} else
   327 		if ( strcmp(argv[1], "-hw") == 0 ) {
   328 			video_flags |= SDL_HWSURFACE;
   329 			argv += 1;
   330 			argc -= 1;
   331 		} else
   332 		if ( strcmp(argv[1], "-flip") == 0 ) {
   333 			video_flags |= SDL_DOUBLEBUF;
   334 			argv += 1;
   335 			argc -= 1;
   336 		} else
   337 		if ( strcmp(argv[1], "-fullscreen") == 0 ) {
   338 			video_flags |= SDL_FULLSCREEN;
   339 			argv += 1;
   340 			argc -= 1;
   341 		} else
   342 			break;
   343 	}
   344 
   345 	/* Initialize the display */
   346 	screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);
   347 	if ( screen == NULL ) {
   348 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
   349 					w, h, desired_bpp, SDL_GetError());
   350 		quit(1);
   351 	}
   352 	printf("Set%s %dx%dx%d mode\n",
   353 			screen->flags & SDL_FULLSCREEN ? " fullscreen" : "",
   354 			screen->w, screen->h, screen->format->BitsPerPixel);
   355 	printf("(video surface located in %s memory)\n",
   356 			(screen->flags&SDL_HWSURFACE) ? "video" : "system");
   357 	if ( screen->flags & SDL_DOUBLEBUF ) {
   358 		printf("Double-buffering enabled\n");
   359 		flip = 1;
   360 	}
   361 
   362 	/* Set the window manager title bar */
   363 	SDL_WM_SetCaption("SDL test window", "testwin");
   364 
   365 	/* Do all the drawing work */
   366 #ifdef BENCHMARK_SDL
   367 	then = SDL_GetTicks();
   368 	DrawPict(screen, argv[1], speedy, flip, nofade);
   369 	now = SDL_GetTicks();
   370 	printf("Time: %d milliseconds\n", now-then);
   371 #else
   372 	DrawPict(screen, argv[1], speedy, flip, nofade);
   373 #endif
   374 	SDL_Delay(delay*1000);
   375 	SDL_Quit();
   376 	return(0);
   377 }