backends/drm: handle broken legacy drivers better
Some legacy drivers either don't accept gbm buffers suitable for cursors, or don't handle them properly. In order to work around that, always do a CPU import with legacy and use dumb buffers instead. BUG: 453860 CCBUG: 456306
This commit is contained in:
parent
e09ca74295
commit
7f04ea578f
3 changed files with 34 additions and 24 deletions
|
@ -24,7 +24,9 @@ EglGbmCursorLayer::EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pip
|
|||
|
||||
OutputLayerBeginFrameInfo EglGbmCursorLayer::beginFrame()
|
||||
{
|
||||
return m_surface.startRendering(m_pipeline->gpu()->cursorSize(), m_pipeline->renderOrientation(), DrmPlane::Transformation::Rotate0, m_pipeline->cursorFormats(), GBM_BO_USE_LINEAR);
|
||||
// some legacy drivers don't work with linear gbm buffers for the cursor
|
||||
const auto target = m_pipeline->gpu()->atomicModeSetting() ? EglGbmLayerSurface::BufferTarget::Linear : EglGbmLayerSurface::BufferTarget::Dumb;
|
||||
return m_surface.startRendering(m_pipeline->gpu()->cursorSize(), m_pipeline->renderOrientation(), DrmPlane::Transformation::Rotate0, m_pipeline->cursorFormats(), target);
|
||||
}
|
||||
|
||||
void EglGbmCursorLayer::aboutToStartPainting(const QRegion &damagedRegion)
|
||||
|
@ -35,7 +37,9 @@ void EglGbmCursorLayer::aboutToStartPainting(const QRegion &damagedRegion)
|
|||
bool EglGbmCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(renderedRegion)
|
||||
const auto ret = m_surface.endRendering(m_pipeline->renderOrientation(), damagedRegion);
|
||||
// some legacy drivers don't work with linear gbm buffers for the cursor
|
||||
const auto target = m_pipeline->gpu()->atomicModeSetting() ? EglGbmLayerSurface::BufferTarget::Linear : EglGbmLayerSurface::BufferTarget::Dumb;
|
||||
const auto ret = m_surface.endRendering(m_pipeline->renderOrientation(), damagedRegion, target);
|
||||
if (ret.has_value()) {
|
||||
QRegion throwaway;
|
||||
std::tie(m_currentBuffer, throwaway) = ret.value();
|
||||
|
|
|
@ -55,9 +55,9 @@ void EglGbmLayerSurface::destroyResources()
|
|||
m_oldGbmSurface.reset();
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t additionalFlags)
|
||||
OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target)
|
||||
{
|
||||
if (!checkGbmSurface(bufferSize, formats, additionalFlags)) {
|
||||
if (!checkGbmSurface(bufferSize, formats, target == BufferTarget::Linear)) {
|
||||
return {};
|
||||
}
|
||||
if (!m_gbmSurface->makeContextCurrent()) {
|
||||
|
@ -118,7 +118,7 @@ void EglGbmLayerSurface::aboutToStartPainting(DrmOutput *output, const QRegion &
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> EglGbmLayerSurface::endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion)
|
||||
std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> EglGbmLayerSurface::endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion, BufferTarget target)
|
||||
{
|
||||
if (m_shadowBuffer) {
|
||||
GLFramebuffer::popFramebuffer();
|
||||
|
@ -126,7 +126,7 @@ std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> EglGbmLayerS
|
|||
m_shadowBuffer->render(renderOrientation);
|
||||
}
|
||||
GLFramebuffer::popFramebuffer();
|
||||
if (m_gpu == m_eglBackend->gpu()) {
|
||||
if (m_gpu == m_eglBackend->gpu() && target != BufferTarget::Dumb) {
|
||||
if (const auto buffer = m_gbmSurface->swapBuffers(damagedRegion)) {
|
||||
m_currentBuffer = buffer;
|
||||
auto ret = DrmFramebuffer::createFramebuffer(buffer);
|
||||
|
@ -138,7 +138,7 @@ std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> EglGbmLayerS
|
|||
} else {
|
||||
if (const auto gbmBuffer = m_gbmSurface->swapBuffers(damagedRegion)) {
|
||||
m_currentBuffer = gbmBuffer;
|
||||
const auto buffer = importBuffer();
|
||||
const auto buffer = target == BufferTarget::Dumb ? importWithCpu() : importBuffer();
|
||||
if (buffer) {
|
||||
return std::tuple(buffer, damagedRegion);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> EglGbmLayerS
|
|||
return {};
|
||||
}
|
||||
|
||||
bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t flags)
|
||||
bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, bool forceLinear)
|
||||
{
|
||||
if (doesGbmSurfaceFit(m_gbmSurface.get(), bufferSize, formats)) {
|
||||
m_oldGbmSurface.reset();
|
||||
|
@ -155,7 +155,7 @@ bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap<uin
|
|||
if (doesGbmSurfaceFit(m_oldGbmSurface.get(), bufferSize, formats)) {
|
||||
m_gbmSurface = m_oldGbmSurface;
|
||||
} else {
|
||||
if (!createGbmSurface(bufferSize, formats, flags)) {
|
||||
if (!createGbmSurface(bufferSize, formats, forceLinear)) {
|
||||
return false;
|
||||
}
|
||||
// dmabuf might work with the new surface
|
||||
|
@ -167,7 +167,7 @@ bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap<uin
|
|||
return m_gbmSurface != nullptr;
|
||||
}
|
||||
|
||||
bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, uint32_t flags)
|
||||
bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, bool forceLinear)
|
||||
{
|
||||
static bool modifiersEnvSet = false;
|
||||
static const bool modifiersEnv = qEnvironmentVariableIntValue("KWIN_DRM_USE_MODIFIERS", &modifiersEnvSet) != 0;
|
||||
|
@ -190,10 +190,11 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, co
|
|||
return false;
|
||||
}
|
||||
}
|
||||
int gbmFlags = flags | GBM_BO_USE_RENDERING;
|
||||
uint32_t gbmFlags = GBM_BO_USE_RENDERING;
|
||||
if (m_gpu == m_eglBackend->gpu()) {
|
||||
gbmFlags |= GBM_BO_USE_SCANOUT;
|
||||
} else {
|
||||
}
|
||||
if (forceLinear || m_gpu != m_eglBackend->gpu()) {
|
||||
gbmFlags |= GBM_BO_USE_LINEAR;
|
||||
}
|
||||
const auto ret = GbmSurface::createSurface(m_eglBackend, size, format, gbmFlags, config);
|
||||
|
@ -206,7 +207,7 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, co
|
|||
}
|
||||
}
|
||||
|
||||
bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t flags)
|
||||
bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, bool forceLinear)
|
||||
{
|
||||
QVector<GbmFormat> sortedFormats;
|
||||
for (auto it = formats.begin(); it != formats.end(); it++) {
|
||||
|
@ -231,7 +232,7 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap<uint32_t
|
|||
if (m_importMode == MultiGpuImportMode::DumbBufferXrgb8888 && format.drmFormat != DRM_FORMAT_XRGB8888) {
|
||||
continue;
|
||||
}
|
||||
if (formats.contains(format.drmFormat) && createGbmSurface(size, format.drmFormat, formats[format.drmFormat], flags)) {
|
||||
if (formats.contains(format.drmFormat) && createGbmSurface(size, format.drmFormat, formats[format.drmFormat], forceLinear)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -355,9 +356,9 @@ std::shared_ptr<GLTexture> EglGbmLayerSurface::texture() const
|
|||
return m_eglBackend->importBufferObjectAsTexture(m_currentBuffer->bo());
|
||||
}
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t additionalFlags)
|
||||
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target)
|
||||
{
|
||||
if (!checkGbmSurface(bufferSize, formats, additionalFlags) || !m_gbmSurface->makeContextCurrent()) {
|
||||
if (!checkGbmSurface(bufferSize, formats, target == BufferTarget::Linear) || !m_gbmSurface->makeContextCurrent()) {
|
||||
return nullptr;
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -365,13 +366,13 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize
|
|||
if (m_currentBuffer) {
|
||||
if (m_gpu != m_eglBackend->gpu()) {
|
||||
auto oldImportMode = m_importMode;
|
||||
auto buffer = importBuffer();
|
||||
auto buffer = target == BufferTarget::Dumb ? importWithCpu() : importBuffer();
|
||||
if (buffer) {
|
||||
return buffer;
|
||||
} else if (m_importMode != oldImportMode) {
|
||||
// try again with the new import mode
|
||||
// recursion depth is limited by the number of import modes
|
||||
return renderTestBuffer(bufferSize, formats, additionalFlags);
|
||||
return renderTestBuffer(bufferSize, formats);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -41,20 +41,25 @@ public:
|
|||
EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend);
|
||||
~EglGbmLayerSurface();
|
||||
|
||||
OutputLayerBeginFrameInfo startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t additionalFlags = 0);
|
||||
enum class BufferTarget {
|
||||
Normal,
|
||||
Linear,
|
||||
Dumb
|
||||
};
|
||||
OutputLayerBeginFrameInfo startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target = BufferTarget::Normal);
|
||||
void aboutToStartPainting(DrmOutput *output, const QRegion &damagedRegion);
|
||||
std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion);
|
||||
std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion, BufferTarget target = BufferTarget::Normal);
|
||||
|
||||
bool doesSurfaceFit(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const;
|
||||
std::shared_ptr<GLTexture> texture() const;
|
||||
void destroyResources();
|
||||
EglGbmBackend *eglBackend() const;
|
||||
std::shared_ptr<DrmFramebuffer> renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t additionalFlags = 0);
|
||||
std::shared_ptr<DrmFramebuffer> renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target = BufferTarget::Normal);
|
||||
|
||||
private:
|
||||
bool checkGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t flags);
|
||||
bool createGbmSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, uint32_t flags);
|
||||
bool createGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t flags);
|
||||
bool checkGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, bool forceLinear);
|
||||
bool createGbmSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, bool forceLinear);
|
||||
bool createGbmSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats, bool forceLinear);
|
||||
bool doesGbmSurfaceFit(GbmSurface *surf, const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const;
|
||||
|
||||
bool doesShadowBufferFit(ShadowBuffer *buffer, const QSize &size, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation) const;
|
||||
|
|
Loading…
Reference in a new issue