Fixed bug #49
authorSam Lantinga <slouken@libsdl.org>
Mon, 08 May 2006 05:33:02 +0000
changeset 17807a36f01acf71
parent 1779 67fc81efcfc3
child 1781 d8030f368b84
Fixed bug #49

Added support for non-blocking VT switching on the framebuffer console.
src/video/fbcon/SDL_fb3dfx.c
src/video/fbcon/SDL_fbevents.c
src/video/fbcon/SDL_fbmatrox.c
src/video/fbcon/SDL_fbriva.c
src/video/fbcon/SDL_fbvideo.c
src/video/fbcon/SDL_fbvideo.h
     1.1 --- a/src/video/fbcon/SDL_fb3dfx.c	Mon May 08 05:30:15 2006 +0000
     1.2 +++ b/src/video/fbcon/SDL_fb3dfx.c	Mon May 08 05:33:02 2006 +0000
     1.3 @@ -57,6 +57,9 @@
     1.4  	int dstX, dstY;
     1.5  
     1.6  	/* Don't blit to the display surface when switched away */
     1.7 +	if ( switched_away ) {
     1.8 +		return -2; /* no hardware access */
     1.9 +	}
    1.10  	if ( dst == this->screen ) {
    1.11  		SDL_mutexP(hw_lock);
    1.12  	}
    1.13 @@ -102,6 +105,9 @@
    1.14  	Uint32 use_colorkey;
    1.15  
    1.16  	/* Don't blit to the display surface when switched away */
    1.17 +	if ( switched_away ) {
    1.18 +		return -2; /* no hardware access */
    1.19 +	}
    1.20  	if ( dst == this->screen ) {
    1.21  		SDL_mutexP(hw_lock);
    1.22  	}
     2.1 --- a/src/video/fbcon/SDL_fbevents.c	Mon May 08 05:30:15 2006 +0000
     2.2 +++ b/src/video/fbcon/SDL_fbevents.c	Mon May 08 05:33:02 2006 +0000
     2.3 @@ -209,6 +209,8 @@
     2.4  			SDL_SetError("Unable to set keyboard in graphics mode");
     2.5  			return(-1);
     2.6  		}
     2.7 +		/* Prevent switching the virtual terminal */
     2.8 +		ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
     2.9  	}
    2.10  	return(keyboard_fd);
    2.11  }
    2.12 @@ -222,6 +224,7 @@
    2.13  		saved_kbd_mode = -1;
    2.14  
    2.15  		/* Head back over to the original virtual terminal */
    2.16 +		ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
    2.17  		if ( saved_vt > 0 ) {
    2.18  			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
    2.19  		}
    2.20 @@ -456,7 +459,7 @@
    2.21  			{0xFF}
    2.22  	*/
    2.23  	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
    2.24 -	Uint8 reset = 0xff;
    2.25 +	/*Uint8 reset = 0xff;*/
    2.26  	fd_set fdset;
    2.27  	struct timeval tv;
    2.28  	int retval = 0;
    2.29 @@ -916,65 +919,60 @@
    2.30  	return;
    2.31  }
    2.32  
    2.33 -/* Handle switching to another VC, returns when our VC is back.
    2.34 -   This isn't necessarily the best solution.  For SDL 1.3 we need
    2.35 -   a way of notifying the application when we lose access to the
    2.36 -   video hardware and when we regain it.
    2.37 - */
    2.38 +/* Handle switching to another VC, returns when our VC is back */
    2.39 +static void switch_vt_prep(_THIS)
    2.40 +{
    2.41 +	SDL_Surface *screen = SDL_VideoSurface;
    2.42 +
    2.43 +	SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS));
    2.44 +
    2.45 +	/* Save the contents of the screen, and go to text mode */
    2.46 +	wait_idle(this);
    2.47 +	screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch);
    2.48 +	screen_contents = (Uint8 *)SDL_malloc(screen_arealen);
    2.49 +	if ( screen_contents ) {
    2.50 +		SDL_memcpy(screen_contents, screen->pixels, screen_arealen);
    2.51 +	}
    2.52 +	FB_SavePaletteTo(this, 256, screen_palette);
    2.53 +	ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo);
    2.54 +	ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
    2.55 +	ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
    2.56 +}
    2.57 +static void switch_vt_done(_THIS)
    2.58 +{
    2.59 +	SDL_Surface *screen = SDL_VideoSurface;
    2.60 +
    2.61 +	/* Restore graphics mode and the contents of the screen */
    2.62 +	ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
    2.63 +	ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
    2.64 +	ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo);
    2.65 +	FB_RestorePaletteFrom(this, 256, screen_palette);
    2.66 +	if ( screen_contents ) {
    2.67 +		SDL_memcpy(screen->pixels, screen_contents, screen_arealen);
    2.68 +		SDL_free(screen_contents);
    2.69 +		screen_contents = NULL;
    2.70 +	}
    2.71 +
    2.72 +	SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS));
    2.73 +}
    2.74  static void switch_vt(_THIS, unsigned short which)
    2.75  {
    2.76 -	struct fb_var_screeninfo vinfo;
    2.77  	struct vt_stat vtstate;
    2.78 -	unsigned short v_active;
    2.79 -	__u16 saved_pal[3*256];
    2.80 -	SDL_Surface *screen;
    2.81 -	Uint32 screen_arealen;
    2.82 -	Uint8 *screen_contents = NULL;
    2.83  
    2.84  	/* Figure out whether or not we're switching to a new console */
    2.85  	if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
    2.86  	     (which == vtstate.v_active) ) {
    2.87  		return;
    2.88  	}
    2.89 -	v_active = vtstate.v_active;
    2.90 -
    2.91 -	/* Save the contents of the screen, and go to text mode */
    2.92 -	SDL_mutexP(hw_lock);
    2.93 -	wait_idle(this);
    2.94 -	screen = SDL_VideoSurface;
    2.95 -	if ( !SDL_ShadowSurface ) {
    2.96 -		screen_arealen = (screen->h*screen->pitch);
    2.97 -		screen_contents = (Uint8 *)SDL_malloc(screen_arealen);
    2.98 -		if ( screen_contents ) {
    2.99 -			SDL_memcpy(screen_contents, (Uint8 *)screen->pixels + screen->offset, screen_arealen);
   2.100 -		}
   2.101 -	}
   2.102 -	FB_SavePaletteTo(this, 256, saved_pal);
   2.103 -	ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo);
   2.104 -	ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
   2.105  
   2.106  	/* New console, switch to it */
   2.107 +	SDL_mutexP(hw_lock);
   2.108 +	switch_vt_prep(this);
   2.109  	if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
   2.110 -		/* Wait for our console to be activated again */
   2.111  		ioctl(keyboard_fd, VT_WAITACTIVE, which);
   2.112 -		while ( ioctl(keyboard_fd, VT_WAITACTIVE, v_active) < 0 ) {
   2.113 -			if ( (errno != EINTR) && (errno != EAGAIN) ) {
   2.114 -				/* Unknown VT error - cancel this */
   2.115 -				break;
   2.116 -			}
   2.117 -			SDL_Delay(500);
   2.118 -		}
   2.119 -	}
   2.120 -
   2.121 -	/* Restore graphics mode and the contents of the screen */
   2.122 -	ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
   2.123 -	ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);
   2.124 -	FB_RestorePaletteFrom(this, 256, saved_pal);
   2.125 -	if ( screen_contents ) {
   2.126 -		SDL_memcpy((Uint8 *)screen->pixels + screen->offset, screen_contents, screen_arealen);
   2.127 -		SDL_free(screen_contents);
   2.128 +		switched_away = 1;
   2.129  	} else {
   2.130 -		SDL_UpdateRect(screen, 0, 0, 0, 0);
   2.131 +		switch_vt_done(this);
   2.132  	}
   2.133  	SDL_mutexV(hw_lock);
   2.134  }
   2.135 @@ -1032,6 +1030,18 @@
   2.136  	static struct timeval zero;
   2.137  
   2.138  	do {
   2.139 +		if ( switched_away ) {
   2.140 +			struct vt_stat vtstate;
   2.141 +
   2.142 +			SDL_mutexP(hw_lock);
   2.143 +			if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) &&
   2.144 +			     vtstate.v_active == current_vt ) {
   2.145 +				switched_away = 0;
   2.146 +				switch_vt_done(this);
   2.147 +			}
   2.148 +			SDL_mutexV(hw_lock);
   2.149 +		}
   2.150 +
   2.151  		posted = 0;
   2.152  
   2.153  		FD_ZERO(&fdset);
     3.1 --- a/src/video/fbcon/SDL_fbmatrox.c	Mon May 08 05:30:15 2006 +0000
     3.2 +++ b/src/video/fbcon/SDL_fbmatrox.c	Mon May 08 05:33:02 2006 +0000
     3.3 @@ -70,6 +70,9 @@
     3.4  	Uint32 fillop;
     3.5  
     3.6  	/* Don't blit to the display surface when switched away */
     3.7 +	if ( switched_away ) {
     3.8 +		return -2; /* no hardware access */
     3.9 +	}
    3.10  	if ( dst == this->screen ) {
    3.11  		SDL_mutexP(hw_lock);
    3.12  	}
    3.13 @@ -132,6 +135,9 @@
    3.14  	}
    3.15  
    3.16  	/* Don't blit to the display surface when switched away */
    3.17 +	if ( switched_away ) {
    3.18 +		return -2; /* no hardware access */
    3.19 +	}
    3.20  	if ( dst == this->screen ) {
    3.21  		SDL_mutexP(hw_lock);
    3.22  	}
     4.1 --- a/src/video/fbcon/SDL_fbriva.c	Mon May 08 05:30:15 2006 +0000
     4.2 +++ b/src/video/fbcon/SDL_fbriva.c	Mon May 08 05:33:02 2006 +0000
     4.3 @@ -77,6 +77,9 @@
     4.4  	RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET);
     4.5  
     4.6  	/* Don't blit to the display surface when switched away */
     4.7 +	if ( switched_away ) {
     4.8 +		return -2; /* no hardware access */
     4.9 +	}
    4.10  	if ( dst == this->screen ) {
    4.11  		SDL_mutexP(hw_lock);
    4.12  	}
    4.13 @@ -120,6 +123,9 @@
    4.14  	}
    4.15  
    4.16  	/* Don't blit to the display surface when switched away */
    4.17 +	if ( switched_away ) {
    4.18 +		return -2; /* no hardware access */
    4.19 +	}
    4.20  	if ( dst == this->screen ) {
    4.21  		SDL_mutexP(hw_lock);
    4.22  	}
     5.1 --- a/src/video/fbcon/SDL_fbvideo.c	Mon May 08 05:30:15 2006 +0000
     5.2 +++ b/src/video/fbcon/SDL_fbvideo.c	Mon May 08 05:33:02 2006 +0000
     5.3 @@ -1238,26 +1238,10 @@
     5.4  	surface->hwdata = NULL;
     5.5  }
     5.6  
     5.7 -/* Routine to check to see if the frame buffer virtual terminal */
     5.8 -/* is the current(active) one.  If it is not, result will cause */
     5.9 -/* Lock to fail.  (would have waited forever, since the fbevent */
    5.10 -/* keyboard handler maintains a lock when switched away from    */
    5.11 -/* current) */
    5.12 -static __inline__ int FB_IsFrameBufferActive(_THIS)
    5.13 -{
    5.14 -	struct vt_stat vtstate;
    5.15 -	if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
    5.16 -	     (current_vt != vtstate.v_active) ) {
    5.17 -		return 0;
    5.18 -	}
    5.19 -	return 1;
    5.20 -}
    5.21 -
    5.22 -
    5.23  static int FB_LockHWSurface(_THIS, SDL_Surface *surface)
    5.24  {
    5.25 -	if ( !FB_IsFrameBufferActive(this) ) {
    5.26 -		return -1; /* fail locking. */
    5.27 +	if ( switched_away ) {
    5.28 +		return -2; /* no hardware access */
    5.29  	}
    5.30  	if ( surface == this->screen ) {
    5.31  		SDL_mutexP(hw_lock);
    5.32 @@ -1293,6 +1277,10 @@
    5.33  
    5.34  static int FB_FlipHWSurface(_THIS, SDL_Surface *surface)
    5.35  {
    5.36 +	if ( switched_away ) {
    5.37 +		return -2; /* no hardware access */
    5.38 +	}
    5.39 +
    5.40  	/* Wait for vertical retrace and then flip display */
    5.41  	cache_vinfo.yoffset = flip_page*surface->h;
    5.42  	if ( FB_IsSurfaceBusy(this->screen) ) {
    5.43 @@ -1333,6 +1321,10 @@
    5.44      Uint32 *src, *srcPtr;
    5.45      Uint8  *dst, *dstPtr;
    5.46  
    5.47 +    if ( switched_away ) {
    5.48 +        return; /* no hardware access */
    5.49 +    }
    5.50 +
    5.51      screen = this->screen;
    5.52      FBPitch = screen->w >> 3;
    5.53      SRCPitch = screen->pitch >> 2;
     6.1 --- a/src/video/fbcon/SDL_fbvideo.h	Mon May 08 05:30:15 2006 +0000
     6.2 +++ b/src/video/fbcon/SDL_fbvideo.h	Mon May 08 05:33:02 2006 +0000
     6.3 @@ -85,6 +85,11 @@
     6.4  	int surfaces_memleft;
     6.5  
     6.6  	SDL_mutex *hw_lock;
     6.7 +	int switched_away;
     6.8 +	struct fb_var_screeninfo screen_vinfo;
     6.9 +	Uint32 screen_arealen;
    6.10 +	Uint8 *screen_contents;
    6.11 +	__u16  screen_palette[3*256];
    6.12  
    6.13  	void (*wait_vbl)(_THIS);
    6.14  	void (*wait_idle)(_THIS);
    6.15 @@ -117,6 +122,11 @@
    6.16  #define surfaces_memtotal	(this->hidden->surfaces_memtotal)
    6.17  #define surfaces_memleft	(this->hidden->surfaces_memleft)
    6.18  #define hw_lock			(this->hidden->hw_lock)
    6.19 +#define switched_away		(this->hidden->switched_away)
    6.20 +#define screen_vinfo		(this->hidden->screen_vinfo)
    6.21 +#define screen_arealen		(this->hidden->screen_arealen)
    6.22 +#define screen_contents		(this->hidden->screen_contents)
    6.23 +#define screen_palette		(this->hidden->screen_palette)
    6.24  #define wait_vbl		(this->hidden->wait_vbl)
    6.25  #define wait_idle		(this->hidden->wait_idle)
    6.26