src/video/svga/SDL_svgavideo.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SVGA_Available
  2. SVGA_DeleteDevice
  3. SVGA_CreateDevice
  4. SVGA_AddMode
  5. SVGA_UpdateVideoInfo
  6. SVGA_VideoInit
  7. SVGA_ListModes
  8. SVGA_SetVideoMode
  9. SVGA_AllocHWSurface
  10. SVGA_FreeHWSurface
  11. SVGA_LockHWSurface
  12. SVGA_UnlockHWSurface
  13. SVGA_FlipHWSurface
  14. SVGA_DirectUpdate
  15. SVGA_BankedUpdate
  16. SVGA_SetColors
  17. SVGA_VideoQuit

   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: SDL_svgavideo.c,v 1.1.2.11 2001/02/10 07:20:07 hercules Exp $";
  26 #endif
  27 
  28 /* SVGAlib based SDL video driver implementation.
  29 */
  30 
  31 #include <stdlib.h>
  32 #include <stdio.h>
  33 #include <unistd.h>
  34 #include <sys/stat.h>
  35 
  36 #if defined(linux)
  37 #include <linux/vt.h>
  38 #elif defined(__FreeBSD__)
  39 #include <sys/consio.h>
  40 #else
  41 #error You must choose your operating system here
  42 #endif
  43 #include <vga.h>
  44 #include <vgamouse.h>
  45 #include <vgakeyboard.h>
  46 
  47 #include "SDL.h"
  48 #include "SDL_error.h"
  49 #include "SDL_video.h"
  50 #include "SDL_mouse.h"
  51 #include "SDL_sysvideo.h"
  52 #include "SDL_pixels_c.h"
  53 #include "SDL_events_c.h"
  54 #include "SDL_svgavideo.h"
  55 #include "SDL_svgaevents_c.h"
  56 #include "SDL_svgamouse_c.h"
  57 
  58 
  59 /* Initialization/Query functions */
  60 static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat);
  61 static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
  62 static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
  63 static int SVGA_SetColors(_THIS, int firstcolor, int ncolors,
  64                           SDL_Color *colors);
  65 static void SVGA_VideoQuit(_THIS);
  66 
  67 /* Hardware surface functions */
  68 static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface);
  69 static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface);
  70 static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface);
  71 static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface);
  72 static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface);
  73 
  74 /* SVGAlib driver bootstrap functions */
  75 
  76 static int SVGA_Available(void)
     /* [<][>][^][v][top][bottom][index][help] */
  77 {
  78         /* Check to see if we are root and stdin is a virtual console */
  79         int console;
  80 
  81         console = STDIN_FILENO;
  82         if ( console >= 0 ) {
  83                 struct stat sb;
  84                 struct vt_mode dummy;
  85 
  86                 if ( (fstat(console, &sb) < 0) ||
  87                      (ioctl(console, VT_GETMODE, &dummy) < 0) ) {
  88                         console = -1;
  89                 }
  90         }
  91         return((geteuid() == 0) && (console >= 0));
  92 }
  93 
  94 static void SVGA_DeleteDevice(SDL_VideoDevice *device)
     /* [<][>][^][v][top][bottom][index][help] */
  95 {
  96         free(device->hidden);
  97         free(device);
  98 }
  99 
 100 static SDL_VideoDevice *SVGA_CreateDevice(int devindex)
     /* [<][>][^][v][top][bottom][index][help] */
 101 {
 102         SDL_VideoDevice *device;
 103 
 104         /* Initialize all variables that we clean on shutdown */
 105         device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
 106         if ( device ) {
 107                 memset(device, 0, (sizeof *device));
 108                 device->hidden = (struct SDL_PrivateVideoData *)
 109                                 malloc((sizeof *device->hidden));
 110         }
 111         if ( (device == NULL) || (device->hidden == NULL) ) {
 112                 SDL_OutOfMemory();
 113                 if ( device ) {
 114                         free(device);
 115                 }
 116                 return(0);
 117         }
 118         memset(device->hidden, 0, (sizeof *device->hidden));
 119 
 120         /* Set the function pointers */
 121         device->VideoInit = SVGA_VideoInit;
 122         device->ListModes = SVGA_ListModes;
 123         device->SetVideoMode = SVGA_SetVideoMode;
 124         device->SetColors = SVGA_SetColors;
 125         device->UpdateRects = NULL;
 126         device->VideoQuit = SVGA_VideoQuit;
 127         device->AllocHWSurface = SVGA_AllocHWSurface;
 128         device->CheckHWBlit = NULL;
 129         device->FillHWRect = NULL;
 130         device->SetHWColorKey = NULL;
 131         device->SetHWAlpha = NULL;
 132         device->LockHWSurface = SVGA_LockHWSurface;
 133         device->UnlockHWSurface = SVGA_UnlockHWSurface;
 134         device->FlipHWSurface = NULL;
 135         device->FreeHWSurface = SVGA_FreeHWSurface;
 136         device->SetCaption = NULL;
 137         device->SetIcon = NULL;
 138         device->IconifyWindow = NULL;
 139         device->GrabInput = NULL;
 140         device->GetWMInfo = NULL;
 141         device->InitOSKeymap = SVGA_InitOSKeymap;
 142         device->PumpEvents = SVGA_PumpEvents;
 143 
 144         device->free = SVGA_DeleteDevice;
 145 
 146         return device;
 147 }
 148 
 149 VideoBootStrap SVGALIB_bootstrap = {
 150         "svgalib", "SVGAlib",
 151         SVGA_Available, SVGA_CreateDevice
 152 };
 153 
 154 static int SVGA_AddMode(_THIS, int mode, int actually_add, int force)
     /* [<][>][^][v][top][bottom][index][help] */
 155 {
 156         vga_modeinfo *modeinfo;
 157 
 158         modeinfo = vga_getmodeinfo(mode);
 159         if ( force || ( modeinfo->flags & CAPABLE_LINEAR ) ) {
 160                 int i, j;
 161 
 162                 i = modeinfo->bytesperpixel-1;
 163                 if ( actually_add ) {
 164                         SDL_Rect saved_rect[2];
 165                         int      saved_mode[2];
 166                         int b;
 167 
 168                         /* Add the mode, sorted largest to smallest */
 169                         b = 0;
 170                         j = 0;
 171                         while ( (SDL_modelist[i][j]->w > modeinfo->width) ||
 172                                 (SDL_modelist[i][j]->h > modeinfo->height) ) {
 173                                 ++j;
 174                         }
 175                         /* Skip modes that are already in our list */
 176                         if ( (SDL_modelist[i][j]->w == modeinfo->width) &&
 177                              (SDL_modelist[i][j]->h == modeinfo->height) ) {
 178                                 return(0);
 179                         }
 180                         /* Insert the new mode */
 181                         saved_rect[b] = *SDL_modelist[i][j];
 182                         saved_mode[b] = SDL_vgamode[i][j];
 183                         SDL_modelist[i][j]->w = modeinfo->width;
 184                         SDL_modelist[i][j]->h = modeinfo->height;
 185                         SDL_vgamode[i][j] = mode;
 186                         /* Everybody scoot down! */
 187                         if ( saved_rect[b].w && saved_rect[b].h ) {
 188                             for ( ++j; SDL_modelist[i][j]->w; ++j ) {
 189                                 saved_rect[!b] = *SDL_modelist[i][j];
 190                                 saved_mode[!b] = SDL_vgamode[i][j];
 191                                 *SDL_modelist[i][j] = saved_rect[b];
 192                                 SDL_vgamode[i][j] = saved_mode[b];
 193                                 b = !b;
 194                             }
 195                             *SDL_modelist[i][j] = saved_rect[b];
 196                             SDL_vgamode[i][j] = saved_mode[b];
 197                         }
 198                 } else {
 199                         ++SDL_nummodes[i];
 200                 }
 201         }
 202         return( force || ( modeinfo->flags & CAPABLE_LINEAR ) );
 203 }
 204 
 205 static void SVGA_UpdateVideoInfo(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 206 {
 207         vga_modeinfo *modeinfo;
 208 
 209         this->info.wm_available = 0;
 210         this->info.hw_available = 1;
 211         modeinfo = vga_getmodeinfo(vga_getcurrentmode());
 212         this->info.video_mem = (modeinfo->maxpixels/1024);
 213         if ( modeinfo->bytesperpixel > 0 ) {
 214                 this->info.video_mem *= modeinfo->bytesperpixel;
 215         }
 216         /* FIXME: Add hardware accelerated blit information */
 217 #if 0
 218 printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not ");
 219 #endif
 220 }
 221 
 222 int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat)
     /* [<][>][^][v][top][bottom][index][help] */
 223 {
 224         int keyboard;
 225         int i, j;
 226         int mode, total_modes;
 227 
 228         /* Initialize all variables that we clean on shutdown */
 229         for ( i=0; i<NUM_MODELISTS; ++i ) {
 230                 SDL_nummodes[i] = 0;
 231                 SDL_modelist[i] = NULL;
 232                 SDL_vgamode[i] = NULL;
 233         }
 234 
 235         /* Initialize the library */
 236         vga_disabledriverreport();
 237         if ( vga_init() < 0 ) {
 238                 SDL_SetError("Unable to initialize SVGAlib");
 239                 return(-1);
 240         }
 241         vga_setmode(TEXT);
 242 
 243         /* Enable mouse and keyboard support */
 244         vga_setmousesupport(1);
 245         keyboard = keyboard_init_return_fd();
 246         if ( keyboard < 0 ) {
 247                 SDL_SetError("Unable to initialize keyboard");
 248                 return(-1);
 249         }
 250         if ( SVGA_initkeymaps(keyboard) < 0 ) {
 251                 return(-1);
 252         }
 253         keyboard_seteventhandler(SVGA_keyboardcallback);
 254 
 255         /* Determine the screen depth (use default 8-bit depth) */
 256         vformat->BitsPerPixel = 8;
 257 
 258         /* Enumerate the available fullscreen modes */
 259         total_modes = 0;
 260         for ( mode=vga_lastmodenumber(); mode; --mode ) {
 261                 if ( vga_hasmode(mode) ) {
 262                         if ( SVGA_AddMode(this, mode, 0, 0) ) {
 263                                 ++total_modes;
 264                         }
 265                 }
 266         }
 267         if ( SVGA_AddMode(this, G320x200x256, 0, 1) ) ++total_modes;
 268         if ( total_modes == 0 ) {
 269                 SDL_SetError("No linear video modes available");
 270                 return(-1);
 271         }
 272         for ( i=0; i<NUM_MODELISTS; ++i ) {
 273                 SDL_vgamode[i] = (int *)malloc(SDL_nummodes[i]*sizeof(int));
 274                 if ( SDL_vgamode[i] == NULL ) {
 275                         SDL_OutOfMemory();
 276                         return(-1);
 277                 }
 278                 SDL_modelist[i] = (SDL_Rect **)
 279                                 malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
 280                 if ( SDL_modelist[i] == NULL ) {
 281                         SDL_OutOfMemory();
 282                         return(-1);
 283                 }
 284                 for ( j=0; j<SDL_nummodes[i]; ++j ) {
 285                         SDL_modelist[i][j]=(SDL_Rect *)malloc(sizeof(SDL_Rect));
 286                         if ( SDL_modelist[i][j] == NULL ) {
 287                                 SDL_OutOfMemory();
 288                                 return(-1);
 289                         }
 290                         memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect));
 291                 }
 292                 SDL_modelist[i][j] = NULL;
 293         }
 294         for ( mode=vga_lastmodenumber(); mode; --mode ) {
 295                 if ( vga_hasmode(mode) ) {
 296                         SVGA_AddMode(this, mode, 1, 0);
 297                 }
 298         }
 299         SVGA_AddMode(this, G320x200x256, 1, 1);
 300 
 301         /* Free extra (duplicated) modes */
 302         for ( i=0; i<NUM_MODELISTS; ++i ) {
 303                 j = 0;
 304                 while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) {
 305                         j++;
 306                 }
 307                 while ( SDL_modelist[i][j] ) {
 308                         free(SDL_modelist[i][j]);
 309                         SDL_modelist[i][j] = NULL;
 310                         j++;
 311                 }
 312         }
 313 
 314         /* Fill in our hardware acceleration capabilities */
 315         SVGA_UpdateVideoInfo(this);
 316 
 317         /* We're done! */
 318         return(0);
 319 }
 320 
 321 SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
     /* [<][>][^][v][top][bottom][index][help] */
 322 {
 323         return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
 324 }
 325 
 326 /* Various screen update functions available */
 327 static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
 328 static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects);
 329 
 330 SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current,
     /* [<][>][^][v][top][bottom][index][help] */
 331                                 int width, int height, int bpp, Uint32 flags)
 332 {
 333         int mode;
 334         int vgamode;
 335         vga_modeinfo *modeinfo;
 336 
 337         /* Try to set the requested linear video mode */
 338         bpp = (bpp+7)/8-1;
 339         for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) {
 340                 if ( (SDL_modelist[bpp][mode]->w == width) &&
 341                      (SDL_modelist[bpp][mode]->h == height) ) {
 342                         break;
 343                 }
 344         }
 345         if ( SDL_modelist[bpp][mode] == NULL ) {
 346                 SDL_SetError("Couldn't find requested mode in list");
 347                 return(NULL);
 348         }
 349         vga_setmode(SDL_vgamode[bpp][mode]);
 350         vga_setpage(0);
 351 
 352         vgamode=SDL_vgamode[bpp][mode];
 353         if ((vga_setlinearaddressing()<0) && (vgamode!=G320x200x256)) {
 354                 SDL_SetError("Unable to set linear addressing");
 355                 return(NULL);
 356         }
 357         modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]);
 358 
 359         /* Update hardware acceleration info */
 360         SVGA_UpdateVideoInfo(this);
 361 
 362         /* Allocate the new pixel format for the screen */
 363         bpp = (bpp+1)*8;
 364         if ( (bpp == 16) && (modeinfo->colors == 32768) ) {
 365                 bpp = 15;
 366         }
 367         if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
 368                 return(NULL);
 369         }
 370 
 371         /* Set up the new mode framebuffer */
 372         current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
 373         current->w = width;
 374         current->h = height;
 375         current->pitch = modeinfo->linewidth;
 376         current->pixels = vga_getgraphmem();
 377 
 378         /* Set the blit function */
 379         this->UpdateRects = SVGA_DirectUpdate;
 380 
 381         /* Set up the mouse handler again (buggy SVGAlib 1.40) */
 382         mouse_seteventhandler(SVGA_mousecallback);
 383 
 384         /* We're done */
 385         return(current);
 386 }
 387 
 388 /* We don't actually allow hardware surfaces other than the main one */
 389 static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 390 {
 391         return(-1);
 392 }
 393 static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395         return;
 396 }
 397 
 398 /* We need to wait for vertical retrace on page flipped displays */
 399 static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 400 {
 401         if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
 402                 vga_waitretrace();
 403         }
 404         return(0);
 405 }
 406 static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 407 {
 408         return;
 409 }
 410 
 411 /* FIXME: How is this done with SVGAlib? */
 412 static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 413 {
 414         return(0);
 415 }
 416 
 417 static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
     /* [<][>][^][v][top][bottom][index][help] */
 418 {
 419         return;
 420 }
 421 
 422 /* FIXME: Can this be used under SVGAlib? */
 423 static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects)
     /* [<][>][^][v][top][bottom][index][help] */
 424 {
 425         return;
 426 }
 427 
 428 int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
     /* [<][>][^][v][top][bottom][index][help] */
 429 {
 430         int i;
 431 
 432         for(i = 0; i < ncolors; i++) {
 433                 vga_setpalette(firstcolor + i,
 434                                colors[i].r>>2,
 435                                colors[i].g>>2,
 436                                colors[i].b>>2);
 437         }
 438         return(1);
 439 }
 440 
 441 /* Note:  If we are terminated, this could be called in the middle of
 442    another SDL video routine -- notably UpdateRects.
 443 */
 444 void SVGA_VideoQuit(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 445 {
 446         int i, j;
 447 
 448         /* Reset the console video mode */
 449         if ( this->screen && (this->screen->w && this->screen->h) ) {
 450                 vga_setmode(TEXT);
 451         }
 452         keyboard_close();
 453 
 454         /* Free video mode lists */
 455         for ( i=0; i<NUM_MODELISTS; ++i ) {
 456                 if ( SDL_modelist[i] != NULL ) {
 457                         for ( j=0; SDL_modelist[i][j]; ++j )
 458                                 free(SDL_modelist[i][j]);
 459                         free(SDL_modelist[i]);
 460                         SDL_modelist[i] = NULL;
 461                 }
 462                 if ( SDL_vgamode[i] != NULL ) {
 463                         free(SDL_vgamode[i]);
 464                         SDL_vgamode[i] = NULL;
 465                 }
 466         }
 467         if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
 468                 /* Direct screen access, no memory buffer */
 469                 this->screen->pixels = NULL;
 470         }
 471 }

/* [<][>][^][v][top][bottom][index][help] */