- Implement fullscreen DGA via fbdev access under Linux. Besides, r/w access

to /dev/mem is required on Linux to use XF86 DGA mode. Otherwise, there is
now a fallback to fbdev.
- Forward port some features from Basilisk II (set_window_name,
disable_mouse_accel).
- Don't SIGSTOP the emulation thread on suspend since that would completely
stop the process on Linux. Use a frame buffer lock instead (as B2 does)
This commit is contained in:
gbeauche 2005-03-27 19:05:18 +00:00
parent 0bc6418ea6
commit d27832cb1c
3 changed files with 344 additions and 46 deletions

View File

@ -17,6 +17,7 @@ ulimit -c 0
dnl Options.
AC_ARG_ENABLE(jit, [ --enable-jit enable JIT compiler [default=yes]], [WANT_JIT=$enableval], [WANT_JIT=yes])
AC_ARG_ENABLE(ppc-emulator, [ --enable-ppc-emulator use the selected PowerPC emulator [default=auto]], [WANT_EMULATED_PPC=$enableval], [WANT_EMULATED_PPC=auto])
AC_ARG_ENABLE(fbdev-dga, [ --enable-fbdev-dga use direct frame buffer access via /dev/fb0 [default=yes]], [WANT_FBDEV_DGA=$enableval], [WANT_FBDEV_DGA=yes])
AC_ARG_ENABLE(xf86-dga, [ --enable-xf86-dga use the XFree86 DGA extension [default=yes]], [WANT_XF86_DGA=$enableval], [WANT_XF86_DGA=yes])
AC_ARG_ENABLE(xf86-vidmode, [ --enable-xf86-vidmode use the XFree86 VidMode extension [default=no]], [WANT_XF86_VIDMODE=$enableval], [WANT_XF86_VIDMODE=no])
AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes])
@ -122,6 +123,7 @@ dnl Do we need SDL?
WANT_SDL=no
if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then
WANT_SDL=yes
WANT_FBDEV_DGA=no
WANT_XF86_DGA=no
WANT_XF86_VIDMODE=no
WANT_FBDEV_DGA=no
@ -205,6 +207,16 @@ no:linux*|no:netbsd*)
;;
esac
dnl We use FBDev DGA if possible.
if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then
AC_CHECK_HEADER(linux/fb.h, [
AC_DEFINE(ENABLE_FBDEV_DGA, 1, [Define if using Linux fbdev extension.])
], [
AC_MSG_WARN([Could not find Linux FBDev extension, ignoring --enable-fbdev-dga.])
WANT_FBDEV_DGA=no
])
fi
dnl We use XFree86 DGA if possible.
if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then
AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, [
@ -1167,6 +1179,7 @@ echo
echo SheepShaver configuration summary:
echo
echo SDL support ...................... : $SDL_SUPPORT
echo FBDev DGA support ................ : $WANT_FBDEV_DGA
echo XFree86 DGA support .............. : $WANT_XF86_DGA
echo XFree86 VidMode support .......... : $WANT_XF86_VIDMODE
echo Using PowerPC emulator ........... : $EMULATED_PPC

View File

@ -1268,21 +1268,6 @@ void QuitEmulator(void)
}
/*
* Pause/resume emulator
*/
void PauseEmulator(void)
{
pthread_kill(emul_thread, SIGSTOP);
}
void ResumeEmulator(void)
{
pthread_kill(emul_thread, SIGCONT);
}
/*
* Dump 68k registers
*/

View File

@ -18,6 +18,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* NOTES:
* The Ctrl key works like a qualifier for special actions:
* Ctrl-Tab = suspend DGA mode
* Ctrl-Esc = emergency quit
* Ctrl-F1 = mount floppy
* Ctrl-F5 = grab mouse (in windowed mode)
*/
#include "sysdeps.h"
#include <X11/Xlib.h>
@ -31,6 +40,11 @@
#include <algorithm>
#ifdef ENABLE_FBDEV_DGA
# include <linux/fb.h>
# include <sys/ioctl.h>
#endif
#ifdef ENABLE_XF86_DGA
# include <X11/extensions/xf86dga.h>
#endif
@ -109,6 +123,7 @@ static int color_class;
static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes
static Colormap cmap[2]; // Two colormaps (DGA) for 8-bit mode
static XColor x_palette[256]; // Color palette to be used as CLUT and gamma table
static int orig_accel_numer, orig_accel_denom, orig_threshold; // Original mouse acceleration
static XColor black, white;
static unsigned long black_pixel, white_pixel;
@ -131,8 +146,17 @@ static uint8 *the_buffer_copy = NULL; // Copy of Mac frame buffer
static uint32 the_buffer_size; // Size of allocated the_buffer
// Variables for DGA mode
static bool is_fbdev_dga_mode = false; // Flag: Use FBDev DGA mode?
static int current_dga_cmap;
#ifdef ENABLE_FBDEV_DGA
static int fb_dev_fd = -1; // Handle to fb device name
static struct fb_fix_screeninfo fb_finfo; // Fixed info
static struct fb_var_screeninfo fb_vinfo; // Variable info
static struct fb_var_screeninfo fb_orig_vinfo; // Variable info to restore later
static struct fb_cmap fb_oldcmap; // Colormap to restore later
#endif
#ifdef ENABLE_XF86_VIDMODE
// Variables for XF86 VidMode support
static XF86VidModeModeInfo **x_video_modes; // Array of all available modes
@ -153,6 +177,20 @@ static pthread_mutex_t x_palette_lock = PTHREAD_MUTEX_INITIALIZER;
#define UNLOCK_PALETTE
#endif
// Mutex to protect frame buffer
#ifdef HAVE_SPINLOCKS
static spinlock_t frame_buffer_lock = SPIN_LOCK_UNLOCKED;
#define LOCK_FRAME_BUFFER spin_lock(&frame_buffer_lock)
#define UNLOCK_FRAME_BUFFER spin_unlock(&frame_buffer_lock)
#elif defined(HAVE_PTHREADS)
static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_FRAME_BUFFER pthread_mutex_lock(&frame_buffer_lock);
#define UNLOCK_FRAME_BUFFER pthread_mutex_unlock(&frame_buffer_lock);
#else
#define LOCK_FRAME_BUFFER
#define UNLOCK_FRAME_BUFFER
#endif
// Prototypes
static void *redraw_func(void *arg);
@ -364,6 +402,36 @@ static bool find_visual_for_depth(int depth)
* Open display (window or fullscreen)
*/
// Set window name and class
static void set_window_name(Window w, int name)
{
const char *str = GetString(name);
XStoreName(x_display, w, str);
XSetIconName(x_display, w, str);
XClassHint *hints;
hints = XAllocClassHint();
if (hints) {
hints->res_name = "SheepShaver";
hints->res_class = "SheepShaver";
XSetClassHint(x_display, w, hints);
XFree(hints);
}
}
// Set window input focus flag
static void set_window_focus(Window w)
{
XWMHints *hints = XAllocWMHints();
if (hints) {
hints->input = True;
hints->initial_state = NormalState;
hints->flags = InputHint | StateHint;
XSetWMHints(x_display, w, hints);
XFree(hints);
}
}
// Set WM_DELETE_WINDOW protocol on window (preventing it from being destroyed by the WM when clicking on the "close" widget)
static Atom WM_DELETE_WINDOW = (Atom)0;
static void set_window_delete_protocol(Window w)
@ -389,6 +457,18 @@ static void wait_unmapped(Window w)
} while ((e.type != UnmapNotify) || (e.xmap.event != w));
}
// Disable mouse acceleration
static void disable_mouse_accel(void)
{
XChangePointerControl(x_display, True, False, 1, 1, 0);
}
// Restore mouse acceleration to original value
static void restore_mouse_accel(void)
{
XChangePointerControl(x_display, True, True, orig_accel_numer, orig_accel_denom, orig_threshold);
}
// Trap SHM errors
static bool shm_error = false;
static int (*old_error_handler)(Display *, XErrorEvent *);
@ -421,8 +501,11 @@ static bool open_window(int width, int height)
the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel | CWBackingStore | CWColormap, &wattr);
// Set window name
XStoreName(x_display, the_win, GetString(STR_WINDOW_TITLE));
// Set window name/class
set_window_name(the_win, STR_WINDOW_TITLE);
// Indicate that we want keyboard input
set_window_focus(the_win);
// Set delete protocol property
set_window_delete_protocol(the_win);
@ -550,9 +633,127 @@ static bool open_window(int width, int height)
return true;
}
// Open FBDev display
static bool open_fbdev(int width, int height)
{
#ifdef ENABLE_FBDEV_DGA
if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo) != 0) {
D(bug("[fbdev] Can't get FSCREENINFO: %s\n", strerror(errno)));
return false;
}
D(bug("[fbdev] Device ID: %s\n", fb_finfo.id));
D(bug("[fbdev] smem_start: %p [%d bytes]\n", fb_finfo.smem_start, fb_finfo.smem_len));
int fb_type = fb_finfo.type;
const char *fb_type_str = NULL;
switch (fb_type) {
case FB_TYPE_PACKED_PIXELS: fb_type_str = "Packed Pixels"; break;
case FB_TYPE_PLANES: fb_type_str = "Non interleaved planes"; break;
case FB_TYPE_INTERLEAVED_PLANES: fb_type_str = "Interleaved planes"; break;
case FB_TYPE_TEXT: fb_type_str = "Text/attributes"; break;
case FB_TYPE_VGA_PLANES: fb_type_str = "EGA/VGA planes"; break;
default: fb_type_str = "<unknown>"; break;
}
D(bug("[fbdev] type: %s\n", fb_type_str));
int fb_visual = fb_finfo.visual;
const char *fb_visual_str;
switch (fb_visual) {
case FB_VISUAL_MONO01: fb_visual_str = "Monochrome 1=Black 0=White"; break;
case FB_VISUAL_MONO10: fb_visual_str = "Monochrome 1=While 0=Black"; break;
case FB_VISUAL_TRUECOLOR: fb_visual_str = "True color"; break;
case FB_VISUAL_PSEUDOCOLOR: fb_visual_str = "Pseudo color (like atari)"; break;
case FB_VISUAL_DIRECTCOLOR: fb_visual_str = "Direct color"; break;
case FB_VISUAL_STATIC_PSEUDOCOLOR: fb_visual_str = "Pseudo color readonly"; break;
default: fb_visual_str = "<unknown>"; break;
}
D(bug("[fbdev] visual: %s\n", fb_visual_str));
if (fb_type != FB_TYPE_PACKED_PIXELS) {
D(bug("[fbdev] type %s not supported\n", fb_type_str));
return false;
}
// Map frame buffer
the_buffer = (uint8 *)mmap(NULL, fb_finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev_fd, 0);
if (the_buffer == MAP_FAILED) {
D(bug("[fbdev] Can't mmap /dev/fb0: %s\n", strerror(errno)));
return false;
}
// Set absolute mouse mode
ADBSetRelMouseMode(false);
// Create window
XSetWindowAttributes wattr;
wattr.event_mask = eventmask = dga_eventmask;
wattr.override_redirect = True;
wattr.colormap = (depth == 1 ? DefaultColormap(x_display, screen) : cmap[0]);
the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
InputOutput, vis, CWEventMask | CWOverrideRedirect |
(color_class == DirectColor ? CWColormap : 0), &wattr);
// Show window
XMapRaised(x_display, the_win);
wait_mapped(the_win);
// Grab mouse and keyboard
XGrabKeyboard(x_display, the_win, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(x_display, the_win, True,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
disable_mouse_accel();
// Create no_cursor
mac_cursor = XCreatePixmapCursor(x_display,
XCreatePixmap(x_display, the_win, 1, 1, 1),
XCreatePixmap(x_display, the_win, 1, 1, 1),
&black, &white, 0, 0);
XDefineCursor(x_display, the_win, mac_cursor);
// Init blitting routines
int bytes_per_row = TrivialBytesPerRow((width + 7) & ~7, DepthModeForPixelDepth(depth));
#if ENABLE_VOSF
bool native_byte_order;
#ifdef WORDS_BIGENDIAN
native_byte_order = (XImageByteOrder(x_display) == MSBFirst);
#else
native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
// Screen_blitter_init() returns TRUE if VOSF is mandatory
// i.e. the framebuffer update function is not Blit_Copy_Raw
use_vosf = Screen_blitter_init(visualFormat, native_byte_order, depth);
if (use_vosf) {
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
the_host_buffer = the_buffer;
the_buffer_size = page_extend((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
}
#else
use_vosf = false;
#endif
#endif
// Set frame buffer base
D(bug("the_buffer = %p, use_vosf = %d\n", the_buffer, use_vosf));
screen_base = Host2MacAddr(the_buffer);
VModes[cur_mode].viRowBytes = bytes_per_row;
return true;
#else
ErrorAlert("SheepShaver has been compiled with DGA support disabled.");
return false;
#endif
}
// Open DGA display (!! should use X11 VidMode extensions to set mode)
static bool open_dga(int width, int height)
{
if (is_fbdev_dga_mode)
return false;
#ifdef ENABLE_XF86_DGA
// Set relative mouse mode
ADBSetRelMouseMode(true);
@ -647,6 +848,9 @@ static bool open_display(void)
D(bug("open_display()\n"));
const VideoInfo &mode = VModes[cur_mode];
// Get original mouse acceleration
XGetPointerControl(x_display, &orig_accel_numer, &orig_accel_denom, &orig_threshold);
// Find best available X visual
if (!find_visual_for_depth(mode.viAppleMode)) {
ErrorAlert(GetString(STR_NO_XVISUAL_ERR));
@ -727,8 +931,17 @@ static bool open_display(void)
depth = depth_of_video_mode(mode.viAppleMode);
bool display_open = false;
if (display_type == DIS_SCREEN)
if (display_type == DIS_SCREEN) {
display_open = open_dga(VModes[cur_mode].viXsize, VModes[cur_mode].viYsize);
#ifdef ENABLE_FBDEV_DGA
// Try to fallback to FBDev DGA mode
if (!display_open) {
is_fbdev_dga_mode = true;
display_open = open_fbdev(VModes[cur_mode].viXsize, VModes[cur_mode].viYsize);
}
#endif
}
else if (display_type == DIS_WINDOW)
display_open = open_window(VModes[cur_mode].viXsize, VModes[cur_mode].viYsize);
@ -777,9 +990,36 @@ static void close_window(void)
XSync(x_display, false);
}
// Close FBDev mode
static void close_fbdev(void)
{
#ifdef ENABLE_FBDEV_DGA
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
uint8 *fb_base;
if (!use_vosf) {
// don't free() the screen buffer in driver_base dtor
fb_base = the_buffer;
the_buffer = NULL;
}
#ifdef ENABLE_VOSF
else {
// don't free() the screen buffer in driver_base dtor
fb_base = the_host_buffer;
the_host_buffer = NULL;
}
#endif
munmap(fb_base, fb_finfo.smem_len);
#endif
}
// Close DGA mode
static void close_dga(void)
{
if (is_fbdev_dga_mode)
return;
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, 0);
XUngrabPointer(x_display, CurrentTime);
@ -805,8 +1045,12 @@ static void close_dga(void)
static void close_display(void)
{
if (display_type == DIS_SCREEN)
close_dga();
if (display_type == DIS_SCREEN) {
if (is_fbdev_dga_mode)
close_fbdev();
else
close_dga();
}
else if (display_type == DIS_WINDOW)
close_window();
@ -861,6 +1105,9 @@ static void close_display(void)
}
}
#endif
// Restore mouse acceleration
restore_mouse_accel();
}
@ -1088,10 +1335,16 @@ bool VideoInit(void)
#ifdef ENABLE_XF86_DGA
// DGA available?
int event_base, error_base;
is_fbdev_dga_mode = false;
if (local_X11 && XF86DGAQueryExtension(x_display, &event_base, &error_base)) {
int dga_flags = 0;
XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
has_dga = dga_flags & XF86DGADirectPresent;
#if defined(__linux__)
// Check r/w permission on /dev/mem for DGA mode to work
if (has_dga && access("/dev/mem", R_OK | W_OK) != 0)
has_dga = false;
#endif
} else
has_dga = false;
#endif
@ -1104,6 +1357,22 @@ bool VideoInit(void)
XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes);
#endif
#ifdef ENABLE_FBDEV_DGA
// FBDev available?
if (!has_dga && local_X11) {
if ((fb_dev_fd = open("/dev/fb0", O_RDWR)) > 0) {
if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo) != 0)
close(fb_dev_fd);
else {
has_dga = true;
is_fbdev_dga_mode = true;
fb_orig_vinfo = fb_vinfo;
D(bug("Frame buffer device initial resolution: %dx%dx%d\n", fb_vinfo.xres, fb_vinfo.yres, fb_vinfo.bits_per_pixel));
}
}
}
#endif
// Find black and white colors
XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black);
XAllocColor(x_display, DefaultColormap(x_display, screen), &black);
@ -1256,6 +1525,10 @@ bool VideoInit(void)
XSetErrorHandler(ignore_errors);
#endif
// Lock down frame buffer
XSync(x_display, false);
LOCK_FRAME_BUFFER;
// Start periodic thread
XSync(x_display, false);
Set_pthread_attr(&redraw_thread_attr, 0);
@ -1280,6 +1553,11 @@ void VideoExit(void)
redraw_thread_active = false;
}
// Unlock frame buffer
UNLOCK_FRAME_BUFFER;
XSync(x_display, false);
D(bug(" frame buffer unlocked\n"));
#ifdef ENABLE_VOSF
if (use_vosf) {
// Deinitialize VOSF
@ -1294,6 +1572,14 @@ void VideoExit(void)
XFlush(x_display);
XSync(x_display, false);
}
#ifdef ENABLE_FBDEV_DGA
// Close framebuffer device
if (fb_dev_fd >= 0) {
close(fb_dev_fd);
fb_dev_fd = -1;
}
#endif
}
@ -1301,9 +1587,6 @@ void VideoExit(void)
* Suspend/resume emulator
*/
extern void PauseEmulator(void);
extern void ResumeEmulator(void);
static void suspend_emul(void)
{
if (display_type == DIS_SCREEN) {
@ -1311,9 +1594,8 @@ static void suspend_emul(void)
ADBKeyUp(0x36);
ctrl_down = false;
// Pause MacOS thread
PauseEmulator();
emul_suspended = true;
// Lock frame buffer (this will stop the MacOS thread)
LOCK_FRAME_BUFFER;
// Save frame buffer
fb_save = malloc(VModes[cur_mode].viYsize * VModes[cur_mode].viRowBytes);
@ -1321,29 +1603,32 @@ static void suspend_emul(void)
Mac2Host_memcpy(fb_save, screen_base, VModes[cur_mode].viYsize * VModes[cur_mode].viRowBytes);
// Close full screen display
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, 0);
if (!is_fbdev_dga_mode)
XF86DGADirectVideo(x_display, screen, 0);
#endif
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
#endif
restore_mouse_accel();
XUnmapWindow(x_display, the_win);
wait_unmapped(the_win);
XSync(x_display, false);
// Open "suspend" window
XSetWindowAttributes wattr;
wattr.event_mask = KeyPressMask;
wattr.background_pixel = black_pixel;
wattr.border_pixel = black_pixel;
wattr.background_pixel = (vis == DefaultVisual(x_display, screen) ? black_pixel : 0);
wattr.backing_store = Always;
wattr.backing_planes = xdepth;
wattr.colormap = DefaultColormap(x_display, screen);
XSync(x_display, false);
wattr.colormap = (depth == 1 ? DefaultColormap(x_display, screen) : cmap[0]);
suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth,
InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel |
CWBackingStore | CWBackingPlanes | (xdepth == 8 ? CWColormap : 0), &wattr);
XSync(x_display, false);
XStoreName(x_display, suspend_win, GetString(STR_SUSPEND_WINDOW_TITLE));
XMapRaised(x_display, suspend_win);
XSync(x_display, false);
InputOutput, vis, CWEventMask | CWBackPixel | CWBackingStore | CWColormap, &wattr);
set_window_name(suspend_win, STR_SUSPEND_WINDOW_TITLE);
set_window_focus(suspend_win);
XMapWindow(x_display, suspend_win);
emul_suspended = true;
}
}
@ -1354,11 +1639,18 @@ static void resume_emul(void)
XSync(x_display, false);
// Reopen full screen display
XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
XMapRaised(x_display, the_win);
wait_mapped(the_win);
XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
Window w = is_fbdev_dga_mode ? the_win : rootwin;
XGrabKeyboard(x_display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(x_display, w, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
disable_mouse_accel();
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
XF86DGASetViewPort(x_display, screen, 0, 0);
if (!is_fbdev_dga_mode) {
XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
XF86DGASetViewPort(x_display, screen, 0, 0);
}
#endif
XSync(x_display, false);
@ -1387,9 +1679,9 @@ static void resume_emul(void)
if (depth == 8)
palette_changed = true;
// Resume MacOS thread
// Unlock frame buffer (and continue MacOS thread)
UNLOCK_FRAME_BUFFER;
emul_suspended = false;
ResumeEmulator();
}
@ -1705,6 +1997,11 @@ void VideoVBL(void)
if (emerg_quit)
QuitEmulator();
// Temporarily give up frame buffer lock (this is the point where
// we are suspended when the user presses Ctrl-Tab)
UNLOCK_FRAME_BUFFER;
LOCK_FRAME_BUFFER;
// Execute video VBL
if (private_data != NULL && private_data->interruptsEnabled)
VSLDoInterruptService(private_data->vslServiceID);
@ -1984,7 +2281,7 @@ static void handle_palette_changes(void)
}
#ifdef ENABLE_XF86_DGA
if (display_type == DIS_SCREEN) {
if (display_type == DIS_SCREEN && !is_fbdev_dga_mode) {
current_dga_cmap ^= 1;
if (!IsDirectMode(mode) && cmap[current_dga_cmap])
XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
@ -2029,8 +2326,11 @@ static void *redraw_func(void *arg)
quit_full_screen = false;
if (display_type == DIS_SCREEN) {
XDisplayLock();
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, 0);
if (is_fbdev_dga_mode)
XF86DGADirectVideo(x_display, screen, 0);
#endif
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
XUnmapWindow(x_display, the_win);