Skip to content
Permalink
Browse files

Fixed bug #49

Added support for non-blocking VT switching on the framebuffer console.
  • Loading branch information
slouken committed May 8, 2006
1 parent bd31237 commit 2431bf5e1da81eb388f9b0a60af0fc2796e99eba
@@ -57,6 +57,9 @@ static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
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 @@ static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
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);
}
@@ -209,6 +209,8 @@ int FB_EnterGraphicsMode(_THIS)
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 @@ void FB_LeaveGraphicsMode(_THIS)
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 @@ static int set_imps2_mode(int fd)
{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 @@ static void handle_mouse(_THIS)
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 @@ void FB_PumpEvents(_THIS)
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);
@@ -70,6 +70,9 @@ static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
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 @@ static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
}

/* 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);
}
@@ -77,6 +77,9 @@ static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
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 @@ static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
}

/* 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);
}
@@ -1238,26 +1238,10 @@ static void FB_FreeHWSurface(_THIS, SDL_Surface *surface)
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 void FB_WaitIdle(_THIS)

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 @@ static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects)
Uint32 *src, *srcPtr;
Uint8 *dst, *dstPtr;

if ( switched_away ) {
return; /* no hardware access */
}

screen = this->screen;
FBPitch = screen->w >> 3;
SRCPitch = screen->pitch >> 2;
@@ -85,6 +85,11 @@ struct SDL_PrivateVideoData {
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 @@ struct SDL_PrivateVideoData {
#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)

0 comments on commit 2431bf5

Please sign in to comment.