summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornia <nia@netbsd.org>2024-05-03 22:42:11 +0000
committerAlan Coopersmith <alan.coopersmith@oracle.com>2024-05-03 22:42:11 +0000
commit14d55de20e795d03a75ec03db301dd73615684b0 (patch)
tree1ec1c607bf335eb6f404b70267746955e56fdcff
parentb669c42077cf171fb0a5a8afa6bcaf17ed39c57f (diff)
Nintendo Wii (YUY2 framebuffer) support from Jared D. McNeillHEADmaster
-rw-r--r--src/wsfb_driver.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/wsfb_driver.c b/src/wsfb_driver.c
index b488ff2..81741df 100644
--- a/src/wsfb_driver.c
+++ b/src/wsfb_driver.c
@@ -127,6 +127,10 @@ static Bool WsfbDGASetMode(ScrnInfoPtr, DGAModePtr);
static void WsfbDGASetViewport(ScrnInfoPtr, int, int, int);
static Bool WsfbDGAInit(ScrnInfoPtr, ScreenPtr);
#endif
+
+#ifdef WSDISPLAY_TYPE_HOLLYWOOD
+static void WsfbShadowUpdateRGB16ToYUY2(ScreenPtr, shadowBufPtr);
+#endif
static Bool WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
pointer ptr);
@@ -146,6 +150,15 @@ enum { WSFB_ROTATE_NONE = 0,
*/
static int pix24bpp = 0;
+/*
+ * Screen-independent lookup table for RGB16 to YUV conversions.
+ */
+#ifdef WSDISPLAY_TYPE_HOLLYWOOD
+static unsigned char *mapRGB16ToY = NULL;
+static unsigned char *mapRGB16ToU = NULL;
+static unsigned char *mapRGB16ToV = NULL;
+#endif
+
#define WSFB_VERSION 4000
#define WSFB_NAME "wsfb"
#define WSFB_DRIVER_NAME "wsfb"
@@ -227,6 +240,7 @@ typedef struct {
int rotate;
Bool shadowFB;
void * shadow;
+ Bool useRGB16ToYUY2;
CloseScreenProcPtr CloseScreen;
CreateScreenResourcesProcPtr CreateScreenResources;
void (*PointerMoved)(SCRN_ARG_TYPE, int, int);
@@ -547,6 +561,24 @@ WsfbPreInit(ScrnInfoPtr pScrn, int flags)
"Shadow FB option ignored on depth < 8\n");
}
+ fPtr->useRGB16ToYUY2 = FALSE;
+#ifdef WSDISPLAY_TYPE_HOLLYWOOD
+ /*
+ * Hollywood has a YUY2 framebuffer, but we treat it as
+ * RGB565 and convert with a custom shadowproc.
+ */
+ if (wstype == WSDISPLAY_TYPE_HOLLYWOOD) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Enabling RGB16->YUY2 conversion for Hollywood\n");
+ fPtr->useRGB16ToYUY2 = TRUE;
+ if (!fPtr->shadowFB) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Shadow FB forced on for RGB16->YUY2 conversion\n");
+ fPtr->shadowFB = TRUE;
+ }
+ }
+#endif
+
/* Rotation */
fPtr->rotate = WSFB_ROTATE_NONE;
if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) {
@@ -1326,3 +1358,100 @@ WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
return FALSE;
}
}
+
+#ifdef WSDISPLAY_TYPE_HOLLYWOOD
+static inline void
+WsfbCopyRGB16ToYUY2(void *dest, void *src, int len)
+{
+ uint16_t *src16 = src;
+ uint32_t *dest32 = dest;
+
+ while (len > 0) {
+ const uint16_t rgb0 = src16[0];
+ const uint16_t rgb1 = src16[1];
+ const uint16_t rgb = ((rgb0 >> 1) & ~0x8410) +
+ ((rgb1 >> 1) & ~0x8410) +
+ ((rgb0 & rgb1) & 0x0841);
+ const uint32_t y0 = mapRGB16ToY[rgb0];
+ const uint32_t y1 = mapRGB16ToY[rgb1];
+ const uint32_t u = mapRGB16ToU[rgb];
+ const uint32_t v = mapRGB16ToV[rgb];
+
+ *dest32 = (y0 << 24) | (u << 16) | (y1 << 8) | v;
+
+ dest32++;
+ src16 += 2;
+ len -= 4;
+ }
+}
+
+void
+WsfbShadowUpdateRGB16ToYUY2(ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+ RegionPtr damage = DamageRegion (pBuf->pDamage);
+ PixmapPtr pShadow = pBuf->pPixmap;
+ int nbox = RegionNumRects (damage);
+ BoxPtr pbox = RegionRects (damage);
+ FbBits *shaBase, *shaLine, *sha;
+ FbStride shaStride;
+ int scrBase, scrLine, scr;
+ int shaBpp;
+ int shaXoff, shaYoff; /* XXX assumed to be zero */
+ int x, y, w, h, width;
+ int i;
+ FbBits *winBase = NULL, *win;
+ CARD32 winSize;
+
+ fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff);
+ while (nbox--)
+ {
+ x = pbox->x1 * shaBpp;
+ y = pbox->y1;
+ w = (pbox->x2 - pbox->x1) * shaBpp;
+ h = pbox->y2 - pbox->y1;
+
+ scrLine = (x >> FB_SHIFT);
+ shaLine = shaBase + y * shaStride + (x >> FB_SHIFT);
+
+ x &= FB_MASK;
+ w = (w + x + FB_MASK) >> FB_SHIFT;
+
+ while (h--)
+ {
+ winSize = 0;
+ scrBase = 0;
+ width = w;
+ scr = scrLine;
+ sha = shaLine;
+ while (width) {
+ /* how much remains in this window */
+ i = scrBase + winSize - scr;
+ if (i <= 0 || scr < scrBase)
+ {
+ winBase = (FbBits *) (*pBuf->window) (pScreen,
+ y,
+ scr * sizeof (FbBits),
+ SHADOW_WINDOW_WRITE,
+ &winSize,
+ pBuf->closure);
+ if(!winBase)
+ return;
+ scrBase = scr;
+ winSize /= sizeof (FbBits);
+ i = winSize;
+ }
+ win = winBase + (scr - scrBase);
+ if (i > width)
+ i = width;
+ width -= i;
+ scr += i;
+ WsfbCopyRGB16ToYUY2(win, sha, i * sizeof(FbBits));
+ sha += i;
+ }
+ shaLine += shaStride;
+ y++;
+ }
+ pbox++;
+ }
+}
+#endif