[PATCH 3/3] drmmode: add support for multi-screen reverse optimus

alexdeucher at gmail.com alexdeucher at gmail.com
Wed Jul 31 06:04:04 PDT 2013


From: Alex Deucher <alexander.deucher at amd.com>

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 at amd.com>
---
 src/drmmode_display.c |   52 ++++++++++++++++++++++++++++++++++++++++--------
 src/drmmode_display.h |    1 +
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index e34afff..9c21817 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 2fccfda..41e29f6 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 {
-- 
1.7.7.5



More information about the xorg-driver-ati mailing list