modesetting: Internal storage of scanout pixmaps

modesetting relied on randr_crtc->scanout_pixmap being consistent with
calls to SetScanoutPixmap, which is very fragile and makes a lot of
assumptions about the caller's behavior.

For example, RRReplaceScanoutPixmap(), when dropping off with !size_fits,
will set randr_crtc->scanout_pixmap = NULL and then call SetScanoutPixmap.
Without this patch, drmmode_set_scanout_pixmap_(cpu/gpu) will think that
there is no scanout pixmap to tear down, because it's already been set to
NULL.

By keeping track of the scanout pixmap in its internal state, modesetting
can avoid these types of bugs and reduce constraints on calling
conventions.

v1: N/A
v2: N/A
v3: N/A
v4: N/A
v5: Initial commit
v6: Rebase onto ToT
v7: Unchanged

Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
This commit is contained in:
Alex Goins 2016-06-16 20:06:49 -07:00 committed by Adam Jackson
parent 1bdbc7e764
commit f4c37eeee7
3 changed files with 22 additions and 12 deletions

View File

@ -532,10 +532,10 @@ static void
dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(scrn);
PixmapPtr pixmap = crtc->randr_crtc->scanout_pixmap;
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
PixmapPtr pixmap = drmmode_crtc->prime_pixmap;
DamagePtr damage = drmmode_crtc->slave_damage;
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
int fb_id = ppriv->fb_id;
int ret;
@ -554,10 +554,11 @@ dispatch_slave_dirty(ScreenPtr pScreen)
for (c = 0; c < xf86_config->num_crtc; c++) {
xf86CrtcPtr crtc = xf86_config->crtc[c];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
if (!crtc->randr_crtc)
if (!drmmode_crtc)
continue;
if (!crtc->randr_crtc->scanout_pixmap)
if (!drmmode_crtc->prime_pixmap)
continue;
dispatch_dirty_crtc(scrn, crtc);

View File

@ -454,10 +454,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
fb_id = drmmode->fb_id;
if (crtc->randr_crtc->scanout_pixmap) {
if (drmmode_crtc->prime_pixmap) {
if (!drmmode->reverse_prime_offload_mode) {
msPixmapPrivPtr ppriv =
msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
fb_id = ppriv->fb_id;
x = 0;
} else
@ -639,8 +639,8 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
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);
if (drmmode_crtc->prime_pixmap) {
PixmapStopDirtyTracking(drmmode_crtc->prime_pixmap, screenpix);
if (drmmode->fb_id) {
drmModeRmFB(drmmode->fd, drmmode->fb_id);
drmmode->fb_id = 0;
@ -690,8 +690,8 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
void *ptr;
if (!ppix) {
if (crtc->randr_crtc->scanout_pixmap) {
ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
if (drmmode_crtc->prime_pixmap) {
ppriv = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
drmModeRmFB(drmmode->fd, ppriv->fb_id);
ppriv->fb_id = 0;
}
@ -727,13 +727,19 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
static Bool
drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
{
Bool ret;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
if (drmmode->reverse_prime_offload_mode)
return drmmode_set_scanout_pixmap_gpu(crtc, ppix);
ret = drmmode_set_scanout_pixmap_gpu(crtc, ppix);
else
return drmmode_set_scanout_pixmap_cpu(crtc, ppix);
ret = drmmode_set_scanout_pixmap_cpu(crtc, ppix);
if (ret)
drmmode_crtc->prime_pixmap = ppix;
return ret;
}
static void *

View File

@ -103,7 +103,10 @@ typedef struct {
drmmode_bo rotate_bo;
unsigned rotate_fb_id;
PixmapPtr prime_pixmap;
unsigned prime_pixmap_x;
/**
* @{ MSC (vblank count) handling for the PRESENT extension.
*