diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am index 82c4f2f32..ca7e05aac 100644 --- a/hw/xfree86/drivers/modesetting/Makefile.am +++ b/hw/xfree86/drivers/modesetting/Makefile.am @@ -51,6 +51,8 @@ modesetting_drv_la_SOURCES = \ dumb_bo.c \ dumb_bo.h \ present.c \ + sh3224.c \ + sh3224.h \ vblank.c \ $(NULL) diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index 256ca9580..7167800a1 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -60,6 +60,7 @@ #endif #include "driver.h" +#include "sh3224.h" static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y); static Bool CloseScreen(ScreenPtr pScreen); @@ -701,6 +702,11 @@ try_enable_glamor(ScrnInfoPtr pScrn) ms->drmmode.glamor = FALSE; #ifdef GLAMOR + if (ms->drmmode.force_24_32) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n"); + return; + } + if (!do_glamor) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n"); return; @@ -849,10 +855,16 @@ PreInit(ScrnInfoPtr pScrn, int flags) ms->drmmode.fd = ms->fd; drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp); - if (defaultdepth == 24 && defaultbpp == 24) - bppflags = SupportConvert32to24 | Support24bppFb; - else - bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; + if (defaultdepth == 24 && defaultbpp == 24) { + ms->drmmode.force_24_32 = TRUE; + ms->drmmode.kbpp = 24; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using 24bpp hw front buffer with 32bpp shadow\n"); + defaultbpp = 32; + } else { + ms->drmmode.kbpp = defaultbpp; + } + bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; if (!xf86SetDepthBpp (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags)) @@ -903,18 +915,24 @@ PreInit(ScrnInfoPtr pScrn, int flags) if (!ms->drmmode.glamor) { Bool prefer_shadow = TRUE; - ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); - if (!ret) { - prefer_shadow = !!value; - } + if (ms->drmmode.force_24_32) { + prefer_shadow = TRUE; + ms->drmmode.shadow_enable = TRUE; + } else { + ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); + if (!ret) { + prefer_shadow = !!value; + } - ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->drmmode.Options, - OPTION_SHADOW_FB, - prefer_shadow); + ms->drmmode.shadow_enable = + xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB, + prefer_shadow); + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ShadowFB: preferred %s, enabled %s\n", prefer_shadow ? "YES" : "NO", + ms->drmmode.force_24_32 ? "FORCE" : ms->drmmode.shadow_enable ? "YES" : "NO"); } @@ -987,7 +1005,7 @@ msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, modesettingPtr ms = modesettingPTR(pScrn); int stride; - stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; + stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8; *size = stride; return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset); @@ -1142,6 +1160,7 @@ CreateScreenResources(ScreenPtr pScreen) Bool ret; void *pixels = NULL; int err; + Bool use_ms_shadow = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32; pScreen->CreateScreenResources = ms->createScreenResources; ret = pScreen->CreateScreenResources(pScreen); @@ -1173,7 +1192,8 @@ CreateScreenResources(ScreenPtr pScreen) FatalError("Couldn't adjust screen pixmap\n"); if (ms->drmmode.shadow_enable) { - if (!shadowAdd(pScreen, rootPixmap, msUpdatePacked, + if (!shadowAdd(pScreen, rootPixmap, + use_ms_shadow ? ms_shadowUpdate32to24 : msUpdatePacked, msShadowWindow, 0, 0)) return FALSE; } diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index f2a08aebb..9801d32ad 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -705,7 +705,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (fb_id == 0) { ret = drmModeAddFB(drmmode->fd, pScrn->virtualX, pScrn->virtualY, - pScrn->depth, pScrn->bitsPerPixel, + pScrn->depth, drmmode->kbpp, drmmode_bo_get_pitch(&drmmode->front_bo), drmmode_bo_get_handle(&drmmode->front_bo), &drmmode->fb_id); @@ -1018,14 +1018,14 @@ drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height) int ret; if (!drmmode_create_bo(drmmode, &drmmode_crtc->rotate_bo, - width, height, crtc->scrn->bitsPerPixel)) { + width, height, drmmode->kbpp)) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Couldn't allocate shadow memory for rotated CRTC\n"); return NULL; } ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, - crtc->scrn->bitsPerPixel, + drmmode->kbpp, drmmode_bo_get_pitch(&drmmode_crtc->rotate_bo), drmmode_bo_get_handle(&drmmode_crtc->rotate_bo), &drmmode_crtc->rotate_fb_id); @@ -1096,7 +1096,7 @@ drmmode_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) rotate_pixmap = drmmode_create_pixmap_header(scrn->pScreen, width, height, scrn->depth, - scrn->bitsPerPixel, + drmmode->kbpp, rotate_pitch, pPixData); @@ -1985,6 +1985,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) uint32_t old_fb_id; int i, pitch, old_width, old_height, old_pitch; int cpp = (scrn->bitsPerPixel + 7) / 8; + int kcpp = (drmmode->kbpp + 7) / 8; PixmapPtr ppix = screen->GetScreenPixmap(screen); void *new_pixels = NULL; @@ -2007,14 +2008,14 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) drmmode->fb_id = 0; if (!drmmode_create_bo(drmmode, &drmmode->front_bo, - width, height, scrn->bitsPerPixel)) + width, height, drmmode->kbpp)) goto fail; pitch = drmmode_bo_get_pitch(&drmmode->front_bo); scrn->virtualX = width; scrn->virtualY = height; - scrn->displayWidth = pitch / cpp; + scrn->displayWidth = pitch / kcpp; if (!drmmode->gbm) { new_pixels = drmmode_map_front_bo(drmmode); @@ -2023,8 +2024,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) } if (drmmode->shadow_enable) { - uint32_t size = scrn->displayWidth * scrn->virtualY * - ((scrn->bitsPerPixel + 7) >> 3); + uint32_t size = scrn->displayWidth * scrn->virtualY * cpp; new_pixels = calloc(1, size); if (new_pixels == NULL) goto fail; @@ -2032,7 +2032,8 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) drmmode->shadow_fb = new_pixels; } - screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, new_pixels); + screen->ModifyPixmapHeader(ppix, width, height, -1, -1, + scrn->displayWidth * cpp, new_pixels); if (!drmmode_glamor_handle_new_screen_pixmap(drmmode)) goto fail; @@ -2059,7 +2060,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) drmmode->front_bo = old_front; scrn->virtualX = old_width; scrn->virtualY = old_height; - scrn->displayWidth = old_pitch / cpp; + scrn->displayWidth = old_pitch / kcpp; drmmode->fb_id = old_fb_id; return FALSE; @@ -2426,7 +2427,7 @@ drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int width; int height; - int bpp = pScrn->bitsPerPixel; + int bpp = ms->drmmode.kbpp; int i; int cpp = (bpp + 7) / 8; diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index 6d2c0a4bc..b954fa001 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -48,6 +48,7 @@ typedef struct { unsigned fb_id; drmModeFBPtr mode_fb; int cpp; + int kbpp; ScrnInfoPtr scrn; struct gbm_device *gbm; @@ -67,6 +68,7 @@ typedef struct { Bool shadow_enable; /** Is Option "PageFlip" enabled? */ Bool pageflip; + Bool force_24_32; void *shadow_fb; /** diff --git a/hw/xfree86/drivers/modesetting/sh3224.c b/hw/xfree86/drivers/modesetting/sh3224.c new file mode 100644 index 000000000..a64a1031e --- /dev/null +++ b/hw/xfree86/drivers/modesetting/sh3224.c @@ -0,0 +1,140 @@ +/* + * + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include "dix-config.h" +#endif + +#include "shadow.h" +#include "fb.h" + +#include "sh3224.h" +#define Get8(a) ((CARD32) READ(a)) + +#if BITMAP_BIT_ORDER == MSBFirst +#define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) +#define Put24(a,p) ((WRITE((a+0), (CARD8) ((p) >> 16))), \ + (WRITE((a+1), (CARD8) ((p) >> 8))), \ + (WRITE((a+2), (CARD8) (p)))) +#else +#define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) +#define Put24(a,p) ((WRITE((a+0), (CARD8) (p))), \ + (WRITE((a+1), (CARD8) ((p) >> 8))), \ + (WRITE((a+2), (CARD8) ((p) >> 16)))) +#endif + +static void +sh24_32BltLine(CARD8 *srcLine, + CARD8 *dstLine, + int width) +{ + CARD32 *src; + CARD8 *dst; + int w; + CARD32 pixel; + + src = (CARD32 *) srcLine; + dst = dstLine; + w = width; + + while (((long)dst & 3) && w) { + w--; + pixel = READ(src++); + Put24(dst, pixel); + dst += 3; + } + /* Do four aligned pixels at a time */ + while (w >= 4) { + CARD32 s0, s1; + + s0 = READ(src++); + s1 = READ(src++); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) dst, (s0 & 0xffffff) | (s1 << 24)); +#else + WRITE((CARD32 *) dst, (s0 << 8) | ((s1 & 0xffffff) >> 16)); +#endif + s0 = READ(src++); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) (dst + 4), + ((s1 & 0xffffff) >> 8) | (s0 << 16)); +#else + WRITE((CARD32 *) (dst + 4), + (s1 << 16) | ((s0 & 0xffffff) >> 8)); +#endif + s1 = READ(src++); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) (dst + 8), + ((s0 & 0xffffff) >> 16) | (s1 << 8)); +#else + WRITE((CARD32 *) (dst + 8), (s0 << 24) | (s1 & 0xffffff)); +#endif + dst += 12; + w -= 4; + } + while (w--) { + pixel = READ(src++); + Put24(dst, pixel); + dst += 3; + } +} + +void +ms_shadowUpdate32to24(ScreenPtr pScreen, shadowBufPtr pBuf) +{ + RegionPtr damage = shadowDamage(pBuf); + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = RegionNumRects(damage); + BoxPtr pbox = RegionRects(damage); + FbStride shaStride; + int shaBpp; + _X_UNUSED int shaXoff, shaYoff; + int x, y, w, h; + CARD32 winSize; + FbBits *shaBase, *shaLine; + CARD8 *winBase = NULL, *winLine; + + fbGetDrawable(&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, + shaYoff); + + /* just get the initial window base + stride */ + winBase = (*pBuf->window)(pScreen, 0, 0, SHADOW_WINDOW_WRITE, + &winSize, pBuf->closure); + + while (nbox--) { + x = pbox->x1; + y = pbox->y1; + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + + winLine = winBase + y * winSize + (x * 3); + shaLine = shaBase + y * shaStride + ((x * shaBpp) >> FB_SHIFT); + + while (h--) { + sh24_32BltLine((CARD8 *)shaLine, (CARD8 *)winLine, w); + winLine += winSize; + shaLine += shaStride; + } + pbox++; + } +} diff --git a/hw/xfree86/drivers/modesetting/sh3224.h b/hw/xfree86/drivers/modesetting/sh3224.h new file mode 100644 index 000000000..fc301f99d --- /dev/null +++ b/hw/xfree86/drivers/modesetting/sh3224.h @@ -0,0 +1,7 @@ +#ifndef SH3224_H +#define SH3224_H + +void +ms_shadowUpdate32to24(ScreenPtr pScreen, shadowBufPtr pBuf); + +#endif