Mercurial > sdl-ios-xcode
annotate test/testpalette.c @ 1554:0ca607a5d173
Fixed bug #84
Date: Sun, 23 Oct 2005 16:39:03 +0200
From: "A. Schmid" <sahib@phreaker.net>
Subject: [SDL] no software surfaces with svgalib driver?
Hi,
I noticed that the SDL (1.2.9) svgalib driver only makes use of linear
addressable (framebuffer) video modes. On older systems (like one of
mine), linear addressable modes are often not available.
Especially for cards with VESA VBE < 2.0 the svgalib vesa driver is
unusable, since VESA only supports framebuffering for VBE 2.0 and later.
The changes necessary to add support for software surfaces seem to be
relatively small. I only had to hack src/video/svga/SDL_svgavideo.c (see
attached patch). The code worked fine for me, but it is no more than a
proof of concept and should be reviewed (probably has a memory leak when
switching modes). It also uses the vgagl library (included in the
svgalib package) and needs to be linked against it.
-Alex
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 19 Mar 2006 12:04:40 +0000 |
parents | 4d241ea8a1cd |
children | 14717b52abc0 |
rev | line source |
---|---|
0 | 1 /* |
2 * testpalette.c | |
3 * | |
4 * A simple test of runtime palette modification for animation | |
5 * (using the SDL_SetPalette() API). | |
6 */ | |
7 | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <math.h> | |
12 | |
13 /* This isn't in the Windows headers */ | |
14 #ifndef M_PI | |
15 #define M_PI 3.14159265358979323846 | |
16 #endif | |
17 | |
18 #include <SDL.h> | |
19 | |
20 /* screen size */ | |
21 #define SCRW 640 | |
22 #define SCRH 480 | |
23 | |
24 #define NBOATS 5 | |
25 #define SPEED 2 | |
26 | |
27 #ifndef MIN | |
28 #define MIN(a, b) ((a) < (b) ? (a) : (b)) | |
29 #endif | |
30 #ifndef MAX | |
31 #define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
32 #endif | |
33 | |
34 /* | |
35 * wave colours: Made by taking a narrow cross-section of a wave picture | |
36 * in Gimp, saving in PPM ascii format and formatting with Emacs macros. | |
37 */ | |
38 static SDL_Color wavemap[] = { | |
39 {0,2,103}, {0,7,110}, {0,13,117}, {0,19,125}, | |
40 {0,25,133}, {0,31,141}, {0,37,150}, {0,43,158}, | |
41 {0,49,166}, {0,55,174}, {0,61,182}, {0,67,190}, | |
42 {0,73,198}, {0,79,206}, {0,86,214}, {0,96,220}, | |
43 {5,105,224}, {12,112,226}, {19,120,227}, {26,128,229}, | |
44 {33,135,230}, {40,143,232}, {47,150,234}, {54,158,236}, | |
45 {61,165,238}, {68,173,239}, {75,180,241}, {82,188,242}, | |
46 {89,195,244}, {96,203,246}, {103,210,248}, {112,218,250}, | |
47 {124,224,250}, {135,226,251}, {146,229,251}, {156,231,252}, | |
48 {167,233,252}, {178,236,252}, {189,238,252}, {200,240,252}, | |
49 {211,242,252}, {222,244,252}, {233,247,252}, {242,249,252}, | |
50 {237,250,252}, {209,251,252}, {174,251,252}, {138,252,252}, | |
51 {102,251,252}, {63,250,252}, {24,243,252}, {7,225,252}, | |
52 {4,203,252}, {3,181,252}, {2,158,252}, {1,136,251}, | |
53 {0,111,248}, {0,82,234}, {0,63,213}, {0,50,192}, | |
54 {0,39,172}, {0,28,152}, {0,17,132}, {0,7,114} | |
55 }; | |
56 | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
57 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
58 static void quit(int rc) |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
59 { |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
60 SDL_Quit(); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
61 exit(rc); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
62 } |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
63 |
0 | 64 static void sdlerr(char *when) |
65 { | |
66 fprintf(stderr, "SDL error: %s: %s\n", when, SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
67 quit(1); |
0 | 68 } |
69 | |
70 /* create a background surface */ | |
71 static SDL_Surface *make_bg(SDL_Surface *screen, int startcol) | |
72 { | |
73 int i; | |
74 SDL_Surface *bg = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, | |
75 8, 0, 0, 0, 0); | |
76 if(!bg) | |
77 sdlerr("creating background surface"); | |
78 | |
79 /* set the palette to the logical screen palette so that blits | |
80 won't be translated */ | |
81 SDL_SetColors(bg, screen->format->palette->colors, 0, 256); | |
82 | |
83 /* Make a wavy background pattern using colours 0-63 */ | |
84 if(SDL_LockSurface(bg) < 0) | |
85 sdlerr("locking background"); | |
86 for(i = 0; i < SCRH; i++) { | |
87 Uint8 *p = (Uint8 *)bg->pixels + i * bg->pitch; | |
88 int j, d; | |
89 d = 0; | |
90 for(j = 0; j < SCRW; j++) { | |
91 int v = MAX(d, -2); | |
92 v = MIN(v, 2); | |
93 if(i > 0) | |
94 v += p[-bg->pitch] + 65 - startcol; | |
95 p[j] = startcol + (v & 63); | |
96 d += ((rand() >> 3) % 3) - 1; | |
97 } | |
98 } | |
99 SDL_UnlockSurface(bg); | |
100 return(bg); | |
101 } | |
102 | |
103 /* | |
104 * Return a surface flipped horisontally. Only works for 8bpp; | |
105 * extension to arbitrary bitness is left as an exercise for the reader. | |
106 */ | |
107 static SDL_Surface *hflip(SDL_Surface *s) | |
108 { | |
109 int i; | |
110 SDL_Surface *z = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 8, | |
111 0, 0, 0, 0); | |
112 /* copy palette */ | |
113 SDL_SetColors(z, s->format->palette->colors, | |
114 0, s->format->palette->ncolors); | |
115 if(SDL_LockSurface(s) < 0 || SDL_LockSurface(z) < 0) | |
116 sdlerr("locking flip images"); | |
117 | |
118 for(i = 0; i < s->h; i++) { | |
119 int j; | |
120 Uint8 *from = (Uint8 *)s->pixels + i * s->pitch; | |
121 Uint8 *to = (Uint8 *)z->pixels + i * z->pitch + s->w - 1; | |
122 for(j = 0; j < s->w; j++) | |
123 to[-j] = from[j]; | |
124 } | |
125 | |
126 SDL_UnlockSurface(z); | |
127 SDL_UnlockSurface(s); | |
128 return z; | |
129 } | |
130 | |
131 int main(int argc, char **argv) | |
132 { | |
133 SDL_Color cmap[256]; | |
134 SDL_Surface *screen; | |
135 SDL_Surface *bg; | |
136 SDL_Surface *boat[2]; | |
137 unsigned vidflags = 0; | |
138 unsigned start; | |
139 int fade_max = 400; | |
140 int fade_level, fade_dir; | |
141 int boatcols, frames, i, red; | |
142 int boatx[NBOATS], boaty[NBOATS], boatdir[NBOATS]; | |
143 int gamma_fade = 0; | |
144 int gamma_ramp = 0; | |
145 | |
146 if(SDL_Init(SDL_INIT_VIDEO) < 0) | |
147 sdlerr("initialising SDL"); | |
148 | |
149 while(--argc) { | |
150 ++argv; | |
151 if(strcmp(*argv, "-hw") == 0) | |
152 vidflags |= SDL_HWSURFACE; | |
153 else if(strcmp(*argv, "-fullscreen") == 0) | |
154 vidflags |= SDL_FULLSCREEN; | |
155 else if(strcmp(*argv, "-nofade") == 0) | |
156 fade_max = 1; | |
157 else if(strcmp(*argv, "-gamma") == 0) | |
158 gamma_fade = 1; | |
159 else if(strcmp(*argv, "-gammaramp") == 0) | |
160 gamma_ramp = 1; | |
161 else { | |
162 fprintf(stderr, | |
163 "usage: testpalette " | |
164 " [-hw] [-fullscreen] [-nofade] [-gamma] [-gammaramp]\n"); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
165 quit(1); |
0 | 166 } |
167 } | |
168 | |
169 /* Ask explicitly for 8bpp and a hardware palette */ | |
1516
4d241ea8a1cd
Updated MacOS Classic build
Sam Lantinga <slouken@libsdl.org>
parents:
1429
diff
changeset
|
170 if((screen = SDL_SetVideoMode(SCRW, SCRH, 8, vidflags | SDL_HWPALETTE)) == NULL) { |
0 | 171 fprintf(stderr, "error setting %dx%d 8bpp indexed mode: %s\n", |
172 SCRW, SCRH, SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
173 quit(1); |
0 | 174 } |
175 | |
1429
aff0170f9f1b
Date: Sat, 25 Feb 2006 14:26:19 +0100 (CET)
Sam Lantinga <slouken@libsdl.org>
parents:
1151
diff
changeset
|
176 if (vidflags & SDL_FULLSCREEN) SDL_ShowCursor (SDL_FALSE); |
aff0170f9f1b
Date: Sat, 25 Feb 2006 14:26:19 +0100 (CET)
Sam Lantinga <slouken@libsdl.org>
parents:
1151
diff
changeset
|
177 |
1516
4d241ea8a1cd
Updated MacOS Classic build
Sam Lantinga <slouken@libsdl.org>
parents:
1429
diff
changeset
|
178 if((boat[0] = SDL_LoadBMP("sail.bmp")) == NULL) |
0 | 179 sdlerr("loading sail.bmp"); |
180 /* We've chosen magenta (#ff00ff) as colour key for the boat */ | |
181 SDL_SetColorKey(boat[0], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
182 SDL_MapRGB(boat[0]->format, 0xff, 0x00, 0xff)); | |
183 boatcols = boat[0]->format->palette->ncolors; | |
184 boat[1] = hflip(boat[0]); | |
185 SDL_SetColorKey(boat[1], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
186 SDL_MapRGB(boat[1]->format, 0xff, 0x00, 0xff)); | |
187 | |
188 /* | |
189 * First set the physical screen palette to black, so the user won't | |
190 * see our initial drawing on the screen. | |
191 */ | |
192 memset(cmap, 0, sizeof(cmap)); | |
193 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, 256); | |
194 | |
195 /* | |
196 * Proper palette management is important when playing games with the | |
197 * colormap. We have divided the palette as follows: | |
198 * | |
199 * index 0..(boatcols-1): used for the boat | |
200 * index boatcols..(boatcols+63): used for the waves | |
201 */ | |
202 SDL_SetPalette(screen, SDL_LOGPAL, | |
203 boat[0]->format->palette->colors, 0, boatcols); | |
204 SDL_SetPalette(screen, SDL_LOGPAL, wavemap, boatcols, 64); | |
205 | |
206 /* | |
207 * Now the logical screen palette is set, and will remain unchanged. | |
208 * The boats already have the same palette so fast blits can be used. | |
209 */ | |
210 memcpy(cmap, screen->format->palette->colors, 256 * sizeof(SDL_Color)); | |
211 | |
212 /* save the index of the red colour for later */ | |
213 red = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00); | |
214 | |
215 bg = make_bg(screen, boatcols); /* make a nice wavy background surface */ | |
216 | |
217 /* initial screen contents */ | |
218 if(SDL_BlitSurface(bg, NULL, screen, NULL) < 0) | |
219 sdlerr("blitting background to screen"); | |
220 SDL_Flip(screen); /* actually put the background on screen */ | |
221 | |
222 /* determine initial boat placements */ | |
223 for(i = 0; i < NBOATS; i++) { | |
224 boatx[i] = (rand() % (SCRW + boat[0]->w)) - boat[0]->w; | |
225 boaty[i] = i * (SCRH - boat[0]->h) / (NBOATS - 1); | |
226 boatdir[i] = ((rand() >> 5) & 1) * 2 - 1; | |
227 } | |
228 | |
229 start = SDL_GetTicks(); | |
230 frames = 0; | |
231 fade_dir = 1; | |
232 fade_level = 0; | |
233 do { | |
234 SDL_Event e; | |
235 SDL_Rect updates[NBOATS]; | |
236 SDL_Rect r; | |
237 int redphase; | |
238 | |
239 /* A small event loop: just exit on any key or mouse button event */ | |
240 while(SDL_PollEvent(&e)) { | |
241 if(e.type == SDL_KEYDOWN || e.type == SDL_QUIT | |
242 || e.type == SDL_MOUSEBUTTONDOWN) { | |
243 if(fade_dir < 0) | |
244 fade_level = 0; | |
245 fade_dir = -1; | |
246 } | |
247 } | |
248 | |
249 /* move boats */ | |
250 for(i = 0; i < NBOATS; i++) { | |
251 int old_x = boatx[i]; | |
252 /* update boat position */ | |
253 boatx[i] += boatdir[i] * SPEED; | |
254 if(boatx[i] <= -boat[0]->w || boatx[i] >= SCRW) | |
255 boatdir[i] = -boatdir[i]; | |
256 | |
257 /* paint over the old boat position */ | |
258 r.x = old_x; | |
259 r.y = boaty[i]; | |
260 r.w = boat[0]->w; | |
261 r.h = boat[0]->h; | |
262 if(SDL_BlitSurface(bg, &r, screen, &r) < 0) | |
263 sdlerr("blitting background"); | |
264 | |
265 /* construct update rectangle (bounding box of old and new pos) */ | |
266 updates[i].x = MIN(old_x, boatx[i]); | |
267 updates[i].y = boaty[i]; | |
268 updates[i].w = boat[0]->w + SPEED; | |
269 updates[i].h = boat[0]->h; | |
270 /* clip update rectangle to screen */ | |
271 if(updates[i].x < 0) { | |
272 updates[i].w += updates[i].x; | |
273 updates[i].x = 0; | |
274 } | |
275 if(updates[i].x + updates[i].w > SCRW) | |
276 updates[i].w = SCRW - updates[i].x; | |
277 } | |
278 | |
279 for(i = 0; i < NBOATS; i++) { | |
280 /* paint boat on new position */ | |
281 r.x = boatx[i]; | |
282 r.y = boaty[i]; | |
283 if(SDL_BlitSurface(boat[(boatdir[i] + 1) / 2], NULL, | |
284 screen, &r) < 0) | |
285 sdlerr("blitting boat"); | |
286 } | |
287 | |
288 /* cycle wave palette */ | |
289 for(i = 0; i < 64; i++) | |
290 cmap[boatcols + ((i + frames) & 63)] = wavemap[i]; | |
291 | |
292 if(fade_dir) { | |
293 /* Fade the entire palette in/out */ | |
294 fade_level += fade_dir; | |
295 | |
296 if(gamma_fade) { | |
297 /* Fade linearly in gamma level (lousy) */ | |
298 float level = (float)fade_level / fade_max; | |
299 if(SDL_SetGamma(level, level, level) < 0) | |
300 sdlerr("setting gamma"); | |
301 | |
302 } else if(gamma_ramp) { | |
303 /* Fade using gamma ramp (better) */ | |
304 Uint16 ramp[256]; | |
305 for(i = 0; i < 256; i++) | |
306 ramp[i] = (i * fade_level / fade_max) << 8; | |
307 if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0) | |
308 sdlerr("setting gamma ramp"); | |
309 | |
310 } else { | |
311 /* Fade using direct palette manipulation (best) */ | |
312 memcpy(cmap, screen->format->palette->colors, | |
313 boatcols * sizeof(SDL_Color)); | |
314 for(i = 0; i < boatcols + 64; i++) { | |
315 cmap[i].r = cmap[i].r * fade_level / fade_max; | |
316 cmap[i].g = cmap[i].g * fade_level / fade_max; | |
317 cmap[i].b = cmap[i].b * fade_level / fade_max; | |
318 } | |
319 } | |
320 if(fade_level == fade_max) | |
321 fade_dir = 0; | |
322 } | |
323 | |
324 /* pulse the red colour (done after the fade, for a night effect) */ | |
325 redphase = frames % 64; | |
326 cmap[red].r = (int)(255 * sin(redphase * M_PI / 63)); | |
327 | |
328 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, boatcols + 64); | |
329 | |
330 /* update changed areas of the screen */ | |
331 SDL_UpdateRects(screen, NBOATS, updates); | |
332 frames++; | |
333 } while(fade_level > 0); | |
334 | |
335 printf("%d frames, %.2f fps\n", | |
336 frames, 1000.0 * frames / (SDL_GetTicks() - start)); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
337 |
1429
aff0170f9f1b
Date: Sat, 25 Feb 2006 14:26:19 +0100 (CET)
Sam Lantinga <slouken@libsdl.org>
parents:
1151
diff
changeset
|
338 if (vidflags & SDL_FULLSCREEN) SDL_ShowCursor (SDL_TRUE); |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
339 SDL_Quit(); |
0 | 340 return 0; |
341 } | |
342 |