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