[comp.graphics] A faster replrop for Suns.

pokey@well.UUCP (Jef Poskanzer) (12/31/88)

[Those who read comp.sys.sun have already seen a version of this message.
I am re-posting it here to get better coverage, and because I have made
some changes to the code since I submitted it to sun-spots a few weeks
ago.]

I was playing around with screenload recently, and added a -t for
tiling flag.  But I was not happy with the speed.  Just from watching a
small bitmap get tiled over the full screen, it looks like pr_replrop
is doing a simple linear replication.  Now, any graphics hacker knows
that since edge handling is expensive in bit blitting, a large blit
goes faster than N smaller blits with the same area.  So I whipped up a
quick binary replication wrapper routine, and did some timings.  For
tiling a small bitmap over the full screen, on a 3/50, my replrop goes
four times faster than Sun's.

The routine is appended.  This should be 100% compatible with pr_replrop.
If anyone finds any cases where this isn't so, please let me know.  Also,
I would be interested in hearing whether similar speedups are seen on
other configurations, such as color frame buffers.
---
Jef

             Jef Poskanzer   jef@rtsg.ee.lbl.gov   ...well!pokey

jef_pr_replrop(dpr, dx, dy, dw, dh, op, spr, sx, sy)
Pixrect *dpr, *spr;
int dx, dy, dw, dh, op, sx, sy;
{
	register int w, h, status;

	if ( spr == (Pixrect *) 0 ) {
		/* Special case the NULL pixrect. */
		w = dw;
		h = dh;
	} else {
		w = spr->pr_size.x;
		/* Avoid tiny horizontal blits. */
		while ( w < 256 ) w *= 2;
		if ( w > dw ) w = dw;

		h = spr->pr_size.y;
		/* But no edge effects vertically, so no problem. */
		if ( h > dh ) h = dh;
	}

	if (status = pr_replrop(dpr, dx, dy, w, h, op, spr, sx, sy))
		return status;

	while ( w < dw || h < dh ) {
		if ( w < dw )
			if (status = pr_rop(dpr, dx + w, dy, w, h, PIX_SRC, dpr,
				dx, dy))
				return status;
		if ( h < dh )
			if (status = pr_rop(dpr, dx, dy + h, w, h, PIX_SRC, dpr,
				dx, dy))
				return status;
		if ( w < dw && h < dh )
			if (status = pr_rop(dpr, dx + w, dy + h, w, h, PIX_SRC,
				dpr, dx, dy))
				return status;
		w *= 2;
		h *= 2;
	}
	return 0;
}