From c8ff63337a8b1f552c801050283f62d92d997ae6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 11 May 2012 16:35:05 +0100 Subject: dirty pixmap tracking --- src/driver.c | 91 +++++++++++++++++++++++++++++++++++++++++---------- src/drmmode_display.c | 75 +++++++++++++++++++++++++++++++++++++++++- src/drmmode_display.h | 5 ++- 3 files changed, 151 insertions(+), 20 deletions(-) diff --git a/src/driver.c b/src/driver.c index ff86c07..e26b19e 100644 --- a/src/driver.c +++ b/src/driver.c @@ -287,7 +287,8 @@ ms_udev_probe(DriverPtr driver, scrn->LeaveVT = LeaveVT; scrn->FreeScreen = FreeScreen; scrn->ValidMode = ValidMode; - scrn->roles = ROLE_SLAVE_OUTPUT; + scrn->roles = RR_Role_Slave_Output; + scrn->abilities = 0; xf86DrvMsg(scrn->scrnIndex, X_INFO, "using drv %s\n", dev ? dev->path : "default device"); } @@ -361,11 +362,13 @@ GetRec(ScrnInfoPtr pScrn) return TRUE; } -static void dispatch_dirty(ScreenPtr pScreen) +static int dispatch_dirty_region(ScrnInfoPtr scrn, + PixmapPtr pixmap, + DamagePtr damage, + int fb_id) { - ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(scrn); - RegionPtr dirty = DamageRegion(ms->damage); + RegionPtr dirty = DamageRegion(damage); unsigned num_cliprects = REGION_NUM_RECTS(dirty); if (num_cliprects) { @@ -382,21 +385,68 @@ static void dispatch_dirty(ScreenPtr pScreen) } /* TODO query connector property to see if this is needed */ - ret = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, clip, num_cliprects); + ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); + DamageEmpty(damage); if (ret) { - if (ret == -EINVAL || ret == -ENOSYS) { - ms->dirty_enabled = FALSE; - DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); - DamageDestroy(ms->damage); - ms->damage = NULL; - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n"); - return; - } else - ErrorF("%s: failed to send dirty (%i, %s)\n", - __func__, ret, strerror(-ret)); + if (ret == -EINVAL) + return ret; } - - DamageEmpty(ms->damage); + } + return 0; +} + +static void dispatch_dirty(ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + modesettingPtr ms = modesettingPTR(scrn); + PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); + int fb_id = ms->drmmode.fb_id; + int ret; + + ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id); + if (ret == -EINVAL || ret == -ENOSYS) { + ms->dirty_enabled = FALSE; + DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); + DamageDestroy(ms->damage); + ms->damage = NULL; + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n"); + return; + } +} + +static void dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc) +{ + modesettingPtr ms = modesettingPTR(scrn); + ScreenPtr pScreen = scrn->pScreen; + PixmapPtr pixmap = crtc->randr_crtc->slave_pixmap; + msPixmapPrivPtr ppriv = msGetPixmapPriv(pixmap); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + DamagePtr damage = drmmode_crtc->slave_damage; + int fb_id = ppriv->fb_id; + int ret; + + ret = dispatch_dirty_region(scrn, pixmap, damage, fb_id); + if (ret) { + + } +} + +static void dispatch_slave_dirty(ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + modesettingPtr ms = modesettingPTR(scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->randr_crtc) + continue; + if (!crtc->randr_crtc->slave_pixmap) + continue; + + dispatch_dirty_crtc(scrn, crtc); } } @@ -408,8 +458,13 @@ static void msBlockHandler(ScreenPtr pScreen, pointer blockData, pointer pTimeou pScreen->BlockHandler = ms->BlockHandler; pScreen->BlockHandler(pScreen, blockData, pTimeout, pReadmask); pScreen->BlockHandler = msBlockHandler; - if (ms->dirty_enabled) + + if (pScreen->isGPU) { + dispatch_slave_dirty(pScreen); + } else if (ms->dirty_enabled) dispatch_dirty(pScreen); + + } static void diff --git a/src/drmmode_display.c b/src/drmmode_display.c index c140bfc..78e3168 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -31,6 +31,7 @@ #include #include +#include #include #include "xf86str.h" #include "X11/Xatom.h" @@ -50,6 +51,8 @@ #include #endif +#include + static struct dumb_bo *dumb_bo_create(int fd, const unsigned width, const unsigned height, const unsigned bpp) @@ -371,7 +374,11 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); fb_id = drmmode->fb_id; - if (drmmode_crtc->rotate_fb_id) { + if (crtc->randr_crtc->slave_pixmap) { + msPixmapPrivPtr ppriv = msGetPixmapPriv(crtc->randr_crtc->slave_pixmap); + fb_id = ppriv->fb_id; + x = y = 0; + } else if (drmmode_crtc->rotate_fb_id) { fb_id = drmmode_crtc->rotate_fb_id; x = y = 0; } @@ -488,6 +495,52 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, size, red, green, blue); } +static Bool +drmmode_set_slave_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + msPixmapPrivPtr ppriv; + void *ptr; + + if (!ppix) { + if (crtc->randr_crtc->slave_pixmap) { + ppriv = msGetPixmapPriv(crtc->randr_crtc->slave_pixmap); + drmModeRmFB(drmmode->fd, ppriv->fb_id); + } + if (drmmode_crtc->slave_damage) { + DamageUnregister(&crtc->randr_crtc->slave_pixmap->drawable, + drmmode_crtc->slave_damage); + drmmode_crtc->slave_damage = NULL; + } + return TRUE; + } + + ppriv = msGetPixmapPriv(ppix); + if (!drmmode_crtc->slave_damage) { + drmmode_crtc->slave_damage = DamageCreate(NULL, NULL, + DamageReportNone, + TRUE, + crtc->randr_crtc->pScreen, + NULL); + } + ptr = drmmode_map_slave_bo(drmmode, ppriv); + ppix->devPrivate.ptr = ptr; + DamageRegister(&ppix->drawable, drmmode_crtc->slave_damage); + + if (ppriv->fb_id == 0) { + int r; + r = drmModeAddFB(drmmode->fd, ppix->drawable.width, + ppix->drawable.height, + ppix->drawable.depth, + ppix->drawable.bitsPerPixel, + ppix->devKind, + ppriv->backing_bo->handle, + &ppriv->fb_id); + } + return TRUE; +} + static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .dpms = drmmode_crtc_dpms, .set_mode_major = drmmode_set_mode_major, @@ -499,6 +552,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .gamma_set = drmmode_crtc_gamma_set, .destroy = NULL, /* XXX */ + .set_slave_pixmap = drmmode_set_slave_pixmap, }; static void @@ -1071,6 +1125,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) int i, num_dvi = 0, num_hdmi = 0; int ret; uint64_t value = 0; + xf86ProviderPtr provider; /* check for dumb capability */ ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value); @@ -1095,9 +1150,13 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) for (i = 0; i < drmmode->mode_res->count_connectors; i++) drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi); + /* workout clones */ drmmode_clones_init(pScrn, drmmode); + provider = xf86ProviderCreate(pScrn); + if (provider == NULL) + return FALSE; xf86InitialConfiguration(pScrn, TRUE); return TRUE; @@ -1357,6 +1416,20 @@ void *drmmode_map_front_bo(drmmode_ptr drmmode) } +void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv) +{ + int ret; + + if (ppriv->backing_bo->ptr) + return ppriv->backing_bo->ptr; + + ret = dumb_bo_map(drmmode->fd, ppriv->backing_bo); + if (ret) + return NULL; + + return ppriv->backing_bo->ptr; +} + Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 259f01e..fac6c28 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -67,6 +67,9 @@ typedef struct { struct dumb_bo *cursor_bo; unsigned rotate_fb_id; uint16_t lut_r[256], lut_g[256], lut_b[256]; + DamagePtr slave_damage; + PixmapPtr slave_pixmap; + int slave_fb_id; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -112,7 +115,7 @@ Bool drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode); void *drmmode_map_front_bo(drmmode_ptr drmmode); Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode); void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode); - +void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv); Bool drmmode_SetSlaveBO(PixmapPtr ppix, drmmode_ptr drmmode, int fd_handle, int pitch, int size); -- cgit v1.2.3