summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-01-07 15:28:53 +1000
committerDave Airlie <airlied@redhat.com>2013-01-07 15:28:53 +1000
commitfe8af58cf82cddcffb4f354a5b3ba3bb1173bfe0 (patch)
tree8533d37a64d676c1bd3c58f605a563ca9247b9d1
parent8f934fad5d4934936b3265f272ca81e73c60d7dc (diff)
nouveau: hack reverse optimus uprev-optimus
-rw-r--r--src/drmmode_display.c40
-rw-r--r--src/nv_driver.c69
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
}