backends: move more things from output layers to kwin core
This commit is contained in:
parent
3232a63ac1
commit
445567f54e
32 changed files with 248 additions and 219 deletions
|
@ -25,7 +25,7 @@ EglGbmCursorLayer::EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pip
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> EglGbmCursorLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> EglGbmCursorLayer::doBeginFrame()
|
||||
{
|
||||
if (m_pipeline->amdgpuVrrWorkaroundActive()) {
|
||||
return std::nullopt;
|
||||
|
@ -36,7 +36,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmCursorLayer::beginFrame()
|
|||
return m_surface.startRendering(m_pipeline->gpu()->cursorSize(), m_pipeline->output()->transform().combine(OutputTransform::FlipY), m_pipeline->cursorFormats(), m_pipeline->colorDescription(), m_pipeline->output()->channelFactors(), m_pipeline->iccProfile(), m_pipeline->output()->needsColormanagement());
|
||||
}
|
||||
|
||||
bool EglGbmCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool EglGbmCursorLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
return m_surface.endRendering(damagedRegion);
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ class EglGbmCursorLayer : public DrmPipelineLayer
|
|||
public:
|
||||
EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
|
||||
bool checkTestBuffer() override;
|
||||
void releaseBuffers() override;
|
||||
|
|
|
@ -33,14 +33,14 @@ EglGbmLayer::EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline)
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::doBeginFrame()
|
||||
{
|
||||
m_scanoutBuffer.reset();
|
||||
|
||||
return m_surface.startRendering(m_pipeline->mode()->size(), m_pipeline->output()->transform().combine(OutputTransform::FlipY), m_pipeline->formats(), m_pipeline->colorDescription(), m_pipeline->output()->channelFactors(), m_pipeline->iccProfile(), m_pipeline->output()->needsColormanagement());
|
||||
}
|
||||
|
||||
bool EglGbmLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool EglGbmLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
return m_surface.endRendering(damagedRegion);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ std::shared_ptr<GLTexture> EglGbmLayer::texture() const
|
|||
{
|
||||
if (m_scanoutBuffer) {
|
||||
const auto ret = m_surface.eglBackend()->importDmaBufAsTexture(*m_scanoutBuffer->buffer()->dmabufAttributes());
|
||||
ret->setContentTransform(m_scanoutBufferTransform.combine(OutputTransform::FlipY));
|
||||
ret->setContentTransform(offloadTransform().combine(OutputTransform::FlipY));
|
||||
return ret;
|
||||
} else {
|
||||
return m_surface.texture();
|
||||
|
@ -66,7 +66,7 @@ ColorDescription EglGbmLayer::colorDescription() const
|
|||
return m_surface.colorDescription();
|
||||
}
|
||||
|
||||
bool EglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &size, OutputTransform transform, const ColorDescription &color)
|
||||
bool EglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color)
|
||||
{
|
||||
static bool valid;
|
||||
static const bool directScanoutDisabled = qEnvironmentVariableIntValue("KWIN_DRM_NO_DIRECT_SCANOUT", &valid) == 1 && valid;
|
||||
|
@ -80,21 +80,17 @@ bool EglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceR
|
|||
// kernel documentation says that
|
||||
// "Devices that don’t support subpixel plane coordinates can ignore the fractional part."
|
||||
// so we need to make sure that doesn't cause a difference vs the composited result
|
||||
m_bufferSourceBox = sourceRect.toRect();
|
||||
if (sourceRect != m_bufferSourceBox) {
|
||||
if (sourceRect() != sourceRect().toRect()) {
|
||||
return false;
|
||||
}
|
||||
const auto neededTransform = transform.combine(m_pipeline->output()->transform().inverted());
|
||||
const auto plane = m_pipeline->crtc()->primaryPlane();
|
||||
if (neededTransform != OutputTransform::Kind::Normal && (!plane || !plane->supportsTransformation(neededTransform))) {
|
||||
if (offloadTransform() != OutputTransform::Kind::Normal && (!plane || !plane->supportsTransformation(offloadTransform()))) {
|
||||
return false;
|
||||
}
|
||||
// importing a buffer from another GPU without an explicit modifier can mess up the buffer format
|
||||
if (buffer->dmabufAttributes()->modifier == DRM_FORMAT_MOD_INVALID && m_pipeline->gpu()->platform()->gpuCount() > 1) {
|
||||
return false;
|
||||
}
|
||||
m_scanoutTransform = neededTransform;
|
||||
m_scanoutBufferTransform = transform;
|
||||
m_scanoutBuffer = m_pipeline->gpu()->importBuffer(buffer, FileDescriptor{});
|
||||
if (m_scanoutBuffer && m_pipeline->testScanout()) {
|
||||
m_surface.forgetDamage(); // TODO: Use absolute frame sequence numbers for indexing the DamageJournal. It's more flexible and less error-prone
|
||||
|
@ -121,16 +117,6 @@ std::chrono::nanoseconds EglGbmLayer::queryRenderTime() const
|
|||
return m_surface.queryRenderTime();
|
||||
}
|
||||
|
||||
OutputTransform EglGbmLayer::hardwareTransform() const
|
||||
{
|
||||
return m_scanoutBuffer ? m_scanoutTransform : OutputTransform::Normal;
|
||||
}
|
||||
|
||||
QRect EglGbmLayer::bufferSourceBox() const
|
||||
{
|
||||
return m_scanoutBuffer ? m_bufferSourceBox : QRect(QPoint(0, 0), m_surface.currentBuffer()->buffer()->size());
|
||||
}
|
||||
|
||||
DrmDevice *EglGbmLayer::scanoutDevice() const
|
||||
{
|
||||
return m_pipeline->gpu()->drmDevice();
|
||||
|
|
|
@ -27,28 +27,21 @@ class EglGbmLayer : public DrmPipelineLayer
|
|||
public:
|
||||
EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
bool checkTestBuffer() override;
|
||||
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
|
||||
std::shared_ptr<GLTexture> texture() const override;
|
||||
ColorDescription colorDescription() const;
|
||||
void releaseBuffers() override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
OutputTransform hardwareTransform() const override;
|
||||
QRect bufferSourceBox() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
||||
private:
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &size, OutputTransform transform, const ColorDescription &color) override;
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color) override;
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> m_scanoutBuffer;
|
||||
// the transform the drm plane will apply to the buffer
|
||||
OutputTransform m_scanoutTransform = OutputTransform::Kind::Normal;
|
||||
// the output transform the buffer is made for
|
||||
OutputTransform m_scanoutBufferTransform = OutputTransform::Kind::Normal;
|
||||
QRect m_bufferSourceBox;
|
||||
|
||||
EglGbmLayerSurface m_surface;
|
||||
};
|
||||
|
|
|
@ -442,6 +442,17 @@ DrmPipeline::Error DrmGpu::testPendingConfiguration()
|
|||
return c1->crtcId.value() > c2->crtcId.value();
|
||||
});
|
||||
}
|
||||
// reset all outputs to their most basic configuration (primary plane without scaling)
|
||||
// for the test, and set the target rects appropriately
|
||||
for (const auto output : std::as_const(m_drmOutputs)) {
|
||||
if (!output->lease()) {
|
||||
const auto primary = output->primaryLayer();
|
||||
primary->setTargetRect(QRect(QPoint(0, 0), output->connector()->pipeline()->mode()->size()));
|
||||
primary->setSourceRect(QRect(QPoint(0, 0), output->connector()->pipeline()->mode()->size()));
|
||||
primary->setEnabled(true);
|
||||
output->cursorLayer()->setEnabled(false);
|
||||
}
|
||||
}
|
||||
return checkCrtcAssignment(connectors, crtcs);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "drm_layer.h"
|
||||
#include "core/graphicsbuffer.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_output.h"
|
||||
#include "drm_pipeline.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
@ -17,6 +18,11 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
DrmOutputLayer::DrmOutputLayer(Output *output)
|
||||
: OutputLayer(output)
|
||||
{
|
||||
}
|
||||
|
||||
DrmOutputLayer::~DrmOutputLayer() = default;
|
||||
|
||||
std::shared_ptr<GLTexture> DrmOutputLayer::texture() const
|
||||
|
@ -25,18 +31,8 @@ std::shared_ptr<GLTexture> DrmOutputLayer::texture() const
|
|||
}
|
||||
|
||||
DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline)
|
||||
: m_pipeline(pipeline)
|
||||
: DrmOutputLayer(pipeline->output())
|
||||
, m_pipeline(pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
OutputTransform DrmPipelineLayer::hardwareTransform() const
|
||||
{
|
||||
return OutputTransform::Kind::Normal;
|
||||
}
|
||||
|
||||
QRect DrmPipelineLayer::bufferSourceBox() const
|
||||
{
|
||||
const auto buffer = currentBuffer();
|
||||
return buffer ? QRect(QPoint(0, 0), currentBuffer()->buffer()->size()) : QRect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ class DrmPipeline;
|
|||
class DrmOutputLayer : public OutputLayer
|
||||
{
|
||||
public:
|
||||
explicit DrmOutputLayer(Output *output);
|
||||
virtual ~DrmOutputLayer();
|
||||
|
||||
virtual std::shared_ptr<GLTexture> texture() const;
|
||||
|
@ -37,8 +38,6 @@ public:
|
|||
|
||||
virtual bool checkTestBuffer() = 0;
|
||||
virtual std::shared_ptr<DrmFramebuffer> currentBuffer() const = 0;
|
||||
virtual OutputTransform hardwareTransform() const;
|
||||
virtual QRect bufferSourceBox() const;
|
||||
|
||||
protected:
|
||||
DrmPipeline *const m_pipeline;
|
||||
|
|
|
@ -211,21 +211,6 @@ DrmPipeline::Error DrmPipeline::prepareAtomicCommit(DrmAtomicCommit *commit, Com
|
|||
return Error::None;
|
||||
}
|
||||
|
||||
static QRect centerBuffer(const QSize &bufferSize, const QSize &modeSize)
|
||||
{
|
||||
const double widthScale = bufferSize.width() / double(modeSize.width());
|
||||
const double heightScale = bufferSize.height() / double(modeSize.height());
|
||||
if (widthScale > heightScale) {
|
||||
const QSize size = bufferSize / widthScale;
|
||||
const uint32_t yOffset = (modeSize.height() - size.height()) / 2;
|
||||
return QRect(QPoint(0, yOffset), size);
|
||||
} else {
|
||||
const QSize size = bufferSize / heightScale;
|
||||
const uint32_t xOffset = (modeSize.width() - size.width()) / 2;
|
||||
return QRect(QPoint(xOffset, 0), size);
|
||||
}
|
||||
}
|
||||
|
||||
DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commit)
|
||||
{
|
||||
commit->setPresentationMode(m_pending.presentationMode);
|
||||
|
@ -256,7 +241,7 @@ DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commi
|
|||
return Error::InvalidArguments;
|
||||
}
|
||||
const auto primary = m_pending.crtc->primaryPlane();
|
||||
const auto transform = m_primaryLayer->hardwareTransform();
|
||||
const auto transform = m_primaryLayer->offloadTransform();
|
||||
const auto planeTransform = DrmPlane::outputTransformToPlaneTransform(transform);
|
||||
if (primary->rotation.isValid()) {
|
||||
if (!primary->rotation.hasEnum(planeTransform)) {
|
||||
|
@ -266,7 +251,7 @@ DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commi
|
|||
} else if (planeTransform != DrmPlane::Transformation::Rotate0) {
|
||||
return Error::InvalidArguments;
|
||||
}
|
||||
primary->set(commit, m_primaryLayer->bufferSourceBox(), centerBuffer(transform.map(fb->buffer()->size()), m_pending.mode->size()));
|
||||
primary->set(commit, m_primaryLayer->sourceRect().toRect(), m_primaryLayer->targetRect());
|
||||
commit->addBuffer(m_pending.crtc->primaryPlane(), fb);
|
||||
if (fb->buffer()->dmabufAttributes()->format == DRM_FORMAT_NV12) {
|
||||
if (!primary->colorEncoding.isValid() || !primary->colorRange.isValid()) {
|
||||
|
@ -284,7 +269,7 @@ void DrmPipeline::prepareAtomicCursor(DrmAtomicCommit *commit)
|
|||
auto plane = m_pending.crtc->cursorPlane();
|
||||
const auto layer = cursorLayer();
|
||||
if (layer->isEnabled()) {
|
||||
plane->set(commit, layer->bufferSourceBox(), QRect(layer->position().toPoint(), gpu()->cursorSize()));
|
||||
plane->set(commit, layer->sourceRect().toRect(), layer->targetRect());
|
||||
commit->addProperty(plane->crtcId, m_pending.crtc->id());
|
||||
commit->addBuffer(plane, layer->currentBuffer());
|
||||
if (plane->vmHotspotX.isValid() && plane->vmHotspotY.isValid()) {
|
||||
|
|
|
@ -30,7 +30,7 @@ DrmPipeline::Error DrmPipeline::presentLegacy()
|
|||
return err;
|
||||
}
|
||||
const auto buffer = m_primaryLayer->currentBuffer();
|
||||
if (m_primaryLayer->bufferSourceBox() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
|
||||
if (m_primaryLayer->sourceRect() != m_primaryLayer->targetRect() || m_primaryLayer->targetRect() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
|
||||
return Error::InvalidArguments;
|
||||
}
|
||||
auto commit = std::make_unique<DrmLegacyCommit>(this, buffer);
|
||||
|
@ -54,7 +54,7 @@ DrmPipeline::Error DrmPipeline::legacyModeset()
|
|||
return Error::TestBufferFailed;
|
||||
}
|
||||
const auto buffer = m_primaryLayer->currentBuffer();
|
||||
if (m_primaryLayer->bufferSourceBox() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
|
||||
if (m_primaryLayer->sourceRect() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
|
||||
return Error::InvalidArguments;
|
||||
}
|
||||
auto commit = std::make_unique<DrmLegacyCommit>(this, buffer);
|
||||
|
@ -184,8 +184,8 @@ bool DrmPipeline::setCursorLegacy()
|
|||
struct drm_mode_cursor2 arg = {
|
||||
.flags = DRM_MODE_CURSOR_BO | DRM_MODE_CURSOR_MOVE,
|
||||
.crtc_id = m_pending.crtc->id(),
|
||||
.x = int32_t(m_cursorLayer->position().x()),
|
||||
.y = int32_t(m_cursorLayer->position().y()),
|
||||
.x = int32_t(m_cursorLayer->targetRect().x()),
|
||||
.y = int32_t(m_cursorLayer->targetRect().y()),
|
||||
.width = (uint32_t)gpu()->cursorSize().width(),
|
||||
.height = (uint32_t)gpu()->cursorSize().height(),
|
||||
.handle = handle,
|
||||
|
|
|
@ -26,7 +26,7 @@ DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline)
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmQPainterLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmQPainterLayer::doBeginFrame()
|
||||
{
|
||||
if (!doesSwapchainFit()) {
|
||||
m_swapchain = std::make_shared<QPainterSwapchain>(m_pipeline->gpu()->drmDevice()->allocator(), m_pipeline->mode()->size(), DRM_FORMAT_XRGB8888);
|
||||
|
@ -46,7 +46,7 @@ std::optional<OutputLayerBeginFrameInfo> DrmQPainterLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool DrmQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool DrmQPainterLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
m_currentFramebuffer = m_pipeline->gpu()->importBuffer(m_currentBuffer->buffer(), FileDescriptor{});
|
||||
|
@ -111,7 +111,7 @@ DrmCursorQPainterLayer::DrmCursorQPainterLayer(DrmPipeline *pipeline)
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmCursorQPainterLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmCursorQPainterLayer::doBeginFrame()
|
||||
{
|
||||
if (!m_swapchain) {
|
||||
m_swapchain = std::make_shared<QPainterSwapchain>(m_pipeline->gpu()->drmDevice()->allocator(), m_pipeline->gpu()->cursorSize(), DRM_FORMAT_ARGB8888);
|
||||
|
@ -127,7 +127,7 @@ std::optional<OutputLayerBeginFrameInfo> DrmCursorQPainterLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool DrmCursorQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool DrmCursorQPainterLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
m_currentFramebuffer = m_pipeline->gpu()->importBuffer(m_currentBuffer->buffer(), FileDescriptor{});
|
||||
|
@ -169,11 +169,11 @@ QHash<uint32_t, QList<uint64_t>> DrmCursorQPainterLayer::supportedDrmFormats() c
|
|||
}
|
||||
|
||||
DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output)
|
||||
: m_output(output)
|
||||
: DrmOutputLayer(output)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmVirtualQPainterLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> DrmVirtualQPainterLayer::doBeginFrame()
|
||||
{
|
||||
if (m_image.isNull() || m_image.size() != m_output->modeSize()) {
|
||||
m_image = QImage(m_output->modeSize(), QImage::Format_RGB32);
|
||||
|
@ -185,7 +185,7 @@ std::optional<OutputLayerBeginFrameInfo> DrmVirtualQPainterLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool DrmVirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool DrmVirtualQPainterLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
return true;
|
||||
|
|
|
@ -27,8 +27,8 @@ class DrmQPainterLayer : public DrmPipelineLayer
|
|||
public:
|
||||
DrmQPainterLayer(DrmPipeline *pipeline);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
bool checkTestBuffer() override;
|
||||
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
|
||||
void releaseBuffers() override;
|
||||
|
@ -52,8 +52,8 @@ class DrmCursorQPainterLayer : public DrmPipelineLayer
|
|||
public:
|
||||
DrmCursorQPainterLayer(DrmPipeline *pipeline);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
|
||||
bool checkTestBuffer() override;
|
||||
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
|
||||
|
@ -75,8 +75,8 @@ class DrmVirtualQPainterLayer : public DrmOutputLayer
|
|||
public:
|
||||
DrmVirtualQPainterLayer(DrmVirtualOutput *output);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
|
||||
void releaseBuffers() override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
|
@ -85,7 +85,6 @@ public:
|
|||
|
||||
private:
|
||||
QImage m_image;
|
||||
DrmVirtualOutput *const m_output;
|
||||
std::chrono::steady_clock::time_point m_renderStart;
|
||||
std::chrono::nanoseconds m_renderTime;
|
||||
};
|
||||
|
|
|
@ -27,14 +27,14 @@ namespace KWin
|
|||
{
|
||||
|
||||
VirtualEglGbmLayer::VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output)
|
||||
: m_output(output)
|
||||
: DrmOutputLayer(output)
|
||||
, m_eglBackend(eglBackend)
|
||||
{
|
||||
}
|
||||
|
||||
VirtualEglGbmLayer::~VirtualEglGbmLayer() = default;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualEglGbmLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualEglGbmLayer::doBeginFrame()
|
||||
{
|
||||
// gbm surface
|
||||
if (doesGbmSwapchainFit(m_gbmSwapchain.get())) {
|
||||
|
@ -79,7 +79,7 @@ std::optional<OutputLayerBeginFrameInfo> VirtualEglGbmLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool VirtualEglGbmLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool VirtualEglGbmLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_query->end();
|
||||
glFlush();
|
||||
|
@ -134,7 +134,7 @@ std::shared_ptr<GLTexture> VirtualEglGbmLayer::texture() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool VirtualEglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color)
|
||||
bool VirtualEglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color)
|
||||
{
|
||||
static bool valid;
|
||||
static const bool directScanoutDisabled = qEnvironmentVariableIntValue("KWIN_DRM_NO_DIRECT_SCANOUT", &valid) == 1 && valid;
|
||||
|
@ -142,7 +142,7 @@ bool VirtualEglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sourceRect != QRectF(QPointF(0, 0), targetSize) || targetSize != m_output->modeSize() || targetSize != buffer->size()) {
|
||||
if (sourceRect() != targetRect() || targetRect().topLeft() != QPointF(0, 0) || targetRect().size() != m_output->modeSize() || targetRect().size() != buffer->size() || offloadTransform() != OutputTransform::Kind::Normal) {
|
||||
return false;
|
||||
}
|
||||
m_scanoutBuffer = buffer;
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output);
|
||||
~VirtualEglGbmLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
|
||||
std::shared_ptr<GLTexture> texture() const override;
|
||||
void releaseBuffers() override;
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
const ColorDescription &colorDescription() const;
|
||||
|
||||
private:
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color) override;
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color) override;
|
||||
std::shared_ptr<EglSwapchain> createGbmSwapchain() const;
|
||||
bool doesGbmSwapchainFit(EglSwapchain *swapchain) const;
|
||||
|
||||
|
@ -58,7 +58,6 @@ private:
|
|||
std::shared_ptr<EglSwapchainSlot> m_currentSlot;
|
||||
std::unique_ptr<GLRenderTimeQuery> m_query;
|
||||
|
||||
DrmVirtualOutput *const m_output;
|
||||
EglGbmBackend *const m_eglBackend;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ namespace KWin
|
|||
{
|
||||
|
||||
VirtualEglLayer::VirtualEglLayer(Output *output, VirtualEglBackend *backend)
|
||||
: m_backend(backend)
|
||||
, m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ std::shared_ptr<GLTexture> VirtualEglLayer::texture() const
|
|||
return m_current->texture();
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualEglLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualEglLayer::doBeginFrame()
|
||||
{
|
||||
m_backend->makeCurrent();
|
||||
|
||||
|
@ -62,7 +62,7 @@ std::optional<OutputLayerBeginFrameInfo> VirtualEglLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool VirtualEglLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool VirtualEglLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_query->end();
|
||||
glFlush(); // flush pending rendering commands.
|
||||
|
|
|
@ -30,8 +30,8 @@ class VirtualEglLayer : public OutputLayer
|
|||
public:
|
||||
VirtualEglLayer(Output *output, VirtualEglBackend *backend);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
|
||||
std::shared_ptr<GLTexture> texture() const;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
|
@ -40,7 +40,6 @@ public:
|
|||
|
||||
private:
|
||||
VirtualEglBackend *const m_backend;
|
||||
Output *m_output;
|
||||
std::shared_ptr<EglSwapchain> m_swapchain;
|
||||
std::shared_ptr<EglSwapchainSlot> m_current;
|
||||
std::unique_ptr<GLRenderTimeQuery> m_query;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
VirtualQPainterLayer::VirtualQPainterLayer(Output *output, VirtualQPainterBackend *backend)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ VirtualQPainterLayer::~VirtualQPainterLayer()
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::doBeginFrame()
|
||||
{
|
||||
const QSize nativeSize(m_output->modeSize());
|
||||
if (!m_swapchain || m_swapchain->size() != nativeSize) {
|
||||
|
@ -49,7 +49,7 @@ std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool VirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool VirtualQPainterLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
return true;
|
||||
|
|
|
@ -32,15 +32,14 @@ public:
|
|||
VirtualQPainterLayer(Output *output, VirtualQPainterBackend *backend);
|
||||
~VirtualQPainterLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
QImage *image();
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
||||
private:
|
||||
Output *const m_output;
|
||||
VirtualQPainterBackend *const m_backend;
|
||||
std::unique_ptr<QPainterSwapchain> m_swapchain;
|
||||
std::shared_ptr<QPainterSwapchainSlot> m_current;
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Wayland
|
|||
static const bool bufferAgeEnabled = qEnvironmentVariable("KWIN_USE_BUFFER_AGE") != QStringLiteral("0");
|
||||
|
||||
WaylandEglPrimaryLayer::WaylandEglPrimaryLayer(WaylandOutput *output, WaylandEglBackend *backend)
|
||||
: m_waylandOutput(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -56,14 +56,14 @@ std::shared_ptr<GLTexture> WaylandEglPrimaryLayer::texture() const
|
|||
return m_buffer->texture();
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandEglPrimaryLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandEglPrimaryLayer::doBeginFrame()
|
||||
{
|
||||
if (!m_backend->openglContext()->makeCurrent()) {
|
||||
qCCritical(KWIN_WAYLAND_BACKEND) << "Make Context Current failed";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const QSize nativeSize = m_waylandOutput->modeSize();
|
||||
const QSize nativeSize = m_output->modeSize();
|
||||
if (!m_swapchain || m_swapchain->size() != nativeSize) {
|
||||
const QHash<uint32_t, QList<uint64_t>> formatTable = m_backend->backend()->display()->linuxDmabuf()->formats();
|
||||
uint32_t format = DRM_FORMAT_INVALID;
|
||||
|
@ -102,7 +102,7 @@ std::optional<OutputLayerBeginFrameInfo> WaylandEglPrimaryLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool WaylandEglPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool WaylandEglPrimaryLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_query->end();
|
||||
// Flush rendering commands to the dmabuf.
|
||||
|
@ -116,14 +116,14 @@ bool WaylandEglPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegi
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WaylandEglPrimaryLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color)
|
||||
bool WaylandEglPrimaryLayer::doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color)
|
||||
{
|
||||
Q_ASSERT(!m_presentationBuffer);
|
||||
// TODO use viewporter to relax this check
|
||||
if (sourceRect != QRectF(QPointF(0, 0), targetSize) || targetSize != m_waylandOutput->modeSize()) {
|
||||
if (sourceRect() != targetRect() || targetRect() != QRectF(QPointF(0, 0), m_output->modeSize())) {
|
||||
return false;
|
||||
}
|
||||
if (transform != OutputTransform::Kind::Normal || color != ColorDescription::sRGB) {
|
||||
if (offloadTransform() != OutputTransform::Kind::Normal || color != ColorDescription::sRGB) {
|
||||
return false;
|
||||
}
|
||||
m_presentationBuffer = m_backend->backend()->importBuffer(buffer);
|
||||
|
@ -132,10 +132,11 @@ bool WaylandEglPrimaryLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRec
|
|||
|
||||
void WaylandEglPrimaryLayer::present()
|
||||
{
|
||||
KWayland::Client::Surface *surface = m_waylandOutput->surface();
|
||||
const auto waylandOutput = static_cast<WaylandOutput *>(m_output);
|
||||
KWayland::Client::Surface *surface = waylandOutput->surface();
|
||||
surface->attachBuffer(m_presentationBuffer);
|
||||
surface->damage(m_damageJournal.lastDamage());
|
||||
surface->setScale(std::ceil(m_waylandOutput->scale()));
|
||||
surface->setScale(std::ceil(waylandOutput->scale()));
|
||||
surface->commit();
|
||||
m_presentationBuffer = nullptr;
|
||||
}
|
||||
|
@ -157,7 +158,7 @@ QHash<uint32_t, QList<uint64_t>> WaylandEglPrimaryLayer::supportedDrmFormats() c
|
|||
}
|
||||
|
||||
WaylandEglCursorLayer::WaylandEglCursorLayer(WaylandOutput *output, WaylandEglBackend *backend)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -167,14 +168,14 @@ WaylandEglCursorLayer::~WaylandEglCursorLayer()
|
|||
m_backend->openglContext()->makeCurrent();
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandEglCursorLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandEglCursorLayer::doBeginFrame()
|
||||
{
|
||||
if (!m_backend->openglContext()->makeCurrent()) {
|
||||
qCCritical(KWIN_WAYLAND_BACKEND) << "Make Context Current failed";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto tmp = size().expandedTo(QSize(64, 64));
|
||||
const auto tmp = targetRect().size().expandedTo(QSize(64, 64));
|
||||
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
||||
if (!m_swapchain || m_swapchain->size() != bufferSize) {
|
||||
const QHash<uint32_t, QList<uint64_t>> formatTable = m_backend->backend()->display()->linuxDmabuf()->formats();
|
||||
|
@ -213,7 +214,7 @@ std::optional<OutputLayerBeginFrameInfo> WaylandEglCursorLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool WaylandEglCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool WaylandEglCursorLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_query->end();
|
||||
// Flush rendering commands to the dmabuf.
|
||||
|
@ -222,7 +223,7 @@ bool WaylandEglCursorLayer::endFrame(const QRegion &renderedRegion, const QRegio
|
|||
wl_buffer *buffer = m_backend->backend()->importBuffer(m_buffer->buffer());
|
||||
Q_ASSERT(buffer);
|
||||
|
||||
m_output->cursor()->update(buffer, scale(), hotspot().toPoint());
|
||||
static_cast<WaylandOutput *>(m_output)->cursor()->update(buffer, scale(), hotspot().toPoint());
|
||||
|
||||
EGLNativeFence releaseFence{m_backend->eglDisplayObject()};
|
||||
m_swapchain->release(m_buffer, releaseFence.takeFileDescriptor());
|
||||
|
|
|
@ -42,15 +42,14 @@ public:
|
|||
std::shared_ptr<GLTexture> texture() const;
|
||||
void present();
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color) override;
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color) override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
||||
private:
|
||||
WaylandOutput *m_waylandOutput;
|
||||
DamageJournal m_damageJournal;
|
||||
std::shared_ptr<EglSwapchain> m_swapchain;
|
||||
std::shared_ptr<EglSwapchainSlot> m_buffer;
|
||||
|
@ -69,8 +68,8 @@ public:
|
|||
WaylandEglCursorLayer(WaylandOutput *output, WaylandEglBackend *backend);
|
||||
~WaylandEglCursorLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
|
|
@ -26,7 +26,8 @@ namespace Wayland
|
|||
{
|
||||
|
||||
WaylandQPainterPrimaryLayer::WaylandQPainterPrimaryLayer(WaylandOutput *output, WaylandQPainterBackend *backend)
|
||||
: m_waylandOutput(output)
|
||||
: OutputLayer(output)
|
||||
, m_waylandOutput(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -54,7 +55,7 @@ QRegion WaylandQPainterPrimaryLayer::accumulateDamage(int bufferAge) const
|
|||
return m_damageJournal.accumulate(bufferAge, infiniteRegion());
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterPrimaryLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterPrimaryLayer::doBeginFrame()
|
||||
{
|
||||
const QSize nativeSize(m_waylandOutput->modeSize());
|
||||
if (!m_swapchain || m_swapchain->size() != nativeSize) {
|
||||
|
@ -73,7 +74,7 @@ std::optional<OutputLayerBeginFrameInfo> WaylandQPainterPrimaryLayer::beginFrame
|
|||
};
|
||||
}
|
||||
|
||||
bool WaylandQPainterPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool WaylandQPainterPrimaryLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
m_damageJournal.add(damagedRegion);
|
||||
|
@ -96,7 +97,7 @@ QHash<uint32_t, QList<uint64_t>> WaylandQPainterPrimaryLayer::supportedDrmFormat
|
|||
}
|
||||
|
||||
WaylandQPainterCursorLayer::WaylandQPainterCursorLayer(WaylandOutput *output, WaylandQPainterBackend *backend)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -105,9 +106,9 @@ WaylandQPainterCursorLayer::~WaylandQPainterCursorLayer()
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterCursorLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterCursorLayer::doBeginFrame()
|
||||
{
|
||||
const auto tmp = size().expandedTo(QSize(64, 64));
|
||||
const auto tmp = targetRect().size().expandedTo(QSize(64, 64));
|
||||
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
||||
if (!m_swapchain || m_swapchain->size() != bufferSize) {
|
||||
m_swapchain = std::make_unique<QPainterSwapchain>(m_backend->graphicsBufferAllocator(), bufferSize, DRM_FORMAT_ARGB8888);
|
||||
|
@ -125,13 +126,13 @@ std::optional<OutputLayerBeginFrameInfo> WaylandQPainterCursorLayer::beginFrame(
|
|||
};
|
||||
}
|
||||
|
||||
bool WaylandQPainterCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool WaylandQPainterCursorLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
wl_buffer *buffer = m_output->backend()->importBuffer(m_back->buffer());
|
||||
wl_buffer *buffer = static_cast<WaylandOutput *>(m_output)->backend()->importBuffer(m_back->buffer());
|
||||
Q_ASSERT(buffer);
|
||||
|
||||
m_output->cursor()->update(buffer, scale(), hotspot().toPoint());
|
||||
static_cast<WaylandOutput *>(m_output)->cursor()->update(buffer, scale(), hotspot().toPoint());
|
||||
m_swapchain->release(m_back);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ public:
|
|||
WaylandQPainterPrimaryLayer(WaylandOutput *output, WaylandQPainterBackend *backend);
|
||||
~WaylandQPainterPrimaryLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
@ -68,14 +68,13 @@ public:
|
|||
WaylandQPainterCursorLayer(WaylandOutput *output, WaylandQPainterBackend *backend);
|
||||
~WaylandQPainterCursorLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
||||
private:
|
||||
WaylandOutput *m_output;
|
||||
WaylandQPainterBackend *m_backend;
|
||||
std::unique_ptr<QPainterSwapchain> m_swapchain;
|
||||
std::shared_ptr<QPainterSwapchainSlot> m_back;
|
||||
|
|
|
@ -31,16 +31,17 @@ namespace KWin
|
|||
{
|
||||
|
||||
EglLayer::EglLayer(EglBackend *backend)
|
||||
: m_backend(backend)
|
||||
: OutputLayer(nullptr)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> EglLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> EglLayer::doBeginFrame()
|
||||
{
|
||||
return m_backend->beginFrame();
|
||||
}
|
||||
|
||||
bool EglLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool EglLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_backend->endFrame(renderedRegion, damagedRegion);
|
||||
return true;
|
||||
|
|
|
@ -35,8 +35,8 @@ class EglLayer : public OutputLayer
|
|||
public:
|
||||
EglLayer(EglBackend *backend);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
|
|
@ -99,16 +99,17 @@ bool SwapEventFilter::event(xcb_generic_event_t *event)
|
|||
}
|
||||
|
||||
GlxLayer::GlxLayer(GlxBackend *backend)
|
||||
: m_backend(backend)
|
||||
: OutputLayer(nullptr)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> GlxLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> GlxLayer::doBeginFrame()
|
||||
{
|
||||
return m_backend->beginFrame();
|
||||
return m_backend->doBeginFrame();
|
||||
}
|
||||
|
||||
bool GlxLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool GlxLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_backend->endFrame(renderedRegion, damagedRegion);
|
||||
return true;
|
||||
|
@ -660,7 +661,7 @@ std::unique_ptr<SurfaceTexture> GlxBackend::createSurfaceTextureX11(SurfacePixma
|
|||
return std::make_unique<GlxSurfaceTextureX11>(this, pixmap);
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo GlxBackend::beginFrame()
|
||||
OutputLayerBeginFrameInfo GlxBackend::doBeginFrame()
|
||||
{
|
||||
QRegion repaint;
|
||||
makeCurrent();
|
||||
|
|
|
@ -63,8 +63,8 @@ class GlxLayer : public OutputLayer
|
|||
public:
|
||||
GlxLayer(GlxBackend *backend);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
GlxBackend(::Display *display, X11StandaloneBackend *backend);
|
||||
~GlxBackend() override;
|
||||
std::unique_ptr<SurfaceTexture> createSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
|
||||
OutputLayerBeginFrameInfo beginFrame();
|
||||
OutputLayerBeginFrameInfo doBeginFrame();
|
||||
void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
|
||||
std::chrono::nanoseconds queryRenderTime();
|
||||
void present(Output *output, const std::shared_ptr<OutputFrame> &frame) override;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace KWin
|
|||
{
|
||||
|
||||
X11WindowedEglPrimaryLayer::X11WindowedEglPrimaryLayer(X11WindowedEglBackend *backend, X11WindowedOutput *output)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_output(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ X11WindowedEglPrimaryLayer::~X11WindowedEglPrimaryLayer()
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedEglPrimaryLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedEglPrimaryLayer::doBeginFrame()
|
||||
{
|
||||
if (!m_backend->openglContext()->makeCurrent()) {
|
||||
return std::nullopt;
|
||||
|
@ -68,7 +69,7 @@ std::optional<OutputLayerBeginFrameInfo> X11WindowedEglPrimaryLayer::beginFrame(
|
|||
};
|
||||
}
|
||||
|
||||
bool X11WindowedEglPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool X11WindowedEglPrimaryLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_query->end();
|
||||
return true;
|
||||
|
@ -129,7 +130,7 @@ QHash<uint32_t, QList<uint64_t>> X11WindowedEglPrimaryLayer::supportedDrmFormats
|
|||
}
|
||||
|
||||
X11WindowedEglCursorLayer::X11WindowedEglCursorLayer(X11WindowedEglBackend *backend, X11WindowedOutput *output)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -141,13 +142,13 @@ X11WindowedEglCursorLayer::~X11WindowedEglCursorLayer()
|
|||
m_texture.reset();
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedEglCursorLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedEglCursorLayer::doBeginFrame()
|
||||
{
|
||||
if (!m_backend->openglContext()->makeCurrent()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto tmp = size().expandedTo(QSize(64, 64));
|
||||
const auto tmp = targetRect().size().expandedTo(QSize(64, 64));
|
||||
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
||||
if (!m_texture || m_texture->size() != bufferSize) {
|
||||
m_texture = GLTexture::allocate(GL_RGBA8, bufferSize);
|
||||
|
@ -166,7 +167,7 @@ std::optional<OutputLayerBeginFrameInfo> X11WindowedEglCursorLayer::beginFrame()
|
|||
};
|
||||
}
|
||||
|
||||
bool X11WindowedEglCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool X11WindowedEglCursorLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
QImage buffer(m_framebuffer->size(), QImage::Format_RGBA8888_Premultiplied);
|
||||
|
||||
|
@ -174,7 +175,7 @@ bool X11WindowedEglCursorLayer::endFrame(const QRegion &renderedRegion, const QR
|
|||
glReadPixels(0, 0, buffer.width(), buffer.height(), GL_RGBA, GL_UNSIGNED_BYTE, buffer.bits());
|
||||
GLFramebuffer::popFramebuffer();
|
||||
|
||||
m_output->cursor()->update(buffer.mirrored(false, true), hotspot());
|
||||
static_cast<X11WindowedOutput *>(m_output)->cursor()->update(buffer.mirrored(false, true), hotspot());
|
||||
m_query->end();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -28,8 +28,8 @@ public:
|
|||
X11WindowedEglPrimaryLayer(X11WindowedEglBackend *backend, X11WindowedOutput *output);
|
||||
~X11WindowedEglPrimaryLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
@ -53,14 +53,13 @@ public:
|
|||
X11WindowedEglCursorLayer(X11WindowedEglBackend *backend, X11WindowedOutput *output);
|
||||
~X11WindowedEglCursorLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
||||
private:
|
||||
X11WindowedOutput *const m_output;
|
||||
X11WindowedEglBackend *const m_backend;
|
||||
std::unique_ptr<GLFramebuffer> m_framebuffer;
|
||||
std::unique_ptr<GLTexture> m_texture;
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace KWin
|
|||
{
|
||||
|
||||
X11WindowedQPainterPrimaryLayer::X11WindowedQPainterPrimaryLayer(X11WindowedOutput *output, X11WindowedQPainterBackend *backend)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_output(output)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
@ -32,7 +33,7 @@ X11WindowedQPainterPrimaryLayer::~X11WindowedQPainterPrimaryLayer()
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterPrimaryLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterPrimaryLayer::doBeginFrame()
|
||||
{
|
||||
const QSize bufferSize = m_output->modeSize();
|
||||
if (!m_swapchain || m_swapchain->size() != bufferSize) {
|
||||
|
@ -54,7 +55,7 @@ std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterPrimaryLayer::beginF
|
|||
};
|
||||
}
|
||||
|
||||
bool X11WindowedQPainterPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool X11WindowedQPainterPrimaryLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
return true;
|
||||
|
@ -106,13 +107,14 @@ QHash<uint32_t, QList<uint64_t>> X11WindowedQPainterPrimaryLayer::supportedDrmFo
|
|||
}
|
||||
|
||||
X11WindowedQPainterCursorLayer::X11WindowedQPainterCursorLayer(X11WindowedOutput *output)
|
||||
: m_output(output)
|
||||
: OutputLayer(output)
|
||||
, m_output(output)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterCursorLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterCursorLayer::doBeginFrame()
|
||||
{
|
||||
const auto tmp = size().expandedTo(QSize(64, 64));
|
||||
const auto tmp = targetRect().size().expandedTo(QSize(64, 64));
|
||||
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
|
||||
if (m_buffer.size() != bufferSize) {
|
||||
m_buffer = QImage(bufferSize, QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -130,7 +132,7 @@ std::chrono::nanoseconds X11WindowedQPainterCursorLayer::queryRenderTime() const
|
|||
return m_renderTime;
|
||||
}
|
||||
|
||||
bool X11WindowedQPainterCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
bool X11WindowedQPainterCursorLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
|
||||
m_output->cursor()->update(m_buffer, hotspot());
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
X11WindowedQPainterPrimaryLayer(X11WindowedOutput *output, X11WindowedQPainterBackend *backend);
|
||||
~X11WindowedQPainterPrimaryLayer() override;
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
@ -58,8 +58,8 @@ class X11WindowedQPainterCursorLayer : public OutputLayer
|
|||
public:
|
||||
explicit X11WindowedQPainterCursorLayer(X11WindowedOutput *output);
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::optional<OutputLayerBeginFrameInfo> doBeginFrame() override;
|
||||
bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
std::chrono::nanoseconds queryRenderTime() const override;
|
||||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
|
|
|
@ -256,6 +256,21 @@ void WaylandCompositor::stop()
|
|||
Q_EMIT compositingToggled(false);
|
||||
}
|
||||
|
||||
static QRect centerBuffer(const QSizeF &bufferSize, const QSize &modeSize)
|
||||
{
|
||||
const double widthScale = bufferSize.width() / double(modeSize.width());
|
||||
const double heightScale = bufferSize.height() / double(modeSize.height());
|
||||
if (widthScale > heightScale) {
|
||||
const QSize size = (bufferSize / widthScale).toSize();
|
||||
const uint32_t yOffset = (modeSize.height() - size.height()) / 2;
|
||||
return QRect(QPoint(0, yOffset), size);
|
||||
} else {
|
||||
const QSize size = (bufferSize / heightScale).toSize();
|
||||
const uint32_t xOffset = (modeSize.width() - size.width()) / 2;
|
||||
return QRect(QPoint(xOffset, 0), size);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandCompositor::composite(RenderLoop *renderLoop)
|
||||
{
|
||||
if (m_backend->checkGraphicsReset()) {
|
||||
|
@ -305,6 +320,7 @@ void WaylandCompositor::composite(RenderLoop *renderLoop)
|
|||
return sublayer->isVisible();
|
||||
});
|
||||
if (scanoutPossible) {
|
||||
primaryLayer->setTargetRect(centerBuffer(output->transform().map(scanoutCandidate->size()), output->modeSize()));
|
||||
directScanout = primaryLayer->attemptScanout(scanoutCandidate);
|
||||
}
|
||||
} else {
|
||||
|
@ -312,6 +328,7 @@ void WaylandCompositor::composite(RenderLoop *renderLoop)
|
|||
}
|
||||
|
||||
if (!directScanout) {
|
||||
primaryLayer->setTargetRect(QRect(QPoint(0, 0), output->modeSize()));
|
||||
if (auto beginInfo = primaryLayer->beginFrame()) {
|
||||
auto &[renderTarget, repaint] = beginInfo.value();
|
||||
|
||||
|
@ -392,9 +409,8 @@ void WaylandCompositor::addOutput(Output *output)
|
|||
bufferSize = *fixedSize;
|
||||
nativeCursorRect = output->transform().map(QRectF(outputLocalRect.topLeft() * output->scale(), bufferSize), output->pixelSize());
|
||||
}
|
||||
outputLayer->setPosition(nativeCursorRect.topLeft());
|
||||
outputLayer->setHotspot(output->transform().map(cursor->hotspot() * output->scale(), bufferSize));
|
||||
outputLayer->setSize(bufferSize);
|
||||
outputLayer->setTargetRect(QRect(nativeCursorRect.topLeft().toPoint(), bufferSize));
|
||||
if (auto beginInfo = outputLayer->beginFrame()) {
|
||||
const RenderTarget &renderTarget = beginInfo->renderTarget;
|
||||
|
||||
|
@ -437,8 +453,8 @@ void WaylandCompositor::addOutput(Output *output)
|
|||
if (outputLayer) {
|
||||
if (outputLayer->isEnabled()) {
|
||||
const QRectF nativeCursorRect = output->transform()
|
||||
.map(QRectF(outputLocalRect.topLeft() * output->scale(), outputLayer->size()), output->pixelSize());
|
||||
outputLayer->setPosition(nativeCursorRect.topLeft());
|
||||
.map(QRectF(outputLocalRect.topLeft() * output->scale(), outputLayer->targetRect().size()), output->pixelSize());
|
||||
outputLayer->setTargetRect(QRect(nativeCursorRect.topLeft().toPoint(), outputLayer->targetRect().size()));
|
||||
hardwareCursor = output->updateCursorLayer();
|
||||
} else if (!cursorLayer->isVisible() && !forceSoftwareCursor) {
|
||||
// this is for the case that the cursor wasn't visible because it was on a different output before
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
OutputLayer::OutputLayer(QObject *parent)
|
||||
: QObject(parent)
|
||||
OutputLayer::OutputLayer(Output *output)
|
||||
: m_output(output)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,16 +37,6 @@ void OutputLayer::setHotspot(const QPointF &hotspot)
|
|||
m_hotspot = hotspot;
|
||||
}
|
||||
|
||||
QSizeF OutputLayer::size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void OutputLayer::setSize(const QSizeF &size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
std::optional<QSize> OutputLayer::fixedSize() const
|
||||
{
|
||||
return std::nullopt;
|
||||
|
@ -72,7 +62,7 @@ bool OutputLayer::needsRepaint() const
|
|||
return !m_repaints.isEmpty();
|
||||
}
|
||||
|
||||
bool OutputLayer::doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color)
|
||||
bool OutputLayer::doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -97,7 +87,11 @@ bool OutputLayer::attemptScanout(SurfaceItem *surfaceItem)
|
|||
surfaceItem->setScanoutHint(scanoutDevice(), supportedDrmFormats());
|
||||
return false;
|
||||
}
|
||||
const bool ret = doAttemptScanout(buffer, surfaceItem->bufferSourceBox(), surfaceItem->destinationSize(), surfaceItem->bufferTransform(), surfaceItem->colorDescription());
|
||||
m_sourceRect = surfaceItem->bufferSourceBox();
|
||||
m_bufferTransform = surfaceItem->bufferTransform();
|
||||
const auto desiredTransform = m_output ? m_output->transform() : OutputTransform::Kind::Normal;
|
||||
m_offloadTransform = m_bufferTransform.combine(desiredTransform.inverted());
|
||||
const bool ret = doAttemptScanout(buffer, surfaceItem->colorDescription());
|
||||
if (ret) {
|
||||
surfaceItem->resetDamage();
|
||||
// ensure the pixmap is updated when direct scanout ends
|
||||
|
@ -106,6 +100,19 @@ bool OutputLayer::attemptScanout(SurfaceItem *surfaceItem)
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::optional<OutputLayerBeginFrameInfo> OutputLayer::beginFrame()
|
||||
{
|
||||
m_sourceRect = QRectF(QPointF(0, 0), m_targetRect.size());
|
||||
m_bufferTransform = m_output ? m_output->transform() : OutputTransform::Kind::Normal;
|
||||
m_offloadTransform = OutputTransform::Kind::Normal;
|
||||
return doBeginFrame();
|
||||
}
|
||||
|
||||
bool OutputLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
return doEndFrame(renderedRegion, damagedRegion);
|
||||
}
|
||||
|
||||
void OutputLayer::notifyNoScanoutCandidate()
|
||||
{
|
||||
if (m_scanoutCandidate) {
|
||||
|
@ -114,16 +121,6 @@ void OutputLayer::notifyNoScanoutCandidate()
|
|||
}
|
||||
}
|
||||
|
||||
void OutputLayer::setPosition(const QPointF &position)
|
||||
{
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
QPointF OutputLayer::position() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void OutputLayer::setEnabled(bool enable)
|
||||
{
|
||||
m_enabled = enable;
|
||||
|
@ -134,6 +131,36 @@ bool OutputLayer::isEnabled() const
|
|||
return m_enabled;
|
||||
}
|
||||
|
||||
QRectF OutputLayer::sourceRect() const
|
||||
{
|
||||
return m_sourceRect;
|
||||
}
|
||||
|
||||
void OutputLayer::setSourceRect(const QRectF &rect)
|
||||
{
|
||||
m_sourceRect = rect;
|
||||
}
|
||||
|
||||
OutputTransform OutputLayer::offloadTransform() const
|
||||
{
|
||||
return m_offloadTransform;
|
||||
}
|
||||
|
||||
OutputTransform OutputLayer::bufferTransform() const
|
||||
{
|
||||
return m_bufferTransform;
|
||||
}
|
||||
|
||||
QRect OutputLayer::targetRect() const
|
||||
{
|
||||
return m_targetRect;
|
||||
}
|
||||
|
||||
void OutputLayer::setTargetRect(const QRect &rect)
|
||||
{
|
||||
m_targetRect = rect;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "moc_outputlayer.cpp"
|
||||
|
|
|
@ -32,7 +32,7 @@ class KWIN_EXPORT OutputLayer : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OutputLayer(QObject *parent = nullptr);
|
||||
explicit OutputLayer(Output *output);
|
||||
|
||||
qreal scale() const;
|
||||
void setScale(qreal scale);
|
||||
|
@ -40,8 +40,6 @@ public:
|
|||
QPointF hotspot() const;
|
||||
void setHotspot(const QPointF &hotspot);
|
||||
|
||||
QSizeF size() const;
|
||||
void setSize(const QSizeF &size);
|
||||
/**
|
||||
* For most drm drivers, the buffer used for the cursor has to have a fixed size.
|
||||
* If such a fixed size is required by the backend, this function should return it
|
||||
|
@ -53,20 +51,14 @@ public:
|
|||
void addRepaint(const QRegion ®ion);
|
||||
bool needsRepaint() const;
|
||||
|
||||
/**
|
||||
* @arg position in device coordinates
|
||||
*/
|
||||
void setPosition(const QPointF &position);
|
||||
QPointF position() const;
|
||||
|
||||
/**
|
||||
* Enables or disables this layer. Note that disabling the primary layer will cause problems
|
||||
*/
|
||||
void setEnabled(bool enable);
|
||||
bool isEnabled() const;
|
||||
|
||||
virtual std::optional<OutputLayerBeginFrameInfo> beginFrame() = 0;
|
||||
virtual bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) = 0;
|
||||
std::optional<OutputLayerBeginFrameInfo> beginFrame();
|
||||
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
|
||||
|
||||
/**
|
||||
* Tries to import the newest buffer of the surface for direct scanout
|
||||
|
@ -87,16 +79,40 @@ public:
|
|||
virtual DrmDevice *scanoutDevice() const = 0;
|
||||
virtual QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the source rect this output layer should sample from, in buffer local coordinates
|
||||
*/
|
||||
QRectF sourceRect() const;
|
||||
void setSourceRect(const QRectF &rect);
|
||||
/**
|
||||
* Returns the target rect this output layer should be shown at, in device coordinates
|
||||
*/
|
||||
QRect targetRect() const;
|
||||
void setTargetRect(const QRect &rect);
|
||||
/**
|
||||
* Returns the transform this layer will apply to content passed to it
|
||||
*/
|
||||
OutputTransform offloadTransform() const;
|
||||
/**
|
||||
* Returns the transform a buffer passed into this layer already has
|
||||
*/
|
||||
OutputTransform bufferTransform() const;
|
||||
|
||||
protected:
|
||||
virtual bool doAttemptScanout(GraphicsBuffer *buffer, const QRectF &sourceRect, const QSizeF &targetSize, OutputTransform transform, const ColorDescription &color);
|
||||
virtual bool doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color);
|
||||
virtual std::optional<OutputLayerBeginFrameInfo> doBeginFrame() = 0;
|
||||
virtual bool doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) = 0;
|
||||
|
||||
QRegion m_repaints;
|
||||
QPointF m_hotspot;
|
||||
QPointF m_position;
|
||||
QSizeF m_size;
|
||||
QRectF m_sourceRect;
|
||||
QRect m_targetRect;
|
||||
qreal m_scale = 1.0;
|
||||
bool m_enabled = false;
|
||||
OutputTransform m_offloadTransform = OutputTransform::Kind::Normal;
|
||||
OutputTransform m_bufferTransform = OutputTransform::Kind::Normal;
|
||||
QPointer<SurfaceItem> m_scanoutCandidate;
|
||||
Output *const m_output;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
Loading…
Reference in a new issue