summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-07-30 10:08:25 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-08-05 17:59:43 -0400
commitc5cbfcf575b0b4aea6f797558ae974c1453c8e07 (patch)
treed177b24d3ec7ced393a5d04fa313eb2ddf6f9faf
parent429d5b797769895eb4f5fef816ce4e2f3a342031 (diff)
drmmode: add support for multi-screen reverse optimus
Initial reverse optimus didn't consider multiple screens, so this overhauls the code to use the new X server interface, and allows for multiple outputs on the dGPU to be used with the iGPU doing the rendering. Ported from Dave's nouveau patch. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/drmmode_display.c52
-rw-r--r--src/drmmode_display.h1
2 files changed, 44 insertions, 9 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 244a98f8..1df104d1 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -521,14 +521,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
}
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
crtc->gamma_blue, crtc->gamma_size);
-
+
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
fb_id = drmmode->fb_id;
#ifdef RADEON_PIXMAP_SHARING
- if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap)
- x = y = 0;
- else
+ if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
+ x = drmmode_crtc->scanout_pixmap_x;
+ y = 0;
+ } else
#endif
if (drmmode_crtc->rotate_fb_id) {
fb_id = drmmode_crtc->rotate_fb_id;
@@ -741,25 +742,58 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
{
ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
PixmapPtr screenpix = screen->GetScreenPixmap(screen);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ int c, total_width = 0, max_height = 0, this_x = 0;
if (!ppix) {
if (crtc->randr_crtc->scanout_pixmap)
PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
+ drmmode_crtc->scanout_pixmap_x = 0;
return TRUE;
}
- if (ppix->drawable.width > screenpix->drawable.width ||
- ppix->drawable.height > screenpix->drawable.height) {
+ /* iterate over all the attached crtcs -
+ work out bounding box */
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr iter = xf86_config->crtc[c];
+ if (!iter->enabled && iter != crtc)
+ continue;
+ if (iter == crtc) {
+ this_x = total_width;
+ total_width += ppix->drawable.width;
+ if (max_height < ppix->drawable.height)
+ max_height = ppix->drawable.height;
+ } else {
+ total_width += iter->mode.HDisplay;
+ if (max_height < iter->mode.VDisplay)
+ max_height = iter->mode.VDisplay;
+ }
+#ifndef HAS_DIRTYTRACKING2
+ if (iter != crtc) {
+ ErrorF("Cannot do multiple crtcs without X server dirty tracking 2 interface\n");
+ return FALSE;
+ }
+#endif
+ }
+
+ if (total_width != screenpix->drawable.width ||
+ max_height != screenpix->drawable.height) {
Bool ret;
- ret = drmmode_xf86crtc_resize(crtc->scrn, ppix->drawable.width, ppix->drawable.height);
+ ret = drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height);
if (ret == FALSE)
return FALSE;
screenpix = screen->GetScreenPixmap(screen);
- screen->width = screenpix->drawable.width = ppix->drawable.width;
- screen->height = screenpix->drawable.height = ppix->drawable.height;
+ screen->width = screenpix->drawable.width = total_width;
+ screen->height = screenpix->drawable.height = max_height;
}
+ drmmode_crtc->scanout_pixmap_x = this_x;
+#ifdef HAS_DIRTYTRACKING2
+ PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
+#else
PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
+#endif
return TRUE;
}
#endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 2fccfda7..41e29f62 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -81,6 +81,7 @@ typedef struct {
int dpms_last_fps;
uint32_t interpolated_vblanks;
uint16_t lut_r[256], lut_g[256], lut_b[256];
+ int scanout_pixmap_x;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {