Fixed bug #49
Added support for non-blocking VT switching on the framebuffer console.
--- a/src/video/fbcon/SDL_fb3dfx.c Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fb3dfx.c Mon May 08 05:33:02 2006 +0000
@@ -57,6 +57,9 @@
int dstX, dstY;
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
@@ -102,6 +105,9 @@
Uint32 use_colorkey;
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
--- a/src/video/fbcon/SDL_fbevents.c Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fbevents.c Mon May 08 05:33:02 2006 +0000
@@ -209,6 +209,8 @@
SDL_SetError("Unable to set keyboard in graphics mode");
return(-1);
}
+ /* Prevent switching the virtual terminal */
+ ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
}
return(keyboard_fd);
}
@@ -222,6 +224,7 @@
saved_kbd_mode = -1;
/* Head back over to the original virtual terminal */
+ ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
if ( saved_vt > 0 ) {
ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
}
@@ -456,7 +459,7 @@
{0xFF}
*/
Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
- Uint8 reset = 0xff;
+ /*Uint8 reset = 0xff;*/
fd_set fdset;
struct timeval tv;
int retval = 0;
@@ -916,65 +919,60 @@
return;
}
-/* Handle switching to another VC, returns when our VC is back.
- This isn't necessarily the best solution. For SDL 1.3 we need
- a way of notifying the application when we lose access to the
- video hardware and when we regain it.
- */
+/* Handle switching to another VC, returns when our VC is back */
+static void switch_vt_prep(_THIS)
+{
+ SDL_Surface *screen = SDL_VideoSurface;
+
+ SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS));
+
+ /* Save the contents of the screen, and go to text mode */
+ wait_idle(this);
+ screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch);
+ screen_contents = (Uint8 *)SDL_malloc(screen_arealen);
+ if ( screen_contents ) {
+ SDL_memcpy(screen_contents, screen->pixels, screen_arealen);
+ }
+ FB_SavePaletteTo(this, 256, screen_palette);
+ ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo);
+ ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
+ ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
+}
+static void switch_vt_done(_THIS)
+{
+ SDL_Surface *screen = SDL_VideoSurface;
+
+ /* Restore graphics mode and the contents of the screen */
+ ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
+ ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
+ ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo);
+ FB_RestorePaletteFrom(this, 256, screen_palette);
+ if ( screen_contents ) {
+ SDL_memcpy(screen->pixels, screen_contents, screen_arealen);
+ SDL_free(screen_contents);
+ screen_contents = NULL;
+ }
+
+ SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS));
+}
static void switch_vt(_THIS, unsigned short which)
{
- struct fb_var_screeninfo vinfo;
struct vt_stat vtstate;
- unsigned short v_active;
- __u16 saved_pal[3*256];
- SDL_Surface *screen;
- Uint32 screen_arealen;
- Uint8 *screen_contents = NULL;
/* Figure out whether or not we're switching to a new console */
if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
(which == vtstate.v_active) ) {
return;
}
- v_active = vtstate.v_active;
-
- /* Save the contents of the screen, and go to text mode */
- SDL_mutexP(hw_lock);
- wait_idle(this);
- screen = SDL_VideoSurface;
- if ( !SDL_ShadowSurface ) {
- screen_arealen = (screen->h*screen->pitch);
- screen_contents = (Uint8 *)SDL_malloc(screen_arealen);
- if ( screen_contents ) {
- SDL_memcpy(screen_contents, (Uint8 *)screen->pixels + screen->offset, screen_arealen);
- }
- }
- FB_SavePaletteTo(this, 256, saved_pal);
- ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo);
- ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
/* New console, switch to it */
+ SDL_mutexP(hw_lock);
+ switch_vt_prep(this);
if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
- /* Wait for our console to be activated again */
ioctl(keyboard_fd, VT_WAITACTIVE, which);
- while ( ioctl(keyboard_fd, VT_WAITACTIVE, v_active) < 0 ) {
- if ( (errno != EINTR) && (errno != EAGAIN) ) {
- /* Unknown VT error - cancel this */
- break;
- }
- SDL_Delay(500);
- }
- }
-
- /* Restore graphics mode and the contents of the screen */
- ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
- ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);
- FB_RestorePaletteFrom(this, 256, saved_pal);
- if ( screen_contents ) {
- SDL_memcpy((Uint8 *)screen->pixels + screen->offset, screen_contents, screen_arealen);
- SDL_free(screen_contents);
+ switched_away = 1;
} else {
- SDL_UpdateRect(screen, 0, 0, 0, 0);
+ switch_vt_done(this);
}
SDL_mutexV(hw_lock);
}
@@ -1032,6 +1030,18 @@
static struct timeval zero;
do {
+ if ( switched_away ) {
+ struct vt_stat vtstate;
+
+ SDL_mutexP(hw_lock);
+ if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) &&
+ vtstate.v_active == current_vt ) {
+ switched_away = 0;
+ switch_vt_done(this);
+ }
+ SDL_mutexV(hw_lock);
+ }
+
posted = 0;
FD_ZERO(&fdset);
--- a/src/video/fbcon/SDL_fbmatrox.c Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fbmatrox.c Mon May 08 05:33:02 2006 +0000
@@ -70,6 +70,9 @@
Uint32 fillop;
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
@@ -132,6 +135,9 @@
}
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
--- a/src/video/fbcon/SDL_fbriva.c Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fbriva.c Mon May 08 05:33:02 2006 +0000
@@ -77,6 +77,9 @@
RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET);
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
@@ -120,6 +123,9 @@
}
/* Don't blit to the display surface when switched away */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
if ( dst == this->screen ) {
SDL_mutexP(hw_lock);
}
--- a/src/video/fbcon/SDL_fbvideo.c Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fbvideo.c Mon May 08 05:33:02 2006 +0000
@@ -1238,26 +1238,10 @@
surface->hwdata = NULL;
}
-/* Routine to check to see if the frame buffer virtual terminal */
-/* is the current(active) one. If it is not, result will cause */
-/* Lock to fail. (would have waited forever, since the fbevent */
-/* keyboard handler maintains a lock when switched away from */
-/* current) */
-static __inline__ int FB_IsFrameBufferActive(_THIS)
-{
- struct vt_stat vtstate;
- if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
- (current_vt != vtstate.v_active) ) {
- return 0;
- }
- return 1;
-}
-
-
static int FB_LockHWSurface(_THIS, SDL_Surface *surface)
{
- if ( !FB_IsFrameBufferActive(this) ) {
- return -1; /* fail locking. */
+ if ( switched_away ) {
+ return -2; /* no hardware access */
}
if ( surface == this->screen ) {
SDL_mutexP(hw_lock);
@@ -1293,6 +1277,10 @@
static int FB_FlipHWSurface(_THIS, SDL_Surface *surface)
{
+ if ( switched_away ) {
+ return -2; /* no hardware access */
+ }
+
/* Wait for vertical retrace and then flip display */
cache_vinfo.yoffset = flip_page*surface->h;
if ( FB_IsSurfaceBusy(this->screen) ) {
@@ -1333,6 +1321,10 @@
Uint32 *src, *srcPtr;
Uint8 *dst, *dstPtr;
+ if ( switched_away ) {
+ return; /* no hardware access */
+ }
+
screen = this->screen;
FBPitch = screen->w >> 3;
SRCPitch = screen->pitch >> 2;
--- a/src/video/fbcon/SDL_fbvideo.h Mon May 08 05:30:15 2006 +0000
+++ b/src/video/fbcon/SDL_fbvideo.h Mon May 08 05:33:02 2006 +0000
@@ -85,6 +85,11 @@
int surfaces_memleft;
SDL_mutex *hw_lock;
+ int switched_away;
+ struct fb_var_screeninfo screen_vinfo;
+ Uint32 screen_arealen;
+ Uint8 *screen_contents;
+ __u16 screen_palette[3*256];
void (*wait_vbl)(_THIS);
void (*wait_idle)(_THIS);
@@ -117,6 +122,11 @@
#define surfaces_memtotal (this->hidden->surfaces_memtotal)
#define surfaces_memleft (this->hidden->surfaces_memleft)
#define hw_lock (this->hidden->hw_lock)
+#define switched_away (this->hidden->switched_away)
+#define screen_vinfo (this->hidden->screen_vinfo)
+#define screen_arealen (this->hidden->screen_arealen)
+#define screen_contents (this->hidden->screen_contents)
+#define screen_palette (this->hidden->screen_palette)
#define wait_vbl (this->hidden->wait_vbl)
#define wait_idle (this->hidden->wait_idle)