Module Name: xsrc Committed By: martin Date: Sat Feb 3 11:49:31 UTC 2024
Modified Files: xsrc/external/mit/xf86-video-wsfb/dist/src [netbsd-10]: wsfb.h wsfb_driver.c Log Message: Pull up following revision(s) (requested by jmcneill in ticket #562): external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c: revision 1.48 external/mit/xf86-video-wsfb/dist/src/wsfb.h: revision 1.11 xf86-video-wsfb: Add support for Nintendo Wii The Wii's framebuffer is YUY2, so add a custom shadowproc that converts from RGB565 to YUY2 on the fly. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.10.2.1 \ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h cvs rdiff -u -r1.47 -r1.47.2.1 \ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h diff -u xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h:1.10 xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h:1.10.2.1 --- xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h:1.10 Sat Sep 10 19:23:03 2022 +++ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h Sat Feb 3 11:49:31 2024 @@ -73,6 +73,7 @@ typedef struct { void * shadow; Bool HWCursor; Bool useSwap32; + Bool useRGB16ToYUY2; #ifdef HAVE_SHADOW_AFB Bool planarAfb; #endif Index: xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c diff -u xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c:1.47 xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c:1.47.2.1 --- xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c:1.47 Sat Sep 10 19:25:44 2022 +++ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c Sat Feb 3 11:49:31 2024 @@ -133,6 +133,7 @@ static void WsfbDGASetViewport(ScrnInfoP static Bool WsfbDGAInit(ScrnInfoPtr, ScreenPtr); #endif +static void WsfbShadowUpdateRGB16ToYUY2(ScreenPtr, shadowBufPtr); static void WsfbShadowUpdateSwap32(ScreenPtr, shadowBufPtr); static void WsfbShadowUpdateSplit(ScreenPtr, shadowBufPtr); @@ -154,6 +155,13 @@ enum { WSFB_ROTATE_NONE = 0, */ static int pix24bpp = 0; +/* + * Screen-independent lookup table for RGB16 to YUV conversions. + */ +static unsigned char *mapRGB16ToY = NULL; +static unsigned char *mapRGB16ToU = NULL; +static unsigned char *mapRGB16ToV = NULL; + #define WSFB_VERSION 4000 #define WSFB_NAME "wsfb" #define WSFB_DRIVER_NAME "wsfb" @@ -610,6 +618,25 @@ WsfbPreInit(ScrnInfoPtr pScrn, int flags fPtr->shadowFB = TRUE; } } + + fPtr->useRGB16ToYUY2 = FALSE; +#ifdef WSDISPLAY_TYPE_HOLLYWOOD + 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; + } + /* + * Hollywood has a YUY2 framebuffer, but we treat it as + * RGB565 and convert with a custom shadowproc. + */ + fPtr->fbi.fbi_pixeltype = WSFB_RGB; + } +#endif /* Rotation */ fPtr->rotate = WSFB_ROTATE_NONE; if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) { @@ -823,6 +850,35 @@ WsfbCreateScreenResources(ScreenPtr pScr pPixmap = pScreen->GetScreenPixmap(pScreen); if (fPtr->fbi.fbi_flags & WSFB_VRAM_IS_SPLIT) { shadowproc = WsfbShadowUpdateSplit; + } else if (fPtr->useRGB16ToYUY2) { + /* Build RGB16 to Y, U, and V lookup tables */ + if (mapRGB16ToY == NULL) { + mapRGB16ToY = malloc(0x30000); + if (mapRGB16ToY == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot malloc %d bytes for RGB16->YUY2\n", + 0x30000); + return FALSE; + } + mapRGB16ToU = mapRGB16ToY + 0x10000; + mapRGB16ToV = mapRGB16ToY + 0x20000; + for (unsigned int n = 0; n < 0x10000; n++) { + /* RGB565 values, scaled to 8 bits */ + const double R = (((n >> 11) & 0x1f) * 255) / 31; + const double G = (((n >> 5) & 0x3f) * 255) / 63; + const double B = (((n >> 0) & 0x1f) * 255) / 31; + + /* Convert to YUV */ + mapRGB16ToY[n] = + 0.257 * R + 0.504 * G + 0.098 * B + 16; + mapRGB16ToU[n] = + -0.148 * R - 0.291 * G + 0.439 * B + 128; + mapRGB16ToV[n] = + 0.439 * R - 0.368 * G - 0.071 * B + 128; + } + } + + shadowproc = WsfbShadowUpdateRGB16ToYUY2; } else if (fPtr->useSwap32) { shadowproc = WsfbShadowUpdateSwap32; } else if (fPtr->rotate) { @@ -1682,6 +1738,101 @@ WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDr } 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++; + } +} + +static inline void memcpy32sw(void *dest, void *src, int len) { uint32_t *d = dest, *s = src;