1 |
|
/* |
2 |
|
* video_x.cpp - Video/graphics emulation, X11 specific stuff |
3 |
|
* |
4 |
< |
* SheepShaver (C) 1997-2005 Marc Hellwig and Christian Bauer |
4 |
> |
* SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
37 |
|
#include <sys/shm.h> |
38 |
|
#include <errno.h> |
39 |
|
#include <pthread.h> |
40 |
+ |
#include <semaphore.h> |
41 |
|
|
42 |
|
#include <algorithm> |
43 |
|
|
54 |
|
# include <X11/extensions/xf86vmode.h> |
55 |
|
#endif |
56 |
|
|
57 |
+ |
#ifdef ENABLE_FBDEV_DGA |
58 |
+ |
# include <sys/mman.h> |
59 |
+ |
#endif |
60 |
+ |
|
61 |
|
#include "main.h" |
62 |
|
#include "adb.h" |
63 |
|
#include "prefs.h" |
88 |
|
static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread |
89 |
|
static pthread_t redraw_thread; // Redraw thread |
90 |
|
|
86 |
– |
static bool local_X11; // Flag: X server running on local machine? |
91 |
|
static volatile bool thread_stop_req = false; |
92 |
< |
static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req |
92 |
> |
static sem_t thread_stop_ack; |
93 |
> |
static sem_t thread_resume_req; |
94 |
|
|
95 |
+ |
static bool local_X11; // Flag: X server running on local machine? |
96 |
|
static bool has_dga = false; // Flag: Video DGA capable |
97 |
|
static bool has_vidmode = false; // Flag: VidMode extension available |
98 |
|
|
170 |
|
#endif |
171 |
|
|
172 |
|
// Mutex to protect palette |
173 |
< |
#ifdef HAVE_SPINLOCKS |
168 |
< |
static spinlock_t x_palette_lock = SPIN_LOCK_UNLOCKED; |
169 |
< |
#define LOCK_PALETTE spin_lock(&x_palette_lock) |
170 |
< |
#define UNLOCK_PALETTE spin_unlock(&x_palette_lock) |
171 |
< |
#elif defined(HAVE_PTHREADS) |
173 |
> |
#if defined(HAVE_PTHREADS) |
174 |
|
static pthread_mutex_t x_palette_lock = PTHREAD_MUTEX_INITIALIZER; |
175 |
|
#define LOCK_PALETTE pthread_mutex_lock(&x_palette_lock) |
176 |
|
#define UNLOCK_PALETTE pthread_mutex_unlock(&x_palette_lock) |
177 |
+ |
#elif defined(HAVE_SPINLOCKS) |
178 |
+ |
static spinlock_t x_palette_lock = SPIN_LOCK_UNLOCKED; |
179 |
+ |
#define LOCK_PALETTE spin_lock(&x_palette_lock) |
180 |
+ |
#define UNLOCK_PALETTE spin_unlock(&x_palette_lock) |
181 |
|
#else |
182 |
|
#define LOCK_PALETTE |
183 |
|
#define UNLOCK_PALETTE |
184 |
|
#endif |
185 |
|
|
186 |
|
// Mutex to protect frame buffer |
187 |
< |
#ifdef HAVE_SPINLOCKS |
182 |
< |
static spinlock_t frame_buffer_lock = SPIN_LOCK_UNLOCKED; |
183 |
< |
#define LOCK_FRAME_BUFFER spin_lock(&frame_buffer_lock) |
184 |
< |
#define UNLOCK_FRAME_BUFFER spin_unlock(&frame_buffer_lock) |
185 |
< |
#elif defined(HAVE_PTHREADS) |
187 |
> |
#if defined(HAVE_PTHREADS) |
188 |
|
static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER; |
189 |
|
#define LOCK_FRAME_BUFFER pthread_mutex_lock(&frame_buffer_lock); |
190 |
|
#define UNLOCK_FRAME_BUFFER pthread_mutex_unlock(&frame_buffer_lock); |
191 |
+ |
#elif defined(HAVE_SPINLOCKS) |
192 |
+ |
static spinlock_t frame_buffer_lock = SPIN_LOCK_UNLOCKED; |
193 |
+ |
#define LOCK_FRAME_BUFFER spin_lock(&frame_buffer_lock) |
194 |
+ |
#define UNLOCK_FRAME_BUFFER spin_unlock(&frame_buffer_lock) |
195 |
|
#else |
196 |
|
#define LOCK_FRAME_BUFFER |
197 |
|
#define UNLOCK_FRAME_BUFFER |
699 |
|
} |
700 |
|
D(bug("[fbdev] visual: %s\n", fb_visual_str)); |
701 |
|
|
702 |
< |
if (fb_visual != FB_VISUAL_TRUECOLOR) { |
702 |
> |
if (fb_visual != FB_VISUAL_TRUECOLOR && fb_visual != FB_VISUAL_DIRECTCOLOR) { |
703 |
|
D(bug("[fbdev] visual '%s' not supported\n", fb_visual_str)); |
704 |
|
return false; |
705 |
|
} |
1025 |
|
#endif |
1026 |
|
|
1027 |
|
// Zero screen buffers, viRowBytes is initialized at this stage |
1028 |
< |
memset(the_buffer, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
1029 |
< |
memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
1028 |
> |
if (display_open) { |
1029 |
> |
memset(the_buffer, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
1030 |
> |
memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
1031 |
> |
} |
1032 |
|
return display_open; |
1033 |
|
} |
1034 |
|
|
1372 |
|
|
1373 |
|
// Check if X server runs on local machine |
1374 |
|
local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0) |
1375 |
+ |
|| (strncmp(XDisplayName(x_display_name), "/", 1) == 0) |
1376 |
|
|| (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0); |
1377 |
|
|
1378 |
|
// Init keycode translation |
1648 |
|
#endif |
1649 |
|
|
1650 |
|
// Open window/screen |
1651 |
< |
if (!open_display()) |
1651 |
> |
if (!open_display()) { |
1652 |
> |
ErrorAlert(GetString(STR_OPEN_WINDOW_ERR)); |
1653 |
|
return false; |
1654 |
+ |
} |
1655 |
|
|
1656 |
|
#if 0 |
1657 |
|
// Ignore errors from now on |
1664 |
|
|
1665 |
|
// Start periodic thread |
1666 |
|
XSync(x_display, false); |
1667 |
+ |
if (sem_init(&thread_stop_ack, 0, 0) < 0) |
1668 |
+ |
return false; |
1669 |
+ |
if (sem_init(&thread_resume_req, 0, 0) < 0) |
1670 |
+ |
return false; |
1671 |
|
Set_pthread_attr(&redraw_thread_attr, 0); |
1672 |
|
redraw_thread_cancel = false; |
1673 |
|
redraw_thread_active = (pthread_create(&redraw_thread, &redraw_thread_attr, redraw_func, NULL) == 0); |
1687 |
|
redraw_thread_cancel = true; |
1688 |
|
pthread_cancel(redraw_thread); |
1689 |
|
pthread_join(redraw_thread, NULL); |
1690 |
+ |
sem_destroy(&thread_stop_ack); |
1691 |
+ |
sem_destroy(&thread_resume_req); |
1692 |
|
redraw_thread_active = false; |
1693 |
|
} |
1694 |
|
|
2166 |
|
csSave->savePage = ReadMacInt16(ParamPtr + csPage); |
2167 |
|
|
2168 |
|
// Disable interrupts and pause redraw thread |
2152 |
– |
DisableInterrupt(); |
2153 |
– |
thread_stop_ack = false; |
2169 |
|
thread_stop_req = true; |
2170 |
< |
while (!thread_stop_ack) ; |
2170 |
> |
sem_wait(&thread_stop_ack); |
2171 |
> |
thread_stop_req = false; |
2172 |
> |
DisableInterrupt(); |
2173 |
|
|
2174 |
|
/* close old display */ |
2175 |
|
close_display(); |
2190 |
|
csSave->saveMode=VModes[cur_mode].viAppleMode; |
2191 |
|
|
2192 |
|
// Enable interrupts and resume redraw thread |
2176 |
– |
thread_stop_req = false; |
2193 |
|
EnableInterrupt(); |
2194 |
+ |
sem_post(&thread_resume_req); |
2195 |
|
return noErr; |
2196 |
|
} |
2197 |
|
} |
2443 |
|
while (!redraw_thread_cancel) { |
2444 |
|
|
2445 |
|
// Pause if requested (during video mode switches) |
2446 |
< |
while (thread_stop_req) |
2447 |
< |
thread_stop_ack = true; |
2446 |
> |
if (thread_stop_req) { |
2447 |
> |
sem_post(&thread_stop_ack); |
2448 |
> |
sem_wait(&thread_resume_req); |
2449 |
> |
} |
2450 |
|
|
2451 |
|
int64 delay = next - GetTicks_usec(); |
2452 |
|
if (delay < -VIDEO_REFRESH_DELAY) { |
2560 |
|
} |
2561 |
|
return NULL; |
2562 |
|
} |
2563 |
+ |
|
2564 |
+ |
|
2565 |
+ |
/* |
2566 |
+ |
* Record dirty area from NQD |
2567 |
+ |
*/ |
2568 |
+ |
|
2569 |
+ |
void video_set_dirty_area(int x, int y, int w, int h) |
2570 |
+ |
{ |
2571 |
+ |
VideoInfo const & mode = VModes[cur_mode]; |
2572 |
+ |
const int screen_width = VIDEO_MODE_X; |
2573 |
+ |
const int screen_height = VIDEO_MODE_Y; |
2574 |
+ |
const int bytes_per_row = VIDEO_MODE_ROW_BYTES; |
2575 |
+ |
|
2576 |
+ |
#ifdef ENABLE_VOSF |
2577 |
+ |
if (use_vosf) { |
2578 |
+ |
vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row); |
2579 |
+ |
return; |
2580 |
+ |
} |
2581 |
+ |
#endif |
2582 |
+ |
|
2583 |
+ |
// XXX handle dirty bounding boxes for non-VOSF modes |
2584 |
+ |
} |