platforms/drm: refactor presentation in gbm backend
This commit is contained in:
parent
da71d218c8
commit
ee4b4fc9a3
6 changed files with 38 additions and 54 deletions
|
@ -617,7 +617,7 @@ void DrmOutput::pageFlipped()
|
|||
}
|
||||
}
|
||||
|
||||
bool DrmOutput::present(const QSharedPointer<DrmBuffer> &buffer)
|
||||
bool DrmOutput::present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion)
|
||||
{
|
||||
if (!buffer || buffer->bufferId() == 0) {
|
||||
return false;
|
||||
|
@ -627,7 +627,12 @@ bool DrmOutput::present(const QSharedPointer<DrmBuffer> &buffer)
|
|||
}
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(m_renderLoop);
|
||||
setVrr(renderLoopPrivate->presentMode == RenderLoopPrivate::SyncMode::Adaptive);
|
||||
return m_gpu->atomicModeSetting() ? presentAtomically(buffer) : presentLegacy(buffer);
|
||||
if (m_gpu->atomicModeSetting() ? presentAtomically(buffer) : presentLegacy(buffer)) {
|
||||
Q_EMIT outputChange(damagedRegion);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DrmOutput::dpmsAtomicOff()
|
||||
|
@ -941,4 +946,13 @@ bool DrmOutput::isCursorVisible()
|
|||
return m_cursor[m_cursorIndex] && QRect(m_cursorPos, m_cursor[m_cursorIndex]->size()).intersects(QRect(0, 0, m_mode.vdisplay, m_mode.hdisplay));
|
||||
}
|
||||
|
||||
DrmBuffer *DrmOutput::currentBuffer() const
|
||||
{
|
||||
if (m_primaryPlane) {
|
||||
return m_primaryPlane->current().get();
|
||||
} else {
|
||||
return m_crtc->current().get();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
bool updateCursor();
|
||||
void moveCursor();
|
||||
bool init(drmModeConnector *connector);
|
||||
bool present(const QSharedPointer<DrmBuffer> &buffer);
|
||||
bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion);
|
||||
void pageFlipped();
|
||||
|
||||
bool isDpmsEnabled() const {
|
||||
|
@ -71,6 +71,7 @@ public:
|
|||
const DrmPlane *primaryPlane() const {
|
||||
return m_primaryPlane;
|
||||
}
|
||||
DrmBuffer *currentBuffer() const;
|
||||
|
||||
bool initCursor(const QSize &cursorSize);
|
||||
|
||||
|
|
|
@ -289,13 +289,12 @@ QRegion EglGbmBackend::beginFrameForSecondaryGpu(DrmOutput *drmOutput)
|
|||
return prepareRenderingForOutput(*it);
|
||||
}
|
||||
|
||||
void EglGbmBackend::importFramebuffer(Output &output) const
|
||||
QSharedPointer<DrmBuffer> EglGbmBackend::importFramebuffer(Output &output) const
|
||||
{
|
||||
if (!renderingBackend()->swapBuffers(output.output)) {
|
||||
qCWarning(KWIN_DRM) << "swapping buffers failed on output" << output.output;
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
output.buffer = nullptr;
|
||||
const auto size = output.output->modeSize();
|
||||
if (output.importMode == ImportMode::Dmabuf) {
|
||||
uint32_t stride = 0;
|
||||
|
@ -313,8 +312,7 @@ void EglGbmBackend::importFramebuffer(Output &output) const
|
|||
if (importedBuffer) {
|
||||
auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, importedBuffer, nullptr);
|
||||
if (buffer->bufferId() > 0) {
|
||||
output.buffer = buffer;
|
||||
return;
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,12 +329,12 @@ void EglGbmBackend::importFramebuffer(Output &output) const
|
|||
if (output.importSwapchain) {
|
||||
auto buffer = output.importSwapchain->acquireBuffer();
|
||||
if (renderingBackend()->exportFramebuffer(output.output, buffer->data(), size, buffer->stride())) {
|
||||
output.buffer = buffer;
|
||||
return;
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
qCWarning(KWIN_DRM) << "all imports failed on output" << output.output;
|
||||
// TODO turn off output?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EglGbmBackend::renderFramebufferToSurface(Output &output)
|
||||
|
@ -457,31 +455,6 @@ void EglGbmBackend::aboutToStartPainting(int screenId, const QRegion &damagedReg
|
|||
}
|
||||
}
|
||||
|
||||
bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion)
|
||||
{
|
||||
if (isPrimary() && !directScanoutActive(output)) {
|
||||
output.buffer = output.gbmSurface->swapBuffersForDrm();
|
||||
} else if (!output.buffer) {
|
||||
qCDebug(KWIN_DRM) << "imported buffer does not exist!";
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_EMIT output.output->outputChange(damagedRegion);
|
||||
if (!output.output->present(output.buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (supportsBufferAge()) {
|
||||
eglQuerySurface(eglDisplay(), output.gbmSurface->eglSurface(), EGL_BUFFER_AGE_EXT, &output.bufferAge);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EglGbmBackend::directScanoutActive(const Output &output)
|
||||
{
|
||||
return output.surfaceInterface != nullptr;
|
||||
}
|
||||
|
||||
PlatformSurfaceTexture *EglGbmBackend::createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap)
|
||||
{
|
||||
return new BasicEGLSurfaceTextureInternal(this, pixmap);
|
||||
|
@ -544,14 +517,16 @@ void EglGbmBackend::endFrame(int screenId, const QRegion &renderedRegion,
|
|||
Output &output = m_outputs[screenId];
|
||||
DrmOutput *drmOutput = output.output;
|
||||
|
||||
QSharedPointer<DrmBuffer> buffer;
|
||||
if (isPrimary()) {
|
||||
renderFramebufferToSurface(output);
|
||||
buffer = output.gbmSurface->swapBuffersForDrm();
|
||||
} else {
|
||||
importFramebuffer(output);
|
||||
buffer = importFramebuffer(output);
|
||||
}
|
||||
|
||||
const QRegion dirty = damagedRegion.intersected(output.output->geometry());
|
||||
if (!presentOnOutput(output, dirty)) {
|
||||
if (!buffer || !output.output->present(buffer, dirty)) {
|
||||
output.damageHistory.clear();
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(drmOutput->renderLoop());
|
||||
renderLoopPrivate->notifyFrameFailed();
|
||||
|
@ -559,6 +534,7 @@ void EglGbmBackend::endFrame(int screenId, const QRegion &renderedRegion,
|
|||
}
|
||||
|
||||
if (supportsBufferAge()) {
|
||||
eglQuerySurface(eglDisplay(), output.gbmSurface->eglSurface(), EGL_BUFFER_AGE_EXT, &output.bufferAge);
|
||||
if (output.damageHistory.count() > 10) {
|
||||
output.damageHistory.removeLast();
|
||||
}
|
||||
|
@ -636,19 +612,18 @@ bool EglGbmBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
|||
} else {
|
||||
damage = output.output->geometry();
|
||||
}
|
||||
output.buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, importedBuffer, buffer);
|
||||
auto oldSurface = output.surfaceInterface;
|
||||
output.surfaceInterface = surface;
|
||||
auto bo = QSharedPointer<DrmGbmBuffer>::create(m_gpu, importedBuffer, buffer);
|
||||
// ensure that a context is current like with normal presentation
|
||||
makeCurrent();
|
||||
if (presentOnOutput(output, damage)) {
|
||||
if (oldSurface != surface) {
|
||||
if (output.output->present(bo, damage)) {
|
||||
output.damageHistory.clear();
|
||||
if (output.surfaceInterface != surface) {
|
||||
auto path = surface->client()->executablePath();
|
||||
qCDebug(KWIN_DRM).nospace() << "Direct scanout starting on output " << output.output->name() << " for application \"" << path << "\"";
|
||||
}
|
||||
output.surfaceInterface = surface;
|
||||
return true;
|
||||
} else {
|
||||
output.surfaceInterface = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -677,10 +652,9 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *abstra
|
|||
glTexture->setYInverted(true);
|
||||
return glTexture;
|
||||
}
|
||||
|
||||
auto gbmBuffer = dynamic_cast<GbmBuffer*>(itOutput->buffer.data());
|
||||
GbmBuffer *gbmBuffer = itOutput->gbmSurface->currentBuffer().get();
|
||||
if (!gbmBuffer) {
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: Dumb buffer used for presentation!";
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!";
|
||||
return {};
|
||||
}
|
||||
EGLImageKHR image = eglCreateImageKHR(eglDisplay(), nullptr, EGL_NATIVE_PIXMAP_KHR, gbmBuffer->getBo(), nullptr);
|
||||
|
|
|
@ -82,7 +82,6 @@ private:
|
|||
};
|
||||
struct Output {
|
||||
DrmOutput *output = nullptr;
|
||||
QSharedPointer<DrmBuffer> buffer;
|
||||
QSharedPointer<GbmSurface> gbmSurface;
|
||||
int bufferAge = 0;
|
||||
/**
|
||||
|
@ -105,10 +104,7 @@ private:
|
|||
void prepareRenderFramebuffer(const Output &output) const;
|
||||
void renderFramebufferToSurface(Output &output);
|
||||
QRegion prepareRenderingForOutput(Output &output) const;
|
||||
void importFramebuffer(Output &output) const;
|
||||
|
||||
bool presentOnOutput(Output &output, const QRegion &damagedRegion);
|
||||
bool directScanoutActive(const Output &output);
|
||||
QSharedPointer<DrmBuffer> importFramebuffer(Output &output) const;
|
||||
|
||||
QVector<Output> m_outputs;
|
||||
QVector<Output> m_secondaryGpuOutputs;
|
||||
|
|
|
@ -506,7 +506,6 @@ QRegion EglStreamBackend::beginFrame(int screenId)
|
|||
void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(renderedRegion);
|
||||
Q_UNUSED(damagedRegion);
|
||||
|
||||
Output &renderOutput = m_outputs[screenId];
|
||||
DrmOutput *drmOutput = renderOutput.output;
|
||||
|
@ -534,7 +533,7 @@ void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, con
|
|||
frameFailed = true;
|
||||
}
|
||||
}
|
||||
if (!frameFailed && !renderOutput.output->present(buffer)) {
|
||||
if (!frameFailed && !renderOutput.output->present(buffer, damagedRegion)) {
|
||||
frameFailed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ void DrmQPainterBackend::endFrame(int screenId, int mask, const QRegion &damage)
|
|||
const Output &rendererOutput = m_outputs[screenId];
|
||||
DrmOutput *drmOutput = rendererOutput.output;
|
||||
|
||||
if (!drmOutput->present(rendererOutput.swapchain->currentBuffer())) {
|
||||
if (!drmOutput->present(rendererOutput.swapchain->currentBuffer(), drmOutput->geometry())) {
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(drmOutput->renderLoop());
|
||||
renderLoopPrivate->notifyFrameFailed();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue