platforms/drm: change when to reset the output with eglstreams
In order to accomodate crtc or primary plane changes on outputs we need to dynamically recreate rendering resources with EglStreams as the stream is tied to the crtc or plane currently in use.
This commit is contained in:
parent
d057bd41c9
commit
65b55e2045
2 changed files with 33 additions and 14 deletions
|
@ -306,6 +306,7 @@ bool EglStreamBackend::resetOutput(Output &o)
|
|||
if (isPrimary()) {
|
||||
// dumb buffer used for modesetting
|
||||
o.buffer = QSharedPointer<DrmDumbBuffer>::create(m_gpu, sourceSize);
|
||||
o.targetPlane = drmOutput->pipeline()->primaryPlane();
|
||||
|
||||
EGLAttrib streamAttribs[] = {
|
||||
EGL_STREAM_FIFO_LENGTH_KHR, 0, // mailbox mode
|
||||
|
@ -319,13 +320,8 @@ bool EglStreamBackend::resetOutput(Output &o)
|
|||
}
|
||||
|
||||
EGLAttrib outputAttribs[3];
|
||||
if (drmOutput->pipeline()->primaryPlane()) {
|
||||
outputAttribs[0] = EGL_DRM_PLANE_EXT;
|
||||
outputAttribs[1] = drmOutput->pipeline()->primaryPlane()->id();
|
||||
} else {
|
||||
outputAttribs[0] = EGL_DRM_CRTC_EXT;
|
||||
outputAttribs[1] = drmOutput->pipeline()->crtc()->id();
|
||||
}
|
||||
outputAttribs[0] = EGL_DRM_PLANE_EXT;
|
||||
outputAttribs[1] = o.targetPlane->id();
|
||||
outputAttribs[2] = EGL_NONE;
|
||||
EGLint numLayers;
|
||||
EGLOutputLayerEXT outputLayer;
|
||||
|
@ -392,12 +388,6 @@ bool EglStreamBackend::addOutput(DrmAbstractOutput *output)
|
|||
if (!isPrimary() && !renderingBackend()->addOutput(drmOutput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(drmOutput, &DrmOutput::currentModeChanged, this,
|
||||
[drmOutput, this] {
|
||||
resetOutput(m_outputs[drmOutput]);
|
||||
}
|
||||
);
|
||||
m_outputs.insert(output, o);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -483,11 +473,34 @@ PlatformSurfaceTexture *EglStreamBackend::createPlatformSurfaceTextureWayland(Su
|
|||
return new EglStreamSurfaceTextureWayland(this, pixmap);
|
||||
}
|
||||
|
||||
bool EglStreamBackend::needsReset(const Output &o) const
|
||||
{
|
||||
if (o.targetPlane != o.output->pipeline()->primaryPlane()) {
|
||||
return true;
|
||||
}
|
||||
QSize surfaceSize = o.dumbSwapchain ? o.dumbSwapchain->size() : o.buffer->size();
|
||||
if (surfaceSize != o.output->sourceSize()) {
|
||||
return true;
|
||||
}
|
||||
bool needsTexture = surfaceSize != o.output->pixelSize();
|
||||
if (needsTexture) {
|
||||
return !o.shadowBuffer || o.shadowBuffer->textureSize() != o.output->pixelSize();
|
||||
} else {
|
||||
return o.shadowBuffer != nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QRegion EglStreamBackend::beginFrame(AbstractOutput *drmOutput)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
const Output &o = m_outputs[drmOutput];
|
||||
Output &o = m_outputs[drmOutput];
|
||||
if (isPrimary()) {
|
||||
if (needsReset(o)) {
|
||||
if (!resetOutput(o)) {
|
||||
// handle this better?
|
||||
return {};
|
||||
}
|
||||
}
|
||||
makeContextCurrent(o);
|
||||
if (o.shadowBuffer) {
|
||||
o.shadowBuffer->bind();
|
||||
|
|
|
@ -21,6 +21,8 @@ class DrmAbstractOutput;
|
|||
class DrmDumbBuffer;
|
||||
class DumbSwapchain;
|
||||
class ShadowBuffer;
|
||||
class DrmCrtc;
|
||||
class DrmPlane;
|
||||
|
||||
/**
|
||||
* @brief OpenGL Backend using Egl with an EGLDevice.
|
||||
|
@ -68,12 +70,16 @@ private:
|
|||
EGLStreamKHR eglStream = EGL_NO_STREAM_KHR;
|
||||
QSharedPointer<ShadowBuffer> shadowBuffer;
|
||||
|
||||
DrmPlane *targetPlane = nullptr;
|
||||
|
||||
// for operation as secondary GPU
|
||||
QSharedPointer<DumbSwapchain> dumbSwapchain;
|
||||
};
|
||||
bool resetOutput(Output &output);
|
||||
bool createEglSurface(Output &o);
|
||||
bool makeContextCurrent(const Output &output);
|
||||
void cleanupOutput(Output &output);
|
||||
bool needsReset(const Output &o) const;
|
||||
|
||||
QMap<AbstractOutput *, Output> m_outputs;
|
||||
KWaylandServer::EglStreamControllerInterface *m_eglStreamControllerInterface;
|
||||
|
|
Loading…
Reference in a new issue