#define CIRRUS_PNPMMIO_SIZE 0x1000
-#define BLTUNSAFE(s) \
- ( \
- ( /* check dst is within bounds */ \
- (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \
- + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
- (s)->vga.vram_size \
- ) || \
- ( /* check src is within bounds */ \
- (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \
- + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
- (s)->vga.vram_size \
- ) \
- )
+// If blit is out of bounds, reduce height.
+static void check_blit(int32_t addr, uint32_t mask, int pitch, int width, int *height, int depth, int dir)
+{
+ int h = *height;
+ int32_t off;
+ if (!h || !width)
+ return;
+ addr &= mask;
+ off = addr + pitch * (h - 1);
+ if (dir > 0) {
+ off += width * (depth / 8);
+ } else {
+ off -= width * (depth / 8);
+ }
+ if (off > mask + 1) {
+ h -= (off - (mask + 1) + pitch - 1) / pitch;
+ } else if (off < 0) {
+ h -= ((-off) + pitch - 1) / pitch;
+ }
+ if (h < 0)
+ h = 0;
+ *height = h;
+}
+
+#define INITBLIT \
+ dst += (dstaddr & dstmask); \
+ src += (srcaddr & srcmask);
+
+#define INITBLIT_DST \
+ dst += (dstaddr & dstmask);
+
+#define BLTCHECK_DST(skip) \
+ check_blit(dstaddr, dstmask, dstpitch, bltwidth - skip, &bltheight, DEPTH, 1);
+
+#define BLTCHECK_FWD \
+ check_blit(dstaddr, dstmask, dstpitch, bltwidth, &bltheight, 8, 1); \
+ check_blit(srcaddr, srcmask, srcpitch, bltwidth, &bltheight, 8, 1); \
+ INITBLIT;
+
+#define BLTCHECK_BKWD \
+ check_blit(dstaddr, dstmask, dstpitch, bltwidth, &bltheight, 8, -1); \
+ check_blit(srcaddr, srcmask, srcpitch, bltwidth, &bltheight, 8, -1); \
+ INITBLIT;
#if 0
typedef struct PCICirrusVGAState {
***************************************/
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
{
}
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
- uint8_t *dst,
- int dstpitch, int bltwidth,int bltheight)
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ int dstpitch, int bltwidth,int bltheight)
{
}
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
const uint8_t * src)
{
- uint8_t *dst;
-
- dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
-
-// if (BLTUNSAFE(s))
-// return 0;
-
- (*s->cirrus_rop) (s, dst, src,
- s->cirrus_blt_dstpitch, 0,
- s->cirrus_blt_width, s->cirrus_blt_height);
+ (*s->cirrus_rop) (s,
+ s->vga.vram_ptr, s->cirrus_blt_dstaddr, s->cirrus_addr_mask,
+ src, 0, s->cirrus_addr_mask,
+ s->cirrus_blt_dstpitch, 0,
+ s->cirrus_blt_width, s->cirrus_blt_height);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
s->cirrus_blt_dstpitch, s->cirrus_blt_width,
s->cirrus_blt_height);
{
cirrus_fill_t rop_func;
-// if (BLTUNSAFE(s))
-// return 0;
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ rop_func(s, s->vga.vram_ptr, s->cirrus_blt_dstaddr, s->cirrus_addr_mask,
s->cirrus_blt_dstpitch,
s->cirrus_blt_width, s->cirrus_blt_height);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
if (notify)
graphic_hw_update(s->vga.con);
- (*s->cirrus_rop) (s, s->vga.vram_ptr +
- (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
- s->vga.vram_ptr +
- (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
- s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
- s->cirrus_blt_width, s->cirrus_blt_height);
+ (*s->cirrus_rop) (s,
+ s->vga.vram_ptr, s->cirrus_blt_dstaddr, s->cirrus_addr_mask,
+ s->vga.vram_ptr, s->cirrus_blt_srcaddr, s->cirrus_addr_mask,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
if (notify) {
qemu_console_copy(s->vga.con,
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
{
-// if (BLTUNSAFE(s))
-// return 0;
-
cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
s->cirrus_blt_srcaddr - s->vga.start_addr,
s->cirrus_blt_width, s->cirrus_blt_height);
} else {
/* at least one scan line */
do {
- (*s->cirrus_rop)(s, s->vga.vram_ptr +
- (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+ (*s->cirrus_rop)(s,
+ s->vga.vram_ptr, s->cirrus_blt_dstaddr, s->cirrus_addr_mask,
+ s->cirrus_bltbuf, 0, 0,
+ 0, 0, s->cirrus_blt_width, 1);
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
s->cirrus_blt_width, 1);
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
static void
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
{
int x,y;
+
+ BLTCHECK_FWD
+
dstpitch -= bltwidth;
srcpitch -= bltwidth;
-#if 0
- /* Invalid test! TW */
- if (dstpitch < 0 || srcpitch < 0) {
- /* is 0 valid? srcpitch == 0 could be useful */
- return;
- }
-#endif
-
for (y = 0; y < bltheight; y++) {
for (x = 0; x < (bltwidth & ~3); x += 4) {
ROP_OP_32((uint32_t*)dst, *((uint32_t*)src));
static void
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
- int x,y;
- dstpitch += bltwidth;
+ BLTCHECK_BKWD
+
+ int x,y;
+
+ dstpitch += bltwidth;
srcpitch += bltwidth;
- for (y = 0; y < bltheight; y++) {
+
+ for (y = 0; y < bltheight; y++) {
for (x = 0; x < (bltwidth & ~3); x += 4) {
dst -= 3;
src -= 3;
static void
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
{
- int x,y;
+ BLTCHECK_FWD
+
+ int x,y;
uint8_t p;
- dstpitch -= bltwidth;
+
+ dstpitch -= bltwidth;
srcpitch -= bltwidth;
- for (y = 0; y < bltheight; y++) {
+
+ for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
p = *dst;
ROP_OP(&p, *src);
static void
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
- int x,y;
+ BLTCHECK_BKWD
+
+ int x,y;
uint8_t p;
- dstpitch += bltwidth;
+
+ dstpitch += bltwidth;
srcpitch += bltwidth;
- for (y = 0; y < bltheight; y++) {
+
+ for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
p = *dst;
ROP_OP(&p, *src);
static void
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
- int x,y;
+ BLTCHECK_FWD
+
+ int x,y;
uint8_t p1, p2;
- dstpitch -= bltwidth;
+
+ dstpitch -= bltwidth;
srcpitch -= bltwidth;
- for (y = 0; y < bltheight; y++) {
+
+ for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x+=2) {
p1 = *dst;
p2 = *(dst+1);
static void
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
{
- int x,y;
+ BLTCHECK_BKWD
+
+ int x,y;
uint8_t p1, p2;
- dstpitch += bltwidth;
+
+ dstpitch += bltwidth;
srcpitch += bltwidth;
- for (y = 0; y < bltheight; y++) {
+
+ for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x+=2) {
p1 = *(dst-1);
p2 = *dst;
static void
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
+ (CirrusVGAState * s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *d;
int x, y, pattern_y, pattern_pitch, pattern_x;
unsigned int col;
const uint8_t *src1;
int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8);
#endif
+ BLTCHECK_DST(skipleft)
+ INITBLIT
+
#if DEPTH == 8
pattern_pitch = 8;
#elif DEPTH == 16
/* NOTE: srcpitch is ignored */
static void
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
+ (CirrusVGAState * s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *d;
int x, y;
unsigned bits, bits_xor;
unsigned int col;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+ BLTCHECK_DST(dstskipleft)
+ INITBLIT
+
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
// Color expansion + transparency: fgcol, not bgcol. TW.
col = s->cirrus_blt_fgcol;
static void
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
+ (CirrusVGAState * s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
{
- uint32_t colors[2];
+ uint32_t colors[2];
uint8_t *d;
int x, y;
unsigned bits;
int srcskipleft = s->vga.gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
- colors[0] = s->cirrus_blt_bgcol;
+ BLTCHECK_DST(dstskipleft)
+ INITBLIT
+
+ colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
static void
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
+ (CirrusVGAState * s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits, bits_xor;
unsigned int col;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+ BLTCHECK_DST(dstskipleft)
+ INITBLIT
+
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
// Color expansion + transparency: fgcol, not bgcol. TW.
col = s->cirrus_blt_fgcol;
static void
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
+ (CirrusVGAState * s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int srcskipleft = s->vga.gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
+ BLTCHECK_DST(dstskipleft)
+ INITBLIT
+
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
static void
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
- (CirrusVGAState *s,
- uint8_t *dst, int dst_pitch,
- int width, int height)
+ (CirrusVGAState *s,
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ int dstpitch,
+ int bltwidth, int bltheight)
{
uint8_t *d, *d1;
uint32_t col;
int x, y;
- col = s->cirrus_blt_fgcol;
+ BLTCHECK_DST(0)
+ INITBLIT_DST
+
+ col = s->cirrus_blt_fgcol;
d1 = dst;
- for(y = 0; y < height; y++) {
+ for(y = 0; y < bltheight; y++) {
d = d1;
- for(x = 0; x < width; x += (DEPTH / 8)) {
+ for(x = 0; x < bltwidth; x += (DEPTH / 8)) {
PUTPIXEL();
d += (DEPTH / 8);
}
- d1 += dst_pitch;
+ d1 += dstpitch;
}
}
typedef struct CirrusVGAState CirrusVGAState;
typedef void (*cirrus_bitblt_rop_t) (CirrusVGAState *s,
- uint8_t * dst, const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight);
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ const uint8_t *src, uint32_t srcaddr, uint32_t srcmask,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight);
typedef void (*cirrus_fill_t)(CirrusVGAState *s,
- uint8_t *dst, int dst_pitch, int width, int height);
+ uint8_t *dst, uint32_t dstaddr, uint32_t dstmask,
+ int dst_pitch, int width, int height);
struct CirrusVGAState {
VGACommonState vga;