mirror of
https://github.com/ctm/executor.git
synced 2024-06-05 23:29:33 +00:00
297 lines
8.8 KiB
C
297 lines
8.8 KiB
C
/* Copyright 1995 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_srcblt[] =
|
|
"$Id: srcblt.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/vdriver.h"
|
|
#include "rsys/prefs.h"
|
|
#include "rsys/host.h"
|
|
|
|
int srcblt_log2_bpp asm ("_srcblt_log2_bpp");
|
|
|
|
const INTEGER *srcblt_rgn_start asm ("_srcblt_rgn_start");
|
|
|
|
const void **srcblt_stub_table asm ("_srcblt_stub_table");
|
|
|
|
int32 srcblt_x_offset asm ("_srcblt_x_offset");
|
|
|
|
int32 srcblt_src_row_bytes asm ("_srcblt_src_row_bytes");
|
|
int32 srcblt_dst_row_bytes asm ("_srcblt_dst_row_bytes");
|
|
|
|
uint32 srcblt_fg_color asm ("_srcblt_fg_color");
|
|
uint32 srcblt_bk_color asm ("_srcblt_bk_color");
|
|
|
|
char *srcblt_src_baseaddr asm ("_srcblt_src_baseaddr");
|
|
char *srcblt_dst_baseaddr asm ("_srcblt_dst_baseaddr");
|
|
|
|
int srcblt_shift_offset asm ("_srcblt_shift_offset");
|
|
|
|
boolean_t srcblt_reverse_scanlines_p asm ("_srcblt_reverse_scanlines_p");
|
|
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
uint16 srcblt_src_selector asm ("_srcblt_src_selector");
|
|
uint16 srcblt_dst_selector asm ("_srcblt_dst_selector");
|
|
#endif
|
|
|
|
/* We use this macro to avoid page faults when aligning pointers. */
|
|
#define MIN_PAGE_SIZE 512
|
|
|
|
|
|
boolean_t
|
|
srcblt_rgn (RgnHandle rh, int mode, int log2_bpp,
|
|
const blt_bitmap_t *src, const blt_bitmap_t *dst,
|
|
Point *src_origin, Point *dst_origin,
|
|
uint32 fg_color, uint32 bk_color)
|
|
{
|
|
uint32 mask, tile;
|
|
unsigned long dst_align32_offset, src_align32_offset;
|
|
long src_x_offset, src_y_offset, left_shift;
|
|
char *dst_baseaddr, *src_baseaddr;
|
|
#if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS)
|
|
boolean_t cursor_maybe_changed_p, old_vis_p;
|
|
#endif
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
boolean_t needs_seg_override_p;
|
|
#endif
|
|
|
|
/* check_bitmap (src, CHKR_RO); */
|
|
check_bitmap (dst, CHKR_WO);
|
|
|
|
/* Record log2 bpp. */
|
|
srcblt_log2_bpp = log2_bpp;
|
|
|
|
/* Tile fg and bk colors out to 32bpp. */
|
|
mask = ROMlib_pixel_size_mask[log2_bpp];
|
|
tile = ROMlib_pixel_tile_scale[log2_bpp];
|
|
srcblt_fg_color = (fg_color & mask) * tile;
|
|
srcblt_bk_color = (bk_color & mask) * tile;
|
|
|
|
/* Canonicalize mode for RGB. */
|
|
if (log2_bpp > 3)
|
|
mode ^= (srcCopy ^ notSrcCopy);
|
|
|
|
mode &= 7;
|
|
|
|
#if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS)
|
|
cursor_maybe_changed_p = old_vis_p = FALSE;
|
|
if (VDRIVER_BYPASS_INTERNAL_FBUF_P ())
|
|
{
|
|
int top, left;
|
|
RgnPtr rp = STARH (rh);
|
|
|
|
if (active_screen_addr_p (src))
|
|
{
|
|
srcblt_src_row_bytes = vdriver_real_screen_row_bytes;
|
|
src_baseaddr = (char *) vdriver_real_screen_baseaddr;
|
|
if (vdriver_flip_real_screen_pixels_p)
|
|
mode ^= (srcCopy ^ notSrcCopy);
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
srcblt_src_selector = vga_screen_selector;
|
|
#endif
|
|
|
|
/* I'm a lazy bastard and don't want to figure out the
|
|
* coordinate system sludge. Copying from the screen is
|
|
* uncommon anyway.
|
|
*/
|
|
old_vis_p = host_set_cursor_visible (FALSE);
|
|
cursor_maybe_changed_p = TRUE;
|
|
}
|
|
else
|
|
{
|
|
srcblt_src_row_bytes = CW (src->rowBytes) & ROWBYTES_VALUE_BITS;
|
|
src_baseaddr = (char *) MR (src->baseAddr);
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
asm ("movw %%ds,%0" : "=m" (srcblt_src_selector));
|
|
#endif
|
|
}
|
|
if (active_screen_addr_p (dst))
|
|
{
|
|
srcblt_dst_row_bytes = vdriver_real_screen_row_bytes;
|
|
dst_baseaddr = (char *) vdriver_real_screen_baseaddr;
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
srcblt_dst_selector = vga_screen_selector;
|
|
#endif
|
|
top = CW (dst->bounds.top);
|
|
left = CW (dst->bounds.left);
|
|
|
|
/* Hide the cursor if necessary. */
|
|
old_vis_p |= (host_hide_cursor_if_intersects
|
|
(CW (rp->rgnBBox.top) - top,
|
|
CW (rp->rgnBBox.left) - left,
|
|
CW (rp->rgnBBox.bottom) - top,
|
|
CW (rp->rgnBBox.right) - left));
|
|
cursor_maybe_changed_p = TRUE;
|
|
}
|
|
else
|
|
{
|
|
srcblt_dst_row_bytes = CW (dst->rowBytes) & ROWBYTES_VALUE_BITS;
|
|
dst_baseaddr = (char *) MR (dst->baseAddr);
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
asm ("movw %%ds,%0" : "=m" (srcblt_dst_selector));
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
#endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */
|
|
{
|
|
/* Default to values for non-screen blit. */
|
|
srcblt_src_row_bytes = CW (src->rowBytes) & ROWBYTES_VALUE_BITS;
|
|
srcblt_dst_row_bytes = CW (dst->rowBytes) & ROWBYTES_VALUE_BITS;
|
|
src_baseaddr = (char *) MR (src->baseAddr);
|
|
dst_baseaddr = (char *) MR (dst->baseAddr);
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
asm ("movw %%ds,%0\n\t"
|
|
"movw %%ds,%1"
|
|
: "=m" (srcblt_src_selector), "=m" (srcblt_dst_selector));
|
|
#endif
|
|
}
|
|
|
|
/* Compute the offset to map dst y coords to src bitmap coords.*/
|
|
src_y_offset = (CW (src_origin->v) - CW (src->bounds.top)
|
|
- CW (dst_origin->v));
|
|
src_baseaddr += src_y_offset * srcblt_src_row_bytes;
|
|
dst_baseaddr -= CW (dst->bounds.top) * srcblt_dst_row_bytes;
|
|
|
|
/* Handle the common case of flipped fg/bk colors and a copy xfer mode. */
|
|
if ((mode & 3) == (srcCopy & 3) /* either srcCopy or notSrcCopy */
|
|
&& srcblt_fg_color == 0 && srcblt_bk_color == (uint32) ~0)
|
|
{
|
|
mode ^= (srcCopy ^ notSrcCopy);
|
|
srcblt_bk_color = 0;
|
|
srcblt_fg_color = ~0;
|
|
}
|
|
|
|
srcblt_x_offset = -(CW (dst->bounds.left) << log2_bpp);
|
|
|
|
src_x_offset = (((CW (src_origin->h) - CW (src->bounds.left))
|
|
- (CW (dst_origin->h) - CW (dst->bounds.left)))
|
|
<< log2_bpp);
|
|
src_baseaddr += (src_x_offset >> 3);
|
|
left_shift = src_x_offset & 7;
|
|
|
|
dst_align32_offset = (unsigned long) dst_baseaddr & 3;
|
|
|
|
/* Only align dst % 4 bytes when that cannot cause src to get pushed
|
|
* across a page boundary (which might cause a segfault). If that
|
|
* fails, we'll try to align src % 4 bytes.
|
|
*/
|
|
if (dst_align32_offset)
|
|
{
|
|
int offset;
|
|
|
|
offset = -1; /* default value. */
|
|
if (((unsigned long) src_baseaddr & (MIN_PAGE_SIZE - 1))
|
|
>= dst_align32_offset)
|
|
offset = dst_align32_offset;
|
|
else if (!left_shift)
|
|
{
|
|
/* Might as well align src if we can't align dst. */
|
|
src_align32_offset = (unsigned long) src_baseaddr & 3;
|
|
|
|
if (((unsigned long) dst_baseaddr & (MIN_PAGE_SIZE - 1))
|
|
>= src_align32_offset)
|
|
offset = src_align32_offset;
|
|
}
|
|
|
|
if (offset > 0)
|
|
{
|
|
int bit_offset = offset * 8;
|
|
|
|
srcblt_fg_color = ((srcblt_fg_color >> bit_offset)
|
|
| (srcblt_fg_color << (32 - bit_offset)));
|
|
srcblt_bk_color = ((srcblt_bk_color >> bit_offset)
|
|
| (srcblt_bk_color << (32 - bit_offset)));
|
|
|
|
srcblt_x_offset += bit_offset;
|
|
dst_baseaddr -= offset;
|
|
src_baseaddr -= offset;
|
|
}
|
|
}
|
|
|
|
/* If we are forced to do bit shifting anyway, we might as well
|
|
* long-align the source bitmap and increase the shift count.
|
|
*/
|
|
if (left_shift)
|
|
{
|
|
src_align32_offset = (unsigned long) src_baseaddr & 3;
|
|
src_baseaddr -= src_align32_offset;
|
|
left_shift += src_align32_offset * 8;
|
|
}
|
|
|
|
srcblt_shift_offset = left_shift;
|
|
srcblt_src_baseaddr = src_baseaddr;
|
|
srcblt_dst_baseaddr = dst_baseaddr;
|
|
|
|
/* Note whether we should reverse the order in which we process
|
|
* scanlines. This trick will only work for certain simple regions
|
|
* (e.g. those with only one repeated scanline). At the moment,
|
|
* more complex regions require the bitmap be copied offscreen to a
|
|
* temp buffer.
|
|
*/
|
|
srcblt_reverse_scanlines_p = (src_baseaddr < dst_baseaddr);
|
|
|
|
#if defined (VGA_SCREEN_NEEDS_FAR_PTR)
|
|
needs_seg_override_p = (srcblt_src_selector != srcblt_dst_selector);
|
|
# define FIRST_DIM [needs_seg_override_p]
|
|
#else
|
|
# define FIRST_DIM
|
|
#endif
|
|
|
|
if (left_shift == 0)
|
|
{
|
|
if (srcblt_fg_color == (uint32) ~0 && srcblt_bk_color == 0)
|
|
srcblt_stub_table = srcblt_noshift_stubs FIRST_DIM[mode];
|
|
else
|
|
srcblt_stub_table = srcblt_noshift_fgbk_stubs FIRST_DIM[mode];
|
|
}
|
|
else
|
|
{
|
|
#if defined (USE_PORTABLE_SRCBLT) || !defined (i386)
|
|
if (srcblt_fg_color == (uint32) ~0 && srcblt_bk_color == 0)
|
|
srcblt_stub_table = srcblt_shift_stubs[mode];
|
|
else
|
|
srcblt_stub_table = srcblt_shift_fgbk_stubs[mode];
|
|
#else /* i386 */
|
|
if (arch_type == ARCH_TYPE_I386)
|
|
{
|
|
/* i386 */
|
|
if (srcblt_fg_color == (uint32) ~0 && srcblt_bk_color == 0)
|
|
srcblt_stub_table = srcblt_shift_i386_stubs FIRST_DIM[mode];
|
|
else
|
|
srcblt_stub_table = srcblt_shift_fgbk_i386_stubs FIRST_DIM[mode];
|
|
}
|
|
else
|
|
{
|
|
/* i486 or better */
|
|
if (srcblt_fg_color == (uint32) ~0 && srcblt_bk_color == 0)
|
|
srcblt_stub_table = srcblt_shift_i486_stubs FIRST_DIM[mode];
|
|
else
|
|
srcblt_stub_table = srcblt_shift_fgbk_i486_stubs FIRST_DIM[mode];
|
|
}
|
|
#endif /* i386 */
|
|
}
|
|
|
|
SETUP_SPECIAL_RGN (rh, srcblt_rgn_start);
|
|
|
|
/* Make sure we have access to the raw screen bits. */
|
|
vdriver_accel_wait ();
|
|
|
|
/* Actually do the blit. */
|
|
srcblt_bitmap ();
|
|
|
|
#if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS)
|
|
if (cursor_maybe_changed_p)
|
|
host_set_cursor_visible (old_vis_p);
|
|
#endif
|
|
|
|
return !VDRIVER_BYPASS_INTERNAL_FBUF_P ();
|
|
}
|