mirror of
https://github.com/ctm/executor.git
synced 2024-09-25 22:56:22 +00:00
153 lines
3.8 KiB
C
153 lines
3.8 KiB
C
/* Copyright 1995 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_autorefresh[] =
|
|
"$Id: autorefresh.c 63 2004-12-24 18:19:43Z ctm $";
|
|
#endif
|
|
|
|
#include "rsys/common.h"
|
|
#include "rsys/autorefresh.h"
|
|
#include "rsys/vdriver.h"
|
|
#include "rsys/refresh.h"
|
|
#include "rsys/flags.h"
|
|
#include "rsys/prefs.h"
|
|
|
|
|
|
/* This file provides a mechanism to detect when applications are
|
|
* bypassing QuickDraw and writing directly to screen memory.
|
|
* It works by partitioning the screen into NUM_AUTOREFRESH_STRIPS
|
|
* horizontal strips of equal size. Each strip is periodically
|
|
* checksummed and compared against the last checksum. If the
|
|
* checksum value changes, and QuickDraw didn't change that area
|
|
* of the screen, we know we need to turn on "refresh" mode.
|
|
*/
|
|
|
|
|
|
static boolean_t executor_changed_screen_p[NUM_AUTOREFRESH_STRIPS];
|
|
|
|
|
|
/* Check auto refresh? */
|
|
boolean_t do_autorefresh_p;
|
|
|
|
|
|
/* Returns a value that will tend to change when the screen contents change
|
|
* for the specified horizontal strip on the screen.
|
|
*/
|
|
static uint32
|
|
checksum_strip (int which_strip)
|
|
{
|
|
int n, row_size, strip_rows, next_row_delta;
|
|
const uint32 *base;
|
|
uint32 sum;
|
|
|
|
strip_rows = vdriver_height / NUM_AUTOREFRESH_STRIPS;
|
|
base = (const uint32 *) (vdriver_fbuf
|
|
+ which_strip * strip_rows * vdriver_row_bytes);
|
|
row_size = vdriver_row_bytes / (4U * sizeof (uint32));
|
|
next_row_delta = (vdriver_row_bytes * 2 / sizeof (uint32)) - (row_size * 4U);
|
|
|
|
/* Sum (most of) the longs on every other row in this strip. */
|
|
for (sum = 0, n = strip_rows; n > 0; n -= 2)
|
|
{
|
|
int r;
|
|
|
|
for (r = row_size; r > 0; r--)
|
|
{
|
|
#if defined (i386)
|
|
uint32 t1, t2;
|
|
|
|
/* Hand-scheduled for the Pentium. gcc does a terrible job. */
|
|
asm ("movl (%3),%1\n\t"
|
|
"movl 4(%3),%2\n\t"
|
|
"addl %1,%0\n\t"
|
|
"movl 8(%3),%1\n\t"
|
|
"addl %2,%0\n\t"
|
|
"movl 12(%3),%2\n\t"
|
|
"addl %1,%0\n\t"
|
|
"addl $16,%3\n\t"
|
|
"addl %2,%0"
|
|
: "=r" (sum), "=r" (t1), "=r" (t2), "=r" (base)
|
|
: "0" (sum), "3" (base)
|
|
: "cc");
|
|
#else
|
|
sum += base[0] + base[1] + base[2] + base[3];
|
|
base += 4;
|
|
#endif
|
|
}
|
|
|
|
base += next_row_delta;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
|
|
/* Call this when part of the screen has been changed by Executor,
|
|
* so we don't mistakenly think we need refresh mode.
|
|
*/
|
|
void
|
|
note_executor_changed_screen (int top, int bottom)
|
|
{
|
|
int i, first, last, strip_rows;
|
|
|
|
strip_rows = vdriver_height / NUM_AUTOREFRESH_STRIPS;
|
|
first = top / strip_rows;
|
|
last = (bottom - 1) / strip_rows;
|
|
|
|
if (first >= (int) NUM_AUTOREFRESH_STRIPS || last < 0)
|
|
return;
|
|
|
|
if (first < 0)
|
|
first = 0;
|
|
if (last > (int) NUM_AUTOREFRESH_STRIPS - 1)
|
|
last = NUM_AUTOREFRESH_STRIPS - 1;
|
|
|
|
for (i = first; i <= last; i++)
|
|
executor_changed_screen_p[i] = TRUE;
|
|
}
|
|
|
|
|
|
/* Returns TRUE if refresh should be turned on. */
|
|
boolean_t
|
|
autodetect_refresh (void)
|
|
{
|
|
static uint32 last_checksum[NUM_AUTOREFRESH_STRIPS];
|
|
static boolean_t last_checksum_valid_p[NUM_AUTOREFRESH_STRIPS];
|
|
boolean_t need_refresh_p;
|
|
int i;
|
|
|
|
/* We don't need to autodetect refresh if we're already doing refresh
|
|
* or if we have direct screen access.
|
|
*/
|
|
if (ROMlib_refresh != 0 || !ROMlib_shadow_screen_p)
|
|
{
|
|
memset (last_checksum_valid_p, 0, sizeof last_checksum_valid_p);
|
|
return FALSE;
|
|
}
|
|
|
|
need_refresh_p = FALSE; /* default value */
|
|
|
|
/* Compute checksums for the screen. */
|
|
for (i = NUM_AUTOREFRESH_STRIPS - 1; i >= 0; i--)
|
|
{
|
|
if (executor_changed_screen_p[i])
|
|
{
|
|
executor_changed_screen_p[i] = FALSE; /* reset it */
|
|
last_checksum_valid_p[i] = FALSE;
|
|
}
|
|
else
|
|
{
|
|
uint32 c;
|
|
c = checksum_strip (i);
|
|
if (last_checksum_valid_p[i] && c != last_checksum[i])
|
|
need_refresh_p = TRUE;
|
|
last_checksum[i] = c;
|
|
last_checksum_valid_p[i] = TRUE;
|
|
}
|
|
}
|
|
|
|
return need_refresh_p;
|
|
}
|