Commit 7cc95d93 authored by Xaver Hugl's avatar Xaver Hugl
Browse files

Improvements for direct scanout

Instead of cancelling direct scanout if the client buffer is not
fitting, adjust the atomic planes. Also ignore all toplevels from
other screens.
parent 4638f2f3
......@@ -955,14 +955,23 @@ bool DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable)
{
if (enable) {
const QSize mSize = modeSize();
const QSize sourceSize = hardwareTransforms() ? pixelSize() : mSize;
const QSize bufferSize = m_primaryPlane->next() ? m_primaryPlane->next()->size() : pixelSize();
const QSize sourceSize = hardwareTransforms() ? bufferSize : mSize;
QRect targetRect = QRect(QPoint(0, 0), mSize);
if (mSize != sourceSize) {
targetRect.setSize(sourceSize.scaled(mSize, Qt::AspectRatioMode::KeepAspectRatio));
targetRect.setX((mSize.width() - targetRect.width()) / 2);
targetRect.setY((mSize.height() - targetRect.height()) / 2);
}
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcX), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcY), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcW), sourceSize.width() << 16);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcH), sourceSize.height() << 16);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcW), mSize.width());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcH), mSize.height());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcX), targetRect.x());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcY), targetRect.y());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcW), targetRect.width());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcH), targetRect.height());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcId), m_crtc->id());
} else {
if (m_gpu->deleteBufferAfterPageFlip()) {
......@@ -976,6 +985,8 @@ bool DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable)
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcY), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcW), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::SrcH), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcX), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcY), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcW), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcH), 0);
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcId), 0);
......
......@@ -698,7 +698,8 @@ bool EglGbmBackend::scanout(int screenId, KWaylandServer::SurfaceInterface *surf
}
auto buffer = surface->buffer();
Output output = m_outputs[screenId];
if (buffer->linuxDmabufBuffer()->size() != output.output->modeSize()) {
if (buffer->linuxDmabufBuffer()->size() != output.output->modeSize()
&& output.output->isBeingRecorded()) {
return false;
}
EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer*>(buffer->linuxDmabufBuffer());
......@@ -739,7 +740,7 @@ bool EglGbmBackend::scanout(int screenId, KWaylandServer::SurfaceInterface *surf
}
// damage tracking for screen casting
QRegion damage;
if (output.surfaceInterface == surface) {
if (output.surfaceInterface == surface && buffer->size() == output.output->modeSize()) {
QRegion trackedDamage = surface->trackedDamage();
surface->resetTrackedDamage();
for (const auto &rect : trackedDamage) {
......
......@@ -638,24 +638,23 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
if (!implEffects->blocksDirectScanout()) {
for (int i = stacking_order.count() - 1; i >= 0; i--) {
Window *window = stacking_order[i];
AbstractClient *c = dynamic_cast<AbstractClient*>(window->window());
if (!c) {
break;
}
if (c->isOnScreen(screenId)) {
if (window->isOpaque() && c->isFullScreen()) {
auto pixmap = window->windowPixmap<WindowPixmap>();
if (!pixmap) {
break;
}
pixmap->update();
pixmap = pixmap->topMostSurface();
// the subsurface has to be able to cover the whole window
if (pixmap->position() != QPoint(0, 0)) {
break;
}
directScanout = m_backend->scanout(screenId, pixmap->surface());
Toplevel *toplevel = window->window();
if (toplevel->isOnScreen(screenId)) {
AbstractClient *c = dynamic_cast<AbstractClient*>(toplevel);
if (!c || !c->isFullScreen() || !window->isOpaque()) {
break;
}
auto pixmap = window->windowPixmap<WindowPixmap>();
if (!pixmap) {
break;
}
pixmap->update();
pixmap = pixmap->topMostSurface();
// the subsurface has to be able to cover the whole window
if (pixmap->position() != QPoint(0, 0)) {
break;
}
directScanout = m_backend->scanout(screenId, pixmap->surface());
break;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment