Mercurial > sdl-ios-xcode
annotate src/video/fbcon/SDL_fbvideo.c @ 937:1e6366bde299
Date: Tue, 27 Jul 2004 17:14:00 +0200
From: "Eckhard Stolberg"
Subject: Controller names in SDL for Windows
I'm working on an Atari 2600 emulator for different systems that uses
the SDL. Some time ago someone created an adaptor that lets you use
your old Atari controllers with your computer through the USB port.
Some of the Atari controllers require special handling by the emulator,
so it would be nice, if it would be possible to detect if any of the
controllers connected to the computer is this adaptor.
SDL would allow that with the SDL_JoystickName function, but unfortunately
it doesn't work properly on Windows. On Linux and MacOSX this function
returns the name of the controller, but on Windows you'll only get the
name of the joystick driver. Most joysticks nowadays use the generic
Microsoft driver, so they all return the same name.
In an old MSDN article
(http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarinput/html/msdn_extdirect.asp)
Microsoft describes how to read out the OEM controller names from the registry.
I have implemented this for the SDL controller handler on Windows,
and now reading the joystick name works properly there too.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 21 Aug 2004 03:45:58 +0000 |
parents | b8d311d90021 |
children | 5095c4a264aa |
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:
487
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:
133
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Framebuffer console based SDL video driver implementation. | |
29 */ | |
30 | |
31 #include <stdlib.h> | |
32 #include <stdio.h> | |
33 #include <string.h> | |
34 #include <fcntl.h> | |
35 #include <unistd.h> | |
36 #include <sys/ioctl.h> | |
37 #include <sys/mman.h> | |
38 #include <asm/page.h> /* For definition of PAGE_SIZE */ | |
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_fbvideo.h" | |
48 #include "SDL_fbmouse_c.h" | |
49 #include "SDL_fbevents_c.h" | |
50 #include "SDL_fb3dfx.h" | |
51 #include "SDL_fbmatrox.h" | |
133
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
52 #include "SDL_fbriva.h" |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
53 |
0 | 54 |
55 #if defined(i386) && defined(FB_TYPE_VGA_PLANES) | |
56 #define VGA16_FBCON_SUPPORT | |
57 #ifndef FB_AUX_VGA_PLANES_VGA4 | |
58 #define FB_AUX_VGA_PLANES_VGA4 0 | |
59 #endif | |
60 static inline void outb (unsigned char value, unsigned short port) | |
61 { | |
62 __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port)); | |
63 } | |
64 #endif /* FB_TYPE_VGA_PLANES */ | |
65 | |
66 /* A list of video resolutions that we query for (sorted largest to smallest) */ | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
6
diff
changeset
|
67 static const SDL_Rect checkres[] = { |
0 | 68 { 0, 0, 1600, 1200 }, /* 16 bpp: 0x11E, or 286 */ |
69 { 0, 0, 1408, 1056 }, /* 16 bpp: 0x19A, or 410 */ | |
70 { 0, 0, 1280, 1024 }, /* 16 bpp: 0x11A, or 282 */ | |
71 { 0, 0, 1152, 864 }, /* 16 bpp: 0x192, or 402 */ | |
72 { 0, 0, 1024, 768 }, /* 16 bpp: 0x117, or 279 */ | |
73 { 0, 0, 960, 720 }, /* 16 bpp: 0x18A, or 394 */ | |
74 { 0, 0, 800, 600 }, /* 16 bpp: 0x114, or 276 */ | |
75 { 0, 0, 768, 576 }, /* 16 bpp: 0x182, or 386 */ | |
330
5fed858d551c
Date: 03 Apr 2002 15:28:09 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
76 { 0, 0, 720, 576 }, /* PAL */ |
5fed858d551c
Date: 03 Apr 2002 15:28:09 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
77 { 0, 0, 720, 480 }, /* NTSC */ |
0 | 78 { 0, 0, 640, 480 }, /* 16 bpp: 0x111, or 273 */ |
79 { 0, 0, 640, 400 }, /* 8 bpp: 0x100, or 256 */ | |
80 { 0, 0, 512, 384 }, | |
81 { 0, 0, 320, 240 }, | |
82 { 0, 0, 320, 200 } | |
83 }; | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
6
diff
changeset
|
84 static const struct { |
0 | 85 int xres; |
86 int yres; | |
87 int pixclock; | |
88 int left; | |
89 int right; | |
90 int upper; | |
91 int lower; | |
92 int hslen; | |
93 int vslen; | |
94 int sync; | |
95 int vmode; | |
96 } vesa_timings[] = { | |
97 #ifdef USE_VESA_TIMINGS /* Only tested on Matrox Millenium I */ | |
98 { 640, 400, 39771, 48, 16, 39, 8, 96, 2, 2, 0 }, /* 70 Hz */ | |
99 { 640, 480, 39683, 48, 16, 33, 10, 96, 2, 0, 0 }, /* 60 Hz */ | |
100 { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ | |
101 { 800, 600, 24038, 144, 24, 28, 8, 112, 6, 0, 0 }, /* 60 Hz */ | |
102 { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ | |
103 { 1024, 768, 15386, 160, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ | |
104 { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ | |
105 { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ | |
106 { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ | |
107 { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ | |
108 #else | |
109 /* You can generate these timings from your XF86Config file using | |
110 the 'modeline2fb' perl script included with the fbset package. | |
111 These timings were generated for Matrox Millenium I, 15" monitor. | |
112 */ | |
113 { 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, 2 }, /* 70 Hz */ | |
114 { 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, 2 }, /* 72 Hz */ | |
115 { 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, 0 }, /* 78 Hz */ | |
116 { 640, 400, 31746, 96, 32, 41, 1, 64, 3, 2, 0 }, /* 85 Hz */ | |
117 { 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0 }, /* 75 Hz */ | |
118 { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ | |
119 { 800, 600, 20000, 64, 56, 23, 37, 120, 6, 3, 0 }, /* 72 Hz */ | |
120 { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ | |
121 { 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, 0 }, /* 70 Hz */ | |
122 { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ | |
123 { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ | |
124 { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ | |
125 { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ | |
126 #endif | |
127 }; | |
128 | |
129 /* Initialization/Query functions */ | |
130 static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
131 static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
132 static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
133 #ifdef VGA16_FBCON_SUPPORT | |
134 static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
135 #endif | |
136 static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
137 static void FB_VideoQuit(_THIS); | |
138 | |
139 /* Hardware surface functions */ | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
140 static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size); |
0 | 141 static void FB_FreeHWSurfaces(_THIS); |
142 static int FB_AllocHWSurface(_THIS, SDL_Surface *surface); | |
143 static int FB_LockHWSurface(_THIS, SDL_Surface *surface); | |
144 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
145 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface); | |
146 static void FB_WaitVBL(_THIS); | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
147 static void FB_WaitIdle(_THIS); |
0 | 148 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface); |
149 | |
150 /* Internal palette functions */ | |
151 static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, | |
152 struct fb_var_screeninfo *vinfo); | |
153 static void FB_RestorePalette(_THIS); | |
154 | |
155 /* FB driver bootstrap functions */ | |
156 | |
157 static int FB_Available(void) | |
158 { | |
159 int console; | |
160 const char *SDL_fbdev; | |
161 | |
162 SDL_fbdev = getenv("SDL_FBDEV"); | |
163 if ( SDL_fbdev == NULL ) { | |
164 SDL_fbdev = "/dev/fb0"; | |
165 } | |
166 console = open(SDL_fbdev, O_RDWR, 0); | |
167 if ( console >= 0 ) { | |
168 close(console); | |
169 } | |
170 return(console >= 0); | |
171 } | |
172 | |
173 static void FB_DeleteDevice(SDL_VideoDevice *device) | |
174 { | |
175 free(device->hidden); | |
176 free(device); | |
177 } | |
178 | |
179 static SDL_VideoDevice *FB_CreateDevice(int devindex) | |
180 { | |
181 SDL_VideoDevice *this; | |
182 | |
183 /* Initialize all variables that we clean on shutdown */ | |
184 this = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
185 if ( this ) { | |
186 memset(this, 0, (sizeof *this)); | |
187 this->hidden = (struct SDL_PrivateVideoData *) | |
188 malloc((sizeof *this->hidden)); | |
189 } | |
190 if ( (this == NULL) || (this->hidden == NULL) ) { | |
191 SDL_OutOfMemory(); | |
192 if ( this ) { | |
193 free(this); | |
194 } | |
195 return(0); | |
196 } | |
197 memset(this->hidden, 0, (sizeof *this->hidden)); | |
198 wait_vbl = FB_WaitVBL; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
199 wait_idle = FB_WaitIdle; |
0 | 200 mouse_fd = -1; |
201 keyboard_fd = -1; | |
202 | |
203 /* Set the function pointers */ | |
204 this->VideoInit = FB_VideoInit; | |
205 this->ListModes = FB_ListModes; | |
206 this->SetVideoMode = FB_SetVideoMode; | |
207 this->SetColors = FB_SetColors; | |
208 this->UpdateRects = NULL; | |
209 this->VideoQuit = FB_VideoQuit; | |
210 this->AllocHWSurface = FB_AllocHWSurface; | |
211 this->CheckHWBlit = NULL; | |
212 this->FillHWRect = NULL; | |
213 this->SetHWColorKey = NULL; | |
214 this->SetHWAlpha = NULL; | |
215 this->LockHWSurface = FB_LockHWSurface; | |
216 this->UnlockHWSurface = FB_UnlockHWSurface; | |
217 this->FlipHWSurface = FB_FlipHWSurface; | |
218 this->FreeHWSurface = FB_FreeHWSurface; | |
219 this->SetCaption = NULL; | |
220 this->SetIcon = NULL; | |
221 this->IconifyWindow = NULL; | |
222 this->GrabInput = NULL; | |
223 this->GetWMInfo = NULL; | |
224 this->InitOSKeymap = FB_InitOSKeymap; | |
225 this->PumpEvents = FB_PumpEvents; | |
226 | |
227 this->free = FB_DeleteDevice; | |
228 | |
229 return this; | |
230 } | |
231 | |
232 VideoBootStrap FBCON_bootstrap = { | |
233 "fbcon", "Linux Framebuffer Console", | |
234 FB_Available, FB_CreateDevice | |
235 }; | |
236 | |
237 static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, | |
238 int index, unsigned int *w, unsigned int *h) | |
239 { | |
240 int mode_okay; | |
241 | |
242 mode_okay = 0; | |
243 vinfo->bits_per_pixel = (index+1)*8; | |
244 vinfo->xres = *w; | |
245 vinfo->xres_virtual = *w; | |
246 vinfo->yres = *h; | |
247 vinfo->yres_virtual = *h; | |
248 vinfo->activate = FB_ACTIVATE_TEST; | |
249 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0 ) { | |
250 #ifdef FBCON_DEBUG | |
251 fprintf(stderr, "Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n", *w, *h, (index+1)*8, vinfo->xres, vinfo->yres, vinfo->bits_per_pixel); | |
252 #endif | |
253 if ( (((vinfo->bits_per_pixel+7)/8)-1) == index ) { | |
254 *w = vinfo->xres; | |
255 *h = vinfo->yres; | |
256 mode_okay = 1; | |
257 } | |
258 } | |
259 return mode_okay; | |
260 } | |
261 | |
262 static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h) | |
263 { | |
264 SDL_Rect *mode; | |
265 int i; | |
266 int next_mode; | |
267 | |
268 /* Check to see if we already have this mode */ | |
269 if ( SDL_nummodes[index] > 0 ) { | |
270 mode = SDL_modelist[index][SDL_nummodes[index]-1]; | |
271 if ( (mode->w == w) && (mode->h == h) ) { | |
272 #ifdef FBCON_DEBUG | |
273 fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); | |
274 #endif | |
275 return(0); | |
276 } | |
277 } | |
278 | |
279 /* Only allow a mode if we have a valid timing for it */ | |
6
332f458469f0
Fixed 320x200 video mode on framebuffer console
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
280 next_mode = -1; |
0 | 281 for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { |
282 if ( (w == vesa_timings[i].xres) && | |
283 (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { | |
284 next_mode = i; | |
285 break; | |
286 } | |
287 } | |
6
332f458469f0
Fixed 320x200 video mode on framebuffer console
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
288 if ( next_mode == -1 ) { |
0 | 289 #ifdef FBCON_DEBUG |
290 fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); | |
291 #endif | |
292 return(0); | |
293 } | |
294 | |
295 /* Set up the new video mode rectangle */ | |
296 mode = (SDL_Rect *)malloc(sizeof *mode); | |
297 if ( mode == NULL ) { | |
298 SDL_OutOfMemory(); | |
299 return(-1); | |
300 } | |
301 mode->x = 0; | |
302 mode->y = 0; | |
303 mode->w = w; | |
304 mode->h = h; | |
305 #ifdef FBCON_DEBUG | |
306 fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); | |
307 #endif | |
308 | |
309 /* Allocate the new list of modes, and fill in the new mode */ | |
310 next_mode = SDL_nummodes[index]; | |
311 SDL_modelist[index] = (SDL_Rect **) | |
312 realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); | |
313 if ( SDL_modelist[index] == NULL ) { | |
314 SDL_OutOfMemory(); | |
315 SDL_nummodes[index] = 0; | |
316 free(mode); | |
317 return(-1); | |
318 } | |
319 SDL_modelist[index][next_mode] = mode; | |
320 SDL_modelist[index][next_mode+1] = NULL; | |
321 SDL_nummodes[index]++; | |
322 | |
323 return(0); | |
324 } | |
325 | |
326 static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
327 { | |
328 struct fb_fix_screeninfo finfo; | |
329 struct fb_var_screeninfo vinfo; | |
330 int i, j; | |
331 int current_index; | |
332 unsigned int current_w; | |
333 unsigned int current_h; | |
334 const char *SDL_fbdev; | |
335 | |
336 /* Initialize the library */ | |
337 SDL_fbdev = getenv("SDL_FBDEV"); | |
338 if ( SDL_fbdev == NULL ) { | |
339 SDL_fbdev = "/dev/fb0"; | |
340 } | |
341 console_fd = open(SDL_fbdev, O_RDWR, 0); | |
342 if ( console_fd < 0 ) { | |
343 SDL_SetError("Unable to open %s", SDL_fbdev); | |
344 return(-1); | |
345 } | |
346 | |
347 #ifndef DISABLE_THREADS | |
348 /* Create the hardware surface lock mutex */ | |
349 hw_lock = SDL_CreateMutex(); | |
350 if ( hw_lock == NULL ) { | |
351 SDL_SetError("Unable to create lock mutex"); | |
352 FB_VideoQuit(this); | |
353 return(-1); | |
354 } | |
355 #endif | |
356 | |
357 /* Get the type of video hardware */ | |
358 if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { | |
359 SDL_SetError("Couldn't get console hardware info"); | |
360 FB_VideoQuit(this); | |
361 return(-1); | |
362 } | |
363 switch (finfo.type) { | |
364 case FB_TYPE_PACKED_PIXELS: | |
365 /* Supported, no worries.. */ | |
366 break; | |
367 #ifdef VGA16_FBCON_SUPPORT | |
368 case FB_TYPE_VGA_PLANES: | |
369 /* VGA16 is supported, but that's it */ | |
370 if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) { | |
371 if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) { | |
372 SDL_SetError("No I/O port permissions"); | |
373 FB_VideoQuit(this); | |
374 return(-1); | |
375 } | |
376 this->SetVideoMode = FB_SetVGA16Mode; | |
377 break; | |
378 } | |
379 /* Fall through to unsupported case */ | |
380 #endif /* VGA16_FBCON_SUPPORT */ | |
381 default: | |
382 SDL_SetError("Unsupported console hardware"); | |
383 FB_VideoQuit(this); | |
384 return(-1); | |
385 } | |
386 switch (finfo.visual) { | |
387 case FB_VISUAL_TRUECOLOR: | |
388 case FB_VISUAL_PSEUDOCOLOR: | |
389 case FB_VISUAL_STATIC_PSEUDOCOLOR: | |
390 case FB_VISUAL_DIRECTCOLOR: | |
391 break; | |
392 default: | |
393 SDL_SetError("Unsupported console hardware"); | |
394 FB_VideoQuit(this); | |
395 return(-1); | |
396 } | |
397 | |
398 /* Check if the user wants to disable hardware acceleration */ | |
399 { const char *fb_accel; | |
400 fb_accel = getenv("SDL_FBACCEL"); | |
401 if ( fb_accel ) { | |
402 finfo.accel = atoi(fb_accel); | |
403 } | |
404 } | |
405 | |
406 /* Memory map the device, compensating for buggy PPC mmap() */ | |
407 mapped_offset = (((long)finfo.smem_start) - | |
408 (((long)finfo.smem_start)&~(PAGE_SIZE-1))); | |
409 mapped_memlen = finfo.smem_len+mapped_offset; | |
410 mapped_mem = mmap(NULL, mapped_memlen, | |
411 PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0); | |
412 if ( mapped_mem == (char *)-1 ) { | |
413 SDL_SetError("Unable to memory map the video hardware"); | |
414 mapped_mem = NULL; | |
415 FB_VideoQuit(this); | |
416 return(-1); | |
417 } | |
418 | |
419 /* Determine the current screen depth */ | |
420 if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { | |
421 SDL_SetError("Couldn't get console pixel format"); | |
422 FB_VideoQuit(this); | |
423 return(-1); | |
424 } | |
425 vformat->BitsPerPixel = vinfo.bits_per_pixel; | |
426 if ( vformat->BitsPerPixel < 8 ) { | |
427 /* Assuming VGA16, we handle this via a shadow framebuffer */ | |
428 vformat->BitsPerPixel = 8; | |
429 } | |
430 for ( i=0; i<vinfo.red.length; ++i ) { | |
431 vformat->Rmask <<= 1; | |
432 vformat->Rmask |= (0x00000001<<vinfo.red.offset); | |
433 } | |
434 for ( i=0; i<vinfo.green.length; ++i ) { | |
435 vformat->Gmask <<= 1; | |
436 vformat->Gmask |= (0x00000001<<vinfo.green.offset); | |
437 } | |
438 for ( i=0; i<vinfo.blue.length; ++i ) { | |
439 vformat->Bmask <<= 1; | |
440 vformat->Bmask |= (0x00000001<<vinfo.blue.offset); | |
441 } | |
442 saved_vinfo = vinfo; | |
443 | |
444 /* Save hardware palette, if needed */ | |
445 FB_SavePalette(this, &finfo, &vinfo); | |
446 | |
447 /* If the I/O registers are available, memory map them so we | |
448 can take advantage of any supported hardware acceleration. | |
449 */ | |
450 vinfo.accel_flags = 0; /* Temporarily reserve registers */ | |
451 ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo); | |
452 if ( finfo.accel && finfo.mmio_len ) { | |
453 mapped_iolen = finfo.mmio_len; | |
454 mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE, | |
455 MAP_SHARED, console_fd, mapped_memlen); | |
456 if ( mapped_io == (char *)-1 ) { | |
457 /* Hmm, failed to memory map I/O registers */ | |
458 mapped_io = NULL; | |
459 } | |
460 } | |
461 | |
462 /* Query for the list of available video modes */ | |
463 current_w = vinfo.xres; | |
464 current_h = vinfo.yres; | |
465 current_index = ((vinfo.bits_per_pixel+7)/8)-1; | |
487
414d77a36716
Fixed trashing the framebuffer console on broken video drivers
Sam Lantinga <slouken@libsdl.org>
parents:
330
diff
changeset
|
466 #ifdef BROKEN_MODES |
414d77a36716
Fixed trashing the framebuffer console on broken video drivers
Sam Lantinga <slouken@libsdl.org>
parents:
330
diff
changeset
|
467 FB_AddMode(this, current_index, current_w, current_h); |
414d77a36716
Fixed trashing the framebuffer console on broken video drivers
Sam Lantinga <slouken@libsdl.org>
parents:
330
diff
changeset
|
468 #else |
0 | 469 for ( i=0; i<NUM_MODELISTS; ++i ) { |
470 SDL_nummodes[i] = 0; | |
471 SDL_modelist[i] = NULL; | |
472 for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { | |
473 unsigned int w, h; | |
474 | |
475 /* See if we are querying for the current mode */ | |
476 w = checkres[j].w; | |
477 h = checkres[j].h; | |
478 if ( i == current_index ) { | |
479 if ( (current_w > w) || (current_h > h) ) { | |
480 /* Only check once */ | |
487
414d77a36716
Fixed trashing the framebuffer console on broken video drivers
Sam Lantinga <slouken@libsdl.org>
parents:
330
diff
changeset
|
481 FB_AddMode(this, i, current_w, current_h); |
0 | 482 current_index = -1; |
483 } | |
484 } | |
485 if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { | |
486 FB_AddMode(this, i, w, h); | |
487 } | |
488 } | |
489 } | |
487
414d77a36716
Fixed trashing the framebuffer console on broken video drivers
Sam Lantinga <slouken@libsdl.org>
parents:
330
diff
changeset
|
490 #endif /* BROKEN_MODES */ |
0 | 491 |
492 /* Fill in our hardware acceleration capabilities */ | |
493 this->info.wm_available = 0; | |
494 this->info.hw_available = 1; | |
495 this->info.video_mem = finfo.smem_len/1024; | |
496 if ( mapped_io ) { | |
497 switch (finfo.accel) { | |
498 case FB_ACCEL_MATROX_MGA2064W: | |
499 case FB_ACCEL_MATROX_MGA1064SG: | |
500 case FB_ACCEL_MATROX_MGA2164W: | |
501 case FB_ACCEL_MATROX_MGA2164W_AGP: | |
502 case FB_ACCEL_MATROX_MGAG100: | |
503 /*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */ | |
504 case FB_ACCEL_MATROX_MGAG400: | |
505 #ifdef FBACCEL_DEBUG | |
506 printf("Matrox hardware accelerator!\n"); | |
507 #endif | |
508 FB_MatroxAccel(this, finfo.accel); | |
509 break; | |
510 case FB_ACCEL_3DFX_BANSHEE: | |
511 #ifdef FBACCEL_DEBUG | |
512 printf("3DFX hardware accelerator!\n"); | |
513 #endif | |
514 FB_3DfxAccel(this, finfo.accel); | |
515 break; | |
133
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
516 case FB_ACCEL_NV3: |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
517 case FB_ACCEL_NV4: |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
518 #ifdef FBACCEL_DEBUG |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
519 printf("NVidia hardware accelerator!\n"); |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
520 #endif |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
521 FB_RivaAccel(this, finfo.accel); |
5d4bafca35cd
Added support for hardware accelerated NVidia driver on framebuffer console
Sam Lantinga <slouken@libsdl.org>
parents:
106
diff
changeset
|
522 break; |
0 | 523 default: |
524 #ifdef FBACCEL_DEBUG | |
525 printf("Unknown hardware accelerator.\n"); | |
526 #endif | |
527 break; | |
528 } | |
529 } | |
530 | |
531 /* Enable mouse and keyboard support */ | |
532 if ( FB_OpenKeyboard(this) < 0 ) { | |
533 FB_VideoQuit(this); | |
534 return(-1); | |
535 } | |
536 if ( FB_OpenMouse(this) < 0 ) { | |
537 const char *sdl_nomouse; | |
538 | |
539 sdl_nomouse = getenv("SDL_NOMOUSE"); | |
540 if ( ! sdl_nomouse ) { | |
541 SDL_SetError("Unable to open mouse"); | |
542 FB_VideoQuit(this); | |
543 return(-1); | |
544 } | |
545 } | |
546 | |
547 /* We're done! */ | |
548 return(0); | |
549 } | |
550 | |
551 static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
552 { | |
553 return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); | |
554 } | |
555 | |
556 /* Various screen update functions available */ | |
557 static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
558 #ifdef VGA16_FBCON_SUPPORT | |
559 static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects); | |
560 #endif | |
561 | |
562 #ifdef FBCON_DEBUG | |
563 static void print_vinfo(struct fb_var_screeninfo *vinfo) | |
564 { | |
565 fprintf(stderr, "Printing vinfo:\n"); | |
566 fprintf(stderr, "\txres: %d\n", vinfo->xres); | |
567 fprintf(stderr, "\tyres: %d\n", vinfo->yres); | |
568 fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual); | |
569 fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual); | |
570 fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset); | |
571 fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset); | |
572 fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel); | |
573 fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale); | |
574 fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd); | |
575 fprintf(stderr, "\tactivate: %d\n", vinfo->activate); | |
576 fprintf(stderr, "\theight: %d\n", vinfo->height); | |
577 fprintf(stderr, "\twidth: %d\n", vinfo->width); | |
578 fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags); | |
579 fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock); | |
580 fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin); | |
581 fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin); | |
582 fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin); | |
583 fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin); | |
584 fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len); | |
585 fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len); | |
586 fprintf(stderr, "\tsync: %d\n", vinfo->sync); | |
587 fprintf(stderr, "\tvmode: %d\n", vinfo->vmode); | |
588 fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset); | |
589 fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset); | |
590 fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset); | |
591 fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset); | |
592 } | |
593 static void print_finfo(struct fb_fix_screeninfo *finfo) | |
594 { | |
595 fprintf(stderr, "Printing finfo:\n"); | |
596 fprintf(stderr, "\tsmem_start = %p\n", (char *)finfo->smem_start); | |
597 fprintf(stderr, "\tsmem_len = %d\n", finfo->smem_len); | |
598 fprintf(stderr, "\ttype = %d\n", finfo->type); | |
599 fprintf(stderr, "\ttype_aux = %d\n", finfo->type_aux); | |
600 fprintf(stderr, "\tvisual = %d\n", finfo->visual); | |
601 fprintf(stderr, "\txpanstep = %d\n", finfo->xpanstep); | |
602 fprintf(stderr, "\typanstep = %d\n", finfo->ypanstep); | |
603 fprintf(stderr, "\tywrapstep = %d\n", finfo->ywrapstep); | |
604 fprintf(stderr, "\tline_length = %d\n", finfo->line_length); | |
605 fprintf(stderr, "\tmmio_start = %p\n", (char *)finfo->mmio_start); | |
606 fprintf(stderr, "\tmmio_len = %d\n", finfo->mmio_len); | |
607 fprintf(stderr, "\taccel = %d\n", finfo->accel); | |
608 } | |
609 #endif | |
610 | |
611 static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) | |
612 { | |
613 int matched; | |
614 FILE *fbmodes; | |
615 | |
616 matched = 0; | |
617 fbmodes = fopen("/etc/fb.modes", "r"); | |
618 if ( fbmodes ) { | |
619 /* FIXME: Parse the mode definition file */ | |
620 fclose(fbmodes); | |
621 } | |
622 return(matched); | |
623 } | |
624 | |
625 static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) | |
626 { | |
627 int matched; | |
628 int i; | |
629 | |
630 /* Check for VESA timings */ | |
631 matched = 0; | |
632 for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { | |
633 if ( (vinfo->xres == vesa_timings[i].xres) && | |
634 (vinfo->yres == vesa_timings[i].yres) ) { | |
635 #ifdef FBCON_DEBUG | |
636 fprintf(stderr, "Using VESA timings for %dx%d\n", | |
637 vinfo->xres, vinfo->yres); | |
638 #endif | |
639 if ( vesa_timings[i].pixclock ) { | |
640 vinfo->pixclock = vesa_timings[i].pixclock; | |
641 } | |
642 vinfo->left_margin = vesa_timings[i].left; | |
643 vinfo->right_margin = vesa_timings[i].right; | |
644 vinfo->upper_margin = vesa_timings[i].upper; | |
645 vinfo->lower_margin = vesa_timings[i].lower; | |
646 vinfo->hsync_len = vesa_timings[i].hslen; | |
647 vinfo->vsync_len = vesa_timings[i].vslen; | |
648 vinfo->sync = vesa_timings[i].sync; | |
649 vinfo->vmode = vesa_timings[i].vmode; | |
650 matched = 1; | |
651 break; | |
652 } | |
653 } | |
654 return(matched); | |
655 } | |
656 | |
657 #ifdef VGA16_FBCON_SUPPORT | |
658 static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, | |
659 int width, int height, int bpp, Uint32 flags) | |
660 { | |
661 struct fb_fix_screeninfo finfo; | |
662 struct fb_var_screeninfo vinfo; | |
663 | |
664 /* Set the terminal into graphics mode */ | |
665 if ( FB_EnterGraphicsMode(this) < 0 ) { | |
666 return(NULL); | |
667 } | |
668 | |
669 /* Restore the original palette */ | |
670 FB_RestorePalette(this); | |
671 | |
672 /* Set the video mode and get the final screen format */ | |
673 if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { | |
674 SDL_SetError("Couldn't get console screen info"); | |
675 return(NULL); | |
676 } | |
677 cache_vinfo = vinfo; | |
678 #ifdef FBCON_DEBUG | |
679 fprintf(stderr, "Printing actual vinfo:\n"); | |
680 print_vinfo(&vinfo); | |
681 #endif | |
682 if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { | |
683 return(NULL); | |
684 } | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
685 current->format->palette->ncolors = 16; |
0 | 686 |
687 /* Get the fixed information about the console hardware. | |
688 This is necessary since finfo.line_length changes. | |
689 */ | |
690 if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { | |
691 SDL_SetError("Couldn't get console hardware info"); | |
692 return(NULL); | |
693 } | |
694 #ifdef FBCON_DEBUG | |
695 fprintf(stderr, "Printing actual finfo:\n"); | |
696 print_finfo(&finfo); | |
697 #endif | |
698 | |
699 /* Save hardware palette, if needed */ | |
700 FB_SavePalette(this, &finfo, &vinfo); | |
701 | |
702 /* Set up the new mode framebuffer */ | |
703 current->flags = SDL_FULLSCREEN; | |
704 current->w = vinfo.xres; | |
705 current->h = vinfo.yres; | |
706 current->pitch = current->w; | |
707 current->pixels = malloc(current->h*current->pitch); | |
708 | |
709 /* Set the update rectangle function */ | |
710 this->UpdateRects = FB_VGA16Update; | |
711 | |
712 /* We're done */ | |
713 return(current); | |
714 } | |
715 #endif /* VGA16_FBCON_SUPPORT */ | |
716 | |
717 static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, | |
718 int width, int height, int bpp, Uint32 flags) | |
719 { | |
720 struct fb_fix_screeninfo finfo; | |
721 struct fb_var_screeninfo vinfo; | |
722 int i; | |
723 Uint32 Rmask; | |
724 Uint32 Gmask; | |
725 Uint32 Bmask; | |
726 char *surfaces_mem; | |
727 int surfaces_len; | |
728 | |
729 /* Set the terminal into graphics mode */ | |
730 if ( FB_EnterGraphicsMode(this) < 0 ) { | |
731 return(NULL); | |
732 } | |
733 | |
734 /* Restore the original palette */ | |
735 FB_RestorePalette(this); | |
736 | |
737 /* Set the video mode and get the final screen format */ | |
738 if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { | |
739 SDL_SetError("Couldn't get console screen info"); | |
740 return(NULL); | |
741 } | |
742 #ifdef FBCON_DEBUG | |
743 fprintf(stderr, "Printing original vinfo:\n"); | |
744 print_vinfo(&vinfo); | |
745 #endif | |
746 if ( (vinfo.xres != width) || (vinfo.yres != height) || | |
747 (vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF) ) { | |
748 vinfo.activate = FB_ACTIVATE_NOW; | |
749 vinfo.accel_flags = 0; | |
750 vinfo.bits_per_pixel = bpp; | |
751 vinfo.xres = width; | |
752 vinfo.xres_virtual = width; | |
753 vinfo.yres = height; | |
754 if ( flags & SDL_DOUBLEBUF ) { | |
755 vinfo.yres_virtual = height*2; | |
756 } else { | |
757 vinfo.yres_virtual = height; | |
758 } | |
759 vinfo.xoffset = 0; | |
760 vinfo.yoffset = 0; | |
761 vinfo.red.length = vinfo.red.offset = 0; | |
762 vinfo.green.length = vinfo.green.offset = 0; | |
763 vinfo.blue.length = vinfo.blue.offset = 0; | |
764 vinfo.transp.length = vinfo.transp.offset = 0; | |
765 if ( ! choose_fbmodes_mode(&vinfo) ) { | |
766 choose_vesa_mode(&vinfo); | |
767 } | |
768 #ifdef FBCON_DEBUG | |
769 fprintf(stderr, "Printing wanted vinfo:\n"); | |
770 print_vinfo(&vinfo); | |
771 #endif | |
772 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { | |
773 vinfo.yres_virtual = height; | |
774 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { | |
775 SDL_SetError("Couldn't set console screen info"); | |
776 return(NULL); | |
777 } | |
778 } | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
779 } else { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
780 int maxheight; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
781 |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
782 /* Figure out how much video memory is available */ |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
783 if ( flags & SDL_DOUBLEBUF ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
784 maxheight = height*2; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
785 } else { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
786 maxheight = height; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
787 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
788 if ( vinfo.yres_virtual > maxheight ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
789 vinfo.yres_virtual = maxheight; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
790 } |
0 | 791 } |
792 cache_vinfo = vinfo; | |
793 #ifdef FBCON_DEBUG | |
794 fprintf(stderr, "Printing actual vinfo:\n"); | |
795 print_vinfo(&vinfo); | |
796 #endif | |
797 Rmask = 0; | |
798 for ( i=0; i<vinfo.red.length; ++i ) { | |
799 Rmask <<= 1; | |
800 Rmask |= (0x00000001<<vinfo.red.offset); | |
801 } | |
802 Gmask = 0; | |
803 for ( i=0; i<vinfo.green.length; ++i ) { | |
804 Gmask <<= 1; | |
805 Gmask |= (0x00000001<<vinfo.green.offset); | |
806 } | |
807 Bmask = 0; | |
808 for ( i=0; i<vinfo.blue.length; ++i ) { | |
809 Bmask <<= 1; | |
810 Bmask |= (0x00000001<<vinfo.blue.offset); | |
811 } | |
812 if ( ! SDL_ReallocFormat(current, vinfo.bits_per_pixel, | |
813 Rmask, Gmask, Bmask, 0) ) { | |
814 return(NULL); | |
815 } | |
816 | |
817 /* Get the fixed information about the console hardware. | |
818 This is necessary since finfo.line_length changes. | |
819 */ | |
820 if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { | |
821 SDL_SetError("Couldn't get console hardware info"); | |
822 return(NULL); | |
823 } | |
824 | |
825 /* Save hardware palette, if needed */ | |
826 FB_SavePalette(this, &finfo, &vinfo); | |
827 | |
828 /* Set up the new mode framebuffer */ | |
829 current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); | |
830 current->w = vinfo.xres; | |
831 current->h = vinfo.yres; | |
832 current->pitch = finfo.line_length; | |
833 current->pixels = mapped_mem+mapped_offset; | |
834 | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
835 /* Set up the information for hardware surfaces */ |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
836 surfaces_mem = (char *)current->pixels + |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
837 vinfo.yres_virtual*current->pitch; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
838 surfaces_len = (mapped_memlen-(surfaces_mem-mapped_mem)); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
839 FB_FreeHWSurfaces(this); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
840 FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
841 |
0 | 842 /* Let the application know we have a hardware palette */ |
843 switch (finfo.visual) { | |
844 case FB_VISUAL_PSEUDOCOLOR: | |
845 current->flags |= SDL_HWPALETTE; | |
846 break; | |
847 default: | |
848 break; | |
849 } | |
850 | |
851 /* Update for double-buffering, if we can */ | |
852 if ( flags & SDL_DOUBLEBUF ) { | |
853 if ( vinfo.yres_virtual == (height*2) ) { | |
854 current->flags |= SDL_DOUBLEBUF; | |
855 flip_page = 0; | |
856 flip_address[0] = (char *)current->pixels; | |
857 flip_address[1] = (char *)current->pixels+ | |
858 current->h*current->pitch; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
859 this->screen = current; |
0 | 860 FB_FlipHWSurface(this, current); |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
861 this->screen = NULL; |
0 | 862 } |
863 } | |
864 | |
865 /* Set the update rectangle function */ | |
866 this->UpdateRects = FB_DirectUpdate; | |
867 | |
868 /* We're done */ | |
869 return(current); | |
870 } | |
871 | |
872 #ifdef FBCON_DEBUG | |
873 void FB_DumpHWSurfaces(_THIS) | |
874 { | |
875 vidmem_bucket *bucket; | |
876 | |
877 printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); | |
878 printf("\n"); | |
879 printf(" Base Size\n"); | |
880 for ( bucket=&surfaces; bucket; bucket=bucket->next ) { | |
881 printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); | |
882 if ( bucket->prev ) { | |
883 if ( bucket->base != bucket->prev->base+bucket->prev->size ) { | |
884 printf("Warning, corrupt bucket list! (prev)\n"); | |
885 } | |
886 } else { | |
887 if ( bucket != &surfaces ) { | |
888 printf("Warning, corrupt bucket list! (!prev)\n"); | |
889 } | |
890 } | |
891 if ( bucket->next ) { | |
892 if ( bucket->next->base != bucket->base+bucket->size ) { | |
893 printf("Warning, corrupt bucket list! (next)\n"); | |
894 } | |
895 } | |
896 } | |
897 printf("\n"); | |
898 } | |
899 #endif | |
900 | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
901 static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size) |
0 | 902 { |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
903 vidmem_bucket *bucket; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
904 |
0 | 905 surfaces_memtotal = size; |
906 surfaces_memleft = size; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
907 |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
908 if ( surfaces_memleft > 0 ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
909 bucket = (vidmem_bucket *)malloc(sizeof(*bucket)); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
910 if ( bucket == NULL ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
911 SDL_OutOfMemory(); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
912 return(-1); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
913 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
914 bucket->prev = &surfaces; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
915 bucket->used = 0; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
916 bucket->dirty = 0; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
917 bucket->base = base; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
918 bucket->size = size; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
919 bucket->next = NULL; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
920 } else { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
921 bucket = NULL; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
922 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
923 |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
924 surfaces.prev = NULL; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
925 surfaces.used = 1; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
926 surfaces.dirty = 0; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
927 surfaces.base = screen->pixels; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
928 surfaces.size = (unsigned int)((long)base - (long)surfaces.base); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
929 surfaces.next = bucket; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
930 screen->hwdata = (struct private_hwdata *)&surfaces; |
0 | 931 return(0); |
932 } | |
933 static void FB_FreeHWSurfaces(_THIS) | |
934 { | |
935 vidmem_bucket *bucket, *freeable; | |
936 | |
937 bucket = surfaces.next; | |
938 while ( bucket ) { | |
939 freeable = bucket; | |
940 bucket = bucket->next; | |
941 free(freeable); | |
942 } | |
943 surfaces.next = NULL; | |
944 } | |
945 | |
946 static int FB_AllocHWSurface(_THIS, SDL_Surface *surface) | |
947 { | |
948 vidmem_bucket *bucket; | |
949 int size; | |
950 int extra; | |
951 | |
952 /* Temporarily, we only allow surfaces the same width as display. | |
953 Some blitters require the pitch between two hardware surfaces | |
954 to be the same. Others have interesting alignment restrictions. | |
955 Until someone who knows these details looks at the code... | |
956 */ | |
957 if ( surface->pitch > SDL_VideoSurface->pitch ) { | |
958 SDL_SetError("Surface requested wider than screen"); | |
959 return(-1); | |
960 } | |
961 surface->pitch = SDL_VideoSurface->pitch; | |
962 size = surface->h * surface->pitch; | |
963 #ifdef FBCON_DEBUG | |
964 fprintf(stderr, "Allocating bucket of %d bytes\n", size); | |
965 #endif | |
966 | |
967 /* Quick check for available mem */ | |
968 if ( size > surfaces_memleft ) { | |
969 SDL_SetError("Not enough video memory"); | |
970 return(-1); | |
971 } | |
972 | |
973 /* Search for an empty bucket big enough */ | |
974 for ( bucket=&surfaces; bucket; bucket=bucket->next ) { | |
975 if ( ! bucket->used && (size <= bucket->size) ) { | |
976 break; | |
977 } | |
978 } | |
979 if ( bucket == NULL ) { | |
980 SDL_SetError("Video memory too fragmented"); | |
981 return(-1); | |
982 } | |
983 | |
984 /* Create a new bucket for left-over memory */ | |
985 extra = (bucket->size - size); | |
986 if ( extra ) { | |
987 vidmem_bucket *newbucket; | |
988 | |
989 #ifdef FBCON_DEBUG | |
990 fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); | |
991 #endif | |
992 newbucket = (vidmem_bucket *)malloc(sizeof(*newbucket)); | |
993 if ( newbucket == NULL ) { | |
994 SDL_OutOfMemory(); | |
995 return(-1); | |
996 } | |
997 newbucket->prev = bucket; | |
998 newbucket->used = 0; | |
999 newbucket->base = bucket->base+size; | |
1000 newbucket->size = extra; | |
1001 newbucket->next = bucket->next; | |
1002 if ( bucket->next ) { | |
1003 bucket->next->prev = newbucket; | |
1004 } | |
1005 bucket->next = newbucket; | |
1006 } | |
1007 | |
1008 /* Set the current bucket values and return it! */ | |
1009 bucket->used = 1; | |
1010 bucket->size = size; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1011 bucket->dirty = 0; |
0 | 1012 #ifdef FBCON_DEBUG |
1013 fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); | |
1014 #endif | |
1015 surfaces_memleft -= size; | |
1016 surface->flags |= SDL_HWSURFACE; | |
1017 surface->pixels = bucket->base; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1018 surface->hwdata = (struct private_hwdata *)bucket; |
0 | 1019 return(0); |
1020 } | |
1021 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface) | |
1022 { | |
1023 vidmem_bucket *bucket, *freeable; | |
1024 | |
1025 /* Look for the bucket in the current list */ | |
1026 for ( bucket=&surfaces; bucket; bucket=bucket->next ) { | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1027 if ( bucket == (vidmem_bucket *)surface->hwdata ) { |
0 | 1028 break; |
1029 } | |
1030 } | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1031 if ( bucket && bucket->used ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1032 /* Add the memory back to the total */ |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1033 #ifdef DGA_DEBUG |
0 | 1034 printf("Freeing bucket of %d bytes\n", bucket->size); |
1035 #endif | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1036 surfaces_memleft += bucket->size; |
0 | 1037 |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1038 /* Can we merge the space with surrounding buckets? */ |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1039 bucket->used = 0; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1040 if ( bucket->next && ! bucket->next->used ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1041 #ifdef DGA_DEBUG |
0 | 1042 printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); |
1043 #endif | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1044 freeable = bucket->next; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1045 bucket->size += bucket->next->size; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1046 bucket->next = bucket->next->next; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1047 if ( bucket->next ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1048 bucket->next->prev = bucket; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1049 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1050 free(freeable); |
0 | 1051 } |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1052 if ( bucket->prev && ! bucket->prev->used ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1053 #ifdef DGA_DEBUG |
0 | 1054 printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); |
1055 #endif | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1056 freeable = bucket; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1057 bucket->prev->size += bucket->size; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1058 bucket->prev->next = bucket->next; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1059 if ( bucket->next ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1060 bucket->next->prev = bucket->prev; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1061 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1062 free(freeable); |
0 | 1063 } |
1064 } | |
1065 surface->pixels = NULL; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1066 surface->hwdata = NULL; |
0 | 1067 } |
1068 static int FB_LockHWSurface(_THIS, SDL_Surface *surface) | |
1069 { | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1070 if ( surface == this->screen ) { |
0 | 1071 SDL_mutexP(hw_lock); |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1072 if ( FB_IsSurfaceBusy(surface) ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1073 FB_WaitBusySurfaces(this); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1074 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1075 } else { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1076 if ( FB_IsSurfaceBusy(surface) ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1077 FB_WaitBusySurfaces(this); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1078 } |
0 | 1079 } |
1080 return(0); | |
1081 } | |
1082 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
1083 { | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1084 if ( surface == this->screen ) { |
0 | 1085 SDL_mutexV(hw_lock); |
1086 } | |
1087 } | |
1088 | |
1089 static void FB_WaitVBL(_THIS) | |
1090 { | |
1091 #ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */ | |
1092 ioctl(console_fd, FBIOWAITRETRACE, 0); | |
1093 #endif | |
1094 return; | |
1095 } | |
1096 | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1097 static void FB_WaitIdle(_THIS) |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1098 { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1099 return; |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1100 } |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1101 |
0 | 1102 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface) |
1103 { | |
1104 /* Wait for vertical retrace and then flip display */ | |
1105 cache_vinfo.yoffset = flip_page*surface->h; | |
106
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1106 if ( FB_IsSurfaceBusy(this->screen) ) { |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1107 FB_WaitBusySurfaces(this); |
63ec24e0575f
Merged DGA video surface handling improvements, unified locking code.
Sam Lantinga <slouken@lokigames.com>
parents:
91
diff
changeset
|
1108 } |
0 | 1109 wait_vbl(this); |
1110 if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) { | |
1111 SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed"); | |
1112 return(-1); | |
1113 } | |
1114 flip_page = !flip_page; | |
1115 | |
1116 surface->pixels = flip_address[flip_page]; | |
1117 return(0); | |
1118 } | |
1119 | |
1120 static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) | |
1121 { | |
1122 /* The application is already updating the visible video memory */ | |
1123 return; | |
1124 } | |
1125 | |
1126 #ifdef VGA16_FBCON_SUPPORT | |
1127 /* Code adapted with thanks from the XFree86 VGA16 driver! :) */ | |
1128 #define writeGr(index, value) \ | |
1129 outb(index, 0x3CE); \ | |
1130 outb(value, 0x3CF); | |
1131 #define writeSeq(index, value) \ | |
1132 outb(index, 0x3C4); \ | |
1133 outb(value, 0x3C5); | |
1134 | |
1135 static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects) | |
1136 { | |
1137 SDL_Surface *screen; | |
1138 int width, height, FBPitch, left, i, j, SRCPitch, phase; | |
1139 register Uint32 m; | |
1140 Uint8 s1, s2, s3, s4; | |
1141 Uint32 *src, *srcPtr; | |
1142 Uint8 *dst, *dstPtr; | |
1143 | |
1144 screen = this->screen; | |
1145 FBPitch = screen->w >> 3; | |
1146 SRCPitch = screen->pitch >> 2; | |
1147 | |
1148 writeGr(0x03, 0x00); | |
1149 writeGr(0x05, 0x00); | |
1150 writeGr(0x01, 0x00); | |
1151 writeGr(0x08, 0xFF); | |
1152 | |
1153 while(numrects--) { | |
1154 left = rects->x & ~7; | |
1155 width = (rects->w + 7) >> 3; | |
1156 height = rects->h; | |
1157 src = (Uint32*)screen->pixels + (rects->y * SRCPitch) + (left >> 2); | |
1158 dst = (Uint8*)mapped_mem + (rects->y * FBPitch) + (left >> 3); | |
1159 | |
1160 if((phase = (long)dst & 3L)) { | |
1161 phase = 4 - phase; | |
1162 if(phase > width) phase = width; | |
1163 width -= phase; | |
1164 } | |
1165 | |
1166 while(height--) { | |
1167 writeSeq(0x02, 1 << 0); | |
1168 dstPtr = dst; | |
1169 srcPtr = src; | |
1170 i = width; | |
1171 j = phase; | |
1172 while(j--) { | |
1173 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); | |
1174 *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1175 srcPtr += 2; | |
1176 } | |
1177 while(i >= 4) { | |
1178 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); | |
1179 s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1180 m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101) << 4); | |
1181 s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1182 m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101) << 4); | |
1183 s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1184 m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101) << 4); | |
1185 s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1186 *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); | |
1187 srcPtr += 8; | |
1188 dstPtr += 4; | |
1189 i -= 4; | |
1190 } | |
1191 while(i--) { | |
1192 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); | |
1193 *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); | |
1194 srcPtr += 2; | |
1195 } | |
1196 | |
1197 writeSeq(0x02, 1 << 1); | |
1198 dstPtr = dst; | |
1199 srcPtr = src; | |
1200 i = width; | |
1201 j = phase; | |
1202 while(j--) { | |
1203 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); | |
1204 *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1205 srcPtr += 2; | |
1206 } | |
1207 while(i >= 4) { | |
1208 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); | |
1209 s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1210 m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202) << 4); | |
1211 s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1212 m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202) << 4); | |
1213 s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1214 m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202) << 4); | |
1215 s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1216 *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); | |
1217 srcPtr += 8; | |
1218 dstPtr += 4; | |
1219 i -= 4; | |
1220 } | |
1221 while(i--) { | |
1222 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); | |
1223 *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); | |
1224 srcPtr += 2; | |
1225 } | |
1226 | |
1227 writeSeq(0x02, 1 << 2); | |
1228 dstPtr = dst; | |
1229 srcPtr = src; | |
1230 i = width; | |
1231 j = phase; | |
1232 while(j--) { | |
1233 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); | |
1234 *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1235 srcPtr += 2; | |
1236 } | |
1237 while(i >= 4) { | |
1238 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); | |
1239 s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1240 m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404) << 4); | |
1241 s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1242 m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404) << 4); | |
1243 s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1244 m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404) << 4); | |
1245 s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1246 *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); | |
1247 srcPtr += 8; | |
1248 dstPtr += 4; | |
1249 i -= 4; | |
1250 } | |
1251 while(i--) { | |
1252 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); | |
1253 *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); | |
1254 srcPtr += 2; | |
1255 } | |
1256 | |
1257 writeSeq(0x02, 1 << 3); | |
1258 dstPtr = dst; | |
1259 srcPtr = src; | |
1260 i = width; | |
1261 j = phase; | |
1262 while(j--) { | |
1263 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); | |
1264 *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1265 srcPtr += 2; | |
1266 } | |
1267 while(i >= 4) { | |
1268 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); | |
1269 s1 = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1270 m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808) << 4); | |
1271 s2 = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1272 m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808) << 4); | |
1273 s3 = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1274 m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808) << 4); | |
1275 s4 = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1276 *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); | |
1277 srcPtr += 8; | |
1278 dstPtr += 4; | |
1279 i -= 4; | |
1280 } | |
1281 while(i--) { | |
1282 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); | |
1283 *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; | |
1284 srcPtr += 2; | |
1285 } | |
1286 | |
1287 dst += FBPitch; | |
1288 src += SRCPitch; | |
1289 } | |
1290 rects++; | |
1291 } | |
1292 } | |
1293 #endif /* VGA16_FBCON_SUPPORT */ | |
1294 | |
1295 void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area) | |
1296 { | |
1297 struct fb_cmap cmap; | |
1298 | |
1299 cmap.start = 0; | |
1300 cmap.len = palette_len; | |
1301 cmap.red = &area[0*palette_len]; | |
1302 cmap.green = &area[1*palette_len]; | |
1303 cmap.blue = &area[2*palette_len]; | |
1304 cmap.transp = NULL; | |
1305 ioctl(console_fd, FBIOGETCMAP, &cmap); | |
1306 } | |
1307 | |
1308 void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area) | |
1309 { | |
1310 struct fb_cmap cmap; | |
1311 | |
1312 cmap.start = 0; | |
1313 cmap.len = palette_len; | |
1314 cmap.red = &area[0*palette_len]; | |
1315 cmap.green = &area[1*palette_len]; | |
1316 cmap.blue = &area[2*palette_len]; | |
1317 cmap.transp = NULL; | |
1318 ioctl(console_fd, FBIOPUTCMAP, &cmap); | |
1319 } | |
1320 | |
1321 static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, | |
1322 struct fb_var_screeninfo *vinfo) | |
1323 { | |
1324 int i; | |
1325 | |
1326 /* Save hardware palette, if needed */ | |
1327 if ( finfo->visual == FB_VISUAL_PSEUDOCOLOR ) { | |
1328 saved_cmaplen = 1<<vinfo->bits_per_pixel; | |
1329 saved_cmap=(__u16 *)malloc(3*saved_cmaplen*sizeof(*saved_cmap)); | |
1330 if ( saved_cmap != NULL ) { | |
1331 FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); | |
1332 } | |
1333 } | |
1334 | |
1335 /* Added support for FB_VISUAL_DIRECTCOLOR. | |
1336 With this mode pixel information is passed through the palette... | |
1337 Neat fading and gamma correction effects can be had by simply | |
1338 fooling around with the palette instead of changing the pixel | |
1339 values themselves... Very neat! | |
1340 | |
1341 Adam Meyerowitz 1/19/2000 | |
1342 ameyerow@optonline.com | |
1343 */ | |
1344 if ( finfo->visual == FB_VISUAL_DIRECTCOLOR ) { | |
1345 __u16 new_entries[3*256]; | |
1346 | |
1347 /* Save the colormap */ | |
1348 saved_cmaplen = 256; | |
1349 saved_cmap=(__u16 *)malloc(3*saved_cmaplen*sizeof(*saved_cmap)); | |
1350 if ( saved_cmap != NULL ) { | |
1351 FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); | |
1352 } | |
1353 | |
1354 /* Allocate new identity colormap */ | |
1355 for ( i=0; i<256; ++i ) { | |
1356 new_entries[(0*256)+i] = | |
1357 new_entries[(1*256)+i] = | |
1358 new_entries[(2*256)+i] = (i<<8)|i; | |
1359 } | |
1360 FB_RestorePaletteFrom(this, 256, new_entries); | |
1361 } | |
1362 } | |
1363 | |
1364 static void FB_RestorePalette(_THIS) | |
1365 { | |
1366 /* Restore the original palette */ | |
1367 if ( saved_cmap ) { | |
1368 FB_RestorePaletteFrom(this, saved_cmaplen, saved_cmap); | |
1369 free(saved_cmap); | |
1370 saved_cmap = NULL; | |
1371 } | |
1372 } | |
1373 | |
1374 static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
1375 { | |
1376 int i; | |
1377 __u16 r[256]; | |
1378 __u16 g[256]; | |
1379 __u16 b[256]; | |
1380 struct fb_cmap cmap; | |
1381 | |
1382 /* Set up the colormap */ | |
1383 for (i = 0; i < ncolors; i++) { | |
1384 r[i] = colors[i].r << 8; | |
1385 g[i] = colors[i].g << 8; | |
1386 b[i] = colors[i].b << 8; | |
1387 } | |
1388 cmap.start = firstcolor; | |
1389 cmap.len = ncolors; | |
1390 cmap.red = r; | |
1391 cmap.green = g; | |
1392 cmap.blue = b; | |
1393 cmap.transp = NULL; | |
1394 | |
1395 if( (ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) || | |
1396 !(this->screen->flags & SDL_HWPALETTE) ) { | |
1397 colors = this->screen->format->palette->colors; | |
1398 ncolors = this->screen->format->palette->ncolors; | |
1399 cmap.start = 0; | |
1400 cmap.len = ncolors; | |
1401 memset(r, 0, sizeof(r)); | |
1402 memset(g, 0, sizeof(g)); | |
1403 memset(b, 0, sizeof(b)); | |
1404 if ( ioctl(console_fd, FBIOGETCMAP, &cmap) == 0 ) { | |
1405 for ( i=ncolors-1; i>=0; --i ) { | |
1406 colors[i].r = (r[i]>>8); | |
1407 colors[i].g = (g[i]>>8); | |
1408 colors[i].b = (b[i]>>8); | |
1409 } | |
1410 } | |
1411 return(0); | |
1412 } | |
1413 return(1); | |
1414 } | |
1415 | |
1416 /* Note: If we are terminated, this could be called in the middle of | |
1417 another SDL video routine -- notably UpdateRects. | |
1418 */ | |
1419 static void FB_VideoQuit(_THIS) | |
1420 { | |
1421 int i, j; | |
1422 | |
1423 if ( this->screen ) { | |
1424 /* Clear screen and tell SDL not to free the pixels */ | |
1425 if ( this->screen->pixels && FB_InGraphicsMode(this) ) { | |
1426 #ifdef __powerpc__ /* SIGBUS when using memset() ?? */ | |
1427 Uint8 *rowp = (Uint8 *)this->screen->pixels; | |
1428 int left = this->screen->pitch*this->screen->h; | |
1429 while ( left-- ) { *rowp++ = 0; } | |
1430 #else | |
1431 memset(this->screen->pixels,0,this->screen->h*this->screen->pitch); | |
1432 #endif | |
1433 } | |
1434 /* This test fails when using the VGA16 shadow memory */ | |
1435 if ( ((char *)this->screen->pixels >= mapped_mem) && | |
1436 ((char *)this->screen->pixels < (mapped_mem+mapped_memlen)) ) { | |
1437 this->screen->pixels = NULL; | |
1438 } | |
1439 } | |
1440 | |
1441 /* Clear the lock mutex */ | |
1442 if ( hw_lock ) { | |
1443 SDL_DestroyMutex(hw_lock); | |
1444 hw_lock = NULL; | |
1445 } | |
1446 | |
1447 /* Clean up defined video modes */ | |
1448 for ( i=0; i<NUM_MODELISTS; ++i ) { | |
1449 if ( SDL_modelist[i] != NULL ) { | |
1450 for ( j=0; SDL_modelist[i][j]; ++j ) { | |
1451 free(SDL_modelist[i][j]); | |
1452 } | |
1453 free(SDL_modelist[i]); | |
1454 SDL_modelist[i] = NULL; | |
1455 } | |
1456 } | |
1457 | |
1458 /* Clean up the memory bucket list */ | |
1459 FB_FreeHWSurfaces(this); | |
1460 | |
1461 /* Close console and input file descriptors */ | |
1462 if ( console_fd > 0 ) { | |
1463 /* Unmap the video framebuffer and I/O registers */ | |
1464 if ( mapped_mem ) { | |
1465 munmap(mapped_mem, mapped_memlen); | |
1466 mapped_mem = NULL; | |
1467 } | |
1468 if ( mapped_io ) { | |
1469 munmap(mapped_io, mapped_iolen); | |
1470 mapped_io = NULL; | |
1471 } | |
1472 | |
1473 /* Restore the original video mode and palette */ | |
1474 if ( FB_InGraphicsMode(this) ) { | |
1475 FB_RestorePalette(this); | |
1476 ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo); | |
1477 } | |
1478 | |
1479 /* We're all done with the framebuffer */ | |
1480 close(console_fd); | |
1481 console_fd = -1; | |
1482 } | |
1483 FB_CloseMouse(this); | |
1484 FB_CloseKeyboard(this); | |
1485 } |