mirror of
https://github.com/ctm/executor.git
synced 2024-09-25 22:56:22 +00:00
523 lines
13 KiB
C
523 lines
13 KiB
C
/* Copyright 1995 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_xdata[] =
|
|
"$Id: xdata.c 87 2005-05-25 01:57:33Z ctm $";
|
|
#endif
|
|
|
|
#include "rsys/common.h"
|
|
|
|
#include "MemoryMgr.h"
|
|
|
|
#include "rsys/xdata.h"
|
|
#include "rsys/xdblt.h"
|
|
#include "rsys/tempalloc.h"
|
|
#include "rsys/mman.h"
|
|
|
|
#include "rsys/vdriver.h"
|
|
|
|
boolean_t
|
|
update_xdata_if_needed (xdata_handle_t xh, PixPat *pixpat,
|
|
PixMap *dest)
|
|
{
|
|
xdata_t *x;
|
|
|
|
x = STARH (xh);
|
|
|
|
if (x->ctab_seed_x != CTAB_SEED_X (MR (dest->pmTable))
|
|
|| (1 << x->log2_bpp) != CW (dest->pixelSize)
|
|
|| (x->log2_bpp >= 4 && x->rgb_spec != pixmap_rgb_spec (dest)))
|
|
{
|
|
if (x->raw_pat_bits_mem)
|
|
DisposPtr (x->raw_pat_bits_mem);
|
|
xdata_for_pixpat_with_space (pixpat, dest, xh);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static void
|
|
raw_bits_for_pattern (const Pattern pattern, PixMap *target,
|
|
uint32 *bits, int *row_bytes)
|
|
{
|
|
/* this is a template pattern to be used as the source
|
|
when performing the conversion from the old style
|
|
pattern to the destination */
|
|
static PixMap pattern_pixmap_tmpl =
|
|
{
|
|
/* baseAddr; to be filled in later */
|
|
NULL,
|
|
PIXMAP_DEFAULT_ROWBYTES_X | CWC (1),
|
|
{ CWC (0), CWC (0), CWC (8), CWC (8) },
|
|
/* version */
|
|
CWC (0),
|
|
CWC (0),
|
|
CWC (0),
|
|
|
|
CWC (72), CWC (72),
|
|
|
|
CWC (0),
|
|
/* 1bpp */
|
|
CWC (1),
|
|
/* 1 component */
|
|
CWC (1), CWC (1),
|
|
CWC (0),
|
|
/* color table; to be filled in later */
|
|
NULL,
|
|
|
|
CLC (0),
|
|
};
|
|
/* this is a template pattern to be used as the dest
|
|
when performing the conversion from the old style
|
|
pattern to the destination */
|
|
static PixMap dst_pixmap_tmpl =
|
|
{
|
|
/* baseAddr; to be filled in later */
|
|
NULL,
|
|
0,
|
|
{ CWC (0), CWC (0), CWC (8), CWC (8) },
|
|
/* version */
|
|
CWC (0),
|
|
CWC (0),
|
|
CWC (0),
|
|
|
|
CWC (72), CWC (72),
|
|
|
|
CWC (0),
|
|
CWC (0),
|
|
CWC (0), CWC (0),
|
|
CWC (0),
|
|
/* color table; to be filled in later */
|
|
NULL,
|
|
|
|
CLC (0),
|
|
};
|
|
CTabPtr conv_table;
|
|
CTabHandle fg_bk_ctab;
|
|
int dst_row_bytes, target_depth;
|
|
|
|
pattern_pixmap_tmpl.baseAddr = RM ((Ptr) &pattern[0]);
|
|
fg_bk_ctab = validate_fg_bk_ctab ();
|
|
pattern_pixmap_tmpl.pmTable = RM (ROMlib_bw_ctab);
|
|
conv_table = alloca (CTAB_STORAGE_FOR_SIZE (1));
|
|
conv_table->ctSeed = CTAB_SEED_X (fg_bk_ctab);
|
|
conv_table->ctFlags = CWC (0);
|
|
conv_table->ctSize = CWC (1);
|
|
|
|
conv_table->ctTable[0].value = CWC (0);
|
|
conv_table->ctTable[1].value = CWC (~0);
|
|
|
|
target_depth = CW (target->pixelSize);
|
|
dst_row_bytes = target_depth; /* old-style Patterns always 8 pixels wide. */
|
|
*row_bytes = dst_row_bytes;
|
|
dst_pixmap_tmpl.rowBytes = (CW (dst_row_bytes)
|
|
| (target->rowBytes & ROWBYTES_FLAG_BITS_X)
|
|
| PIXMAP_DEFAULT_ROWBYTES_X);
|
|
pixmap_set_pixel_fields (&dst_pixmap_tmpl, target_depth);
|
|
if (target_depth > 8
|
|
&& active_screen_addr_p (target))
|
|
dst_pixmap_tmpl.pixelType = CWC (vdriver_rgb_pixel_type);
|
|
|
|
dst_pixmap_tmpl.pmTable = PIXMAP_TABLE_X (GD_PMAP (MR (TheGDevice)));
|
|
dst_pixmap_tmpl.baseAddr = (Ptr) RM (bits);
|
|
|
|
convert_pixmap (&pattern_pixmap_tmpl, &dst_pixmap_tmpl,
|
|
&ROMlib_pattern_bounds, conv_table);
|
|
}
|
|
|
|
|
|
static void
|
|
raw_bits_for_color_pattern (PixPatPtr pixpat, PixMap *target,
|
|
uint32 *bits, int *row_bytesp)
|
|
{
|
|
PixMapHandle patmap;
|
|
|
|
patmap = MR (pixpat->patMap);
|
|
LOCK_HANDLE_EXCURSION_1
|
|
(patmap,
|
|
{
|
|
int row_bytes;
|
|
int target_depth;
|
|
PixMap *src;
|
|
PixMap dst;
|
|
Handle data;
|
|
const Rect *bounds;
|
|
|
|
src = STARH (patmap);
|
|
bounds = &src->bounds;
|
|
target_depth = CW (target->pixelSize);
|
|
row_bytes = ((RECT_WIDTH (bounds) * target_depth) + 7) / 8;
|
|
*row_bytesp = row_bytes;
|
|
|
|
dst = *target;
|
|
dst.bounds = *bounds;
|
|
dst.rowBytes = (CW (row_bytes)
|
|
| (target->rowBytes & ROWBYTES_FLAG_BITS_X)
|
|
| PIXMAP_DEFAULT_ROWBYTES_X);
|
|
dst.baseAddr = (Ptr) RM (bits);
|
|
|
|
data = MR (pixpat->patData);
|
|
|
|
LOCK_HANDLE_EXCURSION_1
|
|
(data,
|
|
{
|
|
src->baseAddr = data->p;
|
|
convert_pixmap (src, &dst, bounds, NULL);
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
static void
|
|
raw_bits_for_rgb_pattern (PixPatPtr pixpat, PixMap *target,
|
|
uint32 *bits, int *row_bytes)
|
|
{
|
|
uint32 actual_value;
|
|
RGBColor desired_color;
|
|
int target_depth;
|
|
|
|
/* The color desired for this pixpat is stored in the 5th color
|
|
* table entry for the pixpat. We copy the color in case any of the
|
|
* relevant handles move when we call Color2Index.
|
|
*/
|
|
desired_color = CTAB_TABLE (PIXMAP_TABLE (MR (pixpat->patMap)))[4].rgb;
|
|
|
|
target_depth = CW (target->pixelSize);
|
|
|
|
if (target_depth <= 8)
|
|
{
|
|
actual_value = Color2Index (&desired_color);
|
|
|
|
switch (target_depth)
|
|
{
|
|
case 1:
|
|
actual_value = ((int32) (actual_value << 31)) >> 31;
|
|
break;
|
|
case 2:
|
|
actual_value = (actual_value & 3) * 0x55555555U;
|
|
break;
|
|
case 4:
|
|
actual_value = (actual_value & 0xF) * 0x11111111U;
|
|
break;
|
|
case 8:
|
|
actual_value = (actual_value & 0xFF) * 0x01010101U;
|
|
break;
|
|
default:
|
|
gui_abort ();
|
|
}
|
|
}
|
|
else /* RGB pixel. */
|
|
{
|
|
const rgb_spec_t *rgb_spec;
|
|
|
|
rgb_spec = pixmap_rgb_spec (target);
|
|
gui_assert (rgb_spec != NULL);
|
|
|
|
actual_value = (*rgb_spec->rgbcolor_to_pixel) (rgb_spec, &desired_color,
|
|
TRUE);
|
|
if (target_depth == 16)
|
|
actual_value |= (actual_value << 16);
|
|
}
|
|
|
|
bits[0] = actual_value;
|
|
*row_bytes = 4;
|
|
}
|
|
|
|
|
|
static void
|
|
raw_bits_for_pixpat (PixPat *pixpat, PixMap *target,
|
|
uint32 *bits, int *row_bytes, int *height_override)
|
|
{
|
|
switch (pixpat->patType)
|
|
{
|
|
case CWC (pixpat_old_style_pattern):
|
|
raw_bits_for_pattern (pixpat->pat1Data, target, bits, row_bytes);
|
|
break;
|
|
case CWC (pixpat_color_pattern):
|
|
raw_bits_for_color_pattern (pixpat, target, bits, row_bytes);
|
|
break;
|
|
case CWC (pixpat_rgb_pattern):
|
|
raw_bits_for_rgb_pattern (pixpat, target, bits, row_bytes);
|
|
*height_override = 1;
|
|
break;
|
|
default:
|
|
/* Error! Bogus pixpat type. */
|
|
*row_bytes = 4;
|
|
*bits = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Returns TRUE iff the specified pattern can be compressed to be only
|
|
* four bytes wide with no loss of information.
|
|
*/
|
|
static inline boolean_t
|
|
narrow_p (const uint32 *bits, int row_longs, int height)
|
|
{
|
|
const uint32 *p, *end;
|
|
|
|
end = &bits[row_longs * height];
|
|
|
|
for (p = bits; p != end; p += row_longs)
|
|
{
|
|
uint32 v = p[0];
|
|
int i;
|
|
|
|
for (i = row_longs - 1; i > 0; i--)
|
|
if (p[i] != v)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Returns TRUE iff the specified pattern can be compressed to be only
|
|
* one row tall with no loss of information.
|
|
*/
|
|
static inline boolean_t
|
|
short_p (const uint32 *bits, int row_longs, int height)
|
|
{
|
|
const uint8 *p, *end;
|
|
int row_bytes;
|
|
|
|
row_bytes = row_longs * sizeof (uint32);
|
|
end = ((const uint8 *) bits) + row_bytes * height;
|
|
for (p = ((const uint8 *) bits) + row_bytes; p != end; p += row_bytes)
|
|
{
|
|
if (memcmp (bits, p, row_bytes))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Don't call this directly, use the `xdata_for_pixpat' macro. */
|
|
static void
|
|
xdata_for_raw_data (PixMap *target, xdata_t *x, uint32 *raw_bits,
|
|
int row_bytes, int height)
|
|
{
|
|
uint32 *p, v;
|
|
unsigned row_longs;
|
|
|
|
memset (x, 0, sizeof *x);
|
|
|
|
x->magic_cookie = XDATA_MAGIC_COOKIE;
|
|
x->log2_bpp = ROMlib_log2[CW (target->pixelSize)];
|
|
x->ctab_seed_x = CTAB_SEED_X (MR (target->pmTable));
|
|
x->rgb_spec = pixmap_rgb_spec (target);
|
|
|
|
/* See if it's not a full long wide. */
|
|
if (row_bytes < 4)
|
|
{
|
|
int y;
|
|
|
|
/* Tile the raw bits out to four bytes wide. We do this
|
|
* by converting rows in backwards order, so we don't smash
|
|
* anything before we use it.
|
|
*/
|
|
if (row_bytes == 1)
|
|
{
|
|
for (y = height - 1; y >= 0; y--)
|
|
raw_bits[y] = (((const uint8 *) raw_bits)[y]) * 0x01010101U;
|
|
}
|
|
else if (row_bytes == 2)
|
|
{
|
|
for (y = height - 1; y >= 0; y--)
|
|
raw_bits[y] = (((const uint16 *) raw_bits)[y]) * 0x00010001U;
|
|
}
|
|
else
|
|
abort ();
|
|
|
|
row_bytes = 4;
|
|
}
|
|
|
|
row_longs = row_bytes >> 2;
|
|
|
|
/* Check for a short & narrow pattern (i.e. one that can be
|
|
* compressed to only one row tall and 4 bytes wide with no
|
|
* loss of information). This is a common case because solid
|
|
* colors are so common.
|
|
*/
|
|
v = raw_bits[0];
|
|
for (p = &raw_bits[row_longs * height - 1]; p != raw_bits; p--)
|
|
if (*p != v)
|
|
break;
|
|
|
|
if (p == raw_bits) /* is every uint32 in the pattern the same? */
|
|
{
|
|
int shift;
|
|
|
|
/* short & narrow. */
|
|
x->pat_value = v;
|
|
x->row_bytes = 4;
|
|
x->log2_row_bytes = 2;
|
|
x->byte_size = 4;
|
|
x->row_bits_minus_1 = 31;
|
|
x->height_minus_1 = 0;
|
|
|
|
/* Choose the fastest blitting function we can use. */
|
|
if (x->rgb_spec
|
|
|| ((shift = 1 << x->log2_bpp), /* non-rgb ==> shift < 32 */
|
|
(v != ((v >> shift) | (v << (32 - shift))))))
|
|
{
|
|
x->blt_func = xdblt_xdata_short_narrow;
|
|
x->stub_table_for_mode = xdblt_short_narrow_stubs;
|
|
}
|
|
else
|
|
{
|
|
x->blt_func = xdblt_xdata_norgb_norotate;
|
|
if (v == 0)
|
|
x->stub_table_for_mode = xdblt_zeros_stubs;
|
|
else if (v == (uint32) ~0)
|
|
x->stub_table_for_mode = xdblt_ones_stubs;
|
|
else
|
|
x->stub_table_for_mode = xdblt_short_narrow_stubs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (narrow_p (raw_bits, row_longs, height))
|
|
{
|
|
int i;
|
|
|
|
/* narrow. */
|
|
|
|
/* Allocate some memory, and compute a long-aligned
|
|
* pointer for it. We can't use a Handle here because
|
|
* the Handle might move in such a way as to become no
|
|
* longer long-aligned.
|
|
*/
|
|
x->raw_pat_bits_mem = NewPtr (height * sizeof (uint32) + 3);
|
|
x->pat_bits = (uint32 *) (((unsigned long) x->raw_pat_bits_mem
|
|
+ 3) & ~3);
|
|
for (i = 0; i < height; i++)
|
|
x->pat_bits[i] = raw_bits[i * row_longs];
|
|
x->stub_table_for_mode = xdblt_tall_narrow_stubs;
|
|
|
|
x->row_bytes = sizeof (uint32);
|
|
x->log2_row_bytes = 2;
|
|
x->row_bits_minus_1 = 31;
|
|
x->byte_size = height * sizeof (uint32);
|
|
}
|
|
else /* wide */
|
|
{
|
|
int log2_row_bytes, c;
|
|
|
|
if (short_p (raw_bits, row_longs, height))
|
|
height = 1;
|
|
|
|
for (log2_row_bytes = 0, c = row_bytes; c >>= 1; log2_row_bytes++)
|
|
;
|
|
|
|
x->log2_row_bytes = log2_row_bytes;
|
|
x->row_bytes = row_bytes;
|
|
x->row_bits_minus_1 = (row_bytes * 8) - 1;
|
|
x->byte_size = height << log2_row_bytes;
|
|
|
|
/* Allocate long-aligned memory, as described above. */
|
|
x->raw_pat_bits_mem = NewPtr (x->byte_size + 3);
|
|
x->pat_bits = (uint32 *) (((unsigned long) x->raw_pat_bits_mem
|
|
+ 3) & ~3);
|
|
memcpy (x->pat_bits, raw_bits, x->byte_size);
|
|
|
|
if (height == 1)
|
|
x->stub_table_for_mode = xdblt_short_wide_stubs;
|
|
else
|
|
x->stub_table_for_mode = xdblt_tall_wide_stubs;
|
|
}
|
|
|
|
x->blt_func = xdblt_xdata_complex;
|
|
x->height_minus_1 = height - 1;
|
|
}
|
|
}
|
|
|
|
|
|
xdata_handle_t
|
|
xdata_for_pixpat_with_space (PixPat *pixpat, PixMap *target,
|
|
xdata_handle_t xh)
|
|
{
|
|
uint32 *raw_bits;
|
|
int height;
|
|
unsigned width;
|
|
int max_byte_size, row_bytes;
|
|
TEMP_ALLOC_DECL (raw_bits_temp_storage);
|
|
|
|
LOCK_HANDLE_EXCURSION_1
|
|
(xh,
|
|
{
|
|
xdata_t *x = STARH (xh);
|
|
|
|
/* Compute the dimensions of the PixPat, and allocate scratch
|
|
* space for the biggest possible bitmap that might be required.
|
|
*/
|
|
{
|
|
const Rect *bounds = &PIXMAP_BOUNDS (MR (pixpat->patMap));
|
|
height = RECT_HEIGHT (bounds);
|
|
width = RECT_WIDTH (bounds);
|
|
}
|
|
max_byte_size = width * sizeof (uint32) * height;
|
|
TEMP_ALLOC_ALLOCATE (raw_bits, raw_bits_temp_storage, max_byte_size);
|
|
|
|
/* Compute the raw bits for this pixpat. */
|
|
raw_bits_for_pixpat (pixpat, target, raw_bits, &row_bytes, &height);
|
|
|
|
/* Crank out the xdata. */
|
|
xdata_for_raw_data (target, x, raw_bits, row_bytes, height);
|
|
|
|
TEMP_ALLOC_FREE (raw_bits_temp_storage);
|
|
});
|
|
|
|
return xh;
|
|
}
|
|
|
|
|
|
xdata_handle_t
|
|
xdata_for_pattern (const Pattern pattern, PixMap *target)
|
|
{
|
|
xdata_handle_t xh;
|
|
|
|
xh = (xdata_handle_t) NewHandle (sizeof (xdata_t));
|
|
|
|
LOCK_HANDLE_EXCURSION_1
|
|
(xh,
|
|
{
|
|
uint32 raw_bits[8 * 8]; /* Maximum possible resultant pattern size. */
|
|
int row_bytes;
|
|
xdata_t *x = STARH (xh);
|
|
|
|
/* Compute the raw bits for this pixpat and crank out the xdata. */
|
|
raw_bits_for_pattern (pattern, target, raw_bits, &row_bytes);
|
|
xdata_for_raw_data (target, x, raw_bits, row_bytes, 8);
|
|
});
|
|
|
|
return xh;
|
|
}
|
|
|
|
|
|
void
|
|
xdata_free (xdata_handle_t xh)
|
|
{
|
|
boolean_t xdata_valid_p;
|
|
|
|
xdata_valid_p = xh && (GetHandleSize ((Handle) xh) == sizeof (xdata_t));
|
|
|
|
if (xdata_valid_p)
|
|
{
|
|
Ptr p = HxX (xh, raw_pat_bits_mem);
|
|
if (p)
|
|
DisposPtr (p);
|
|
}
|
|
else
|
|
{
|
|
warning_unexpected ("invalid xdata size; appl juked xdata maybe");
|
|
}
|
|
DisposHandle ((Handle) xh);
|
|
}
|