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.
This commit is contained in:
parent
4638f2f309
commit
7cc95d931b
3 changed files with 33 additions and 22 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue