mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-08-15 11:27:35 +00:00
- new window refresh code from Samuel Lander
This commit is contained in:
@@ -68,7 +68,6 @@ enum {
|
|||||||
DISPLAY_DGA // DGA fullscreen display
|
DISPLAY_DGA // DGA fullscreen display
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
||||||
const char FBDEVICES_FILE_NAME[] = DATADIR "/fbdevices";
|
const char FBDEVICES_FILE_NAME[] = DATADIR "/fbdevices";
|
||||||
@@ -128,6 +127,10 @@ static GC cursor_gc, cursor_mask_gc;
|
|||||||
static uint8 *the_buffer_copy = NULL; // Copy of Mac frame buffer
|
static uint8 *the_buffer_copy = NULL; // Copy of Mac frame buffer
|
||||||
static uint8 the_cursor[64]; // Cursor image data
|
static uint8 the_cursor[64]; // Cursor image data
|
||||||
static bool have_shm = false; // Flag: SHM extensions available
|
static bool have_shm = false; // Flag: SHM extensions available
|
||||||
|
static bool updt_box[17][17]; // Flag for Update
|
||||||
|
static int nr_boxes;
|
||||||
|
static const int sm_uptd[] = {4,1,6,3,0,5,2,7};
|
||||||
|
static int sm_no_boxes[] = {1,8,32,64,128,300};
|
||||||
|
|
||||||
// Variables for XF86 DGA mode
|
// Variables for XF86 DGA mode
|
||||||
static int current_dga_cmap; // Number (0 or 1) of currently installed DGA colormap
|
static int current_dga_cmap; // Number (0 or 1) of currently installed DGA colormap
|
||||||
@@ -214,6 +217,9 @@ static int error_handler(Display *d, XErrorEvent *e)
|
|||||||
// Init window mode
|
// Init window mode
|
||||||
static bool init_window(int width, int height)
|
static bool init_window(int width, int height)
|
||||||
{
|
{
|
||||||
|
int aligned_width = (width + 15) & ~15;
|
||||||
|
int aligned_height = (height + 15) & ~15;
|
||||||
|
|
||||||
// Set absolute mouse mode
|
// Set absolute mouse mode
|
||||||
ADBSetRelMouseMode(false);
|
ADBSetRelMouseMode(false);
|
||||||
|
|
||||||
@@ -227,7 +233,8 @@ static bool init_window(int width, int height)
|
|||||||
wattr.event_mask = eventmask = win_eventmask;
|
wattr.event_mask = eventmask = win_eventmask;
|
||||||
wattr.background_pixel = black_pixel;
|
wattr.background_pixel = black_pixel;
|
||||||
wattr.border_pixel = black_pixel;
|
wattr.border_pixel = black_pixel;
|
||||||
wattr.backing_store = Always;
|
wattr.backing_store = NotUseful;
|
||||||
|
wattr.save_under = false;
|
||||||
wattr.backing_planes = xdepth;
|
wattr.backing_planes = xdepth;
|
||||||
|
|
||||||
XSync(x_display, false);
|
XSync(x_display, false);
|
||||||
@@ -263,9 +270,9 @@ static bool init_window(int width, int height)
|
|||||||
|
|
||||||
// Create SHM image ("height + 2" for safety)
|
// Create SHM image ("height + 2" for safety)
|
||||||
img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
|
img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
|
||||||
shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
|
shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
|
||||||
the_buffer = (uint8 *)shmat(shminfo.shmid, 0, 0);
|
the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
|
||||||
shminfo.shmaddr = img->data = (char *)the_buffer;
|
shminfo.shmaddr = img->data = (char *)the_buffer_copy;
|
||||||
shminfo.readOnly = False;
|
shminfo.readOnly = False;
|
||||||
|
|
||||||
// Try to attach SHM image, catching errors
|
// Try to attach SHM image, catching errors
|
||||||
@@ -286,7 +293,7 @@ static bool init_window(int width, int height)
|
|||||||
|
|
||||||
// Create normal X image if SHM doesn't work ("height + 2" for safety)
|
// Create normal X image if SHM doesn't work ("height + 2" for safety)
|
||||||
if (!have_shm) {
|
if (!have_shm) {
|
||||||
int bytes_per_row = width;
|
int bytes_per_row = aligned_width;
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 1:
|
case 1:
|
||||||
bytes_per_row /= 8;
|
bytes_per_row /= 8;
|
||||||
@@ -300,8 +307,8 @@ static bool init_window(int width, int height)
|
|||||||
bytes_per_row *= 4;
|
bytes_per_row *= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
the_buffer = (uint8 *)malloc((height + 2) * bytes_per_row);
|
the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
|
||||||
img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer, width, height, 32, bytes_per_row);
|
img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1-Bit mode is big-endian
|
// 1-Bit mode is big-endian
|
||||||
@@ -311,24 +318,18 @@ static bool init_window(int width, int height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for frame buffer copy
|
// Allocate memory for frame buffer copy
|
||||||
the_buffer_copy = (uint8 *)malloc((height + 2) * img->bytes_per_line);
|
the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
|
||||||
|
|
||||||
// Create GC
|
// Create GC
|
||||||
the_gc = XCreateGC(x_display, the_win, 0, 0);
|
the_gc = XCreateGC(x_display, the_win, 0, 0);
|
||||||
XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
|
XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
|
||||||
|
|
||||||
// Create cursor
|
// Create no_cursor
|
||||||
cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor, 16, 16, 16, 2);
|
mac_cursor = XCreatePixmapCursor (x_display,
|
||||||
cursor_image->byte_order = MSBFirst;
|
XCreatePixmap (x_display, the_win, 1, 1, 1),
|
||||||
cursor_image->bitmap_bit_order = MSBFirst;
|
XCreatePixmap (x_display, the_win, 1, 1, 1),
|
||||||
cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor+32, 16, 16, 16, 2);
|
&black, &white, 0, 0);
|
||||||
cursor_mask_image->byte_order = MSBFirst;
|
XDefineCursor (x_display, the_win, mac_cursor);
|
||||||
cursor_mask_image->bitmap_bit_order = MSBFirst;
|
|
||||||
cursor_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
|
|
||||||
cursor_mask_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
|
|
||||||
cursor_gc = XCreateGC(x_display, cursor_map, 0, 0);
|
|
||||||
cursor_mask_gc = XCreateGC(x_display, cursor_mask_map, 0, 0);
|
|
||||||
mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, 0, 0);
|
|
||||||
|
|
||||||
// Set VideoMonitor
|
// Set VideoMonitor
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
@@ -845,17 +846,22 @@ void VideoExit(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (the_buffer_copy) {
|
|
||||||
free(the_buffer_copy);
|
|
||||||
the_buffer_copy = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
XFlush(x_display);
|
XFlush(x_display);
|
||||||
XSync(x_display, false);
|
XSync(x_display, false);
|
||||||
if (depth == 8) {
|
if (depth == 8) {
|
||||||
XFreeColormap(x_display, cmap[0]);
|
XFreeColormap(x_display, cmap[0]);
|
||||||
XFreeColormap(x_display, cmap[1]);
|
XFreeColormap(x_display, cmap[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (the_buffer) {
|
||||||
|
free(the_buffer);
|
||||||
|
the_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_shm && the_buffer_copy) {
|
||||||
|
free(the_buffer_copy);
|
||||||
|
the_buffer_copy = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1261,8 +1267,13 @@ static void handle_events(void)
|
|||||||
|
|
||||||
// Hidden parts exposed, force complete refresh of window
|
// Hidden parts exposed, force complete refresh of window
|
||||||
case Expose:
|
case Expose:
|
||||||
if (display_type == DISPLAY_WINDOW)
|
if (display_type == DISPLAY_WINDOW) {
|
||||||
memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
|
int x1, y1;
|
||||||
|
for (y1=0; y1<16; y1++)
|
||||||
|
for (x1=0; x1<16; x1++)
|
||||||
|
updt_box[x1][y1] = true;
|
||||||
|
nr_boxes = 16 * 16;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1273,139 +1284,92 @@ static void handle_events(void)
|
|||||||
* Window display update
|
* Window display update
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void update_display(void)
|
static void update_display(int ticker)
|
||||||
{
|
{
|
||||||
// In classic mode, copy the frame buffer from Mac RAM
|
int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xic, xicl, xi;
|
||||||
if (classic_mode)
|
int xil = 0;
|
||||||
Mac2Host_memcpy(the_buffer, 0x3fa700, VideoMonitor.bytes_per_row * VideoMonitor.y);
|
int rxm = 0, rxmo = 0;
|
||||||
|
|
||||||
// Incremental update code
|
|
||||||
int wide = 0, high = 0, x1, x2, y1, y2, i, j;
|
|
||||||
int bytes_per_row = VideoMonitor.bytes_per_row;
|
int bytes_per_row = VideoMonitor.bytes_per_row;
|
||||||
int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
|
int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
|
||||||
uint8 *p, *p2;
|
int rx = VideoMonitor.bytes_per_row / 16;
|
||||||
|
int ry = VideoMonitor.y / 16;
|
||||||
|
int max_box;
|
||||||
|
|
||||||
// Check for first line from top and first line from bottom that have changed
|
y2s = sm_uptd[ticker % 8];
|
||||||
y1 = 0;
|
y2a = 8;
|
||||||
for (j=0; j<VideoMonitor.y; j++) {
|
for (i = 0; i < 6; i++)
|
||||||
if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
|
if (ticker % (2 << i))
|
||||||
y1 = j;
|
|
||||||
break;
|
break;
|
||||||
}
|
max_box = sm_no_boxes[i];
|
||||||
}
|
|
||||||
y2 = y1 - 1;
|
|
||||||
for (j=VideoMonitor.y-1; j>=y1; j--) {
|
|
||||||
if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
|
|
||||||
y2 = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
high = y2 - y1 + 1;
|
|
||||||
|
|
||||||
// Check for first column from left and first column from right that have changed
|
if (y2a) {
|
||||||
if (high) {
|
for (y1=0; y1<16; y1++) {
|
||||||
if (depth == 1) {
|
for (y2=y2s; y2 < ry; y2 += y2a) {
|
||||||
x1 = VideoMonitor.x;
|
i = ((y1 * ry) + y2) * bytes_per_row;
|
||||||
for (j=y1; j<=y2; j++) {
|
for (x1=0; x1<16; x1++, i += rx) {
|
||||||
p = &the_buffer[j * bytes_per_row];
|
if (updt_box[x1][y1] == false) {
|
||||||
p2 = &the_buffer_copy[j * bytes_per_row];
|
if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) {
|
||||||
for (i=0; i<(x1>>3); i++) {
|
updt_box[x1][y1] = true;
|
||||||
if (*p != *p2) {
|
nr_boxes++;
|
||||||
x1 = i << 3;
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
p++;
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x2 = x1;
|
|
||||||
for (j=y1; j<=y2; j++) {
|
|
||||||
p = &the_buffer[j * bytes_per_row];
|
|
||||||
p2 = &the_buffer_copy[j * bytes_per_row];
|
|
||||||
p += bytes_per_row;
|
|
||||||
p2 += bytes_per_row;
|
|
||||||
for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) {
|
|
||||||
p--;
|
|
||||||
p2--;
|
|
||||||
if (*p != *p2) {
|
|
||||||
x2 = i << 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wide = x2 - x1;
|
|
||||||
|
|
||||||
// Update copy of the_buffer
|
|
||||||
if (high && wide) {
|
|
||||||
for (j=y1; j<=y2; j++) {
|
|
||||||
i = j * bytes_per_row + (x1 >> 3);
|
|
||||||
memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
x1 = VideoMonitor.x;
|
|
||||||
for (j=y1; j<=y2; j++) {
|
|
||||||
p = &the_buffer[j * bytes_per_row];
|
|
||||||
p2 = &the_buffer_copy[j * bytes_per_row];
|
|
||||||
for (i=0; i<x1; i++) {
|
|
||||||
if (memcmp(p, p2, bytes_per_pixel)) {
|
|
||||||
x1 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p += bytes_per_pixel;
|
|
||||||
p2 += bytes_per_pixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x2 = x1;
|
|
||||||
for (j=y1; j<=y2; j++) {
|
|
||||||
p = &the_buffer[j * bytes_per_row];
|
|
||||||
p2 = &the_buffer_copy[j * bytes_per_row];
|
|
||||||
p += bytes_per_row;
|
|
||||||
p2 += bytes_per_row;
|
|
||||||
for (i=VideoMonitor.x; i>x2; i--) {
|
|
||||||
p -= bytes_per_pixel;
|
|
||||||
p2 -= bytes_per_pixel;
|
|
||||||
if (memcmp(p, p2, bytes_per_pixel)) {
|
|
||||||
x2 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wide = x2 - x1;
|
|
||||||
|
|
||||||
// Update copy of the_buffer
|
|
||||||
if (high && wide) {
|
|
||||||
for (j=y1; j<=y2; j++) {
|
|
||||||
i = j * bytes_per_row + x1 * bytes_per_pixel;
|
|
||||||
memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh display
|
if ((nr_boxes <= max_box) && (nr_boxes)) {
|
||||||
if (high && wide) {
|
for (y1=0; y1<16; y1++) {
|
||||||
if (have_shm)
|
for (x1=0; x1<16; x1++) {
|
||||||
XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0);
|
if (updt_box[x1][y1] == true) {
|
||||||
else
|
if (rxm == 0)
|
||||||
XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
|
xm = x1;
|
||||||
}
|
rxm += rx;
|
||||||
|
updt_box[x1][y1] = false;
|
||||||
// Has the Mac started? (cursor data is not valid otherwise)
|
}
|
||||||
if (HasMacStarted()) {
|
if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) {
|
||||||
|
if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) {
|
||||||
// Set new cursor image if it was changed
|
if (rxmo) {
|
||||||
if (memcmp(the_cursor, Mac2HostAddr(0x844), 64)) {
|
xi = xmo * rx;
|
||||||
Mac2Host_memcpy(the_cursor, 0x844, 64);
|
yi = ymo * ry;
|
||||||
memcpy(cursor_image->data, the_cursor, 32);
|
xil = rxmo;
|
||||||
memcpy(cursor_mask_image->data, the_cursor+32, 32);
|
yil = (yo - ymo +1) * ry;
|
||||||
XFreeCursor(x_display, mac_cursor);
|
}
|
||||||
XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
|
rxmo = rxm;
|
||||||
XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
|
xmo = xm;
|
||||||
mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, ReadMacInt8(0x885), ReadMacInt8(0x887));
|
ymo = y1;
|
||||||
XDefineCursor(x_display, the_win, mac_cursor);
|
}
|
||||||
|
rxm = 0;
|
||||||
|
yo = y1;
|
||||||
|
}
|
||||||
|
if (xil) {
|
||||||
|
i = (yi * bytes_per_row) + xi;
|
||||||
|
for (y2=0; y2 < yil; y2++, i += bytes_per_row)
|
||||||
|
memcpy(&the_buffer_copy[i], &the_buffer[i], xil);
|
||||||
|
if (depth == 1) {
|
||||||
|
if (have_shm)
|
||||||
|
XShmPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0);
|
||||||
|
else
|
||||||
|
XPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil);
|
||||||
|
} else {
|
||||||
|
if (have_shm)
|
||||||
|
XShmPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0);
|
||||||
|
else
|
||||||
|
XPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil);
|
||||||
|
}
|
||||||
|
xil = 0;
|
||||||
|
}
|
||||||
|
if ((x1 == 15) && (y1 == 15) && (rxmo)) {
|
||||||
|
x1--;
|
||||||
|
xi = xmo * rx;
|
||||||
|
yi = ymo * ry;
|
||||||
|
xil = rxmo;
|
||||||
|
yil = (yo - ymo +1) * ry;
|
||||||
|
rxmo = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
nr_boxes = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,13 +1439,10 @@ static void *redraw_func(void *arg)
|
|||||||
}
|
}
|
||||||
pthread_mutex_unlock(&palette_lock);
|
pthread_mutex_unlock(&palette_lock);
|
||||||
|
|
||||||
// In window mode, update display and mouse pointer
|
// In window mode, update display
|
||||||
if (display_type == DISPLAY_WINDOW) {
|
if (display_type == DISPLAY_WINDOW) {
|
||||||
tick_counter++;
|
tick_counter++;
|
||||||
if (tick_counter >= frame_skip) {
|
update_display(tick_counter);
|
||||||
tick_counter = 0;
|
|
||||||
update_display();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user