Mercurial > sdl-ios-xcode
annotate src/video/ggi/SDL_ggivideo.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:
17
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* GGI-based SDL video driver implementation. | |
29 */ | |
30 | |
31 #include <stdlib.h> | |
32 #include <stdio.h> | |
33 #include <fcntl.h> | |
34 #include <unistd.h> | |
35 #include <sys/mman.h> | |
36 | |
37 #include <ggi/ggi.h> | |
38 #include <ggi/gii.h> | |
39 | |
40 #include "SDL.h" | |
41 #include "SDL_error.h" | |
42 #include "SDL_video.h" | |
43 #include "SDL_mouse.h" | |
44 #include "SDL_sysvideo.h" | |
45 #include "SDL_pixels_c.h" | |
46 #include "SDL_events_c.h" | |
47 #include "SDL_ggivideo.h" | |
48 #include "SDL_ggimouse_c.h" | |
49 #include "SDL_ggievents_c.h" | |
50 | |
51 | |
52 struct private_hwdata | |
53 { | |
54 ggi_visual_t vis; | |
55 }; | |
56 | |
57 ggi_visual_t VIS; | |
58 | |
59 /* Initialization/Query functions */ | |
60 static int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
61 static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
62 static SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
63 static int GGI_SetColors(_THIS, int firstcolor, int ncolors, | |
64 SDL_Color *colors); | |
65 static void GGI_VideoQuit(_THIS); | |
66 | |
67 /* Hardware surface functions */ | |
68 static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface); | |
69 static int GGI_LockHWSurface(_THIS, SDL_Surface *surface); | |
70 static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
71 static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface); | |
72 | |
73 /* GGI driver bootstrap functions */ | |
74 | |
75 static int GGI_Available(void) | |
76 { | |
77 ggi_visual_t *vis; | |
17
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
78 |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
79 vis = NULL; |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
80 if (ggiInit() == 0) { |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
81 vis = ggiOpen(NULL); |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
82 if (vis != NULL) { |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
83 ggiClose(vis); |
4f22a992f5e9
Fixed crash in GGI detection
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
84 } |
0 | 85 } |
86 return (vis != NULL); | |
87 } | |
88 | |
89 static void GGI_DeleteDevice(SDL_VideoDevice *device) | |
90 { | |
91 free(device->hidden); | |
92 free(device); | |
93 } | |
94 | |
95 static SDL_VideoDevice *GGI_CreateDevice(int devindex) | |
96 { | |
97 SDL_VideoDevice *device; | |
98 | |
99 /* Initialize all variables that we clean on shutdown */ | |
100 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
101 if ( device ) { | |
102 memset(device, 0, (sizeof *device)); | |
103 device->hidden = (struct SDL_PrivateVideoData *) | |
104 malloc((sizeof *device->hidden)); | |
105 } | |
106 if ( (device == NULL) || (device->hidden == NULL) ) { | |
107 SDL_OutOfMemory(); | |
108 if ( device ) { | |
109 free(device); | |
110 } | |
111 return(0); | |
112 } | |
113 memset(device->hidden, 0, (sizeof *device->hidden)); | |
114 | |
115 /* Set the function pointers */ | |
116 device->VideoInit = GGI_VideoInit; | |
117 device->ListModes = GGI_ListModes; | |
118 device->SetVideoMode = GGI_SetVideoMode; | |
119 device->SetColors = GGI_SetColors; | |
120 device->UpdateRects = NULL; | |
121 device->VideoQuit = GGI_VideoQuit; | |
122 device->AllocHWSurface = GGI_AllocHWSurface; | |
123 device->CheckHWBlit = NULL; | |
124 device->FillHWRect = NULL; | |
125 device->SetHWColorKey = NULL; | |
126 device->SetHWAlpha = NULL; | |
127 device->LockHWSurface = GGI_LockHWSurface; | |
128 device->UnlockHWSurface = GGI_UnlockHWSurface; | |
129 device->FlipHWSurface = NULL; | |
130 device->FreeHWSurface = GGI_FreeHWSurface; | |
131 device->SetCaption = NULL; | |
132 device->SetIcon = NULL; | |
133 device->IconifyWindow = NULL; | |
134 device->GrabInput = NULL; | |
135 device->GetWMInfo = NULL; | |
136 device->InitOSKeymap = GGI_InitOSKeymap; | |
137 device->PumpEvents = GGI_PumpEvents; | |
138 | |
139 device->free = GGI_DeleteDevice; | |
140 | |
141 return device; | |
142 } | |
143 | |
144 VideoBootStrap GGI_bootstrap = { | |
145 "ggi", "General Graphics Interface (GGI)", | |
146 GGI_Available, GGI_CreateDevice | |
147 }; | |
148 | |
149 | |
150 static SDL_Rect video_mode; | |
151 static SDL_Rect *SDL_modelist[4] = { NULL, NULL, NULL, NULL }; | |
152 | |
153 int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
154 { | |
155 ggi_mode mode = | |
156 { | |
157 1, | |
158 { GGI_AUTO, GGI_AUTO }, | |
159 { GGI_AUTO, GGI_AUTO }, | |
160 { 0, 0 }, | |
161 GT_AUTO, | |
162 { GGI_AUTO, GGI_AUTO } | |
163 }; | |
164 struct private_hwdata *priv; | |
165 ggi_color pal[256], map[256]; | |
166 const ggi_directbuffer *db; | |
167 int err, num_bufs; | |
168 ggi_pixel white, black; | |
169 | |
170 priv = malloc(sizeof(struct private_hwdata)); | |
171 if (priv == NULL) | |
172 { | |
173 SDL_SetError("Unhandled GGI mode type!\n"); | |
174 GGI_VideoQuit(NULL); | |
175 } | |
176 | |
177 if (ggiInit() != 0) | |
178 { | |
179 SDL_SetError("Unable to initialize GGI!\n"); | |
180 GGI_VideoQuit(NULL); | |
181 } | |
182 | |
183 VIS = ggiOpen(NULL); | |
184 if (VIS == NULL) | |
185 { | |
186 SDL_SetError("Unable to open default GGI visual!\n"); | |
187 ggiExit(); | |
188 GGI_VideoQuit(NULL); | |
189 } | |
190 | |
191 ggiSetFlags(VIS, GGIFLAG_ASYNC); | |
192 | |
193 /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ | |
194 ggiCheckMode(VIS, &mode); | |
195 | |
196 /* At this point we should have a valid mode - try to set it */ | |
197 err = ggiSetMode(VIS, &mode); | |
198 | |
199 /* If we couldn't set _any_ modes, something is very wrong */ | |
200 if (err) | |
201 { | |
202 SDL_SetError("Can't set a mode!\n"); | |
203 ggiClose(VIS); | |
204 ggiExit(); | |
205 GGI_VideoQuit(NULL); | |
206 } | |
207 | |
208 /* Set a palette for palletized modes */ | |
209 if (GT_SCHEME(mode.graphtype) == GT_PALETTE) | |
210 { | |
211 ggiSetColorfulPalette(VIS); | |
212 ggiGetPalette(VIS, 0, 1 << vformat->BitsPerPixel, pal); | |
213 } | |
214 | |
215 /* Now we try to get the DirectBuffer info, which determines whether | |
216 * SDL can access hardware surfaces directly. */ | |
217 | |
218 num_bufs = ggiDBGetNumBuffers(VIS); | |
219 | |
220 if (num_bufs > 0) | |
221 { | |
222 db = ggiDBGetBuffer(VIS, 0); /* Only handle one DB for now */ | |
223 | |
224 vformat->BitsPerPixel = db->buffer.plb.pixelformat->depth; | |
225 | |
226 vformat->Rmask = db->buffer.plb.pixelformat->red_mask; | |
227 vformat->Gmask = db->buffer.plb.pixelformat->green_mask; | |
228 vformat->Bmask = db->buffer.plb.pixelformat->blue_mask; | |
229 | |
230 /* Fill in our hardware acceleration capabilities */ | |
231 | |
232 this->info.wm_available = 0; | |
233 this->info.hw_available = 1; | |
234 this->info.video_mem = db->buffer.plb.stride * mode.virt.y; | |
235 } | |
236 | |
237 video_mode.x = 0; | |
238 video_mode.y = 0; | |
239 video_mode.w = mode.virt.x; | |
240 video_mode.h = mode.virt.y; | |
241 SDL_modelist[((vformat->BitsPerPixel + 7) / 8) - 1] = &video_mode; | |
242 | |
243 /* We're done! */ | |
244 return(0); | |
245 } | |
246 | |
247 static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
248 { | |
249 return(&SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]); | |
250 } | |
251 | |
252 /* Various screen update functions available */ | |
253 static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
254 | |
255 SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) | |
256 { | |
257 ggi_mode mode = | |
258 { | |
259 1, | |
260 { GGI_AUTO, GGI_AUTO }, | |
261 { GGI_AUTO, GGI_AUTO }, | |
262 { 0, 0 }, | |
263 GT_AUTO, | |
264 { GGI_AUTO, GGI_AUTO } | |
265 }; | |
266 const ggi_directbuffer *db; | |
267 ggi_color pal[256]; | |
268 int err; | |
269 | |
270 fprintf(stderr, "GGI_SetVideoMode()\n"); | |
271 | |
272 mode.visible.x = mode.virt.x = width; | |
273 mode.visible.y = mode.virt.y = height; | |
274 | |
275 /* Translate requested SDL bit depth into a GGI mode */ | |
276 switch (bpp) | |
277 { | |
278 case 1: mode.graphtype = GT_1BIT; break; | |
279 case 2: mode.graphtype = GT_2BIT; break; | |
280 case 4: mode.graphtype = GT_4BIT; break; | |
281 case 8: mode.graphtype = GT_8BIT; break; | |
282 case 15: mode.graphtype = GT_15BIT; break; | |
283 case 16: mode.graphtype = GT_16BIT; break; | |
284 case 24: mode.graphtype = GT_24BIT; break; | |
285 case 32: mode.graphtype = GT_32BIT; break; | |
286 default: | |
287 SDL_SetError("Unknown SDL bit depth, using GT_AUTO....\n"); | |
288 mode.graphtype = GT_AUTO; | |
289 } | |
290 | |
291 /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ | |
292 ggiCheckMode(VIS, &mode); | |
293 | |
294 /* At this point we should have a valid mode - try to set it */ | |
295 err = ggiSetMode(VIS, &mode); | |
296 | |
297 /* If we couldn't set _any_ modes, something is very wrong */ | |
298 if (err) | |
299 { | |
300 SDL_SetError("Can't set a mode!\n"); | |
301 ggiClose(VIS); | |
302 ggiExit(); | |
303 GGI_VideoQuit(NULL); | |
304 } | |
305 | |
306 /* Set a palette for palletized modes */ | |
307 if (GT_SCHEME(mode.graphtype) == GT_PALETTE) | |
308 { | |
309 ggiSetColorfulPalette(VIS); | |
310 ggiGetPalette(VIS, 0, 1 << bpp, pal); | |
311 } | |
312 | |
313 db = ggiDBGetBuffer(VIS, 0); | |
314 | |
315 /* Set up the new mode framebuffer */ | |
316 current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); | |
317 current->w = mode.virt.x; | |
318 current->h = mode.virt.y; | |
319 current->pitch = db->buffer.plb.stride; | |
320 current->pixels = db->read; | |
321 | |
322 /* Set the blit function */ | |
323 this->UpdateRects = GGI_DirectUpdate; | |
324 | |
325 /* We're done */ | |
326 return(current); | |
327 } | |
328 | |
329 static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface) | |
330 { | |
331 return(-1); | |
332 } | |
333 static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface) | |
334 { | |
335 return; | |
336 } | |
337 static int GGI_LockHWSurface(_THIS, SDL_Surface *surface) | |
338 { | |
339 return(0); | |
340 } | |
341 static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
342 { | |
343 return; | |
344 } | |
345 | |
346 static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) | |
347 { | |
348 int i; | |
349 | |
350 /* ggiFlush(VIS); */ | |
351 | |
352 for (i = 0; i < numrects; i++) | |
353 { | |
354 ggiFlushRegion(VIS, rects[i].x, rects[i].y, rects[i].w, rects[i].h); | |
355 } | |
356 return; | |
357 } | |
358 | |
359 int GGI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
360 { | |
361 int i; | |
362 ggi_color pal[256]; | |
363 | |
364 /* Set up the colormap */ | |
365 for (i = 0; i < ncolors; i++) | |
366 { | |
367 pal[i].r = (colors[i].r << 8) | colors[i].r; | |
368 pal[i].g = (colors[i].g << 8) | colors[i].g; | |
369 pal[i].b = (colors[i].b << 8) | colors[i].b; | |
370 } | |
371 | |
372 ggiSetPalette(VIS, firstcolor, ncolors, pal); | |
373 | |
374 return 1; | |
375 } | |
376 | |
377 void GGI_VideoQuit(_THIS) | |
378 { | |
379 } | |
380 void GGI_FinalQuit(void) | |
381 { | |
382 } |