[WIP][Drm Backend] Direct Buffer Scanout and Atomic Modesetting improvements
AbandonedPublic

Authored by romangg on Feb 10 2017, 12:02 AM.

Details

Reviewers
None
Group Reviewers
KWin
Summary

This is a combined patch correcting several shortcomings in preliminary support for AMS and including an experimental support for the direct scanout of Wayland buffers for fullscreen windows bypassing the compositor.

AMS:

  • Test mode for atomic commits
  • Cleaned up property adding
  • Fixed atomic DPMS
  • Other minor fixes regarding potential buffer leaks
  • First draft for assigning buffers for overlay planes

Direct Buffer Scanout:

  • Added new DrmBuffer class (will also be used for overlay planes later)
  • Works only on Gl at the moment, skips context switch, uses WindowPixmaps for now.

Problems / open questions:
Marked by TODO_X (all done)

  • On X OpenGl based Compositing fails (probably the direct scanout attempt needs to stop earlier)
  • There is still tearing on direct buffer scanout. EDIT: The problem seems to be only in XWayland apps. Use the following Qt Quick Wayland native test app for comparision:

Diff Detail

Repository
R108 KWin
Lint
Lint Skipped
Unit
Unit Tests Skipped
romangg updated this revision to Diff 11141.Feb 10 2017, 12:02 AM
romangg retitled this revision from to [WIP][Drm Backend] Direct Buffer Scanout and Atomic Modesetting improvements.
romangg updated this object.
romangg edited the test plan for this revision. (Show Details)
romangg added a reviewer: KWin.
romangg set the repository for this revision to R108 KWin.
romangg added a project: KWin.
Restricted Application added a subscriber: kwin. · View Herald TranscriptFeb 10 2017, 12:02 AM
romangg added inline comments.Feb 10 2017, 9:16 AM
scene_opengl.h
33

Not necessary as long as we use BufferInterface in directScanoutForScreen.

romangg added a comment.EditedFeb 11 2017, 3:22 PM

TODO: In DrmBackend::queryResources() multiple objects of type DrmCrtc might get created for different outputs, while describing the same CRTC all along.

On further investigation: Doesn't happen, because we only allow CRTCs exclusively per output.

romangg updated this revision to Diff 11489.Feb 19 2017, 2:34 AM
romangg marked an inline comment as done.
  • Support hotplug events in AMS
  • GBM based buffers in separate file, only included when GBM is available
  • Improve code reuse by using CRTC and Connector objects also in legacy mode to (only) store their ids
romangg added inline comments.Feb 19 2017, 2:22 PM
plugins/platforms/drm/drm_buffer_gbm.cpp
87

Potentially necessary for solving the tearing issues. The unref() below aswell. Otherwise remove.

plugins/platforms/drm/drm_output.h
136

Remove

romangg updated this revision to Diff 11896.Feb 27 2017, 1:04 PM
romangg marked an inline comment as done.

Changes in latest revision:

  • Only do a direct scanout when there are no effects active
  • Don't scanout shm buffers
romangg edited the summary of this revision. (Show Details)Feb 27 2017, 1:06 PM

I just wrote myself a little native Wayland Qt test application going to fullscreen mode with interesting results:

  • Since it was Qt based I had to enable again direct scanout for shm Buffers and this worked without problems
  • There was no tearing at all! So the tearing has to do something with the buffer being normally not an shm buffer or that all the other apps I tried it with are XWayland based (VLC, browsers)

So the tearing has to do something with the buffer being normally not an shm buffer or that all the other apps I tried it with are XWayland based (VLC, browsers)

What about a simple QtQuick View in fullscreen? That would take the non shm buffer.

I'm not sure whether you will like to hear what I will write now. I'm running a 4.10 kernel at the moment with i915.nuclear_pageflip=1, this patch and KWIN_DRM_AMS=1 env variable. And there is NO! tearing at all. Whatever I try I don't get tearing. Either I'm doing something horribly wrong and the patch is not used at all, or it just works and I'm tending for the second case. The only problem I have with this kernel is that wifi stopped to work.

Small request: please add to the KWin debug console or support information a way to check whether AMS is used.

I'm not sure whether you will like to hear what I will write now. I'm running a 4.10 kernel at the moment with i915.nuclear_pageflip=1, this patch and KWIN_DRM_AMS=1 env variable. And there is NO! tearing at all. Whatever I try I don't get tearing. Either I'm doing something horribly wrong and the patch is not used at all, or it just works and I'm tending for the second case. The only problem I have with this kernel is that wifi stopped to work.

Small request: please add to the KWin debug console or support information a way to check whether AMS is used.

I very very much like what you wrote! :) I just checked and I was still using 4.8 so maybe it was a Intel driver bug, which they fixed later (or Mesa which I use from Git via PPA). So did you try it with VLC in full screen mode? You can make sure it's really doing a direct scanout by putting a debug line in directScanout(). Something like:

bool tempDebugVariable = m_backend->directScanoutForScreen(screen, wp->buffer().data());
qDebug() << "useDirectScanout:" << tempDebugVariable;
return tempDebugVariable;

If it spams the log on a fullscreen windows and is true valued, it definitely uses the direct scanout (or the picture on the screen would freeze since it stops the subsequent rendering).

And can you also try without atomic mode setting, since a direct scanout in legacy mode is possible as well?

I just tried it again on another PC and I had the tearing issue there as well. So I assume in your case it didn't use the direct scanout at all. On my PC it also didn't work at first because the last patch to stop a scanout if any effect is active seems to be too strict. On my PC were all the time the effects blur and contrast active (the first one I could deactivate by unsetting the blur effect in SySe, but I don't know because of what the contrast effect is active all the time).

If you want to see how far your direct scanout attempt goes and where it stops, replace this directScanout function with the current one in the diff:

bool SceneOpenGL::directScanout(int screen)
{
    for (int j = stacking_order.count() - 1; 0 < j; --j) {
        Scene::Window *w = stacking_order[j];
        AbstractClient *c = dynamic_cast<AbstractClient*>(w->window());
        if (!c || c->isOnScreen(screen)) {
            // check if opaque full screen windows +
            // buffer exists and is NOT shm +
            // no effects active

            if (c) {
                qDebug() << "xxx1:" << c->isFullScreen() << (c->opacity() == 1.0) << !c->hasAlpha() << static_cast<EffectsHandlerImpl*>(effects)->activeEffects();
                if (c->surface()) {
                    qDebug() << "xxx2:" << c->surface()->buffer();
                    if (c->surface()->buffer()) {
                        qDebug() << "xxx3:" << !c->surface()->buffer()->shmBuffer();
                    }
                }
            }

            if (c && c->isFullScreen() && c->opacity() == 1.0 /*&& !c->hasAlpha()*/ &&
                    c->surface() && c->surface()->buffer() /*&& !c->surface()->buffer()->shmBuffer() &&*/
                    //!static_cast<EffectsHandlerImpl*>(effects)->activeEffects().count()) 
            ){
                // put wayland buffer on scanout plane
                OpenGLWindowPixmap *wp = w->windowPixmap<OpenGLWindowPixmap>();
                wp->updateBuffer();
                qDebug() << "directScanout:" << w;
                return m_backend->directScanoutForScreen(screen, wp->buffer().data());
            }
            return false;
        }
    }
    return false;
}

This version should also in any case do a scanout, since the most strict tests on hasAlpha(), shmBuffer() and activeEffects().count() are skipped.

Just had VLC running and lots of:

xxx1: true true true ("blur", "contrast")
xxx2: KWayland::Server::BufferInterface(0x4733770)
xxx3: true
directScanout: 0x42caf00
xxx1: true true true ("blur", "contrast")
xxx2: KWayland::Server::BufferInterface(0x4733770)
xxx3: true
directScanout: 0x42caf00
xxx1: true true true ("blur", "contrast")
xxx2: KWayland::Server::BufferInterface(0x4733770)
xxx3: true
directScanout: 0x42caf00

And I could also visually see that it's used as e.g. the screenedge approach was not rendered

xxx1: true true true ("blur", "contrast", "screenedge")
xxx2: KWayland::Server::BufferInterface(0x3dd7a50)
xxx3: true
directScanout: 0x42caf00

And no, I did not notice any tearing. But the usual warning should go here: I'm bad in noticing tearing
On the other hand with the 4.7 kernel I have buffer age issues when using e.g. yakuake. It keeps the old buffer around and flickers between a buffer with yakuake after hide and one without. With the 4.10 kernel I'm now running I don't see this problem. So I could imagine it's a driver issue.

Now after a few minutes I do get tearing. But not always, it's not every frame and I need a better test case which shows tearing in a better way.

romangg edited the summary of this revision. (Show Details)Mar 6 2017, 2:50 PM
romangg updated this revision to Diff 12439.Mar 13 2017, 5:43 PM
romangg edited the summary of this revision. (Show Details)
  • Direct scanout doesn't flip the buffer anymore if the Wayland buffer hasn't changed, i.e. there is nothing damaged.
  • Using ref and unref in DrmImportbuffer makes sure the exported buffer is available. We only unref it after a new buffer is about to be presented (i.e. no buffer retire after page flip, need to investigate further, because normally the Wayland buffer shouldn't be needed anymore after page flip)
  • Fixed X OpenGl based compositing: The problem was the moved startPaint method. Reverted that, which means we lose the first frame of an effect on direct scanout at the moment.
romangg abandoned this revision.Mar 26 2017, 8:30 PM

This WIP patch is hereby divided into the following separate patches, in order to enhance clarity:

  1. Remember static kernel objects, amplify use of DrmCrtc: D5118
  2. Reorganize DrmBuffer: D5179
  3. Correct Atomic Mode Setting: D5191
  4. Direct scanout: soon