backends/drm: properly handle pending transformations

AbstractWaylandOutput::pixelSize returns the size with already set transformation
applied but the render backends need the pending transformation
master
Xaver Hugl 3 years ago
parent b06ec13ead
commit 81905dbfaa

@ -25,6 +25,7 @@ public:
virtual bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) = 0;
virtual bool needsSoftwareTransformation() const = 0;
virtual QSize bufferSize() const = 0;
virtual QSize sourceSize() const = 0;
virtual bool isFormatSupported(uint32_t drmFormat) const = 0;
virtual QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const = 0;

@ -406,8 +406,8 @@ bool DrmGpu::testPendingConfiguration(TestMode mode)
// try again without hw rotation
bool hwRotationUsed = false;
for (const auto &pipeline : qAsConst(m_pipelines)) {
hwRotationUsed |= (pipeline->pending.transformation != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0));
pipeline->pending.transformation = DrmPlane::Transformation::Rotate0;
hwRotationUsed |= (pipeline->pending.bufferTransformation != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0));
pipeline->pending.bufferTransformation = DrmPlane::Transformation::Rotate0;
}
return hwRotationUsed ? test() : false;
}

@ -323,7 +323,7 @@ void DrmOutput::updateModes()
bool DrmOutput::needsSoftwareTransformation() const
{
return m_pipeline->pending.transformation != outputToPlaneTransform(transform());
return m_pipeline->pending.bufferTransformation != m_pipeline->pending.sourceTransformation;
}
bool DrmOutput::present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion)
@ -378,6 +378,11 @@ DrmPipeline *DrmOutput::pipeline() const
return m_pipeline;
}
QSize DrmOutput::bufferSize() const
{
return m_pipeline->bufferSize();
}
QSize DrmOutput::sourceSize() const
{
return m_pipeline->sourceSize();
@ -414,8 +419,9 @@ bool DrmOutput::queueChanges(const WaylandOutputConfig &config)
m_pipeline->pending.modeIndex = index;
m_pipeline->pending.overscan = props->overscan;
m_pipeline->pending.rgbRange = props->rgbRange;
if (!envOnlySoftwareRotations) {
m_pipeline->pending.transformation = outputToPlaneTransform(props->transform);
m_pipeline->pending.sourceTransformation = outputToPlaneTransform(props->transform);
if (!envOnlySoftwareRotations && m_gpu->atomicModeSetting()) {
m_pipeline->pending.bufferTransformation = m_pipeline->pending.sourceTransformation;
}
m_pipeline->pending.enabled = props->enabled;
return true;

@ -48,6 +48,7 @@ public:
DrmConnector *connector() const;
DrmPipeline *pipeline() const;
QSize bufferSize() const override;
QSize sourceSize() const override;
bool isFormatSupported(uint32_t drmFormat) const override;
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const override;

@ -192,7 +192,7 @@ bool DrmPipeline::populateAtomicValues(drmModeAtomicReq *req, uint32_t &flags)
pending.crtc->setPending(DrmCrtc::PropertyIndex::VrrEnabled, pending.syncMode == RenderLoopPrivate::SyncMode::Adaptive);
pending.crtc->setPending(DrmCrtc::PropertyIndex::Gamma_LUT, pending.gamma ? pending.gamma->blobId() : 0);
auto modeSize = m_connector->modes()[pending.modeIndex]->size();
pending.crtc->primaryPlane()->set(QPoint(0, 0), m_primaryBuffer ? m_primaryBuffer->size() : modeSize, QPoint(0, 0), modeSize);
pending.crtc->primaryPlane()->set(QPoint(0, 0), m_primaryBuffer ? m_primaryBuffer->size() : bufferSize(), QPoint(0, 0), modeSize);
pending.crtc->primaryPlane()->setBuffer(activePending() ? m_primaryBuffer.get() : nullptr);
if (pending.crtc->cursorPlane()) {
@ -235,7 +235,7 @@ void DrmPipeline::prepareAtomicModeset()
pending.crtc->setPending(DrmCrtc::PropertyIndex::ModeId, activePending() ? mode->blobId() : 0);
pending.crtc->primaryPlane()->setPending(DrmPlane::PropertyIndex::CrtcId, activePending() ? pending.crtc->id() : 0);
pending.crtc->primaryPlane()->setTransformation(pending.transformation);
pending.crtc->primaryPlane()->setTransformation(pending.bufferTransformation);
if (pending.crtc->cursorPlane()) {
pending.crtc->cursorPlane()->setTransformation(DrmPlane::Transformation::Rotate0);
}
@ -291,7 +291,7 @@ void DrmPipeline::atomicCommitSuccessful(CommitMode mode)
bool DrmPipeline::checkTestBuffer()
{
if (!pending.crtc || (m_primaryBuffer && m_primaryBuffer->size() == sourceSize())) {
if (!pending.crtc || (m_primaryBuffer && m_primaryBuffer->size() == bufferSize())) {
return true;
}
auto backend = gpu()->eglBackend();
@ -301,7 +301,7 @@ bool DrmPipeline::checkTestBuffer()
const auto &mods = supportedModifiers(buf->format());
if (backend && buf->format() == backend->drmFormat(m_output)
&& (mods.isEmpty() || mods.contains(buf->modifier()))
&& buf->size() == sourceSize()) {
&& buf->size() == bufferSize()) {
buffer = buf;
}
};
@ -319,13 +319,13 @@ bool DrmPipeline::checkTestBuffer()
if (backend && m_output) {
buffer = backend->renderTestFrame(m_output);
} else if (backend && gpu()->gbmDevice()) {
gbm_bo *bo = gbm_bo_create(gpu()->gbmDevice(), sourceSize().width(), sourceSize().height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
gbm_bo *bo = gbm_bo_create(gpu()->gbmDevice(), bufferSize().width(), bufferSize().height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!bo) {
return false;
}
buffer = QSharedPointer<DrmGbmBuffer>::create(gpu(), bo, nullptr);
} else {
buffer = QSharedPointer<DrmDumbBuffer>::create(gpu(), sourceSize(), DRM_FORMAT_XRGB8888);
buffer = QSharedPointer<DrmDumbBuffer>::create(gpu(), bufferSize(), DRM_FORMAT_XRGB8888);
}
}
if (buffer && buffer->bufferId()) {
@ -395,13 +395,22 @@ void DrmPipeline::applyPendingChanges()
m_next = pending;
}
QSize DrmPipeline::bufferSize() const
{
const auto modeSize = m_connector->modes()[pending.modeIndex]->size();
if (pending.bufferTransformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) {
return modeSize.transposed();
}
return modeSize;
}
QSize DrmPipeline::sourceSize() const
{
auto mode = m_connector->modes()[pending.modeIndex];
if (pending.transformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) {
return mode->size().transposed();
const auto modeSize = m_connector->modes()[pending.modeIndex]->size();
if (pending.sourceTransformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) {
return modeSize.transposed();
}
return mode->size();
return modeSize;
}
bool DrmPipeline::isCursorVisible() const
@ -491,7 +500,7 @@ bool DrmPipeline::needsModeset() const
|| pending.active != m_current.active
|| pending.modeIndex != m_current.modeIndex
|| pending.rgbRange != m_current.rgbRange
|| pending.transformation != m_current.transformation
|| pending.bufferTransformation != m_current.bufferTransformation
|| m_modesetPresentPending;
}

@ -77,7 +77,14 @@ public:
bool modesetPresentPending() const;
void resetModesetPresentPending();
void printDebugInfo() const;
/**
* which size buffers for rendering should have
*/
QSize sourceSize() const;
/**
* what size buffers submitted to this pipeline should have
*/
QSize bufferSize() const;
bool isFormatSupported(uint32_t drmFormat) const;
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const;
@ -95,11 +102,15 @@ public:
AbstractWaylandOutput::RgbRange rgbRange = AbstractWaylandOutput::RgbRange::Automatic;
RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed;
QSharedPointer<DrmGammaRamp> gamma;
DrmPlane::Transformations transformation = DrmPlane::Transformation::Rotate0;
QPoint cursorPos;
QPoint cursorHotspot;
QSharedPointer<DrmDumbBuffer> cursorBo;
// the transformation that this pipeline will apply to submitted buffers
DrmPlane::Transformations bufferTransformation = DrmPlane::Transformation::Rotate0;
// the transformation that buffers submitted to the pipeline should have
DrmPlane::Transformations sourceTransformation = DrmPlane::Transformation::Rotate0;
};
State pending;

@ -75,6 +75,11 @@ void DrmVirtualOutput::updateEnablement(bool enable)
gpu()->platform()->enableOutput(this, enable);
}
QSize DrmVirtualOutput::bufferSize() const
{
return pixelSize();
}
QSize DrmVirtualOutput::sourceSize() const
{
return pixelSize();

@ -29,6 +29,7 @@ public:
~DrmVirtualOutput() override;
bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) override;
QSize bufferSize() const override;
QSize sourceSize() const override;
bool isFormatSupported(uint32_t drmFormat) const override;

@ -157,8 +157,8 @@ bool EglGbmBackend::resetOutput(Output &output)
}
output.current.format = gbmFormat.value();
uint32_t format = gbmFormat.value().drmFormat;
const QSize size = output.output->sourceSize();
QVector<uint64_t> modifiers = output.output->supportedModifiers(format);
const QSize size = output.output->bufferSize();
QSharedPointer<GbmSurface> gbmSurface;
bool modifiersEnvSet = false;
@ -199,7 +199,7 @@ bool EglGbmBackend::resetOutput(Output &output)
output.current.shadowBuffer = nullptr;
} else {
makeContextCurrent(output.current);
output.current.shadowBuffer = QSharedPointer<ShadowBuffer>::create(output.output->pixelSize(), output.current.format);
output.current.shadowBuffer = QSharedPointer<ShadowBuffer>::create(output.output->sourceSize(), output.current.format);
if (!output.current.shadowBuffer->isComplete()) {
return false;
}
@ -517,7 +517,7 @@ SurfaceTexture *EglGbmBackend::createSurfaceTextureWayland(SurfacePixmapWayland
void EglGbmBackend::setViewport(const Output &output) const
{
const QSize size = output.output->pixelSize();
const QSize size = output.output->sourceSize();
glViewport(0, 0, size.width(), size.height());
}
@ -547,13 +547,13 @@ bool EglGbmBackend::doesRenderFit(DrmAbstractOutput *output, const Output::Rende
if (!render.gbmSurface) {
return false;
}
QSize surfaceSize = output->sourceSize();
QSize surfaceSize = output->bufferSize();
if (surfaceSize != render.gbmSurface->size()) {
return false;
}
bool needsTexture = output->needsSoftwareTransformation();
if (needsTexture) {
return render.shadowBuffer && render.shadowBuffer->textureSize() == output->pixelSize();
return render.shadowBuffer && render.shadowBuffer->textureSize() == output->sourceSize();
} else {
return render.shadowBuffer == nullptr;
}
@ -771,7 +771,7 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output
Q_ASSERT(m_outputs.contains(output));
auto &renderOutput = m_outputs[output];
if (renderOutput.current.shadowBuffer) {
const auto glTexture = QSharedPointer<KWin::GLTexture>::create(renderOutput.current.shadowBuffer->texture(), GL_RGBA8, output->pixelSize());
const auto glTexture = QSharedPointer<KWin::GLTexture>::create(renderOutput.current.shadowBuffer->texture(), GL_RGBA8, renderOutput.output->sourceSize());
glTexture->setYInverted(true);
return glTexture;
}

@ -46,13 +46,13 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend, DrmGpu *gpu)
void DrmQPainterBackend::initOutput(DrmAbstractOutput *output)
{
Output o;
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize(), DRM_FORMAT_XRGB8888);
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->sourceSize(), DRM_FORMAT_XRGB8888);
o.output = output;
m_outputs.insert(output, o);
connect(output, &DrmOutput::currentModeChanged, this,
[output, this] {
auto &o = m_outputs[output];
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize(), DRM_FORMAT_XRGB8888);
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->sourceSize(), DRM_FORMAT_XRGB8888);
o.damageJournal.setCapacity(o.swapchain->slotCount());
}
);

Loading…
Cancel
Save