Re: Re: SDLoad and PAL displays

Daniel Thompson <[email protected]> Mon, 27 Feb 2006 20:51:41 +0000
Newsgroups gmane.linux.ports.game-cube.devel
Message-ID <[email protected]>
On Mon, 2006-02-27 at 20:36 +0000, Daniel Thompson wrote:
> coding done these days (though I do have a rather neat little flicker
> filter for SDL that I haven't quite got round to releasing yet).

Sorry for a self reply; it occurred to me how annoying it can be when
people brag about code they haven't released so I decided to let it
out! 

Basically the attached patch adds a simply but highly optimised 3-tap
FIR flicker filter. I have made it optional (based on an env. var.)
since if you already have application level flicker filtering (or a
clever TV) then it will just add extra blur. Flicker filtering made an
especially big difference to X11.

-- 
Daniel Thompson <[email protected]>
SDL-1.2.8-flicker_filter.patch (text/x-patch, 3.2 KB)
A 3 tap FIR vertical flicker filter.
Index: SDL-1.2.8/src/video/gc/SDL_gcvideo.c
===================================================================
--- SDL-1.2.8.orig/src/video/gc/SDL_gcvideo.c	2005-11-15 07:35:39.000000000 +0000
+++ SDL-1.2.8/src/video/gc/SDL_gcvideo.c	2005-11-16 19:42:12.000000000 +0000
@@ -70,6 +70,7 @@
 /* etc. */
 static void GC_InitRGB2YUVTables(void);
 static void GC_UpdateRects(_THIS, int numrects, SDL_Rect * rects);
+static void GC_UpdateRectRGB16_ff(_THIS, SDL_Rect * rect, int pitch);
 static void GC_UpdateRectRGB16(_THIS, SDL_Rect * rect, int pitch);
 static void GC_UpdateRectRGB24(_THIS, SDL_Rect * rect, int pitch);
 static void GC_UpdateRectRGB32(_THIS, SDL_Rect * rect, int pitch);
@@ -375,6 +376,7 @@
 	Uint32 Gmask;
 	Uint32 Bmask;
 	Uint32 *p, *q;
+	const char *flicker_filter;
 
 	GC_DPRINTF("Setting %dx%d %dbpp mode\n", width, height, bpp);
 
@@ -514,8 +516,14 @@
 		_this->hidden->UpdateRect = GC_UpdateRectRGB24;
 		break;
 	case 16:
-		GC_DPRINTF("Using new fast 16bpp blitter\n");
-		_this->hidden->UpdateRect = GC_UpdateRectRGB16;
+		flicker_filter = getenv("SDL_GC_FLICKER_FILTER");
+		if (flicker_filter) {
+			GC_DPRINTF("Using flicker filtered 16bpp blitter\n");
+			_this->hidden->UpdateRect = GC_UpdateRectRGB16_ff;
+		} else {
+			GC_DPRINTF("Using new fast 16bpp blitter\n");
+			_this->hidden->UpdateRect = GC_UpdateRectRGB16;
+		}
 		break;
 	default:
 		GC_DPRINTF("Using NO blitter\n");
@@ -667,6 +675,75 @@
 	    | (((char)Cr) << 0);
 }
 
+static inline Uint32 rgbrgb16_ff(Uint32 rgbrgb, Uint32 above, Uint32 below)
+{
+	const Uint32 R = 0xf800;
+	const Uint32 G = 0x07e0;
+	const Uint32 B = 0x001f;
+
+	const Uint32 _G_R_B = (G << 16) | R | B;
+	const Uint32 R_B_G_ = (R << 16) | (B << 16) | G;
+
+	Uint32 _g_r_b, r_b_g_;
+
+	_g_r_b = (rgbrgb & _G_R_B) << 1;
+	_g_r_b += (above & _G_R_B);
+	_g_r_b += (below & _G_R_B);
+	_g_r_b >>= 2;
+
+	r_b_g_ = (rgbrgb & R_B_G_) >> 1;
+	r_b_g_ += (above & R_B_G_) >> 2;
+	r_b_g_ += (below & R_B_G_) >> 2;
+
+	return (_g_r_b & _G_R_B) | (r_b_g_ & R_B_G_);
+}
+
+static void GC_UpdateRectRGB16_ff(_THIS, SDL_Rect * rect, int pitch)
+{
+	const Uint32 black = 0;
+
+	int width, height, left, line, i, mod, mod32, pitch32;
+	Uint8 *src, *dst;
+	Uint32 *src32, *dst32;
+	union {
+		Uint32 rgbrgb;
+		Uint16 rgb[2];
+	} pp;
+
+	/* XXX case width < 2 needs special treatment */
+
+	/* in pixel units */
+	left = rect->x & ~1;	/* 2 pixel align */
+	width = (rect->w + 1) & ~1;	/* 2 pixel align in excess */
+	line = rect->y;
+	height = rect->h;
+
+	/* in bytes, src and dest are 16bpp */
+	src = _this->hidden->buffer + (line * pitch) + left * 2;
+	dst = mapped_mem + mapped_offset + (line * pitch) + left * 2;
+	mod = pitch - width * 2;
+
+	src32 = (Uint32 *) src;
+	dst32 = (Uint32 *) dst;
+	pitch32 = pitch / 4;
+	mod32 = mod / 4;
+
+	while (height--) {
+		i = width / 2;
+
+		while (i--) {
+			pp.rgbrgb = rgbrgb16_ff(src32[0],
+					0 >= line ? black : src32[-pitch32],
+					479 <= line ? black : src32[pitch32]);
+			*dst32++ = rgbrgb16toyuy2(pp.rgb[0], pp.rgb[1]);
+			src32++;
+		}
+		dst32 += mod32;
+		src32 += mod32;
+		line++;
+	}
+}
+
 static void GC_UpdateRectRGB16(_THIS, SDL_Rect * rect, int pitch)
 {
 	int width, height, left, i, mod, mod32;