Commit 4dadaeae authored by Sam Lantinga's avatar Sam Lantinga

Fixed bug #49

Added support for non-blocking VT switching on the framebuffer console.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401739
parent 11037522
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment