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