diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-07-30 10:08:25 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-08-05 17:59:43 -0400 |
commit | c5cbfcf575b0b4aea6f797558ae974c1453c8e07 (patch) | |
tree | d177b24d3ec7ced393a5d04fa313eb2ddf6f9faf /src | |
parent | 429d5b797769895eb4f5fef816ce4e2f3a342031 (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.c | 52 | ||||
-rw-r--r-- | 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 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 { |