60 |
|
#include "user_strings.h" |
61 |
|
#include "video.h" |
62 |
|
|
63 |
< |
#define DEBUG 1 |
63 |
> |
#define DEBUG 0 |
64 |
|
#include "debug.h" |
65 |
|
|
66 |
|
|
81 |
|
static int16 mouse_wheel_lines = 3; |
82 |
|
|
83 |
|
static int display_type = DISPLAY_WINDOW; // See enum above |
84 |
+ |
static bool local_X11; // Flag: X server running on local machine? |
85 |
|
static uint8 *the_buffer; // Mac frame buffer |
86 |
|
|
87 |
|
#ifdef HAVE_PTHREADS |
165 |
|
|
166 |
|
|
167 |
|
// From main_unix.cpp |
168 |
+ |
extern char *x_display_name; |
169 |
|
extern Display *x_display; |
170 |
|
|
171 |
|
// From sys_unix.cpp |
251 |
|
|
252 |
|
// Read frame skip prefs |
253 |
|
frame_skip = PrefsFindInt32("frameskip"); |
252 |
– |
if (frame_skip == 0) |
253 |
– |
frame_skip = 1; |
254 |
|
|
255 |
|
// Create window |
256 |
|
XSetWindowAttributes wattr; |
290 |
|
|
291 |
|
// Try to create and attach SHM image |
292 |
|
have_shm = false; |
293 |
< |
if (depth != 1 && XShmQueryExtension(x_display)) { |
293 |
> |
if (depth != 1 && local_X11 && XShmQueryExtension(x_display)) { |
294 |
|
|
295 |
|
// Create SHM image ("height + 2" for safety) |
296 |
|
img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height); |
341 |
|
img->bitmap_bit_order = MSBFirst; |
342 |
|
} |
343 |
|
|
344 |
< |
// Allocate memory for frame buffer copy |
344 |
> |
// Allocate memory for frame buffer |
345 |
|
the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line); |
346 |
|
|
347 |
|
// Create GC |
349 |
|
XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes); |
350 |
|
|
351 |
|
// Create no_cursor |
352 |
< |
mac_cursor = XCreatePixmapCursor (x_display, |
353 |
< |
XCreatePixmap (x_display, the_win, 1, 1, 1), |
354 |
< |
XCreatePixmap (x_display, the_win, 1, 1, 1), |
355 |
< |
&black, &white, 0, 0); |
356 |
< |
XDefineCursor (x_display, the_win, mac_cursor); |
352 |
> |
mac_cursor = XCreatePixmapCursor(x_display, |
353 |
> |
XCreatePixmap(x_display, the_win, 1, 1, 1), |
354 |
> |
XCreatePixmap(x_display, the_win, 1, 1, 1), |
355 |
> |
&black, &white, 0, 0); |
356 |
> |
XDefineCursor(x_display, the_win, mac_cursor); |
357 |
|
|
358 |
|
// Set VideoMonitor |
359 |
|
#ifdef WORDS_BIGENDIAN |
660 |
|
|
661 |
|
bool VideoInit(bool classic) |
662 |
|
{ |
663 |
+ |
// Check if X server runs on local machine |
664 |
+ |
local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0) |
665 |
+ |
|| (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0); |
666 |
+ |
|
667 |
|
// Init keycode translation |
668 |
|
keycode_init(); |
669 |
|
|
692 |
|
#ifdef ENABLE_XF86_DGA |
693 |
|
// DGA available? |
694 |
|
int dga_event_base, dga_error_base; |
695 |
< |
if (XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) { |
695 |
> |
if (local_X11 && XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) { |
696 |
|
int dga_flags = 0; |
697 |
|
XF86DGAQueryDirectVideo(x_display, screen, &dga_flags); |
698 |
|
has_dga = dga_flags & XF86DGADirectPresent; |
1315 |
|
// Hidden parts exposed, force complete refresh of window |
1316 |
|
case Expose: |
1317 |
|
if (display_type == DISPLAY_WINDOW) { |
1318 |
< |
int x1, y1; |
1319 |
< |
for (y1=0; y1<16; y1++) |
1320 |
< |
for (x1=0; x1<16; x1++) |
1321 |
< |
updt_box[x1][y1] = true; |
1322 |
< |
nr_boxes = 16 * 16; |
1318 |
> |
if (frame_skip == 0) { // Dynamic refresh |
1319 |
> |
int x1, y1; |
1320 |
> |
for (y1=0; y1<16; y1++) |
1321 |
> |
for (x1=0; x1<16; x1++) |
1322 |
> |
updt_box[x1][y1] = true; |
1323 |
> |
nr_boxes = 16 * 16; |
1324 |
> |
} else |
1325 |
> |
memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y); |
1326 |
|
} |
1327 |
|
break; |
1328 |
|
} |
1334 |
|
* Window display update |
1335 |
|
*/ |
1336 |
|
|
1337 |
< |
static void update_display(int ticker) |
1337 |
> |
// Dynamic display update (variable frame rate for each box) |
1338 |
> |
static void update_display_dynamic(int ticker) |
1339 |
|
{ |
1340 |
|
int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xic, xicl, xi; |
1341 |
|
int xil = 0; |
1424 |
|
} |
1425 |
|
} |
1426 |
|
|
1427 |
+ |
// Static display update (fixed frame rate, but incremental) |
1428 |
+ |
static void update_display_static(void) |
1429 |
+ |
{ |
1430 |
+ |
// Incremental update code |
1431 |
+ |
int wide = 0, high = 0, x1, x2, y1, y2, i, j; |
1432 |
+ |
int bytes_per_row = VideoMonitor.bytes_per_row; |
1433 |
+ |
int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x; |
1434 |
+ |
uint8 *p, *p2; |
1435 |
+ |
|
1436 |
+ |
// Check for first line from top and first line from bottom that have changed |
1437 |
+ |
y1 = 0; |
1438 |
+ |
for (j=0; j<VideoMonitor.y; j++) { |
1439 |
+ |
if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) { |
1440 |
+ |
y1 = j; |
1441 |
+ |
break; |
1442 |
+ |
} |
1443 |
+ |
} |
1444 |
+ |
y2 = y1 - 1; |
1445 |
+ |
for (j=VideoMonitor.y-1; j>=y1; j--) { |
1446 |
+ |
if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) { |
1447 |
+ |
y2 = j; |
1448 |
+ |
break; |
1449 |
+ |
} |
1450 |
+ |
} |
1451 |
+ |
high = y2 - y1 + 1; |
1452 |
+ |
|
1453 |
+ |
// Check for first column from left and first column from right that have changed |
1454 |
+ |
if (high) { |
1455 |
+ |
if (depth == 1) { |
1456 |
+ |
x1 = VideoMonitor.x; |
1457 |
+ |
for (j=y1; j<=y2; j++) { |
1458 |
+ |
p = &the_buffer[j * bytes_per_row]; |
1459 |
+ |
p2 = &the_buffer_copy[j * bytes_per_row]; |
1460 |
+ |
for (i=0; i<(x1>>3); i++) { |
1461 |
+ |
if (*p != *p2) { |
1462 |
+ |
x1 = i << 3; |
1463 |
+ |
break; |
1464 |
+ |
} |
1465 |
+ |
p++; |
1466 |
+ |
p2++; |
1467 |
+ |
} |
1468 |
+ |
} |
1469 |
+ |
x2 = x1; |
1470 |
+ |
for (j=y1; j<=y2; j++) { |
1471 |
+ |
p = &the_buffer[j * bytes_per_row]; |
1472 |
+ |
p2 = &the_buffer_copy[j * bytes_per_row]; |
1473 |
+ |
p += bytes_per_row; |
1474 |
+ |
p2 += bytes_per_row; |
1475 |
+ |
for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) { |
1476 |
+ |
p--; |
1477 |
+ |
p2--; |
1478 |
+ |
if (*p != *p2) { |
1479 |
+ |
x2 = i << 3; |
1480 |
+ |
break; |
1481 |
+ |
} |
1482 |
+ |
} |
1483 |
+ |
} |
1484 |
+ |
wide = x2 - x1; |
1485 |
+ |
|
1486 |
+ |
// Update copy of the_buffer |
1487 |
+ |
if (high && wide) { |
1488 |
+ |
for (j=y1; j<=y2; j++) { |
1489 |
+ |
i = j * bytes_per_row + (x1 >> 3); |
1490 |
+ |
memcpy(the_buffer_copy + i, the_buffer + i, wide >> 3); |
1491 |
+ |
} |
1492 |
+ |
} |
1493 |
+ |
|
1494 |
+ |
} else { |
1495 |
+ |
x1 = VideoMonitor.x; |
1496 |
+ |
for (j=y1; j<=y2; j++) { |
1497 |
+ |
p = &the_buffer[j * bytes_per_row]; |
1498 |
+ |
p2 = &the_buffer_copy[j * bytes_per_row]; |
1499 |
+ |
for (i=0; i<x1; i++) { |
1500 |
+ |
if (memcmp(p, p2, bytes_per_pixel)) { |
1501 |
+ |
x1 = i; |
1502 |
+ |
break; |
1503 |
+ |
} |
1504 |
+ |
p += bytes_per_pixel; |
1505 |
+ |
p2 += bytes_per_pixel; |
1506 |
+ |
} |
1507 |
+ |
} |
1508 |
+ |
x2 = x1; |
1509 |
+ |
for (j=y1; j<=y2; j++) { |
1510 |
+ |
p = &the_buffer[j * bytes_per_row]; |
1511 |
+ |
p2 = &the_buffer_copy[j * bytes_per_row]; |
1512 |
+ |
p += bytes_per_row; |
1513 |
+ |
p2 += bytes_per_row; |
1514 |
+ |
for (i=VideoMonitor.x; i>x2; i--) { |
1515 |
+ |
p -= bytes_per_pixel; |
1516 |
+ |
p2 -= bytes_per_pixel; |
1517 |
+ |
if (memcmp(p, p2, bytes_per_pixel)) { |
1518 |
+ |
x2 = i; |
1519 |
+ |
break; |
1520 |
+ |
} |
1521 |
+ |
} |
1522 |
+ |
} |
1523 |
+ |
wide = x2 - x1; |
1524 |
+ |
|
1525 |
+ |
// Update copy of the_buffer |
1526 |
+ |
if (high && wide) { |
1527 |
+ |
for (j=y1; j<=y2; j++) { |
1528 |
+ |
i = j * bytes_per_row + x1 * bytes_per_pixel; |
1529 |
+ |
memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * wide); |
1530 |
+ |
} |
1531 |
+ |
} |
1532 |
+ |
} |
1533 |
+ |
} |
1534 |
+ |
|
1535 |
+ |
// Refresh display |
1536 |
+ |
if (high && wide) { |
1537 |
+ |
if (have_shm) |
1538 |
+ |
XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0); |
1539 |
+ |
else |
1540 |
+ |
XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high); |
1541 |
+ |
} |
1542 |
+ |
} |
1543 |
+ |
|
1544 |
|
|
1545 |
|
/* |
1546 |
|
* Thread for screen refresh, input handling etc. |
1593 |
|
static int tick_counter = 0; |
1594 |
|
if (display_type == DISPLAY_WINDOW) { |
1595 |
|
tick_counter++; |
1596 |
< |
update_display(tick_counter); |
1596 |
> |
if (frame_skip == 0) |
1597 |
> |
update_display_dynamic(tick_counter); |
1598 |
> |
else if (tick_counter >= frame_skip) { |
1599 |
> |
tick_counter = 0; |
1600 |
> |
update_display_static(); |
1601 |
> |
} |
1602 |
|
} |
1603 |
|
} |
1604 |
|
|