diff options
-rw-r--r-- | src/drmmode_display.c | 40 | ||||
-rw-r--r-- | src/nv_driver.c | 69 |
2 files changed, 104 insertions, 5 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 429e9cc..1521a32 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -51,6 +51,7 @@ typedef struct { #ifdef HAVE_LIBUDEV struct udev_monitor *uevent_monitor; #endif + Bool called_csr; } drmmode_rec, *drmmode_ptr; typedef struct { @@ -345,7 +346,9 @@ 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->scanout_pixmap) + x = y = 0; + else if (drmmode_crtc->rotate_fb_id) { fb_id = drmmode_crtc->rotate_fb_id; x = 0; y = 0; @@ -536,6 +539,37 @@ drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, } } +static Bool +drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) +{ + ScreenPtr screen = xf86ScrnToScreen(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + PixmapPtr screenpix = screen->GetScreenPixmap(screen); + + if (!ppix) { + if (crtc->randr_crtc->scanout_pixmap) + PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix); + return TRUE; + } + + if (!drmmode->called_csr) { + NVPtr pNv = NVPTR(crtc->scrn); + drmmode->called_csr = TRUE; + miCreateScreenResources(screen); + screenpix = screen->GetScreenPixmap(screen); + nouveau_bo_ref(pNv->scanout, &nouveau_pixmap(screenpix)->bo); + } + + PixmapStartDirtyTracking(ppix, screenpix, 0, 0); + + /* need to set this pixmap into some sort of shadowing environment + for now */ + + + return TRUE; +} + static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .dpms = drmmode_crtc_dpms, .set_mode_major = drmmode_set_mode_major, @@ -547,6 +581,8 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .shadow_allocate = drmmode_crtc_shadow_allocate, .shadow_destroy = drmmode_crtc_shadow_destroy, .gamma_set = drmmode_gamma_set, + + .set_scanout_pixmap = drmmode_set_scanout_pixmap, }; @@ -1183,7 +1219,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) drmmode = xnfalloc(sizeof *drmmode); drmmode->fd = fd; drmmode->fb_id = 0; - + drmmode->called_csr = FALSE; xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); drmmode->cpp = cpp; diff --git a/src/nv_driver.c b/src/nv_driver.c index f14c847..5645f59 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -447,15 +447,78 @@ NVFlushCallback(CallbackListPtr *list, pointer user_data, pointer call_data) } #ifdef NOUVEAU_PIXMAP_SHARING +/* + * this function can possibly be improved and optimised, by clipping + * instead of iterating + */ +Bool nvPixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) +{ + ScreenPtr pScreen = dirty->src->drawable.pScreen; + int n; + BoxPtr b; + RegionPtr region = DamageRegion(dirty->damage); + GCPtr pGC; + PixmapPtr dst; + SourceValidateProcPtr SourceValidate; + + /* + * SourceValidate is used by the software cursor code + * to pull the cursor off of the screen when reading + * bits from the frame buffer. Bypassing this function + * leaves the software cursor in place + */ + SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = NULL; + + RegionTranslate(dirty_region, dirty->x, dirty->y); + RegionIntersect(dirty_region, dirty_region, region); + + if (RegionNil(dirty_region)) { + RegionUninit(dirty_region); + return FALSE; + } + + dst = dirty->slave_dst->master_pixmap; + if (dirty->slave_dst->drawable.pScreen == pScreen) + dst = dirty->slave_dst; + + RegionTranslate(dirty_region, -dirty->x, -dirty->y); + n = RegionNumRects(dirty_region); + b = RegionRects(dirty_region); + + pGC = GetScratchGC(dirty->src->drawable.depth, pScreen); + ValidateGC(&dst->drawable, pGC); + + while (n--) { + BoxRec dst_box; + int w, h; + + dst_box = *b; + w = dst_box.x2 - dst_box.x1; + h = dst_box.y2 - dst_box.y1; + + pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC, + dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1); + b++; + } + FreeScratchGC(pGC); + + pScreen->SourceValidate = SourceValidate; + return TRUE; +} + static void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) { RegionRec pixregion; - PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); + if (dirty->slave_dst->drawable.pScreen == screen) + PixmapRegionInit(&pixregion, dirty->src); + else + PixmapRegionInit(&pixregion, dirty->slave_dst); DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); - PixmapSyncDirtyHelper(dirty, &pixregion); + nvPixmapSyncDirtyHelper(dirty, &pixregion); DamageRegionProcessPending(&dirty->slave_dst->drawable); RegionUninit(&pixregion); @@ -676,7 +739,7 @@ nouveau_setup_capabilities(ScrnInfoPtr pScrn) if (value & DRM_PRIME_CAP_EXPORT) pScrn->capabilities |= RR_Capability_SourceOutput; if (value & DRM_PRIME_CAP_IMPORT) - pScrn->capabilities |= RR_Capability_SourceOffload; + pScrn->capabilities |= RR_Capability_SourceOffload | RR_Capability_SinkOutput; } #endif } |