drm/nouveau/kms/nv50-: store window visibility in state
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:47 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 18 May 2018 05:01:29 +0000 (15:01 +1000)
Window visibility is going to become a little more complicated with the
upcoming LUT changes, so store the calculated value to avoid needing to
recalculate the armed state again.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/dispnv50/atom.h
drivers/gpu/drm/nouveau/dispnv50/wndw.c

index b5b8a12a18f263b59f5a7b8e51faa26d40897195..fefb9caaf7b8a790b74904d7880abcf1c241490c 100644 (file)
@@ -136,6 +136,8 @@ nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
 struct nv50_wndw_atom {
        struct drm_plane_state state;
 
+       bool visible;
+
        struct {
                u32  handle;
                u16  offset:12;
index 06d1696b7d03d947466e86616c4c03ee0bde7716..4a685d78ed339d4da8315e5f688d5d11e3b3e612 100644 (file)
@@ -244,26 +244,33 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
        struct nv50_wndw_atom *armw = nv50_wndw_atom(wndw->plane.state);
        struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
        struct nv50_head_atom *harm = NULL, *asyh = NULL;
-       bool varm = false, asyv = false, asym = false;
+       bool modeset = false;
        int ret;
 
        NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
+
+       /* Fetch the assembly state for the head the window will belong to,
+        * and determine whether the window will be visible.
+        */
        if (asyw->state.crtc) {
                asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
                if (IS_ERR(asyh))
                        return PTR_ERR(asyh);
-               asym = drm_atomic_crtc_needs_modeset(&asyh->state);
-               asyv = asyh->state.active;
+               modeset = drm_atomic_crtc_needs_modeset(&asyh->state);
+               asyw->visible = asyh->state.active;
+       } else {
+               asyw->visible = false;
        }
 
+       /* Fetch assembly state for the head the window used to belong to. */
        if (armw->state.crtc) {
                harm = nv50_head_atom_get(asyw->state.state, armw->state.crtc);
                if (IS_ERR(harm))
                        return PTR_ERR(harm);
-               varm = harm->state.crtc->state->active;
        }
 
-       if (asyv) {
+       /* Calculate new window state. */
+       if (asyw->visible) {
                asyw->point.x = asyw->state.crtc_x;
                asyw->point.y = asyw->state.crtc_y;
                if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point)))
@@ -273,18 +280,22 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                if (ret)
                        return ret;
        } else
-       if (varm) {
+       if (armw->visible) {
                nv50_wndw_atomic_check_release(wndw, asyw, harm);
        } else {
                return 0;
        }
 
-       if (!asyv || asym) {
+       /* Aside from the obvious case where the window is actively being
+        * disabled, we might also need to temporarily disable the window
+        * when performing certain modeset operations.
+        */
+       if (!asyw->visible || modeset) {
                asyw->clr.ntfy = armw->ntfy.handle != 0;
                asyw->clr.sema = armw->sema.handle != 0;
                if (wndw->func->image_clr)
                        asyw->clr.image = armw->image.handle[0] != 0;
-               asyw->set.lut = wndw->func->lut && asyv;
+               asyw->set.lut = wndw->func->lut && asyw->visible;
        }
 
        return 0;