/* Copyright 1995 by Abacus Research and * Development, Inc. All rights reserved. */ #if !defined (OMIT_RCSID_STRINGS) char ROMlib_rcsid_xdblt[] = "$Id: xdblt.c 63 2004-12-24 18:19:43Z ctm $"; #endif #include "rsys/common.h" #include "QuickDraw.h" #include "MemoryMgr.h" #include "rsys/xdata.h" #include "rsys/xdblt.h" #include "rsys/vdriver.h" #if defined (USE_VGAVDRIVER) #include "rsys/vgavdriver.h" #endif #include "rsys/quick.h" #include "rsys/cquick.h" #include "rsys/mman.h" #include "rsys/dirtyrect.h" #include "rsys/prefs.h" #include "rsys/host.h" #include "rsys/autorefresh.h" /* Holds the four-byte pattern value, for "short & narrow" patterns. */ uint32 xdblt_pattern_value asm ("_xdblt_pattern_value"); /* Holds the row bytes for the pattern. Always evenly divisible by four. */ uint32 xdblt_log2_pattern_row_bytes asm ("_xdblt_log2_pattern_row_bytes"); /* Holds the row bytes for the pattern. Always evenly divisible by four. */ uint32 xdblt_pattern_height_minus_1 asm ("_xdblt_pattern_height_minus_1"); /* Start and end of the pattern. */ uint32 *xdblt_pattern_baseaddr asm ("_xdblt_pattern_baseaddr"); uint32 *xdblt_pattern_end asm ("_xdblt_pattern_end"); /* Since the pattern may be rotated vertically, we add this to the * row we would otherwise compute to display on bitmap row #N. */ uint32 xdblt_pattern_row_0 asm ("_xdblt_pattern_row_0"); /* Table of functions that describe this transfer mode. */ const void **xdblt_stub_table asm ("_xdblt_stub_table"); /* log base 2 of the bits per pixel of the destination bitmap [0, 5]. */ uint32 xdblt_log2_bpp asm ("_xdblt_log2_bpp"); /* "Special region" data to be transferred. */ const INTEGER *xdblt_rgn_start asm ("_xdblt_rgn_start"); /* Added to the X value grabbed from the region to get the "real" value. */ uint32 xdblt_x_offset asm ("_xdblt_x_offset"); /* Canonicalized base address of the destination bitmap. We offset * the bitmap's base so that (region_y_val * dst_rowbytes) is the * offset from the baseaddr to the proper row. */ uint32 *xdblt_dst_baseaddr asm ("_xdblt_dst_baseaddr"); /* Bytes per row of the destination bitmap. */ uint32 xdblt_dst_row_bytes asm ("_xdblt_dst_row_bytes"); /* Bit pattern inserted for bit insertion modes. */ uint32 xdblt_insert_bits asm ("_xdblt_insert_bits"); #if defined (VGA_SCREEN_NEEDS_FAR_PTR) uint16 xdblt_dst_selector asm ("_xdblt_dst_selector"); #endif #define M(n) CLC (0xFFFFFFFFU >> (n)) const uint32 xdblt_mask_array[32] asm ("_xdblt_mask_array") = { M(0), M(1), M(2), M(3), M(4), M(5), M(6), M(7), M(8), M(9), M(10), M(11), M(12), M(13), M(14), M(15), M(16), M(17), M(18), M(19), M(20), M(21), M(22), M(23), M(24), M(25), M(26), M(27), M(28), M(29), M(30), M(31) }; #undef M /* Since we map all modes to one of { copy, or, xor, and }, sometimes we * need to flip the pattern bits. This table tells us when to do that. */ static const uint32 flip_mask_for_mode[8] = { 0, 0, 0, ~0, ~0, ~0, ~0, 0 }; /* This macro rotates the specified 32 bit value right by the given * number of bits and modifies the input value. It can only be called * if 0 < count < 32; otherwise, the result is undefined. */ #if defined (i386) #define RORL(count, n) \ asm ("rorl %%cl,%0" : "=g" (n) : "c" (count), "0" (n) : "cc"); #elif defined (mc68000) #define RORL(count, n) \ asm ("rorl %1,%0" : "=d" (n) : "d" (count), "0" (n) : "cc"); #else /* !i386 && !mc68000 */ #define RORL(count, n) \ do { \ uint32 _tmp_ = (n); \ int _count_ = (count); \ (n) = (_tmp_ >> _count_) | (_tmp_ << (32 - _count_)); \ } while (0) #endif /* !i386 && !mc68000 */ /* Sometimes we call internal routines but we don't want the mode to * get touched like it normally does. As a workaround we mark the mode * as "canonical" by ORing in some magic high bits. */ #define MODE_CANON_BITS 0x73A12300 #define MODE_CANON_MASK 0xFFFFFF00 #define MODE_CANON_P(m) (((m) & MODE_CANON_MASK) == MODE_CANON_BITS) #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) static inline boolean_t hide_cursor_if_necessary (RgnHandle rh, const PixMap *dst, boolean_t *old_vis) { int top, left; RgnPtr rp; top = CW (dst->bounds.top); left = CW (dst->bounds.left); rp = STARH (rh); *old_vis = 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); return TRUE; } #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ static inline int setup_dst_bitmap (int log2_bpp, PixMap *dst_pixmap) { char *dst; int byte_slop; int row_bytes; /* Long-align the bitmap, and set it up so that * baseaddr + y * row_bytes evaluates to the correct row. */ #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) if (VDRIVER_BYPASS_INTERNAL_FBUF_P () && active_screen_addr_p (dst_pixmap)) { row_bytes = vdriver_real_screen_row_bytes; dst = (char *) vdriver_real_screen_baseaddr; #if defined (VGA_SCREEN_NEEDS_FAR_PTR) xdblt_dst_selector = vga_screen_selector; #endif } else #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ { row_bytes = BITMAP_ROWBYTES (dst_pixmap); dst = (char *) MR (dst_pixmap->baseAddr); #if defined (VGA_SCREEN_NEEDS_FAR_PTR) asm ("movw %%ds,%0" : "=m" (xdblt_dst_selector)); #endif } dst -= row_bytes * CW (dst_pixmap->bounds.top); xdblt_dst_row_bytes = row_bytes; byte_slop = (unsigned long) dst & 3; xdblt_dst_baseaddr = (uint32 *) (dst - byte_slop); xdblt_x_offset = ((byte_slop << 3) - (CW (dst_pixmap->bounds.left) << log2_bpp)); return xdblt_x_offset << 3; } INTEGER phony_special_region[7] = { 0, 0, 0, RGNSTOP, 0, RGNSTOP, RGNSTOPX }; /* This is the fastest blitter function. It can be called when the * xdata is one row tall and 4 bytes wide, the xdata pixels are not * RGB, and when no different value can be achieved by rotating the * pattern value by any multiple of the bits per pixel. Some examples * are 0 or ~0 at any bpp, 0xA1A1A1A1 at 8bpp, 0x55555555 at 2bpp, etc. */ boolean_t xdblt_xdata_norgb_norotate (RgnHandle rh, int mode, int pat_x_rotate_count, int pat_y_rotate_count, xdata_t *x, PixMap *dst) { RgnPtr r; int log2_bpp; boolean_t active_screen_p; vdriver_accel_result_t accel_result; boolean_t mode_canon_p; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) boolean_t cursor_maybe_changed_p, cursor_vis_p; #endif check_bitmap (dst, CHKR_WO); mode_canon_p = MODE_CANON_P (mode); mode &= 7; active_screen_p = active_screen_addr_p (dst); #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) /* If we can blit directly to the real screen, change the mode * appropriately. */ if (VDRIVER_BYPASS_INTERNAL_FBUF_P () && active_screen_p) { cursor_maybe_changed_p = hide_cursor_if_necessary (rh, dst, &cursor_vis_p); } else cursor_maybe_changed_p = FALSE; #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ if (!mode_canon_p) { xdblt_pattern_value = x->pat_value ^ flip_mask_for_mode[mode]; mode &= 3; } if (active_screen_p && mode == (patCopy & 3) /* patCopy or notPatCopy */ && (r = STARH (rh), r->rgnSize == SMALLRGNX)) { int top, left; top = CW (dst->bounds.top); left = CW (dst->bounds.left); accel_result = vdriver_accel_rect_fill (CW (r->rgnBBox.top) - top, CW (r->rgnBBox.left) - left, CW (r->rgnBBox.bottom) - top, CW (r->rgnBBox.right) - left, xdblt_pattern_value & ROMlib_pixel_size_mask[x->log2_bpp]); if (accel_result != VDRIVER_ACCEL_NO_UPDATE) note_executor_changed_screen (CW (r->rgnBBox.top) - top, CW (r->rgnBBox.bottom) - top); } else accel_result = VDRIVER_ACCEL_NO_UPDATE; if (accel_result != VDRIVER_ACCEL_FULL_UPDATE) { xdblt_log2_pattern_row_bytes = 2; xdblt_pattern_row_0 = 0; xdblt_pattern_baseaddr = &xdblt_pattern_value; xdblt_pattern_end = &xdblt_pattern_value + 1; xdblt_stub_table = x->stub_table_for_mode[mode]; xdblt_log2_bpp = log2_bpp = x->log2_bpp; setup_dst_bitmap (log2_bpp, dst); SETUP_SPECIAL_RGN (rh, xdblt_rgn_start); /* Make sure we have access to the raw screen bits. */ vdriver_accel_wait (); /* Actually do the blit. */ xdblt_canon_pattern (); } #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) if (cursor_maybe_changed_p) host_set_cursor_visible (cursor_vis_p); #endif return (!VDRIVER_BYPASS_INTERNAL_FBUF_P () && accel_result == VDRIVER_ACCEL_NO_UPDATE); } /* Contrary to my expectation, a small test program shows that RGB * pattern modes do not seem to get mapped to different low-level * modes. Exactly the same boolean transfer function happens in 16bpp * as in 8bpp. */ #if defined (RGB_NEEDS_MODE_MAPPING) /* This table maps normal modes to the mode to use when the transfer * involves RGB pixels. This is necessary because the 0 bits of * indirect pixels are white, while the 0 bits of indirect pixels are * black. Consequently, the transfer modes have different semantics * when viewed at a raw bit level. */ static const int ind_mode_to_rgb_mode[8] = { patCopy & 7, /* patCopy -> patCopy */ notPatBic & 7, /* patOr -> notPatBic */ patXor & 7, /* patXor -> patXor */ notPatOr & 7, /* patBic -> notPatOr */ notPatCopy & 7, /* notPatCopy -> notPatCopy */ patBic & 7, /* notPatOr -> patBic */ notPatXor & 7, /* notPatXor -> notPatXor */ patOr & 7, /* notPatBic -> patOr */ }; #endif /* RGB_NEEDS_MODE_MAPPING */ boolean_t xdblt_xdata_short_narrow (RgnHandle rh, int mode, int pat_x_rotate_count, int pat_y_rotate_count, xdata_t *x, PixMap *dst) { uint32 v, flip; int rcount, log2_bpp; boolean_t mode_canon_p; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) boolean_t cursor_maybe_changed_p, cursor_vis_p; #endif check_bitmap (dst, CHKR_WO); mode_canon_p = MODE_CANON_P (mode); mode &= 7; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) /* If we can blit directly to the real screen, change the mode * appropriately. */ if (VDRIVER_BYPASS_INTERNAL_FBUF_P () && active_screen_addr_p (dst)) { cursor_maybe_changed_p = hide_cursor_if_necessary (rh, dst, &cursor_vis_p); } else cursor_maybe_changed_p = FALSE; #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ #if defined (RGB_NEEDS_MODE_MAPPING) if (x->rgb_spec && !mode_canon_p) mode = ind_mode_to_rgb_mode[mode]; #endif if (!mode_canon_p) xdblt_stub_table = x->stub_table_for_mode[mode & 3]; else xdblt_stub_table = x->stub_table_for_mode[mode]; if (xdblt_stub_table == xdblt_nop_table) return FALSE; xdblt_log2_bpp = log2_bpp = x->log2_bpp; pat_x_rotate_count <<= log2_bpp; pat_x_rotate_count += setup_dst_bitmap (log2_bpp, dst); SETUP_SPECIAL_RGN (rh, xdblt_rgn_start); if (mode_canon_p) flip = 0; else flip = flip_mask_for_mode[mode]; if (x->rgb_spec) flip &= x->rgb_spec->pixel_bits_mask; v = x->pat_value ^ flip; rcount = pat_x_rotate_count & 31; if (rcount) RORL (rcount, v); xdblt_pattern_value = v; xdblt_log2_pattern_row_bytes = 2; xdblt_pattern_row_0 = 0; xdblt_pattern_baseaddr = &xdblt_pattern_value; xdblt_pattern_end = &xdblt_pattern_value + 1; /* Make sure we have access to the raw screen bits. */ vdriver_accel_wait (); /* Actually do the blit. */ xdblt_canon_pattern (); #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) if (cursor_maybe_changed_p) host_set_cursor_visible (cursor_vis_p); #endif return !VDRIVER_BYPASS_INTERNAL_FBUF_P (); } /* This function XORs FLIP_MASK with all of the longs in the xdata, * and then rotates the given xdata by XROT bits. */ static inline void rotate_and_flip_xdata (xdata_t *x, int xrot, uint32 flip_mask) { /* First flip all bits appropriately. */ if (flip_mask != 0) { uint32 *p, *e; e = xdblt_pattern_end; for (p = xdblt_pattern_baseaddr; p != e; p++) *p ^= flip_mask; } /* Now rotate them appropriately. */ if (xrot != 0) { int row_bytes = (1 << x->log2_row_bytes); if (row_bytes == 4) { uint32 *p, *e; e = xdblt_pattern_end; for (p = xdblt_pattern_baseaddr; p != e; p++) RORL (xrot, *p); } else { uint8 *scratch, *s, *p, *e; int rs, bs; /* The following code rotates the pattern array right by * XROT bits, assuming the bits are stored in bits-big-endian * byte order. */ scratch = alloca (x->byte_size); e = (uint8 *) xdblt_pattern_end; bs = xrot >> 3; rs = xrot & 7; if (rs != 0) { int ls; unsigned xmask; xmask = row_bytes - 1; ls = 8 - rs; /* This is the tricky case, where we aren't * rotating by an integral number of bytes. */ for (p = (uint8 *) xdblt_pattern_baseaddr, s = scratch; p != e; p += row_bytes, s += row_bytes) { uint8 next; int i; next = p[0]; for (i = xmask; i >= 0; i--) { uint8 v = p[i]; s[(i + bs) & xmask] = ((v >> rs) | (next << ls)); next = v; } } memcpy (xdblt_pattern_baseaddr, scratch, x->byte_size); } else { /* Special case for when we are rotating an integral number * of bytes. */ p = (uint8 *) xdblt_pattern_baseaddr; memcpy (scratch, p, x->byte_size); for (s = scratch; p != e; p += row_bytes, s += row_bytes) { memcpy (p, s + row_bytes - bs, bs); memcpy (p + bs, s, row_bytes - bs); } } } } } boolean_t xdblt_xdata_complex (RgnHandle rh, int mode, int pat_x_rotate_count, int pat_y_rotate_count, xdata_t *x, PixMap *dst) { const char *base; uint32 flip_mask; boolean_t mode_canon_p; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) boolean_t cursor_maybe_changed_p, cursor_vis_p; #endif check_bitmap (dst, CHKR_WO); mode_canon_p = MODE_CANON_P (mode); mode &= 7; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) /* If we can blit directly to the real screen, change the mode * appropriately. */ if (VDRIVER_BYPASS_INTERNAL_FBUF_P () && active_screen_addr_p (dst)) { cursor_maybe_changed_p = hide_cursor_if_necessary (rh, dst, &cursor_vis_p); } else cursor_maybe_changed_p = FALSE; #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ #if defined (RGB_NEEDS_MODE_MAPPING) if (x->rgb_spec && !mode_canon_p) mode = ind_mode_to_rgb_mode[mode]; #endif base = (const char *) x->pat_bits; xdblt_pattern_baseaddr = (uint32 *) base; xdblt_pattern_end = (uint32 *) (&base[x->byte_size]); pat_x_rotate_count <<= x->log2_bpp; pat_x_rotate_count += setup_dst_bitmap (x->log2_bpp, dst); if (mode_canon_p) flip_mask = 0; else flip_mask = flip_mask_for_mode[mode]; rotate_and_flip_xdata (x, ((pat_x_rotate_count - x->pat_x_rot) & x->row_bits_minus_1), flip_mask ^ x->pat_flip_mask); x->pat_flip_mask = flip_mask; x->pat_x_rot = pat_x_rotate_count; xdblt_log2_pattern_row_bytes = x->log2_row_bytes; xdblt_log2_bpp = x->log2_bpp; if (mode_canon_p) xdblt_stub_table = x->stub_table_for_mode[mode]; else xdblt_stub_table = x->stub_table_for_mode[mode & 3]; xdblt_pattern_row_0 = (-pat_y_rotate_count) & x->height_minus_1; xdblt_pattern_height_minus_1 = x->height_minus_1; SETUP_SPECIAL_RGN (rh, xdblt_rgn_start); /* Make sure we have access to the raw screen bits. */ vdriver_accel_wait (); xdblt_canon_pattern (); #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) if (cursor_maybe_changed_p) host_set_cursor_visible (cursor_vis_p); #endif return !VDRIVER_BYPASS_INTERNAL_FBUF_P (); } static boolean_t do_short_narrow_pattern (RgnHandle rh, int mode, uint32 v, PixMap *dst, uint32 fg_color, uint32 bk_color, int log2_bpp, const rgb_spec_t *rgb_spec, int pat_x_rotate_count) { int extra_rot, raw_mode; uint32 tv, op_color; RgnPtr r; vdriver_accel_result_t accel_result; check_bitmap (dst, CHKR_WO); extra_rot = setup_dst_bitmap (log2_bpp, dst); /* Flip the bits if it's a "not" mode. */ if (mode & (patCopy ^ notPatCopy)) v ^= ~0; /* Set up the xdblt mode for the given QuickDraw mode. */ switch (mode & 3) { case (patCopy & 3): default: /* Not possible to hit default case w/2 bit switch. */ v = (v & fg_color) | ((~v) & bk_color); if (rgb_spec) v = (v & rgb_spec->pixel_bits_mask) ^ rgb_spec->xor_mask; raw_mode = XDBLT_COPY; break; case (patXor & 3): if (rgb_spec) v &= rgb_spec->pixel_bits_mask; raw_mode = XDBLT_XOR; break; case (patOr & 3): case (patBic & 3): if (v == 0 || (rgb_spec && (v & rgb_spec->pixel_bits_mask) == 0)) return FALSE; op_color = ((mode & 3) == (patOr & 3)) ? fg_color : bk_color; if (v == (uint32) ~0 || (rgb_spec && v == rgb_spec->white_pixel)) { /* Just a copy. */ v = op_color; if (rgb_spec) v = (v & rgb_spec->pixel_bits_mask) ^ rgb_spec->xor_mask; raw_mode = XDBLT_COPY; } else if ((op_color & v) == v || (rgb_spec && op_color == rgb_spec->white_pixel)) { /* Just an or. */ if (rgb_spec) v &= rgb_spec->pixel_bits_mask; raw_mode = XDBLT_OR; } else if ((op_color & v) == 0 || (rgb_spec && op_color == rgb_spec->black_pixel)) { /* Just an and. */ v ^= ~0; if (rgb_spec) v |= ~rgb_spec->pixel_bits_mask; raw_mode = XDBLT_AND; } else /* Tricky case; insert colored bit wherever "v" has a 1 bit. */ { xdblt_insert_bits = op_color; if (rgb_spec) { xdblt_insert_bits = (rgb_spec->xor_mask ^ (xdblt_insert_bits & rgb_spec->pixel_bits_mask)); v |= ~rgb_spec->pixel_bits_mask; /* not really necessary. */ } raw_mode = XDBLT_INSERT; } break; } if (v == 0) { xdblt_stub_table = xdblt_zeros_stubs[raw_mode]; } else if (v == (uint32) ~0) { xdblt_stub_table = xdblt_ones_stubs[raw_mode]; } else { int rcount = ((pat_x_rotate_count << log2_bpp) + extra_rot) & 31; if (rcount) RORL (rcount, v); xdblt_stub_table = xdblt_short_narrow_stubs[raw_mode]; } xdblt_pattern_value = v; /* We can only use the accelerated func for solid color patCopy/notPatCopy * to the screen. */ tv = v; if (log2_bpp < 5) RORL (1 << log2_bpp, tv); if (v == tv && raw_mode == XDBLT_COPY && (r = STARH (rh), r->rgnSize == SMALLRGNX) && active_screen_addr_p (dst)) { int top, left; top = CW (dst->bounds.top); left = CW (dst->bounds.left); accel_result = vdriver_accel_rect_fill (CW (r->rgnBBox.top) - top, CW (r->rgnBBox.left) - left, CW (r->rgnBBox.bottom) - top, CW (r->rgnBBox.right) - left, xdblt_pattern_value & ROMlib_pixel_size_mask[log2_bpp]); if (accel_result != VDRIVER_ACCEL_NO_UPDATE) note_executor_changed_screen (CW (r->rgnBBox.top) - top, CW (r->rgnBBox.bottom) - top); } else accel_result = VDRIVER_ACCEL_NO_UPDATE; if (accel_result != VDRIVER_ACCEL_FULL_UPDATE) { xdblt_log2_bpp = log2_bpp; xdblt_log2_pattern_row_bytes = 2; xdblt_pattern_row_0 = 0; xdblt_pattern_height_minus_1 = 0; xdblt_pattern_baseaddr = &xdblt_pattern_value; xdblt_pattern_end = &xdblt_pattern_value + 1; /* Set up the region appropriately. */ SETUP_SPECIAL_RGN (rh, xdblt_rgn_start); /* Make sure we have access to the raw screen bits. */ vdriver_accel_wait (); /* Actually do the blit. */ xdblt_canon_pattern (); } return (!VDRIVER_BYPASS_INTERNAL_FBUF_P () && accel_result == VDRIVER_ACCEL_NO_UPDATE); } static inline uint32 canonicalize_pat_value_for_mode (uint32 v, int mode, uint32 fg_color, uint32 bk_color, const rgb_spec_t *rgb_spec) { if (mode & (patCopy ^ notPatCopy)) v ^= ~0; switch (mode & 3) { case (patCopy & 3): v = (v & fg_color) | ((~v) & bk_color); if (rgb_spec) v = (v & rgb_spec->pixel_bits_mask) ^ rgb_spec->xor_mask; break; case (patXor & 3): if (rgb_spec) v &= rgb_spec->pixel_bits_mask; break; case (patOr & 3): if (rgb_spec) v &= rgb_spec->pixel_bits_mask; break; case (patBic & 3): if (bk_color == 0) v ^= ~0; else if (rgb_spec) { if (bk_color == rgb_spec->black_pixel) v = ~(v & rgb_spec->pixel_bits_mask); /* Because we can "and" */ else v &= rgb_spec->pixel_bits_mask; } break; } return v; } boolean_t xdblt_pattern (RgnHandle rh, int mode, int pat_x_rotate_count, int pat_y_rotate_count, const Pattern pattern, PixMap *dst, uint32 fg_color, uint32 bk_color) { uint32 v, mask, tile, *p, *end; const rgb_spec_t *rgb_spec = NULL; int log2_bpp; boolean_t update_dirty_p; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) boolean_t cursor_maybe_changed_p, cursor_vis_p; #endif rgb_spec = pixmap_rgb_spec (dst); /* Tile fg and bk colors out to 32bpp. */ log2_bpp = ROMlib_log2[CW (dst->pixelSize)]; mask = ROMlib_pixel_size_mask[log2_bpp]; tile = ROMlib_pixel_tile_scale[log2_bpp]; fg_color = (fg_color & mask) * tile; bk_color = (bk_color & mask) * tile; mode &= 7; #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) /* If we can blit directly to the real screen, change the mode * appropriately. */ if (VDRIVER_BYPASS_INTERNAL_FBUF_P () && active_screen_addr_p (dst)) { cursor_maybe_changed_p = hide_cursor_if_necessary (rh, dst, &cursor_vis_p); } else cursor_maybe_changed_p = FALSE; #endif /* VDRIVER_SUPPORTS_REAL_SCREEN_BLITS */ #if defined (RGB_NEEDS_MODE_MAPPING) if (rgb_spec) mode = ind_mode_to_rgb_mode[mode]; #endif /* See if the pattern is 0x0000000000000000 or 0xFFFFFFFFFFFFFFFF. * These are _extremely_ common cases. */ v = *(const uint32 *)pattern; if ((v + 1U) <= 1U && v == ((const uint32 *)pattern)[1]) { update_dirty_p = do_short_narrow_pattern (rh, mode, v, dst, fg_color, bk_color, log2_bpp, rgb_spec, pat_x_rotate_count); } else { xdata_handle_t xh = xdata_for_pattern (pattern, dst); LOCK_HANDLE_EXCURSION_1 (xh, { xdata_t *x = STARH (xh); p = x->pat_bits; if (p) { int raw_mode; end = (uint32 *) ((char *) p + x->byte_size); for (; p != end; p++) { /* This is a little slow, but who cares about this * case? I can easily speed this up later if need be. */ *p = canonicalize_pat_value_for_mode (*p, mode, fg_color, bk_color, rgb_spec); } if ((mode & 3) == (patBic & 3) && !(bk_color == 0 || (rgb_spec && bk_color == rgb_spec->black_pixel))) { raw_mode = XDBLT_INSERT; xdblt_insert_bits = bk_color; } else if ((mode & 3) == (patOr & 3) && !(fg_color == (uint32) ~0 || (rgb_spec && fg_color == rgb_spec->white_pixel))) { raw_mode = XDBLT_INSERT; xdblt_insert_bits = fg_color; } else { raw_mode = mode & 3; } update_dirty_p = (*x->blt_func) (rh, raw_mode | MODE_CANON_BITS, pat_x_rotate_count, pat_y_rotate_count, x, dst); } else { update_dirty_p = do_short_narrow_pattern (rh, mode, x->pat_value, dst, fg_color, bk_color, log2_bpp, rgb_spec, pat_x_rotate_count); } }); xdata_free (xh); } #if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS) if (cursor_maybe_changed_p) host_set_cursor_visible (cursor_vis_p); #endif return update_dirty_p; }