src/video/svga/SDL_svgavideo.c
changeset 0 74212992fb08
child 1 cf2af46e9e2a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/svga/SDL_svgavideo.c	Thu Apr 26 16:45:43 2001 +0000
     1.3 @@ -0,0 +1,471 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@devolution.com
    1.24 +*/
    1.25 +
    1.26 +#ifdef SAVE_RCSID
    1.27 +static char rcsid =
    1.28 + "@(#) $Id$";
    1.29 +#endif
    1.30 +
    1.31 +/* SVGAlib based SDL video driver implementation.
    1.32 +*/
    1.33 +
    1.34 +#include <stdlib.h>
    1.35 +#include <stdio.h>
    1.36 +#include <unistd.h>
    1.37 +#include <sys/stat.h>
    1.38 +
    1.39 +#if defined(linux)
    1.40 +#include <linux/vt.h>
    1.41 +#elif defined(__FreeBSD__)
    1.42 +#include <sys/consio.h>
    1.43 +#else
    1.44 +#error You must choose your operating system here
    1.45 +#endif
    1.46 +#include <vga.h>
    1.47 +#include <vgamouse.h>
    1.48 +#include <vgakeyboard.h>
    1.49 +
    1.50 +#include "SDL.h"
    1.51 +#include "SDL_error.h"
    1.52 +#include "SDL_video.h"
    1.53 +#include "SDL_mouse.h"
    1.54 +#include "SDL_sysvideo.h"
    1.55 +#include "SDL_pixels_c.h"
    1.56 +#include "SDL_events_c.h"
    1.57 +#include "SDL_svgavideo.h"
    1.58 +#include "SDL_svgaevents_c.h"
    1.59 +#include "SDL_svgamouse_c.h"
    1.60 +
    1.61 +
    1.62 +/* Initialization/Query functions */
    1.63 +static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat);
    1.64 +static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
    1.65 +static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    1.66 +static int SVGA_SetColors(_THIS, int firstcolor, int ncolors,
    1.67 +			  SDL_Color *colors);
    1.68 +static void SVGA_VideoQuit(_THIS);
    1.69 +
    1.70 +/* Hardware surface functions */
    1.71 +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface);
    1.72 +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface);
    1.73 +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface);
    1.74 +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface);
    1.75 +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface);
    1.76 +
    1.77 +/* SVGAlib driver bootstrap functions */
    1.78 +
    1.79 +static int SVGA_Available(void)
    1.80 +{
    1.81 +	/* Check to see if we are root and stdin is a virtual console */
    1.82 +	int console;
    1.83 +
    1.84 +	console = STDIN_FILENO;
    1.85 +	if ( console >= 0 ) {
    1.86 +		struct stat sb;
    1.87 +		struct vt_mode dummy;
    1.88 +
    1.89 +		if ( (fstat(console, &sb) < 0) ||
    1.90 +		     (ioctl(console, VT_GETMODE, &dummy) < 0) ) {
    1.91 +			console = -1;
    1.92 +		}
    1.93 +	}
    1.94 +	return((geteuid() == 0) && (console >= 0));
    1.95 +}
    1.96 +
    1.97 +static void SVGA_DeleteDevice(SDL_VideoDevice *device)
    1.98 +{
    1.99 +	free(device->hidden);
   1.100 +	free(device);
   1.101 +}
   1.102 +
   1.103 +static SDL_VideoDevice *SVGA_CreateDevice(int devindex)
   1.104 +{
   1.105 +	SDL_VideoDevice *device;
   1.106 +
   1.107 +	/* Initialize all variables that we clean on shutdown */
   1.108 +	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   1.109 +	if ( device ) {
   1.110 +		memset(device, 0, (sizeof *device));
   1.111 +		device->hidden = (struct SDL_PrivateVideoData *)
   1.112 +				malloc((sizeof *device->hidden));
   1.113 +	}
   1.114 +	if ( (device == NULL) || (device->hidden == NULL) ) {
   1.115 +		SDL_OutOfMemory();
   1.116 +		if ( device ) {
   1.117 +			free(device);
   1.118 +		}
   1.119 +		return(0);
   1.120 +	}
   1.121 +	memset(device->hidden, 0, (sizeof *device->hidden));
   1.122 +
   1.123 +	/* Set the function pointers */
   1.124 +	device->VideoInit = SVGA_VideoInit;
   1.125 +	device->ListModes = SVGA_ListModes;
   1.126 +	device->SetVideoMode = SVGA_SetVideoMode;
   1.127 +	device->SetColors = SVGA_SetColors;
   1.128 +	device->UpdateRects = NULL;
   1.129 +	device->VideoQuit = SVGA_VideoQuit;
   1.130 +	device->AllocHWSurface = SVGA_AllocHWSurface;
   1.131 +	device->CheckHWBlit = NULL;
   1.132 +	device->FillHWRect = NULL;
   1.133 +	device->SetHWColorKey = NULL;
   1.134 +	device->SetHWAlpha = NULL;
   1.135 +	device->LockHWSurface = SVGA_LockHWSurface;
   1.136 +	device->UnlockHWSurface = SVGA_UnlockHWSurface;
   1.137 +	device->FlipHWSurface = NULL;
   1.138 +	device->FreeHWSurface = SVGA_FreeHWSurface;
   1.139 +	device->SetCaption = NULL;
   1.140 +	device->SetIcon = NULL;
   1.141 +	device->IconifyWindow = NULL;
   1.142 +	device->GrabInput = NULL;
   1.143 +	device->GetWMInfo = NULL;
   1.144 +	device->InitOSKeymap = SVGA_InitOSKeymap;
   1.145 +	device->PumpEvents = SVGA_PumpEvents;
   1.146 +
   1.147 +	device->free = SVGA_DeleteDevice;
   1.148 +
   1.149 +	return device;
   1.150 +}
   1.151 +
   1.152 +VideoBootStrap SVGALIB_bootstrap = {
   1.153 +	"svgalib", "SVGAlib",
   1.154 +	SVGA_Available, SVGA_CreateDevice
   1.155 +};
   1.156 +
   1.157 +static int SVGA_AddMode(_THIS, int mode, int actually_add, int force)
   1.158 +{
   1.159 +	vga_modeinfo *modeinfo;
   1.160 +
   1.161 +	modeinfo = vga_getmodeinfo(mode);
   1.162 +	if ( force || ( modeinfo->flags & CAPABLE_LINEAR ) ) {
   1.163 +		int i, j;
   1.164 +
   1.165 +		i = modeinfo->bytesperpixel-1;
   1.166 +		if ( actually_add ) {
   1.167 +			SDL_Rect saved_rect[2];
   1.168 +			int      saved_mode[2];
   1.169 +			int b;
   1.170 +
   1.171 +			/* Add the mode, sorted largest to smallest */
   1.172 +			b = 0;
   1.173 +			j = 0;
   1.174 +			while ( (SDL_modelist[i][j]->w > modeinfo->width) ||
   1.175 +			        (SDL_modelist[i][j]->h > modeinfo->height) ) {
   1.176 +				++j;
   1.177 +			}
   1.178 +			/* Skip modes that are already in our list */
   1.179 +			if ( (SDL_modelist[i][j]->w == modeinfo->width) &&
   1.180 +			     (SDL_modelist[i][j]->h == modeinfo->height) ) {
   1.181 +				return(0);
   1.182 +			}
   1.183 +			/* Insert the new mode */
   1.184 +			saved_rect[b] = *SDL_modelist[i][j];
   1.185 +			saved_mode[b] = SDL_vgamode[i][j];
   1.186 +			SDL_modelist[i][j]->w = modeinfo->width;
   1.187 +			SDL_modelist[i][j]->h = modeinfo->height;
   1.188 +			SDL_vgamode[i][j] = mode;
   1.189 +			/* Everybody scoot down! */
   1.190 +			if ( saved_rect[b].w && saved_rect[b].h ) {
   1.191 +			    for ( ++j; SDL_modelist[i][j]->w; ++j ) {
   1.192 +				saved_rect[!b] = *SDL_modelist[i][j];
   1.193 +				saved_mode[!b] = SDL_vgamode[i][j];
   1.194 +				*SDL_modelist[i][j] = saved_rect[b];
   1.195 +				SDL_vgamode[i][j] = saved_mode[b];
   1.196 +				b = !b;
   1.197 +			    }
   1.198 +			    *SDL_modelist[i][j] = saved_rect[b];
   1.199 +			    SDL_vgamode[i][j] = saved_mode[b];
   1.200 +			}
   1.201 +		} else {
   1.202 +			++SDL_nummodes[i];
   1.203 +		}
   1.204 +	}
   1.205 +	return( force || ( modeinfo->flags & CAPABLE_LINEAR ) );
   1.206 +}
   1.207 +
   1.208 +static void SVGA_UpdateVideoInfo(_THIS)
   1.209 +{
   1.210 +	vga_modeinfo *modeinfo;
   1.211 +
   1.212 +	this->info.wm_available = 0;
   1.213 +	this->info.hw_available = 1;
   1.214 +	modeinfo = vga_getmodeinfo(vga_getcurrentmode());
   1.215 +	this->info.video_mem = (modeinfo->maxpixels/1024);
   1.216 +	if ( modeinfo->bytesperpixel > 0 ) {
   1.217 +		this->info.video_mem *= modeinfo->bytesperpixel;
   1.218 +	}
   1.219 +	/* FIXME: Add hardware accelerated blit information */
   1.220 +#if 0
   1.221 +printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not ");
   1.222 +#endif
   1.223 +}
   1.224 +
   1.225 +int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat)
   1.226 +{
   1.227 +	int keyboard;
   1.228 +	int i, j;
   1.229 +	int mode, total_modes;
   1.230 +
   1.231 +	/* Initialize all variables that we clean on shutdown */
   1.232 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.233 +		SDL_nummodes[i] = 0;
   1.234 +		SDL_modelist[i] = NULL;
   1.235 +		SDL_vgamode[i] = NULL;
   1.236 +	}
   1.237 +
   1.238 +	/* Initialize the library */
   1.239 +	vga_disabledriverreport();
   1.240 +	if ( vga_init() < 0 ) {
   1.241 +		SDL_SetError("Unable to initialize SVGAlib");
   1.242 +		return(-1);
   1.243 +	}
   1.244 +	vga_setmode(TEXT);
   1.245 +
   1.246 +	/* Enable mouse and keyboard support */
   1.247 +	vga_setmousesupport(1);
   1.248 +	keyboard = keyboard_init_return_fd();
   1.249 +	if ( keyboard < 0 ) {
   1.250 +		SDL_SetError("Unable to initialize keyboard");
   1.251 +		return(-1);
   1.252 +	}
   1.253 +	if ( SVGA_initkeymaps(keyboard) < 0 ) {
   1.254 +		return(-1);
   1.255 +	}
   1.256 +	keyboard_seteventhandler(SVGA_keyboardcallback);
   1.257 +
   1.258 +	/* Determine the screen depth (use default 8-bit depth) */
   1.259 +	vformat->BitsPerPixel = 8;
   1.260 +
   1.261 +	/* Enumerate the available fullscreen modes */
   1.262 +	total_modes = 0;
   1.263 +	for ( mode=vga_lastmodenumber(); mode; --mode ) {
   1.264 +		if ( vga_hasmode(mode) ) {
   1.265 +			if ( SVGA_AddMode(this, mode, 0, 0) ) {
   1.266 +				++total_modes;
   1.267 +			}
   1.268 +		}
   1.269 +	}
   1.270 +	if ( SVGA_AddMode(this, G320x200x256, 0, 1) ) ++total_modes;
   1.271 +	if ( total_modes == 0 ) {
   1.272 +		SDL_SetError("No linear video modes available");
   1.273 +		return(-1);
   1.274 +	}
   1.275 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.276 +		SDL_vgamode[i] = (int *)malloc(SDL_nummodes[i]*sizeof(int));
   1.277 +		if ( SDL_vgamode[i] == NULL ) {
   1.278 +			SDL_OutOfMemory();
   1.279 +			return(-1);
   1.280 +		}
   1.281 +		SDL_modelist[i] = (SDL_Rect **)
   1.282 +				malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
   1.283 +		if ( SDL_modelist[i] == NULL ) {
   1.284 +			SDL_OutOfMemory();
   1.285 +			return(-1);
   1.286 +		}
   1.287 +		for ( j=0; j<SDL_nummodes[i]; ++j ) {
   1.288 +			SDL_modelist[i][j]=(SDL_Rect *)malloc(sizeof(SDL_Rect));
   1.289 +			if ( SDL_modelist[i][j] == NULL ) {
   1.290 +				SDL_OutOfMemory();
   1.291 +				return(-1);
   1.292 +			}
   1.293 +			memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect));
   1.294 +		}
   1.295 +		SDL_modelist[i][j] = NULL;
   1.296 +	}
   1.297 +	for ( mode=vga_lastmodenumber(); mode; --mode ) {
   1.298 +		if ( vga_hasmode(mode) ) {
   1.299 +			SVGA_AddMode(this, mode, 1, 0);
   1.300 +		}
   1.301 +	}
   1.302 +	SVGA_AddMode(this, G320x200x256, 1, 1);
   1.303 +
   1.304 +	/* Free extra (duplicated) modes */
   1.305 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.306 +		j = 0;
   1.307 +		while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) {
   1.308 +			j++;
   1.309 +		}
   1.310 +		while ( SDL_modelist[i][j] ) {
   1.311 +			free(SDL_modelist[i][j]);
   1.312 +			SDL_modelist[i][j] = NULL;
   1.313 +			j++;
   1.314 +		}
   1.315 +	}
   1.316 +
   1.317 +	/* Fill in our hardware acceleration capabilities */
   1.318 +	SVGA_UpdateVideoInfo(this);
   1.319 +
   1.320 +	/* We're done! */
   1.321 +	return(0);
   1.322 +}
   1.323 +
   1.324 +SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   1.325 +{
   1.326 +	return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
   1.327 +}
   1.328 +
   1.329 +/* Various screen update functions available */
   1.330 +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
   1.331 +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects);
   1.332 +
   1.333 +SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current,
   1.334 +				int width, int height, int bpp, Uint32 flags)
   1.335 +{
   1.336 +	int mode;
   1.337 +	int vgamode;
   1.338 +	vga_modeinfo *modeinfo;
   1.339 +
   1.340 +	/* Try to set the requested linear video mode */
   1.341 +	bpp = (bpp+7)/8-1;
   1.342 +	for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) {
   1.343 +		if ( (SDL_modelist[bpp][mode]->w == width) &&
   1.344 +		     (SDL_modelist[bpp][mode]->h == height) ) {
   1.345 +			break;
   1.346 +		}
   1.347 +	}
   1.348 +	if ( SDL_modelist[bpp][mode] == NULL ) {
   1.349 +		SDL_SetError("Couldn't find requested mode in list");
   1.350 +		return(NULL);
   1.351 +	}
   1.352 +	vga_setmode(SDL_vgamode[bpp][mode]);
   1.353 +	vga_setpage(0);
   1.354 +
   1.355 +	vgamode=SDL_vgamode[bpp][mode];
   1.356 +	if ((vga_setlinearaddressing()<0) && (vgamode!=G320x200x256)) {
   1.357 +		SDL_SetError("Unable to set linear addressing");
   1.358 +		return(NULL);
   1.359 +	}
   1.360 +	modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]);
   1.361 +
   1.362 +	/* Update hardware acceleration info */
   1.363 +	SVGA_UpdateVideoInfo(this);
   1.364 +
   1.365 +	/* Allocate the new pixel format for the screen */
   1.366 +	bpp = (bpp+1)*8;
   1.367 +	if ( (bpp == 16) && (modeinfo->colors == 32768) ) {
   1.368 +		bpp = 15;
   1.369 +	}
   1.370 +	if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
   1.371 +		return(NULL);
   1.372 +	}
   1.373 +
   1.374 +	/* Set up the new mode framebuffer */
   1.375 +	current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
   1.376 +	current->w = width;
   1.377 +	current->h = height;
   1.378 +	current->pitch = modeinfo->linewidth;
   1.379 +	current->pixels = vga_getgraphmem();
   1.380 +
   1.381 +	/* Set the blit function */
   1.382 +	this->UpdateRects = SVGA_DirectUpdate;
   1.383 +
   1.384 +	/* Set up the mouse handler again (buggy SVGAlib 1.40) */
   1.385 +	mouse_seteventhandler(SVGA_mousecallback);
   1.386 +
   1.387 +	/* We're done */
   1.388 +	return(current);
   1.389 +}
   1.390 +
   1.391 +/* We don't actually allow hardware surfaces other than the main one */
   1.392 +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface)
   1.393 +{
   1.394 +	return(-1);
   1.395 +}
   1.396 +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface)
   1.397 +{
   1.398 +	return;
   1.399 +}
   1.400 +
   1.401 +/* We need to wait for vertical retrace on page flipped displays */
   1.402 +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface)
   1.403 +{
   1.404 +	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
   1.405 +		vga_waitretrace();
   1.406 +	}
   1.407 +	return(0);
   1.408 +}
   1.409 +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface)
   1.410 +{
   1.411 +	return;
   1.412 +}
   1.413 +
   1.414 +/* FIXME: How is this done with SVGAlib? */
   1.415 +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface)
   1.416 +{
   1.417 +	return(0);
   1.418 +}
   1.419 +
   1.420 +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
   1.421 +{
   1.422 +	return;
   1.423 +}
   1.424 +
   1.425 +/* FIXME: Can this be used under SVGAlib? */
   1.426 +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects)
   1.427 +{
   1.428 +	return;
   1.429 +}
   1.430 +
   1.431 +int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   1.432 +{
   1.433 +        int i;
   1.434 +
   1.435 +	for(i = 0; i < ncolors; i++) {
   1.436 +	        vga_setpalette(firstcolor + i,
   1.437 +			       colors[i].r>>2,
   1.438 +			       colors[i].g>>2,
   1.439 +			       colors[i].b>>2);
   1.440 +	}
   1.441 +	return(1);
   1.442 +}
   1.443 +
   1.444 +/* Note:  If we are terminated, this could be called in the middle of
   1.445 +   another SDL video routine -- notably UpdateRects.
   1.446 +*/
   1.447 +void SVGA_VideoQuit(_THIS)
   1.448 +{
   1.449 +	int i, j;
   1.450 +
   1.451 +	/* Reset the console video mode */
   1.452 +	if ( this->screen && (this->screen->w && this->screen->h) ) {
   1.453 +		vga_setmode(TEXT);
   1.454 +	}
   1.455 +	keyboard_close();
   1.456 +
   1.457 +	/* Free video mode lists */
   1.458 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.459 +		if ( SDL_modelist[i] != NULL ) {
   1.460 +			for ( j=0; SDL_modelist[i][j]; ++j )
   1.461 +				free(SDL_modelist[i][j]);
   1.462 +			free(SDL_modelist[i]);
   1.463 +			SDL_modelist[i] = NULL;
   1.464 +		}
   1.465 +		if ( SDL_vgamode[i] != NULL ) {
   1.466 +			free(SDL_vgamode[i]);
   1.467 +			SDL_vgamode[i] = NULL;
   1.468 +		}
   1.469 +	}
   1.470 +	if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
   1.471 +		/* Direct screen access, no memory buffer */
   1.472 +		this->screen->pixels = NULL;
   1.473 +	}
   1.474 +}