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