e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 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 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | /* libvga based SDL video driver implementation. |
25 | */ |
26 | |
27 | #include <err.h> |
28 | #include <osreldate.h> |
29 | #include <unistd.h> |
30 | #include <sys/stat.h> |
31 | |
32 | #include <sys/fbio.h> |
33 | #include <sys/consio.h> |
34 | #include <sys/kbio.h> |
35 | #include <vgl.h> |
36 | |
37 | #include "SDL_video.h" |
38 | #include "SDL_mouse.h" |
39 | #include "../SDL_sysvideo.h" |
40 | #include "../SDL_pixels_c.h" |
41 | #include "../../events/SDL_events_c.h" |
42 | #include "SDL_vglvideo.h" |
43 | #include "SDL_vglevents_c.h" |
44 | #include "SDL_vglmouse_c.h" |
45 | |
46 | |
47 | /* Initialization/Query functions */ |
48 | static int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat); |
49 | static SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); |
50 | static SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
51 | static int VGL_SetColors(_THIS, int firstcolor, int ncolors, |
52 | SDL_Color *colors); |
53 | static void VGL_VideoQuit(_THIS); |
54 | |
55 | /* Hardware surface functions */ |
56 | static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface); |
57 | static int VGL_LockHWSurface(_THIS, SDL_Surface *surface); |
58 | static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface); |
59 | static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface); |
60 | static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface); |
61 | |
62 | /* Misc function */ |
63 | static VGLMode ** VGLListModes(int depth, int mem_model); |
64 | static void VGLWaitRetrace(void); |
65 | |
66 | /* VGL driver bootstrap functions */ |
67 | |
68 | static int VGL_Available(void) |
69 | { |
70 | /* |
71 | * Check to see if we are root and stdin is a |
72 | * virtual console. Also try to ensure that |
73 | * modes other than 320x200 are available |
74 | */ |
75 | int console, hires_available, i; |
76 | VGLMode **modes; |
77 | |
78 | console = STDIN_FILENO; |
79 | if ( console >= 0 ) { |
80 | struct stat sb; |
81 | struct vt_mode dummy; |
82 | |
83 | if ( (fstat(console, &sb) < 0) || |
84 | (ioctl(console, VT_GETMODE, &dummy) < 0) ) { |
85 | console = -1; |
86 | } |
87 | } |
88 | if (geteuid() != 0 && console == -1) |
89 | return 0; |
90 | |
91 | modes = VGLListModes(8, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); |
92 | hires_available = 0; |
93 | for (i = 0; modes[i] != NULL; i++) { |
94 | if ((modes[i]->ModeInfo.Xsize > 320) && |
95 | (modes[i]->ModeInfo.Ysize > 200) && |
96 | ((modes[i]->ModeInfo.Type == VIDBUF8) || |
97 | (modes[i]->ModeInfo.Type == VIDBUF16) || |
98 | (modes[i]->ModeInfo.Type == VIDBUF32))) { |
99 | hires_available = 1; |
100 | break; |
101 | } |
102 | } |
103 | return hires_available; |
104 | } |
105 | |
106 | static void VGL_DeleteDevice(SDL_VideoDevice *device) |
107 | { |
108 | SDL_free(device->hidden); |
109 | SDL_free(device); |
110 | } |
111 | |
112 | static SDL_VideoDevice *VGL_CreateDevice(int devindex) |
113 | { |
114 | SDL_VideoDevice *device; |
115 | |
116 | /* Initialize all variables that we clean on shutdown */ |
117 | device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); |
118 | if ( device ) { |
119 | SDL_memset(device, 0, (sizeof *device)); |
120 | device->hidden = (struct SDL_PrivateVideoData *) |
121 | SDL_malloc((sizeof *device->hidden)); |
122 | } |
123 | if ( (device == NULL) || (device->hidden == NULL) ) { |
124 | SDL_OutOfMemory(); |
125 | if ( device ) { |
126 | SDL_free(device); |
127 | } |
128 | return(0); |
129 | } |
130 | SDL_memset(device->hidden, 0, (sizeof *device->hidden)); |
131 | |
132 | /* Set the function pointers */ |
133 | device->VideoInit = VGL_VideoInit; |
134 | device->ListModes = VGL_ListModes; |
135 | device->SetVideoMode = VGL_SetVideoMode; |
136 | device->SetColors = VGL_SetColors; |
137 | device->UpdateRects = NULL; |
138 | device->VideoQuit = VGL_VideoQuit; |
139 | device->AllocHWSurface = VGL_AllocHWSurface; |
140 | device->CheckHWBlit = NULL; |
141 | device->FillHWRect = NULL; |
142 | device->SetHWColorKey = NULL; |
143 | device->SetHWAlpha = NULL; |
144 | device->LockHWSurface = VGL_LockHWSurface; |
145 | device->UnlockHWSurface = VGL_UnlockHWSurface; |
146 | device->FlipHWSurface = VGL_FlipHWSurface; |
147 | device->FreeHWSurface = VGL_FreeHWSurface; |
148 | device->SetIcon = NULL; |
149 | device->SetCaption = NULL; |
150 | device->GetWMInfo = NULL; |
151 | device->FreeWMCursor = VGL_FreeWMCursor; |
152 | device->CreateWMCursor = VGL_CreateWMCursor; |
153 | device->ShowWMCursor = VGL_ShowWMCursor; |
154 | device->WarpWMCursor = VGL_WarpWMCursor; |
155 | device->InitOSKeymap = VGL_InitOSKeymap; |
156 | device->PumpEvents = VGL_PumpEvents; |
157 | |
158 | device->free = VGL_DeleteDevice; |
159 | |
160 | return device; |
161 | } |
162 | |
163 | VideoBootStrap VGL_bootstrap = { |
164 | "vgl", "FreeBSD libVGL", |
165 | VGL_Available, VGL_CreateDevice |
166 | }; |
167 | |
168 | static int VGL_AddMode(_THIS, VGLMode *inmode) |
169 | { |
170 | SDL_Rect *mode; |
171 | |
172 | int i, index; |
173 | int next_mode; |
174 | |
175 | /* Check to see if we already have this mode */ |
176 | if (inmode->Depth < 8) { /* Not supported */ |
177 | return 0; |
178 | } |
179 | index = ((inmode->Depth + 7) / 8) - 1; |
180 | for (i=0; i<SDL_nummodes[index]; ++i) { |
181 | mode = SDL_modelist[index][i]; |
182 | if ((mode->w == inmode->ModeInfo.Xsize) && |
183 | (mode->h == inmode->ModeInfo.Ysize)) |
184 | return 0; |
185 | } |
186 | |
187 | /* Set up the new video mode rectangle */ |
188 | mode = (SDL_Rect *)SDL_malloc(sizeof *mode); |
189 | if (mode == NULL) { |
190 | SDL_OutOfMemory(); |
191 | return -1; |
192 | } |
193 | mode->x = 0; |
194 | mode->y = 0; |
195 | mode->w = inmode->ModeInfo.Xsize; |
196 | mode->h = inmode->ModeInfo.Ysize; |
197 | |
198 | /* Allocate the new list of modes, and fill in the new mode */ |
199 | next_mode = SDL_nummodes[index]; |
200 | SDL_modelist[index] = (SDL_Rect **) |
201 | SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); |
202 | if (SDL_modelist[index] == NULL) { |
203 | SDL_OutOfMemory(); |
204 | SDL_nummodes[index] = 0; |
205 | SDL_free(mode); |
206 | return -1; |
207 | } |
208 | SDL_modelist[index][next_mode] = mode; |
209 | SDL_modelist[index][next_mode+1] = NULL; |
210 | SDL_nummodes[index]++; |
211 | |
212 | return 0; |
213 | } |
214 | |
215 | static void VGL_UpdateVideoInfo(_THIS) |
216 | { |
217 | this->info.wm_available = 0; |
218 | this->info.hw_available = 1; |
219 | this->info.video_mem = 0; |
220 | if (VGLCurMode == NULL) { |
221 | return; |
222 | } |
223 | if (VGLCurMode->ModeInfo.PixelBytes > 0) { |
224 | this->info.video_mem = VGLCurMode->ModeInfo.PixelBytes * |
225 | VGLCurMode->ModeInfo.Xsize * |
226 | VGLCurMode->ModeInfo.Ysize; |
227 | } |
228 | } |
229 | |
230 | int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat) |
231 | { |
232 | int i; |
233 | int total_modes; |
234 | VGLMode **modes; |
235 | |
236 | /* Initialize all variables that we clean on shutdown */ |
237 | for ( i=0; i<NUM_MODELISTS; ++i ) { |
238 | SDL_nummodes[i] = 0; |
239 | SDL_modelist[i] = NULL; |
240 | } |
241 | |
242 | /* Enable mouse and keyboard support */ |
243 | if (SDL_getenv("SDL_NO_RAWKBD") == NULL) { |
244 | if (VGLKeyboardInit(VGL_CODEKEYS) != 0) { |
245 | SDL_SetError("Unable to initialize keyboard"); |
246 | return -1; |
247 | } |
248 | } else { |
249 | warnx("Requiest to put keyboard into a raw mode ignored"); |
250 | } |
251 | if (VGL_initkeymaps(STDIN_FILENO) != 0) { |
252 | SDL_SetError("Unable to initialize keymap"); |
253 | return -1; |
254 | } |
255 | if (VGL_initmouse(STDIN_FILENO) != 0) { |
256 | SDL_SetError("Unable to initialize mouse"); |
257 | return -1; |
258 | } |
259 | |
260 | /* Determine the current screen size */ |
261 | if (VGLCurMode != NULL) { |
262 | this->info.current_w = VGLCurMode->ModeInfo.Xsize; |
263 | this->info.current_h = VGLCurMode->ModeInfo.Ysize; |
264 | } |
265 | |
266 | /* Determine the screen depth */ |
267 | if (VGLCurMode != NULL) |
268 | vformat->BitsPerPixel = VGLCurMode->Depth; |
269 | else |
270 | vformat->BitsPerPixel = 16; /* Good default */ |
271 | |
272 | /* Query for the list of available video modes */ |
273 | total_modes = 0; |
274 | modes = VGLListModes(-1, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); |
275 | for (i = 0; modes[i] != NULL; i++) { |
276 | if ((modes[i]->ModeInfo.Type == VIDBUF8) || |
277 | (modes[i]->ModeInfo.Type == VIDBUF16) || |
278 | (modes[i]->ModeInfo.Type == VIDBUF32)) { |
279 | VGL_AddMode(this, modes[i]); |
280 | total_modes++; |
281 | } |
282 | } |
283 | if (total_modes == 0) { |
284 | SDL_SetError("No linear video modes available"); |
285 | return -1; |
286 | } |
287 | |
288 | /* Fill in our hardware acceleration capabilities */ |
289 | VGL_UpdateVideoInfo(this); |
290 | |
291 | /* Create the hardware surface lock mutex */ |
292 | hw_lock = SDL_CreateMutex(); |
293 | if (hw_lock == NULL) { |
294 | SDL_SetError("Unable to create lock mutex"); |
295 | VGL_VideoQuit(this); |
296 | return -1; |
297 | } |
298 | |
299 | /* We're done! */ |
300 | return 0; |
301 | } |
302 | |
303 | SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
304 | { |
305 | return SDL_modelist[((format->BitsPerPixel+7)/8)-1]; |
306 | } |
307 | |
308 | /* Various screen update functions available */ |
309 | static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); |
310 | static void VGL_BankedUpdate(_THIS, int numrects, SDL_Rect *rects); |
311 | |
312 | SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, |
313 | int width, int height, int bpp, Uint32 flags) |
314 | { |
315 | int mode_found; |
316 | int i; |
317 | VGLMode **modes; |
318 | |
319 | modes = VGLListModes(bpp, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); |
320 | mode_found = 0; |
321 | for (i = 0; modes[i] != NULL; i++) { |
322 | if ((modes[i]->ModeInfo.Xsize == width) && |
323 | (modes[i]->ModeInfo.Ysize == height) && |
324 | ((modes[i]->ModeInfo.Type == VIDBUF8) || |
325 | (modes[i]->ModeInfo.Type == VIDBUF16) || |
326 | (modes[i]->ModeInfo.Type == VIDBUF32))) { |
327 | mode_found = 1; |
328 | break; |
329 | } |
330 | } |
331 | if (mode_found == 0) { |
332 | SDL_SetError("No matching video mode found"); |
333 | return NULL; |
334 | } |
335 | |
336 | /* Shutdown previous videomode (if any) */ |
337 | if (VGLCurMode != NULL) |
338 | VGLEnd(); |
339 | |
340 | /* Try to set the requested linear video mode */ |
341 | if (VGLInit(modes[i]->ModeId) != 0) { |
342 | SDL_SetError("Unable to switch to requested mode"); |
343 | return NULL; |
344 | } |
345 | |
346 | VGLCurMode = SDL_realloc(VGLCurMode, sizeof(VGLMode)); |
347 | VGLCurMode->ModeInfo = *VGLDisplay; |
348 | VGLCurMode->Depth = modes[i]->Depth; |
349 | VGLCurMode->ModeId = modes[i]->ModeId; |
350 | VGLCurMode->Rmask = modes[i]->Rmask; |
351 | VGLCurMode->Gmask = modes[i]->Gmask; |
352 | VGLCurMode->Bmask = modes[i]->Bmask; |
353 | |
354 | /* Workaround a bug in libvgl */ |
355 | if (VGLCurMode->ModeInfo.PixelBytes == 0) |
356 | (VGLCurMode->ModeInfo.PixelBytes = 1); |
357 | |
358 | current->w = VGLCurMode->ModeInfo.Xsize; |
359 | current->h = VGLCurMode->ModeInfo.Ysize; |
360 | current->pixels = VGLCurMode->ModeInfo.Bitmap; |
361 | current->pitch = VGLCurMode->ModeInfo.Xsize * |
362 | VGLCurMode->ModeInfo.PixelBytes; |
363 | current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); |
364 | |
365 | /* Check if we are in a pseudo-color mode */ |
366 | if (VGLCurMode->ModeInfo.Type == VIDBUF8) |
367 | current->flags |= SDL_HWPALETTE; |
368 | |
369 | /* Check if we can do doublebuffering */ |
370 | if (flags & SDL_DOUBLEBUF) { |
371 | if (VGLCurMode->ModeInfo.Xsize * 2 <= |
372 | VGLCurMode->ModeInfo.VYsize) { |
373 | current->flags |= SDL_DOUBLEBUF; |
374 | flip_page = 0; |
375 | flip_address[0] = (byte *)current->pixels; |
376 | flip_address[1] = (byte *)current->pixels + |
377 | current->h * current->pitch; |
378 | VGL_FlipHWSurface(this, current); |
379 | } |
380 | } |
381 | |
382 | if (! SDL_ReallocFormat(current, modes[i]->Depth, VGLCurMode->Rmask, |
383 | VGLCurMode->Gmask, VGLCurMode->Bmask, 0)) { |
384 | return NULL; |
385 | } |
386 | |
387 | /* Update hardware acceleration info */ |
388 | VGL_UpdateVideoInfo(this); |
389 | |
390 | /* Set the blit function */ |
391 | this->UpdateRects = VGL_DirectUpdate; |
392 | |
393 | /* We're done */ |
394 | return current; |
395 | } |
396 | |
397 | /* We don't actually allow hardware surfaces other than the main one */ |
398 | static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface) |
399 | { |
400 | return -1; |
401 | } |
402 | static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface) |
403 | { |
404 | return; |
405 | } |
406 | |
407 | /* We need to wait for vertical retrace on page flipped displays */ |
408 | static int VGL_LockHWSurface(_THIS, SDL_Surface *surface) |
409 | { |
410 | if (surface == SDL_VideoSurface) { |
411 | SDL_mutexP(hw_lock); |
412 | } |
413 | return 0; |
414 | } |
415 | static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface) |
416 | { |
417 | if (surface == SDL_VideoSurface) { |
418 | SDL_mutexV(hw_lock); |
419 | } |
420 | } |
421 | |
422 | static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface) |
423 | { |
424 | // VGLWaitRetrace(); |
425 | if (VGLPanScreen(VGLDisplay, 0, flip_page * surface->h) < 0) { |
426 | SDL_SetError("VGLPanSreen() failed"); |
427 | return -1; |
428 | } |
429 | |
430 | flip_page = !flip_page; |
431 | surface->pixels = flip_address[flip_page]; |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) |
437 | { |
438 | return; |
439 | } |
440 | |
441 | static void VGL_BankedUpdate(_THIS, int numrects, SDL_Rect *rects) |
442 | { |
443 | return; |
444 | } |
445 | |
446 | int VGL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
447 | { |
448 | int i; |
449 | |
450 | for(i = 0; i < ncolors; i++) { |
451 | VGLSetPaletteIndex(firstcolor + i, |
452 | colors[i].r>>2, |
453 | colors[i].g>>2, |
454 | colors[i].b>>2); |
455 | } |
456 | return 1; |
457 | } |
458 | |
459 | /* Note: If we are terminated, this could be called in the middle of |
460 | another SDL video routine -- notably UpdateRects. |
461 | */ |
462 | void VGL_VideoQuit(_THIS) |
463 | { |
464 | int i, j; |
465 | |
466 | /* Return the keyboard to the normal state */ |
467 | VGLKeyboardEnd(); |
468 | |
469 | /* Reset the console video mode if we actually initialised one */ |
470 | if (VGLCurMode != NULL) { |
471 | VGLEnd(); |
472 | SDL_free(VGLCurMode); |
473 | VGLCurMode = NULL; |
474 | } |
475 | |
476 | /* Clear the lock mutex */ |
477 | if (hw_lock != NULL) { |
478 | SDL_DestroyMutex(hw_lock); |
479 | hw_lock = NULL; |
480 | } |
481 | |
482 | /* Free video mode lists */ |
483 | for (i = 0; i < NUM_MODELISTS; i++) { |
484 | if (SDL_modelist[i] != NULL) { |
485 | for (j = 0; SDL_modelist[i][j] != NULL; ++j) { |
486 | SDL_free(SDL_modelist[i][j]); |
487 | } |
488 | SDL_free(SDL_modelist[i]); |
489 | SDL_modelist[i] = NULL; |
490 | } |
491 | } |
492 | |
493 | if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { |
494 | /* Direct screen access, not a memory buffer */ |
495 | this->screen->pixels = NULL; |
496 | } |
497 | } |
498 | |
499 | #define VGL_RED_INDEX 0 |
500 | #define VGL_GREEN_INDEX 1 |
501 | #define VGL_BLUE_INDEX 2 |
502 | |
503 | static VGLMode ** |
504 | VGLListModes(int depth, int mem_model) |
505 | { |
506 | static VGLMode **modes = NULL; |
507 | |
508 | VGLBitmap *vminfop; |
509 | VGLMode **modesp, *modescp; |
510 | video_info_t minfo; |
511 | int adptype, i, modenum; |
512 | |
513 | if (modes == NULL) { |
514 | modes = SDL_malloc(sizeof(VGLMode *) * M_VESA_MODE_MAX); |
515 | bzero(modes, sizeof(VGLMode *) * M_VESA_MODE_MAX); |
516 | } |
517 | modesp = modes; |
518 | |
519 | for (modenum = 0; modenum < M_VESA_MODE_MAX; modenum++) { |
520 | minfo.vi_mode = modenum; |
521 | if (ioctl(0, CONS_MODEINFO, &minfo) || ioctl(0, CONS_CURRENT, &adptype)) |
522 | continue; |
523 | if (minfo.vi_mode != modenum) |
524 | continue; |
525 | if ((minfo.vi_flags & V_INFO_GRAPHICS) == 0) |
526 | continue; |
527 | if ((mem_model != -1) && ((minfo.vi_mem_model & mem_model) == 0)) |
528 | continue; |
529 | if ((depth > 1) && (minfo.vi_depth != depth)) |
530 | continue; |
531 | |
532 | /* reallocf can fail */ |
533 | if ((*modesp = reallocf(*modesp, sizeof(VGLMode))) == NULL) |
534 | return NULL; |
535 | modescp = *modesp; |
536 | |
537 | vminfop = &(modescp->ModeInfo); |
538 | bzero(vminfop, sizeof(VGLBitmap)); |
539 | |
540 | vminfop->Type = NOBUF; |
541 | |
542 | vminfop->PixelBytes = 1; /* Good default value */ |
543 | switch (minfo.vi_mem_model) { |
544 | case V_INFO_MM_PLANAR: |
545 | /* we can handle EGA/VGA planar modes only */ |
546 | if (!(minfo.vi_depth != 4 || minfo.vi_planes != 4 |
547 | || (adptype != KD_EGA && adptype != KD_VGA))) |
548 | vminfop->Type = VIDBUF4; |
549 | break; |
550 | case V_INFO_MM_PACKED: |
551 | /* we can do only 256 color packed modes */ |
552 | if (minfo.vi_depth == 8) |
553 | vminfop->Type = VIDBUF8; |
554 | break; |
555 | case V_INFO_MM_VGAX: |
556 | vminfop->Type = VIDBUF8X; |
557 | break; |
558 | #if defined(__FREEBSD__) && (defined(__DragonFly__) || __FreeBSD_version >= 500000) |
559 | case V_INFO_MM_DIRECT: |
560 | vminfop->PixelBytes = minfo.vi_pixel_size; |
561 | switch (vminfop->PixelBytes) { |
562 | case 2: |
563 | vminfop->Type = VIDBUF16; |
564 | break; |
565 | #if notyet |
566 | case 3: |
567 | vminfop->Type = VIDBUF24; |
568 | break; |
569 | #endif |
570 | case 4: |
571 | vminfop->Type = VIDBUF32; |
572 | break; |
573 | default: |
574 | break; |
575 | } |
576 | #endif |
577 | default: |
578 | break; |
579 | } |
580 | if (vminfop->Type == NOBUF) |
581 | continue; |
582 | |
583 | switch (vminfop->Type) { |
584 | case VIDBUF16: |
585 | case VIDBUF32: |
586 | modescp->Rmask = ((1 << minfo.vi_pixel_fsizes[VGL_RED_INDEX]) - 1) << |
587 | minfo.vi_pixel_fields[VGL_RED_INDEX]; |
588 | modescp->Gmask = ((1 << minfo.vi_pixel_fsizes[VGL_GREEN_INDEX]) - 1) << |
589 | minfo.vi_pixel_fields[VGL_GREEN_INDEX]; |
590 | modescp->Bmask = ((1 << minfo.vi_pixel_fsizes[VGL_BLUE_INDEX]) - 1) << |
591 | minfo.vi_pixel_fields[VGL_BLUE_INDEX]; |
592 | break; |
593 | |
594 | default: |
595 | break; |
596 | } |
597 | |
598 | vminfop->Xsize = minfo.vi_width; |
599 | vminfop->Ysize = minfo.vi_height; |
600 | modescp->Depth = minfo.vi_depth; |
601 | |
602 | /* XXX */ |
603 | if (minfo.vi_mode >= M_VESA_BASE) |
604 | modescp->ModeId = _IO('V', minfo.vi_mode - M_VESA_BASE); |
605 | else |
606 | modescp->ModeId = _IO('S', minfo.vi_mode); |
607 | |
608 | /* Sort list */ |
609 | for (i = 0; modes + i < modesp ; i++) { |
610 | if (modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize > |
611 | vminfop->Xsize * modes[i]->ModeInfo.Ysize) |
612 | continue; |
613 | if ((modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize == |
614 | vminfop->Xsize * vminfop->Ysize) && |
615 | (modes[i]->Depth >= modescp->Depth)) |
616 | continue; |
617 | *modesp = modes[i]; |
618 | modes[i] = modescp; |
619 | modescp = *modesp; |
620 | vminfop = &(modescp->ModeInfo); |
621 | } |
622 | |
623 | modesp++; |
624 | } |
625 | |
626 | if (*modesp != NULL) { |
627 | SDL_free(*modesp); |
628 | *modesp = NULL; |
629 | } |
630 | |
631 | return modes; |
632 | } |
633 | |
634 | static void |
635 | VGLWaitRetrace(void) |
636 | { |
637 | while (!(inb(0x3DA) & 8)); |
638 | while (inb(0x3DA) & 8); |
639 | } |
640 | |