Fixes for direct scanout

This commit is contained in:
Xaver Hugl 2021-02-02 16:03:43 +01:00
parent 16f27d2dc6
commit bda47c9043
2 changed files with 53 additions and 48 deletions

View file

@ -629,10 +629,17 @@ void EglGbmBackend::setViewport(const Output &output) const
QRegion EglGbmBackend::beginFrame(int screenId)
{
auto output = m_outputs[screenId];
if (output.directScanoutBuffer) {
gbm_bo_destroy(output.directScanoutBuffer);
output.directScanoutBuffer = nullptr;
output.surfaceInterface = nullptr;
output.bufferInterface = nullptr;
}
if (isPrimary()) {
return prepareRenderingForOutput(m_outputs[screenId]);
return prepareRenderingForOutput(output);
} else {
return renderingBackend()->beginFrameForSecondaryGpu(m_outputs.at(screenId).output);
return renderingBackend()->beginFrameForSecondaryGpu(output.output);
}
}
@ -642,13 +649,6 @@ QRegion EglGbmBackend::prepareRenderingForOutput(Output &output) const
prepareRenderFramebuffer(output);
setViewport(output);
if (output.directScanoutBuffer) {
gbm_bo_destroy(output.directScanoutBuffer);
output.directScanoutBuffer = nullptr;
output.surfaceInterface = nullptr;
output.bufferInterface = nullptr;
}
if (supportsBufferAge()) {
QRegion region;
@ -750,6 +750,9 @@ bool EglGbmBackend::scanout(int screenId, KWaylandServer::SurfaceInterface *surf
} else {
damage = output.output->geometry();
}
if (output.directScanoutBuffer) {
gbm_bo_destroy(output.directScanoutBuffer);
}
output.directScanoutBuffer = importedBuffer;
output.surfaceInterface = surface;
output.bufferInterface = buffer;

View file

@ -626,52 +626,54 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
scaling = 1;
}
bool directScanout = false;
if (m_backend->directScanoutAllowed(screenId)) {
EffectsHandlerImpl *implEffects = static_cast<EffectsHandlerImpl*>(effects);
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());
const GLenum status = glGetGraphicsResetStatus();
if (status != GL_NO_ERROR) {
handleGraphicsReset(status);
} else {
renderLoop->beginFrame();
bool directScanout = false;
if (m_backend->directScanoutAllowed(screenId)) {
EffectsHandlerImpl *implEffects = static_cast<EffectsHandlerImpl*>(effects);
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());
}
break;
}
break;
}
}
}
}
if (!directScanout) {
// prepare rendering makes context current on the output
repaint = m_backend->beginFrame(screenId);
GLVertexBuffer::setVirtualScreenGeometry(geo);
GLRenderTarget::setVirtualScreenGeometry(geo);
GLVertexBuffer::setVirtualScreenScale(scaling);
GLRenderTarget::setVirtualScreenScale(scaling);
const GLenum status = glGetGraphicsResetStatus();
if (status != GL_NO_ERROR) {
handleGraphicsReset(status);
if (directScanout) {
renderLoop->endFrame();
} else {
// prepare rendering makescontext current on the output
repaint = m_backend->beginFrame(screenId);
GLVertexBuffer::setVirtualScreenGeometry(geo);
GLRenderTarget::setVirtualScreenGeometry(geo);
GLVertexBuffer::setVirtualScreenScale(scaling);
GLRenderTarget::setVirtualScreenScale(scaling);
int mask = 0;
updateProjectionMatrix();
renderLoop->beginFrame();
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid,
renderLoop, projectionMatrix(), geo, scaling); // call generic implementation