From: Alex Deucher <[email protected]> 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 <[email protected]> --- 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 c593997..883f0a7 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 _______________________________________________ xorg-driver-ati mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-driver-ati
