executor/src/rawsrcblt.c
2009-06-12 19:03:10 -06:00

236 lines
5.6 KiB
C

/* Copyright 1995 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_rawsrcblt[] =
"$Id: rawsrcblt.c 63 2004-12-24 18:19:43Z ctm $";
#endif
#include "rsys/common.h"
#include "rsys/srcblt.h"
#include "rsys/quick.h"
#include "rsys/xdblt.h"
#include "rsys/rawblt.h"
#if defined (USE_PORTABLE_SRCBLT)
static int srcblt_src_row_stride;
static int srcblt_dst_row_stride;
/* Dummy table, not actually dereferenced. */
const void *srcblt_nop_table[1] = { NULL };
/* This macro is used in `rawsrcstubs.c' */
#define NEXT_ROW (src = (const uint32 *) &src_row_base[s[1].offset], \
dst = (uint32 *) &dst_row_base[s[1].offset])
#include "rawsrcstubs.c"
const void **srcblt_noshift_stubs[8] = {
srcblt_copy_noshift_labels,
srcblt_or_noshift_labels,
srcblt_xor_noshift_labels,
srcblt_notand_noshift_labels,
srcblt_notcopy_noshift_labels,
srcblt_notor_noshift_labels,
srcblt_notxor_noshift_labels,
srcblt_and_noshift_labels
};
const void **srcblt_noshift_fgbk_stubs[8] = {
srcblt_copy_noshift_fgbk_labels,
srcblt_or_noshift_fgbk_labels,
srcblt_xor_noshift_labels,
srcblt_notand_noshift_fgbk_labels,
srcblt_notcopy_noshift_fgbk_labels,
srcblt_notor_noshift_fgbk_labels,
srcblt_notxor_noshift_labels,
srcblt_and_noshift_fgbk_labels
};
const void **srcblt_shift_stubs[8] = {
srcblt_copy_shift_labels,
srcblt_or_shift_labels,
srcblt_xor_shift_labels,
srcblt_notand_shift_labels,
srcblt_notcopy_shift_labels,
srcblt_notor_shift_labels,
srcblt_notxor_shift_labels,
srcblt_and_shift_labels
};
const void **srcblt_shift_fgbk_stubs[8] = {
srcblt_copy_shift_fgbk_labels,
srcblt_or_shift_fgbk_labels,
srcblt_xor_shift_labels,
srcblt_notand_shift_fgbk_labels,
srcblt_notcopy_shift_fgbk_labels,
srcblt_notor_shift_fgbk_labels,
srcblt_notxor_shift_labels,
srcblt_and_shift_fgbk_labels
};
void
srcblt_bitmap (void)
{
blt_section_t section[MAX_BLT_SECTIONS], *sec;
const INTEGER *rgn;
int x, y, next_y, start_x_bit, stop_x_bit, start_x_long, stop_x_long;
int num_rows, num_longs;
uint32 mask;
int log2_bpp;
if (srcblt_stub_table == srcblt_nop_table)
return;
if (srcblt_reverse_scanlines_p)
{
srcblt_src_row_stride = -srcblt_src_row_bytes;
srcblt_dst_row_stride = -srcblt_dst_row_bytes;
}
else
{
srcblt_src_row_stride = srcblt_src_row_bytes;
srcblt_dst_row_stride = srcblt_dst_row_bytes;
}
/* Store log2_bpp in a local variable, for speed. */
log2_bpp = srcblt_log2_bpp;
rgn = srcblt_rgn_start;
y = CW (*rgn++);
if (y == RGNSTOP)
goto done_with_scanlines;
start_scanline:
x = rgn[0];
mask = 0;
sec = section;
if (x == RGNSTOP)
goto fetch_next_y;
start_x_bit = (x << log2_bpp) + srcblt_x_offset;
still_same_long:
mask ^= xdblt_mask_array[start_x_bit & 31];
start_x_long = start_x_bit >> 5;
next_stop:
stop_x_bit = (rgn[1] << log2_bpp) + srcblt_x_offset;
rgn += 2;
stop_x_long = stop_x_bit >> 5;
num_longs = stop_x_long - start_x_long;
if (num_longs == 0)
goto same_long;
/* Different longs. */
if (mask == (uint32) ~0)
goto blt_contig;
/* Mask not solid. */
sec->label = srcblt_stub_table[MASK_STUB];
sec->offset = start_x_long << 2;
sec->arg = mask;
sec++;
if (sec >= &section[MAX_BLT_SECTIONS])
abort ();
/* account for that mask boundary long. */
--num_longs;
if (num_longs == 0)
goto xfer_done;
++start_x_long;
blt_contig:
sec->label = srcblt_stub_table[REPEAT_MOD_0_STUB
+ (num_longs % MAX_LOOP_UNWRAP)];
sec->offset = (start_x_long - ((-num_longs) % MAX_LOOP_UNWRAP)) << 2;
sec->arg = num_longs;
sec++;
xfer_done:
mask = ~0;
same_long:
/* NOTE: the start x bit fetched here may be RGNSTOP. That case
* will be detected later; RGNSTOP will cause the boundary cruft
* to get blitted just like an X not in the same long, so this
* hack works.
*/
start_x_bit = (rgn[0] << log2_bpp) + srcblt_x_offset;
mask ^= xdblt_mask_array[stop_x_bit & 31];
start_x_long = start_x_bit >> 5;
if (start_x_long == stop_x_long)
goto still_same_long;
if (mask == 0)
goto no_boundary_cruft;
sec->label = srcblt_stub_table[MASK_STUB];
sec->offset = stop_x_long << 2;
sec->arg = mask;
sec++;
if (sec >= &section[MAX_BLT_SECTIONS])
abort ();
no_boundary_cruft:
if (rgn[0] == RGNSTOP)
goto fetch_next_y;
mask = xdblt_mask_array[start_x_bit & 31];
goto next_stop;
fetch_next_y:
/* Fetch the starting y value for the next scanline. When we
* get here, rgn points to the RGNSTOP for the last scanline,
* so we have to look two bytes farther to find the next y
* value. Special regions store y's as big endian.
*/
next_y = CW (rgn[1]);
rgn += 2;
if (next_y == RGNSTOP)
goto done_with_scanlines;
/* If this is an empty scanline, don't loop, just move on. */
if (sec == section)
goto done_looping;
sec->label = srcblt_stub_table[DONE_STUB];
sec->offset = sec->arg = 0; /* won't be used */
/* don't bother incrementing sec here */
/* Compute the number of rows to blt. */
num_rows = next_y - y;
/* Call the blitter function. */
{
int first_y;
first_y = srcblt_reverse_scanlines_p ? (next_y - 1) : y;
((void (*)(const blt_section_t *, const uint8 *, uint8 *, long))
srcblt_stub_table[FUNC_PTR]) (section,
((const uint8 *) srcblt_src_baseaddr
+ (first_y * srcblt_src_row_bytes)),
((uint8 *) srcblt_dst_baseaddr
+ (first_y * srcblt_dst_row_bytes)),
num_rows);
}
done_looping:
y = next_y;
goto start_scanline;
done_with_scanlines:
;
}
#endif /* USE_PORTABLE_SRCBLT */