Mercurial > sdl-ios-xcode
annotate src/video/aalib/SDL_aavideo.c @ 1076:8d3b95ece376
[PATCH] SDL_GetVideoMode() do not find the best video mode
The current GetVideoMode() function stops at the first mode which has any
dimensions smaller than the one asked, and gives the previous in the list.
If I ask 336x224 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200
SDL will give me 640x400, because 640x200 as height smaller than what I
asked.
However the best mode is the smaller which has both dimensions bigger
than the one asked (384x240 in my example).
This patch fixes this, plus it does not rely on a sorted video mode list.
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Sun, 12 Jun 2005 16:12:55 +0000 |
parents | b8d311d90021 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* AAlib based SDL video driver implementation. | |
29 */ | |
30 | |
31 #include <stdlib.h> | |
32 #include <stdio.h> | |
33 #include <unistd.h> | |
34 #include <sys/stat.h> | |
35 | |
36 | |
37 #include "SDL.h" | |
38 #include "SDL_error.h" | |
39 #include "SDL_video.h" | |
40 #include "SDL_mouse.h" | |
41 #include "SDL_sysvideo.h" | |
42 #include "SDL_pixels_c.h" | |
43 #include "SDL_events_c.h" | |
44 | |
45 #include "SDL_aavideo.h" | |
46 #include "SDL_aaevents_c.h" | |
47 #include "SDL_aamouse_c.h" | |
48 | |
49 #include <aalib.h> | |
50 | |
51 /* Initialization/Query functions */ | |
52 static int AA_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
53 static SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
54 static SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
55 static int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
56 static void AA_VideoQuit(_THIS); | |
57 | |
58 /* Hardware surface functions */ | |
59 static int AA_AllocHWSurface(_THIS, SDL_Surface *surface); | |
60 static int AA_LockHWSurface(_THIS, SDL_Surface *surface); | |
61 static int AA_FlipHWSurface(_THIS, SDL_Surface *surface); | |
62 static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
63 static void AA_FreeHWSurface(_THIS, SDL_Surface *surface); | |
64 | |
65 /* Cache the VideoDevice struct */ | |
66 static struct SDL_VideoDevice *local_this; | |
67 | |
68 /* AAlib driver bootstrap functions */ | |
69 | |
70 static int AA_Available(void) | |
71 { | |
72 return 1; /* Always available ! */ | |
73 } | |
74 | |
75 static void AA_DeleteDevice(SDL_VideoDevice *device) | |
76 { | |
77 free(device->hidden); | |
78 free(device); | |
79 } | |
80 | |
81 static SDL_VideoDevice *AA_CreateDevice(int devindex) | |
82 { | |
83 SDL_VideoDevice *device; | |
84 | |
85 /* Initialize all variables that we clean on shutdown */ | |
86 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
87 if ( device ) { | |
88 memset(device, 0, (sizeof *device)); | |
89 device->hidden = (struct SDL_PrivateVideoData *) | |
90 malloc((sizeof *device->hidden)); | |
91 } | |
92 if ( (device == NULL) || (device->hidden == NULL) ) { | |
93 SDL_OutOfMemory(); | |
94 if ( device ) { | |
95 free(device); | |
96 } | |
97 return(0); | |
98 } | |
99 memset(device->hidden, 0, (sizeof *device->hidden)); | |
100 | |
101 /* Set the function pointers */ | |
102 device->VideoInit = AA_VideoInit; | |
103 device->ListModes = AA_ListModes; | |
104 device->SetVideoMode = AA_SetVideoMode; | |
105 device->CreateYUVOverlay = NULL; | |
106 device->SetColors = AA_SetColors; | |
107 device->UpdateRects = NULL; | |
108 device->VideoQuit = AA_VideoQuit; | |
109 device->AllocHWSurface = AA_AllocHWSurface; | |
110 device->CheckHWBlit = NULL; | |
111 device->FillHWRect = NULL; | |
112 device->SetHWColorKey = NULL; | |
113 device->SetHWAlpha = NULL; | |
114 device->LockHWSurface = AA_LockHWSurface; | |
115 device->UnlockHWSurface = AA_UnlockHWSurface; | |
116 device->FlipHWSurface = NULL; | |
117 device->FreeHWSurface = AA_FreeHWSurface; | |
118 device->SetCaption = NULL; | |
119 device->SetIcon = NULL; | |
120 device->IconifyWindow = NULL; | |
121 device->GrabInput = NULL; | |
122 device->GetWMInfo = NULL; | |
123 device->InitOSKeymap = AA_InitOSKeymap; | |
124 device->PumpEvents = AA_PumpEvents; | |
125 | |
126 device->free = AA_DeleteDevice; | |
127 | |
128 return device; | |
129 } | |
130 | |
131 VideoBootStrap AALIB_bootstrap = { | |
132 "aalib", "ASCII Art Library", | |
133 AA_Available, AA_CreateDevice | |
134 }; | |
135 | |
136 static void AA_ResizeHandler(aa_context *); | |
137 | |
138 int AA_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
139 { | |
140 int keyboard; | |
141 int i; | |
142 | |
143 /* Initialize all variables that we clean on shutdown */ | |
144 for ( i=0; i<SDL_NUMMODES; ++i ) { | |
145 SDL_modelist[i] = malloc(sizeof(SDL_Rect)); | |
146 SDL_modelist[i]->x = SDL_modelist[i]->y = 0; | |
147 } | |
148 /* Modes sorted largest to smallest */ | |
149 SDL_modelist[0]->w = 1024; SDL_modelist[0]->h = 768; | |
150 SDL_modelist[1]->w = 800; SDL_modelist[1]->h = 600; | |
151 SDL_modelist[2]->w = 640; SDL_modelist[2]->h = 480; | |
152 SDL_modelist[3]->w = 320; SDL_modelist[3]->h = 400; | |
153 SDL_modelist[4]->w = 320; SDL_modelist[4]->h = 240; | |
154 SDL_modelist[5]->w = 320; SDL_modelist[5]->h = 200; | |
155 SDL_modelist[6] = NULL; | |
156 | |
157 /* Initialize the library */ | |
158 | |
159 AA_mutex = SDL_CreateMutex(); | |
160 | |
161 aa_parseoptions (NULL, NULL, NULL, NULL); | |
162 | |
163 AA_context = aa_autoinit(&aa_defparams); | |
164 if ( ! AA_context ) { | |
165 SDL_SetError("Unable to initialize AAlib"); | |
166 return(-1); | |
167 } | |
168 | |
169 /* Enable mouse and keyboard support */ | |
170 | |
171 if ( ! aa_autoinitkbd (AA_context, AA_SENDRELEASE) ) { | |
172 SDL_SetError("Unable to initialize AAlib keyboard"); | |
173 return(-1); | |
174 } | |
175 if ( ! aa_autoinitmouse (AA_context, AA_SENDRELEASE) ) { | |
176 fprintf(stderr,"Warning: Unable to initialize AAlib mouse"); | |
177 } | |
178 AA_rparams = aa_getrenderparams(); | |
179 | |
180 local_this = this; | |
181 | |
182 aa_resizehandler(AA_context, AA_ResizeHandler); | |
183 | |
184 fprintf(stderr,"Using AAlib driver: %s (%s)\n", AA_context->driver->name, AA_context->driver->shortname); | |
185 | |
186 AA_in_x11 = (strcmp(AA_context->driver->shortname,"X11") == 0); | |
187 /* Determine the screen depth (use default 8-bit depth) */ | |
188 vformat->BitsPerPixel = 8; | |
189 vformat->BytesPerPixel = 1; | |
190 | |
191 /* We're done! */ | |
192 return(0); | |
193 } | |
194 | |
195 SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
196 { | |
197 if(format->BitsPerPixel != 8) | |
198 return NULL; | |
199 | |
200 if ( flags & SDL_FULLSCREEN ) { | |
201 return SDL_modelist; | |
202 } else { | |
203 return (SDL_Rect **) -1; | |
204 } | |
205 } | |
206 | |
207 /* From aavga.c | |
208 AAlib does not give us the choice of the actual resolution, thus we have to simulate additional | |
209 resolution by scaling down manually each frame | |
210 */ | |
211 static void fastscale (register char *b1, register char *b2, int x1, int x2, int y1, int y2) | |
212 { | |
213 register int ex, spx = 0, ddx, ddx1; | |
214 int ddy1, ddy, spy = 0, ey; | |
215 int x; | |
216 char *bb1 = b1; | |
217 if (!x1 || !x2 || !y1 || !y2) | |
218 return; | |
219 ddx = x1 + x1; | |
220 ddx1 = x2 + x2; | |
221 if (ddx1 < ddx) | |
222 spx = ddx / ddx1, ddx %= ddx1; | |
223 ddy = y1 + y1; | |
224 ddy1 = y2 + y2; | |
225 if (ddy1 < ddy) | |
226 spy = (ddy / ddy1) * x1, ddy %= ddy1; | |
227 ey = -ddy1; | |
228 for (; y2; y2--) { | |
229 ex = -ddx1; | |
230 for (x = x2; x; x--) { | |
231 *b2 = *b1; | |
232 b2++; | |
233 b1 += spx; | |
234 ex += ddx; | |
235 if (ex > 0) { | |
236 b1++; | |
237 ex -= ddx1; | |
238 } | |
239 } | |
240 bb1 += spy; | |
241 ey += ddy; | |
242 if (ey > 0) { | |
243 bb1 += x1; | |
244 ey -= ddy1; | |
245 } | |
246 b1 = bb1; | |
247 } | |
248 } | |
249 | |
250 /* Various screen update functions available */ | |
251 static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
252 | |
253 SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, | |
254 int width, int height, int bpp, Uint32 flags) | |
255 { | |
256 int mode; | |
257 | |
258 if ( AA_buffer ) { | |
259 free( AA_buffer ); | |
260 } | |
261 | |
262 AA_buffer = malloc(width * height); | |
263 if ( ! AA_buffer ) { | |
264 SDL_SetError("Couldn't allocate buffer for requested mode"); | |
265 return(NULL); | |
266 } | |
267 | |
268 /* printf("Setting mode %dx%d\n", width, height); */ | |
269 | |
270 memset(aa_image(AA_context), 0, aa_imgwidth(AA_context) * aa_imgheight(AA_context)); | |
271 memset(AA_buffer, 0, width * height); | |
272 | |
273 /* Allocate the new pixel format for the screen */ | |
274 if ( ! SDL_ReallocFormat(current, 8, 0, 0, 0, 0) ) { | |
275 return(NULL); | |
276 } | |
277 | |
278 /* Set up the new mode framebuffer */ | |
279 current->flags = SDL_FULLSCREEN; | |
280 AA_w = current->w = width; | |
281 AA_h = current->h = height; | |
282 current->pitch = current->w; | |
283 current->pixels = AA_buffer; | |
284 | |
285 AA_x_ratio = ((double)aa_imgwidth(AA_context)) / ((double)width); | |
286 AA_y_ratio = ((double)aa_imgheight(AA_context)) / ((double)height); | |
287 | |
288 /* Set the blit function */ | |
289 this->UpdateRects = AA_DirectUpdate; | |
290 | |
291 /* We're done */ | |
292 return(current); | |
293 } | |
294 | |
295 static void AA_ResizeHandler(aa_context *context) | |
296 { | |
297 aa_resize(context); | |
298 local_this->hidden->x_ratio = ((double)aa_imgwidth(context)) / ((double)local_this->screen->w); | |
299 local_this->hidden->y_ratio = ((double)aa_imgheight(context)) / ((double)local_this->screen->h); | |
300 | |
301 fastscale (local_this->hidden->buffer, aa_image(context), local_this->hidden->w, aa_imgwidth (context), local_this->hidden->h, aa_imgheight (context)); | |
302 aa_renderpalette(context, local_this->hidden->palette, local_this->hidden->rparams, 0, 0, aa_scrwidth(context), aa_scrheight(context)); | |
303 aa_flush(context); | |
304 } | |
305 | |
306 /* We don't actually allow hardware surfaces other than the main one */ | |
307 static int AA_AllocHWSurface(_THIS, SDL_Surface *surface) | |
308 { | |
309 return(-1); | |
310 } | |
311 static void AA_FreeHWSurface(_THIS, SDL_Surface *surface) | |
312 { | |
313 return; | |
314 } | |
315 | |
316 /* We need to wait for vertical retrace on page flipped displays */ | |
317 static int AA_LockHWSurface(_THIS, SDL_Surface *surface) | |
318 { | |
319 /* TODO ? */ | |
320 return(0); | |
321 } | |
322 static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
323 { | |
324 return; | |
325 } | |
326 | |
327 /* FIXME: How is this done with AAlib? */ | |
328 static int AA_FlipHWSurface(_THIS, SDL_Surface *surface) | |
329 { | |
330 SDL_mutexP(AA_mutex); | |
331 aa_flush(AA_context); | |
332 SDL_mutexV(AA_mutex); | |
333 return(0); | |
334 } | |
335 | |
336 static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) | |
337 { | |
338 int i; | |
339 SDL_Rect *rect; | |
340 | |
341 fastscale (AA_buffer, aa_image(AA_context), AA_w, aa_imgwidth (AA_context), AA_h, aa_imgheight (AA_context)); | |
342 #if 1 | |
343 aa_renderpalette(AA_context, AA_palette, AA_rparams, 0, 0, aa_scrwidth(AA_context), aa_scrheight(AA_context)); | |
344 #else | |
345 /* Render only the rectangles in the list */ | |
346 printf("Update rects : "); | |
347 for ( i=0; i < numrects; ++i ) { | |
348 rect = &rects[i]; | |
349 printf("(%d,%d-%d,%d)", rect->x, rect->y, rect->w, rect->h); | |
350 aa_renderpalette(AA_context, AA_palette, AA_rparams, rect->x * AA_x_ratio, rect->y * AA_y_ratio, rect->w * AA_x_ratio, rect->h * AA_y_ratio); | |
351 } | |
352 printf("\n"); | |
353 #endif | |
354 SDL_mutexP(AA_mutex); | |
355 aa_flush(AA_context); | |
356 SDL_mutexV(AA_mutex); | |
357 return; | |
358 } | |
359 | |
360 int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
361 { | |
362 int i; | |
363 | |
364 for ( i=0; i < ncolors; i++ ) { | |
365 aa_setpalette(AA_palette, firstcolor + i, | |
366 colors[i].r>>2, | |
367 colors[i].g>>2, | |
368 colors[i].b>>2); | |
369 } | |
370 return(1); | |
371 } | |
372 | |
373 /* Note: If we are terminated, this could be called in the middle of | |
374 another SDL video routine -- notably UpdateRects. | |
375 */ | |
376 void AA_VideoQuit(_THIS) | |
377 { | |
378 int i; | |
379 | |
380 aa_uninitkbd(AA_context); | |
381 aa_uninitmouse(AA_context); | |
382 | |
383 /* Free video mode lists */ | |
384 for ( i=0; i<SDL_NUMMODES; ++i ) { | |
385 if ( SDL_modelist[i] != NULL ) { | |
386 free(SDL_modelist[i]); | |
387 SDL_modelist[i] = NULL; | |
388 } | |
389 } | |
390 | |
391 aa_close(AA_context); | |
392 | |
393 SDL_DestroyMutex(AA_mutex); | |
394 | |
395 this->screen->pixels = NULL; | |
396 } |