Port screenId based rendering methods to AbstractOutput
This commit is contained in:
parent
e6cab81b53
commit
1be65e818c
42 changed files with 349 additions and 480 deletions
|
@ -393,16 +393,6 @@ void Compositor::handleOutputDisabled(AbstractOutput *output)
|
|||
unregisterRenderLoop(output->renderLoop());
|
||||
}
|
||||
|
||||
int Compositor::screenForRenderLoop(RenderLoop *renderLoop) const
|
||||
{
|
||||
Q_ASSERT(m_renderLoops.contains(renderLoop));
|
||||
AbstractOutput *output = m_renderLoops.value(renderLoop);
|
||||
if (!output) {
|
||||
return -1;
|
||||
}
|
||||
return kwinApp()->platform()->enabledOutputs().indexOf(output);
|
||||
}
|
||||
|
||||
void Compositor::scheduleRepaint()
|
||||
{
|
||||
for (auto it = m_renderLoops.constBegin(); it != m_renderLoops.constEnd(); ++it) {
|
||||
|
@ -585,9 +575,9 @@ void Compositor::handleFrameRequested(RenderLoop *renderLoop)
|
|||
|
||||
void Compositor::composite(RenderLoop *renderLoop)
|
||||
{
|
||||
const int screenId = screenForRenderLoop(renderLoop);
|
||||
const auto &output = m_renderLoops[renderLoop];
|
||||
|
||||
fTraceDuration("Paint (", screens()->name(screenId), ")");
|
||||
fTraceDuration("Paint (", output ? output->name() : QStringLiteral("screens"), ")");
|
||||
|
||||
// Create a list of all windows in the stacking order
|
||||
QList<Toplevel *> windows = Workspace::self()->xStackingOrder();
|
||||
|
@ -617,10 +607,10 @@ void Compositor::composite(RenderLoop *renderLoop)
|
|||
}
|
||||
}
|
||||
|
||||
const QRegion repaints = m_scene->repaints(screenId);
|
||||
m_scene->resetRepaints(screenId);
|
||||
const QRegion repaints = m_scene->repaints(output);
|
||||
m_scene->resetRepaints(output);
|
||||
|
||||
m_scene->paint(screenId, repaints, windows, renderLoop);
|
||||
m_scene->paint(output, repaints, windows, renderLoop);
|
||||
|
||||
if (waylandServer()) {
|
||||
const std::chrono::milliseconds frameTime =
|
||||
|
@ -634,7 +624,7 @@ void Compositor::composite(RenderLoop *renderLoop)
|
|||
!(window->isLockScreen() || window->isInputMethod())) {
|
||||
continue;
|
||||
}
|
||||
if (!window->isOnScreen(screenId)) {
|
||||
if (!window->isOnOutput(output)) {
|
||||
continue;
|
||||
}
|
||||
if (auto surface = window->surface()) {
|
||||
|
|
|
@ -130,7 +130,6 @@ private:
|
|||
void releaseCompositorSelection();
|
||||
void deleteUnusedSupportProperties();
|
||||
|
||||
int screenForRenderLoop(RenderLoop *renderLoop) const;
|
||||
void registerRenderLoop(RenderLoop *renderLoop, AbstractOutput *output);
|
||||
void unregisterRenderLoop(RenderLoop *renderLoop);
|
||||
|
||||
|
|
46
src/item.cpp
46
src/item.cpp
|
@ -19,20 +19,13 @@ namespace KWin
|
|||
Item::Item(Item *parent)
|
||||
{
|
||||
setParentItem(parent);
|
||||
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
connect(kwinApp()->platform(), &Platform::outputEnabled, this, &Item::reallocRepaints);
|
||||
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Item::reallocRepaints);
|
||||
}
|
||||
reallocRepaints();
|
||||
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Item::removeRepaints);
|
||||
}
|
||||
|
||||
Item::~Item()
|
||||
{
|
||||
setParentItem(nullptr);
|
||||
|
||||
for (int i = 0; i < m_repaints.count(); ++i) {
|
||||
const QRegion dirty = repaints(i);
|
||||
for (const auto &dirty : qAsConst(m_repaints)) {
|
||||
if (!dirty.isEmpty()) {
|
||||
Compositor::self()->addRepaint(dirty);
|
||||
}
|
||||
|
@ -262,19 +255,15 @@ void Item::scheduleRepaintInternal(const QRegion ®ion)
|
|||
const QRegion globalRegion = mapToGlobal(region);
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
|
||||
if (m_repaints.count() != outputs.count()) {
|
||||
return; // Repaints haven't been reallocated yet, do nothing.
|
||||
}
|
||||
for (int screenId = 0; screenId < m_repaints.count(); ++screenId) {
|
||||
AbstractOutput *output = outputs[screenId];
|
||||
for (const auto &output : outputs) {
|
||||
const QRegion dirtyRegion = globalRegion & output->geometry();
|
||||
if (!dirtyRegion.isEmpty()) {
|
||||
m_repaints[screenId] += dirtyRegion;
|
||||
m_repaints[output] += dirtyRegion;
|
||||
output->renderLoop()->scheduleRepaint();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_repaints[0] += globalRegion;
|
||||
m_repaints[nullptr] += globalRegion;
|
||||
kwinApp()->platform()->renderLoop()->scheduleRepaint();
|
||||
}
|
||||
}
|
||||
|
@ -319,32 +308,19 @@ WindowQuadList Item::quads() const
|
|||
return m_quads.value();
|
||||
}
|
||||
|
||||
QRegion Item::repaints(int screen) const
|
||||
QRegion Item::repaints(AbstractOutput *output) const
|
||||
{
|
||||
Q_ASSERT(!m_repaints.isEmpty());
|
||||
const int index = screen != -1 ? screen : 0;
|
||||
if (m_repaints[index] == infiniteRegion()) {
|
||||
return QRect(QPoint(0, 0), screens()->size());
|
||||
}
|
||||
return m_repaints[index];
|
||||
return m_repaints.value(output, QRect(QPoint(0, 0), screens()->size()));
|
||||
}
|
||||
|
||||
void Item::resetRepaints(int screen)
|
||||
void Item::resetRepaints(AbstractOutput *output)
|
||||
{
|
||||
Q_ASSERT(!m_repaints.isEmpty());
|
||||
const int index = screen != -1 ? screen : 0;
|
||||
m_repaints[index] = QRegion();
|
||||
m_repaints.insert(output, QRegion());
|
||||
}
|
||||
|
||||
void Item::reallocRepaints()
|
||||
void Item::removeRepaints(AbstractOutput *output)
|
||||
{
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
m_repaints.resize(kwinApp()->platform()->enabledOutputs().count());
|
||||
} else {
|
||||
m_repaints.resize(1);
|
||||
}
|
||||
|
||||
m_repaints.fill(infiniteRegion());
|
||||
m_repaints.remove(output);
|
||||
}
|
||||
|
||||
bool Item::isVisible() const
|
||||
|
|
10
src/item.h
10
src/item.h
|
@ -17,6 +17,8 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
class AbstractOutput;
|
||||
|
||||
/**
|
||||
* The Item class is the base class for items in the scene.
|
||||
*/
|
||||
|
@ -85,8 +87,8 @@ public:
|
|||
|
||||
void scheduleRepaint(const QRegion ®ion);
|
||||
void scheduleFrame();
|
||||
QRegion repaints(int screen) const;
|
||||
void resetRepaints(int screen);
|
||||
QRegion repaints(AbstractOutput *output) const;
|
||||
void resetRepaints(AbstractOutput *output);
|
||||
|
||||
WindowQuadList quads() const;
|
||||
virtual void preprocess();
|
||||
|
@ -116,11 +118,11 @@ private:
|
|||
void removeChild(Item *item);
|
||||
void updateBoundingRect();
|
||||
void scheduleRepaintInternal(const QRegion ®ion);
|
||||
void reallocRepaints();
|
||||
void markSortedChildItemsDirty();
|
||||
|
||||
bool computeEffectiveVisibility() const;
|
||||
void updateEffectiveVisibility();
|
||||
void removeRepaints(AbstractOutput *output);
|
||||
|
||||
QPointer<Item> m_parentItem;
|
||||
QList<Item *> m_childItems;
|
||||
|
@ -131,7 +133,7 @@ private:
|
|||
int m_z = 0;
|
||||
bool m_visible = true;
|
||||
bool m_effectiveVisible = true;
|
||||
QVector<QRegion> m_repaints;
|
||||
QMap<AbstractOutput *, QRegion> m_repaints;
|
||||
mutable std::optional<WindowQuadList> m_quads;
|
||||
mutable std::optional<QList<Item *>> m_sortedChildItems;
|
||||
};
|
||||
|
|
|
@ -40,9 +40,9 @@ OverlayWindow* OpenGLBackend::overlayWindow() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool OpenGLBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
||||
bool OpenGLBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(surfaceItem)
|
||||
return false;
|
||||
}
|
||||
|
@ -66,16 +66,16 @@ QSharedPointer<KWin::GLTexture> OpenGLBackend::textureForOutput(AbstractOutput*
|
|||
return {};
|
||||
}
|
||||
|
||||
void OpenGLBackend::aboutToStartPainting(int screenId, const QRegion &damage)
|
||||
void OpenGLBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(damage)
|
||||
}
|
||||
|
||||
|
||||
bool OpenGLBackend::directScanoutAllowed(int screen) const
|
||||
bool OpenGLBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
Q_UNUSED(screen);
|
||||
Q_UNUSED(output);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,16 +60,16 @@ public:
|
|||
*
|
||||
* @p damage contains the reported damage as suggested by windows and effects on prepaint calls.
|
||||
*/
|
||||
virtual void aboutToStartPainting(int screenId, const QRegion &damage);
|
||||
virtual void aboutToStartPainting(AbstractOutput *output, const QRegion &damage);
|
||||
virtual bool makeCurrent() = 0;
|
||||
virtual void doneCurrent() = 0;
|
||||
virtual QRegion beginFrame(int screenId) = 0;
|
||||
virtual void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) = 0;
|
||||
virtual QRegion beginFrame(AbstractOutput *output) = 0;
|
||||
virtual void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) = 0;
|
||||
/**
|
||||
* Tries to directly scan out a surface to the screen)
|
||||
* @return if the scanout fails (or is not supported on the specified screen)
|
||||
*/
|
||||
virtual bool scanout(int screenId, SurfaceItem *surfaceItem);
|
||||
virtual bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem);
|
||||
|
||||
/**
|
||||
* @brief Returns the OverlayWindow used by the backend.
|
||||
|
@ -121,7 +121,7 @@ public:
|
|||
{
|
||||
return m_haveNativeFence;
|
||||
}
|
||||
virtual bool directScanoutAllowed(int screen) const;
|
||||
virtual bool directScanoutAllowed(AbstractOutput *output) const;
|
||||
|
||||
/**
|
||||
* The backend specific extensions (e.g. EGL/GLX extensions).
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace KWin
|
|||
class PlatformSurfaceTexture;
|
||||
class SurfacePixmapInternal;
|
||||
class SurfacePixmapWayland;
|
||||
class AbstractOutput;
|
||||
|
||||
class QPainterBackend : public QObject
|
||||
{
|
||||
|
@ -33,8 +34,8 @@ public:
|
|||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap);
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap);
|
||||
|
||||
virtual void endFrame(int screenId, const QRegion &damage) = 0;
|
||||
virtual QRegion beginFrame(int screenId) = 0;
|
||||
virtual void endFrame(AbstractOutput *output, const QRegion &damage) = 0;
|
||||
virtual QRegion beginFrame(AbstractOutput *output) = 0;
|
||||
/**
|
||||
* @brief Whether the creation of the Backend failed.
|
||||
*
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
* @param screenId The id of the screen as used in Screens
|
||||
* @todo Get a better identifier for screen then a counter variable
|
||||
*/
|
||||
virtual QImage *bufferForScreen(int screenId) = 0;
|
||||
virtual QImage *bufferForScreen(AbstractOutput *output) = 0;
|
||||
|
||||
protected:
|
||||
QPainterBackend();
|
||||
|
|
|
@ -26,7 +26,7 @@ class AbstractEglDrmBackend : public AbstractEglBackend
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual int screenCount() const = 0;
|
||||
virtual bool hasOutput(AbstractOutput *output) const = 0;
|
||||
virtual bool addOutput(DrmAbstractOutput *output) = 0;
|
||||
virtual void removeOutput(DrmAbstractOutput *output) = 0;
|
||||
virtual bool swapBuffers(DrmAbstractOutput *output, const QRegion &dirty) {
|
||||
|
|
|
@ -140,16 +140,15 @@ bool EglGbmBackend::initRenderingContext()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EglGbmBackend::resetOutput(Output &output, DrmAbstractOutput *drmOutput)
|
||||
bool EglGbmBackend::resetOutput(Output &output)
|
||||
{
|
||||
output.output = drmOutput;
|
||||
const QSize size = drmOutput->sourceSize();
|
||||
QVector<uint64_t> modifiers = drmOutput->supportedModifiers(m_gbmFormat);
|
||||
const QSize size = output.output->sourceSize();
|
||||
QVector<uint64_t> modifiers = output.output->supportedModifiers(m_gbmFormat);
|
||||
|
||||
QSharedPointer<GbmSurface> gbmSurface;
|
||||
if (modifiers.isEmpty()) {
|
||||
int flags = GBM_BO_USE_RENDERING;
|
||||
if (drmOutput->gpu() == m_gpu) {
|
||||
if (output.output->gpu() == m_gpu) {
|
||||
flags |= GBM_BO_USE_SCANOUT;
|
||||
} else {
|
||||
flags |= GBM_BO_USE_LINEAR;
|
||||
|
@ -173,7 +172,7 @@ bool EglGbmBackend::resetOutput(Output &output, DrmAbstractOutput *drmOutput)
|
|||
output.current = {};
|
||||
output.current.gbmSurface = gbmSurface;
|
||||
|
||||
if (size == drmOutput->pixelSize()) {
|
||||
if (size == output.output->pixelSize()) {
|
||||
output.current.shadowBuffer = nullptr;
|
||||
} else {
|
||||
makeContextCurrent(output.current);
|
||||
|
@ -187,58 +186,37 @@ bool EglGbmBackend::resetOutput(Output &output, DrmAbstractOutput *drmOutput)
|
|||
|
||||
bool EglGbmBackend::addOutput(DrmAbstractOutput *drmOutput)
|
||||
{
|
||||
Output newOutput;
|
||||
newOutput.output = drmOutput;
|
||||
if (isPrimary()) {
|
||||
Output newOutput;
|
||||
if (!resetOutput(newOutput, drmOutput)) {
|
||||
if (!resetOutput(newOutput)) {
|
||||
return false;
|
||||
}
|
||||
if (drmOutput->gpu() == m_gpu) {
|
||||
m_outputs << newOutput;
|
||||
} else {
|
||||
m_secondaryGpuOutputs << newOutput;
|
||||
}
|
||||
} else {
|
||||
Output newOutput;
|
||||
newOutput.output = drmOutput;
|
||||
if (!renderingBackend()->addOutput(drmOutput)) {
|
||||
return false;
|
||||
}
|
||||
m_outputs << newOutput;
|
||||
}
|
||||
m_outputs.insert(drmOutput, newOutput);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EglGbmBackend::removeOutput(DrmAbstractOutput *drmOutput)
|
||||
{
|
||||
QVector<Output> &outputs = drmOutput->gpu() == m_gpu ? m_outputs : m_secondaryGpuOutputs;
|
||||
auto it = std::find_if(outputs.begin(), outputs.end(),
|
||||
[drmOutput] (const Output &output) {
|
||||
return output.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == outputs.end()) {
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
if (isPrimary()) {
|
||||
// shadow buffer needs context current for destruction
|
||||
makeCurrent();
|
||||
} else {
|
||||
renderingBackend()->removeOutput((*it).output);
|
||||
renderingBackend()->removeOutput(drmOutput);
|
||||
}
|
||||
outputs.erase(it);
|
||||
m_outputs.remove(drmOutput);
|
||||
}
|
||||
|
||||
bool EglGbmBackend::swapBuffers(DrmAbstractOutput *drmOutput, const QRegion &dirty)
|
||||
{
|
||||
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
|
||||
[drmOutput] (const Output &output) {
|
||||
return output.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_secondaryGpuOutputs.end()) {
|
||||
return false;
|
||||
}
|
||||
Output &output = *it;
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
Output &output = m_outputs[drmOutput];
|
||||
renderFramebufferToSurface(output);
|
||||
if (output.current.gbmSurface->swapBuffers()) {
|
||||
cleanupRenderData(output.old);
|
||||
|
@ -251,15 +229,8 @@ bool EglGbmBackend::swapBuffers(DrmAbstractOutput *drmOutput, const QRegion &dir
|
|||
|
||||
bool EglGbmBackend::exportFramebuffer(DrmAbstractOutput *drmOutput, void *data, const QSize &size, uint32_t stride)
|
||||
{
|
||||
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
|
||||
[drmOutput] (const Output &output) {
|
||||
return output.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_secondaryGpuOutputs.end()) {
|
||||
return false;
|
||||
}
|
||||
auto bo = it->current.gbmSurface->currentBuffer();
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
auto bo = m_outputs[drmOutput].current.gbmSurface->currentBuffer();
|
||||
if (!bo->map(GBM_BO_TRANSFER_READ)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -272,15 +243,8 @@ bool EglGbmBackend::exportFramebuffer(DrmAbstractOutput *drmOutput, void *data,
|
|||
|
||||
bool EglGbmBackend::exportFramebufferAsDmabuf(DrmAbstractOutput *drmOutput, int *fds, int *strides, int *offsets, uint32_t *num_fds, uint32_t *format, uint64_t *modifier)
|
||||
{
|
||||
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
|
||||
[drmOutput] (const Output &output) {
|
||||
return output.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_secondaryGpuOutputs.end()) {
|
||||
return -1;
|
||||
}
|
||||
auto bo = it->current.gbmSurface->currentBuffer()->getBo();
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
auto bo = m_outputs[drmOutput].current.gbmSurface->currentBuffer()->getBo();
|
||||
if (gbm_bo_get_handle_for_plane(bo, 0).s32 != -1) {
|
||||
*num_fds = gbm_bo_get_plane_count(bo);
|
||||
for (uint32_t i = 0; i < *num_fds; i++) {
|
||||
|
@ -312,15 +276,8 @@ bool EglGbmBackend::exportFramebufferAsDmabuf(DrmAbstractOutput *drmOutput, int
|
|||
|
||||
QRegion EglGbmBackend::beginFrameForSecondaryGpu(DrmAbstractOutput *drmOutput)
|
||||
{
|
||||
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
|
||||
[drmOutput] (const Output &output) {
|
||||
return output.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_secondaryGpuOutputs.end()) {
|
||||
return QRegion();
|
||||
}
|
||||
return prepareRenderingForOutput(*it);
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
return prepareRenderingForOutput(m_outputs[drmOutput]);
|
||||
}
|
||||
|
||||
QSharedPointer<DrmBuffer> EglGbmBackend::importFramebuffer(Output &output, const QRegion &dirty) const
|
||||
|
@ -489,10 +446,11 @@ static QVector<EGLint> regionToRects(const QRegion ®ion, AbstractWaylandOutpu
|
|||
return rects;
|
||||
}
|
||||
|
||||
void EglGbmBackend::aboutToStartPainting(int screenId, const QRegion &damagedRegion)
|
||||
void EglGbmBackend::aboutToStartPainting(AbstractOutput *drmOutput, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT_X(screenId != -1, "aboutToStartPainting", "not using per screen rendering");
|
||||
const Output &output = m_outputs.at(screenId);
|
||||
Q_ASSERT_X(drmOutput, "aboutToStartPainting", "not using per screen rendering");
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
const Output &output = m_outputs[drmOutput];
|
||||
if (output.current.bufferAge > 0 && !damagedRegion.isEmpty() && supportsPartialUpdate()) {
|
||||
const QRegion region = damagedRegion & output.output->geometry();
|
||||
|
||||
|
@ -521,9 +479,10 @@ void EglGbmBackend::setViewport(const Output &output) const
|
|||
glViewport(0, 0, size.width(), size.height());
|
||||
}
|
||||
|
||||
QRegion EglGbmBackend::beginFrame(int screenId)
|
||||
QRegion EglGbmBackend::beginFrame(AbstractOutput *drmOutput)
|
||||
{
|
||||
Output &output = m_outputs[screenId];
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
Output &output = m_outputs[drmOutput];
|
||||
if (output.surfaceInterface) {
|
||||
qCDebug(KWIN_DRM) << "Direct scanout stopped on output" << output.output->name();
|
||||
}
|
||||
|
@ -562,7 +521,7 @@ QRegion EglGbmBackend::prepareRenderingForOutput(Output &output)
|
|||
output.current = output.old;
|
||||
output.old = {};
|
||||
} else {
|
||||
resetOutput(output, output.output);
|
||||
resetOutput(output);
|
||||
}
|
||||
}
|
||||
makeContextCurrent(output.current);
|
||||
|
@ -580,9 +539,10 @@ QRegion EglGbmBackend::prepareRenderingForOutput(Output &output)
|
|||
return geometry;
|
||||
}
|
||||
|
||||
QSharedPointer<DrmBuffer> EglGbmBackend::endFrameWithBuffer(int screenId, const QRegion &dirty)
|
||||
QSharedPointer<DrmBuffer> EglGbmBackend::endFrameWithBuffer(AbstractOutput *drmOutput, const QRegion &dirty)
|
||||
{
|
||||
Output &output = m_outputs[screenId];
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
Output &output = m_outputs[drmOutput];
|
||||
if (isPrimary()) {
|
||||
renderFramebufferToSurface(output);
|
||||
auto buffer = output.current.gbmSurface->swapBuffersForDrm();
|
||||
|
@ -595,16 +555,17 @@ QSharedPointer<DrmBuffer> EglGbmBackend::endFrameWithBuffer(int screenId, const
|
|||
}
|
||||
}
|
||||
|
||||
void EglGbmBackend::endFrame(int screenId, const QRegion &renderedRegion,
|
||||
void EglGbmBackend::endFrame(AbstractOutput *drmOutput, const QRegion &renderedRegion,
|
||||
const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
Q_UNUSED(renderedRegion)
|
||||
|
||||
Output &output = m_outputs[screenId];
|
||||
Output &output = m_outputs[drmOutput];
|
||||
cleanupRenderData(output.old);
|
||||
|
||||
const QRegion dirty = damagedRegion.intersected(output.output->geometry());
|
||||
QSharedPointer<DrmBuffer> buffer = endFrameWithBuffer(screenId, dirty);
|
||||
QSharedPointer<DrmBuffer> buffer = endFrameWithBuffer(drmOutput, dirty);
|
||||
if (!buffer || !output.output->present(buffer, dirty)) {
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(output.output->renderLoop());
|
||||
renderLoopPrivate->notifyFrameFailed();
|
||||
|
@ -620,8 +581,9 @@ void EglGbmBackend::updateBufferAge(Output &output, const QRegion &dirty)
|
|||
}
|
||||
}
|
||||
|
||||
bool EglGbmBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
||||
bool EglGbmBackend::scanout(AbstractOutput *drmOutput, SurfaceItem *surfaceItem)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
SurfaceItemWayland *item = qobject_cast<SurfaceItemWayland *>(surfaceItem);
|
||||
if (!item) {
|
||||
return false;
|
||||
|
@ -636,7 +598,7 @@ bool EglGbmBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
|||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
Output &output = m_outputs[screenId];
|
||||
Output &output = m_outputs[drmOutput];
|
||||
if (buffer->size() != output.output->modeSize()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -714,41 +676,21 @@ bool EglGbmBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
|||
|
||||
QSharedPointer<DrmBuffer> EglGbmBackend::renderTestFrame(DrmAbstractOutput *output)
|
||||
{
|
||||
for (int i = 0; i < m_outputs.count(); i++) {
|
||||
if (m_outputs[i].output == output) {
|
||||
beginFrame(i);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
return endFrameWithBuffer(i, output->geometry());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
beginFrame(output);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
return endFrameWithBuffer(output, output->geometry());
|
||||
}
|
||||
|
||||
QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *abstractOutput) const
|
||||
QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output) const
|
||||
{
|
||||
auto itOutput = std::find_if(m_outputs.begin(), m_outputs.end(),
|
||||
[abstractOutput] (const auto &output) {
|
||||
return output.output == abstractOutput;
|
||||
}
|
||||
);
|
||||
if (itOutput == m_outputs.end()) {
|
||||
itOutput = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
|
||||
[abstractOutput] (const auto &output) {
|
||||
return output.output == abstractOutput;
|
||||
}
|
||||
);
|
||||
if (itOutput == m_secondaryGpuOutputs.end()) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
DrmAbstractOutput *drmOutput = itOutput->output;
|
||||
if (itOutput->current.shadowBuffer) {
|
||||
const auto glTexture = QSharedPointer<KWin::GLTexture>::create(itOutput->current.shadowBuffer->texture(), GL_RGBA8, drmOutput->pixelSize());
|
||||
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());
|
||||
glTexture->setYInverted(true);
|
||||
return glTexture;
|
||||
}
|
||||
GbmBuffer *gbmBuffer = itOutput->current.gbmSurface->currentBuffer().get();
|
||||
GbmBuffer *gbmBuffer = renderOutput.current.gbmSurface->currentBuffer().get();
|
||||
if (!gbmBuffer) {
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!";
|
||||
return {};
|
||||
|
@ -759,12 +701,17 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *abstra
|
|||
return {};
|
||||
}
|
||||
|
||||
return QSharedPointer<EGLImageTexture>::create(eglDisplay(), image, GL_RGBA8, drmOutput->modeSize());
|
||||
return QSharedPointer<EGLImageTexture>::create(eglDisplay(), image, GL_RGBA8, static_cast<DrmAbstractOutput*>(output)->modeSize());
|
||||
}
|
||||
|
||||
bool EglGbmBackend::directScanoutAllowed(int screen) const
|
||||
bool EglGbmBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
return !m_backend->usesSoftwareCursor() && !m_outputs[screen].output->directScanoutInhibited();
|
||||
return !m_backend->usesSoftwareCursor() && output->directScanoutInhibited();
|
||||
}
|
||||
|
||||
bool EglGbmBackend::hasOutput(AbstractOutput *output) const
|
||||
{
|
||||
return m_outputs.contains(output);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,17 +47,14 @@ public:
|
|||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
void init() override;
|
||||
bool scanout(int screenId, SurfaceItem *surfaceItem) override;
|
||||
bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem) override;
|
||||
|
||||
QSharedPointer<GLTexture> textureForOutput(AbstractOutput *requestedOutput) const override;
|
||||
|
||||
int screenCount() const override {
|
||||
return m_outputs.count();
|
||||
}
|
||||
|
||||
bool hasOutput(AbstractOutput *output) const override;
|
||||
bool addOutput(DrmAbstractOutput *output) override;
|
||||
void removeOutput(DrmAbstractOutput *output) override;
|
||||
bool swapBuffers(DrmAbstractOutput *output, const QRegion &dirty) override;
|
||||
|
@ -65,13 +62,13 @@ public:
|
|||
bool exportFramebufferAsDmabuf(DrmAbstractOutput *output, int *fds, int *strides, int *offsets, uint32_t *num_fds, uint32_t *format, uint64_t *modifier) override;
|
||||
QRegion beginFrameForSecondaryGpu(DrmAbstractOutput *output) override;
|
||||
|
||||
bool directScanoutAllowed(int screen) const override;
|
||||
bool directScanoutAllowed(AbstractOutput *output) const override;
|
||||
|
||||
QSharedPointer<DrmBuffer> renderTestFrame(DrmAbstractOutput *output) override;
|
||||
|
||||
protected:
|
||||
void cleanupSurfaces() override;
|
||||
void aboutToStartPainting(int screenId, const QRegion &damage) override;
|
||||
void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
bool initializeEgl();
|
||||
|
@ -99,7 +96,7 @@ private:
|
|||
};
|
||||
|
||||
bool doesRenderFit(DrmAbstractOutput *output, const Output::RenderData &render);
|
||||
bool resetOutput(Output &output, DrmAbstractOutput *drmOutput);
|
||||
bool resetOutput(Output &output);
|
||||
|
||||
bool makeContextCurrent(const Output::RenderData &output) const;
|
||||
void setViewport(const Output &output) const;
|
||||
|
@ -107,13 +104,12 @@ private:
|
|||
void renderFramebufferToSurface(Output &output);
|
||||
QRegion prepareRenderingForOutput(Output &output);
|
||||
QSharedPointer<DrmBuffer> importFramebuffer(Output &output, const QRegion &dirty) const;
|
||||
QSharedPointer<DrmBuffer> endFrameWithBuffer(int screenId, const QRegion &dirty);
|
||||
QSharedPointer<DrmBuffer> endFrameWithBuffer(AbstractOutput *output, const QRegion &dirty);
|
||||
void updateBufferAge(Output &output, const QRegion &dirty);
|
||||
|
||||
void cleanupRenderData(Output::RenderData &output);
|
||||
|
||||
QVector<Output> m_outputs;
|
||||
QVector<Output> m_secondaryGpuOutputs;
|
||||
QMap<AbstractOutput *, Output> m_outputs;
|
||||
uint32_t m_gbmFormat;
|
||||
|
||||
friend class EglGbmTexture;
|
||||
|
|
|
@ -57,28 +57,19 @@ void EglMultiBackend::init()
|
|||
m_initialized = true;
|
||||
}
|
||||
|
||||
QRegion EglMultiBackend::beginFrame(int screenId)
|
||||
QRegion EglMultiBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
int internalScreenId;
|
||||
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||||
Q_ASSERT(backend != nullptr);
|
||||
return backend->beginFrame(internalScreenId);
|
||||
return findBackend(output)->beginFrame(output);
|
||||
}
|
||||
|
||||
void EglMultiBackend::endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion)
|
||||
void EglMultiBackend::endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion)
|
||||
{
|
||||
int internalScreenId;
|
||||
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||||
Q_ASSERT(backend != nullptr);
|
||||
backend->endFrame(internalScreenId, damage, damagedRegion);
|
||||
findBackend(output)->endFrame(output, damage, damagedRegion);
|
||||
}
|
||||
|
||||
bool EglMultiBackend::scanout(int screenId, SurfaceItem *surfaceItem)
|
||||
bool EglMultiBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem)
|
||||
{
|
||||
int internalScreenId;
|
||||
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||||
Q_ASSERT(backend != nullptr);
|
||||
return backend->scanout(internalScreenId, surfaceItem);
|
||||
return findBackend(output)->scanout(output, surfaceItem);
|
||||
}
|
||||
|
||||
bool EglMultiBackend::makeCurrent()
|
||||
|
@ -107,26 +98,20 @@ QSharedPointer<GLTexture> EglMultiBackend::textureForOutput(AbstractOutput *requ
|
|||
return m_backends[0]->textureForOutput(requestedOutput);
|
||||
}
|
||||
|
||||
AbstractEglDrmBackend *EglMultiBackend::findBackend(int screenId, int& internalScreenId) const
|
||||
AbstractEglDrmBackend *EglMultiBackend::findBackend(AbstractOutput *output) const
|
||||
{
|
||||
int screens = 0;
|
||||
for (int i = 0; i < m_backends.count(); i++) {
|
||||
if (screenId < screens + m_backends[i]->screenCount()) {
|
||||
internalScreenId = screenId - screens;
|
||||
return m_backends[i];
|
||||
for (const auto &backend : qAsConst(m_backends)) {
|
||||
if (backend->hasOutput(output)) {
|
||||
return backend;
|
||||
}
|
||||
screens += m_backends[i]->screenCount();
|
||||
}
|
||||
qCDebug(KWIN_DRM) << "could not find backend!" << screenId << "/" << screens;
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EglMultiBackend::directScanoutAllowed(int screenId) const
|
||||
bool EglMultiBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
int internalScreenId;
|
||||
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||||
Q_ASSERT(backend != nullptr);
|
||||
return backend->directScanoutAllowed(internalScreenId);
|
||||
return findBackend(output)->directScanoutAllowed(output);
|
||||
}
|
||||
|
||||
void EglMultiBackend::addGpu(DrmGpu *gpu)
|
||||
|
|
|
@ -24,9 +24,9 @@ public:
|
|||
|
||||
void init() override;
|
||||
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
bool scanout(int screenId, SurfaceItem *surfaceItem) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem) override;
|
||||
|
||||
bool makeCurrent() override;
|
||||
void doneCurrent() override;
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
QSharedPointer<GLTexture> textureForOutput(AbstractOutput *requestedOutput) const override;
|
||||
|
||||
bool directScanoutAllowed(int screen) const override;
|
||||
bool directScanoutAllowed(AbstractOutput *output) const override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void addGpu(DrmGpu *gpu);
|
||||
|
@ -46,7 +46,7 @@ private:
|
|||
QVector<AbstractEglDrmBackend*> m_backends;
|
||||
bool m_initialized = false;
|
||||
|
||||
AbstractEglDrmBackend *findBackend(int screenId, int& internalScreenId) const;
|
||||
AbstractEglDrmBackend *findBackend(AbstractOutput *output) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -298,9 +298,9 @@ bool EglStreamBackend::initRenderingContext()
|
|||
return !m_outputs.isEmpty() && makeContextCurrent(m_outputs.first());
|
||||
}
|
||||
|
||||
bool EglStreamBackend::resetOutput(Output &o, DrmOutput *drmOutput)
|
||||
bool EglStreamBackend::resetOutput(Output &o)
|
||||
{
|
||||
o.output = drmOutput;
|
||||
const auto &drmOutput = o.output;
|
||||
QSize sourceSize = drmOutput->sourceSize();
|
||||
|
||||
if (isPrimary()) {
|
||||
|
@ -385,7 +385,8 @@ bool EglStreamBackend::addOutput(DrmAbstractOutput *output)
|
|||
DrmOutput *drmOutput = qobject_cast<DrmOutput *>(output);
|
||||
if (drmOutput) {
|
||||
Output o;
|
||||
if (!resetOutput(o, drmOutput)) {
|
||||
o.output = drmOutput;
|
||||
if (!resetOutput(o)) {
|
||||
return false;
|
||||
}
|
||||
if (!isPrimary() && !renderingBackend()->addOutput(drmOutput)) {
|
||||
|
@ -394,18 +395,10 @@ bool EglStreamBackend::addOutput(DrmAbstractOutput *output)
|
|||
|
||||
connect(drmOutput, &DrmOutput::modeChanged, this,
|
||||
[drmOutput, this] {
|
||||
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
|
||||
[drmOutput] (const auto &o) {
|
||||
return o.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_outputs.end()) {
|
||||
return;
|
||||
}
|
||||
resetOutput(*it, drmOutput);
|
||||
resetOutput(m_outputs[drmOutput]);
|
||||
}
|
||||
);
|
||||
m_outputs << o;
|
||||
m_outputs.insert(output, o);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -490,9 +483,10 @@ PlatformSurfaceTexture *EglStreamBackend::createPlatformSurfaceTextureWayland(Su
|
|||
return new EglStreamSurfaceTextureWayland(this, pixmap);
|
||||
}
|
||||
|
||||
QRegion EglStreamBackend::beginFrame(int screenId)
|
||||
QRegion EglStreamBackend::beginFrame(AbstractOutput *drmOutput)
|
||||
{
|
||||
const Output &o = m_outputs.at(screenId);
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
const Output &o = m_outputs[drmOutput];
|
||||
if (isPrimary()) {
|
||||
makeContextCurrent(o);
|
||||
if (o.shadowBuffer) {
|
||||
|
@ -504,13 +498,12 @@ QRegion EglStreamBackend::beginFrame(int screenId)
|
|||
}
|
||||
}
|
||||
|
||||
void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void EglStreamBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(output));
|
||||
Q_UNUSED(renderedRegion);
|
||||
|
||||
Output &renderOutput = m_outputs[screenId];
|
||||
DrmOutput *drmOutput = renderOutput.output;
|
||||
|
||||
Output &renderOutput = m_outputs[output];
|
||||
bool frameFailed = false;
|
||||
|
||||
QSharedPointer<DrmDumbBuffer> buffer;
|
||||
|
@ -524,13 +517,13 @@ void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, con
|
|||
frameFailed = true;
|
||||
}
|
||||
} else {
|
||||
if (!renderingBackend()->swapBuffers(drmOutput, damagedRegion.intersected(drmOutput->geometry()))) {
|
||||
qCCritical(KWIN_DRM) << "swapping buffers on render backend for" << drmOutput << "failed!";
|
||||
if (!renderingBackend()->swapBuffers(static_cast<DrmOutput*>(output), damagedRegion.intersected(output->geometry()))) {
|
||||
qCCritical(KWIN_DRM) << "swapping buffers on render backend for" << output << "failed!";
|
||||
frameFailed = true;
|
||||
}
|
||||
buffer = renderOutput.dumbSwapchain->acquireBuffer();
|
||||
if (!frameFailed && !renderingBackend()->exportFramebuffer(drmOutput, buffer->data(), buffer->size(), buffer->stride())) {
|
||||
qCCritical(KWIN_DRM) << "importing framebuffer from render backend for" << drmOutput << "failed!";
|
||||
if (!frameFailed && !renderingBackend()->exportFramebuffer(static_cast<DrmOutput*>(output), buffer->data(), buffer->size(), buffer->stride())) {
|
||||
qCCritical(KWIN_DRM) << "importing framebuffer from render backend for" << output << "failed!";
|
||||
frameFailed = true;
|
||||
}
|
||||
}
|
||||
|
@ -539,11 +532,11 @@ void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, con
|
|||
}
|
||||
|
||||
if (frameFailed) {
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(drmOutput->renderLoop());
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(output->renderLoop());
|
||||
renderLoopPrivate->notifyFrameFailed();
|
||||
} else if (isPrimary()) {
|
||||
EGLAttrib acquireAttribs[] = {
|
||||
EGL_DRM_FLIP_EVENT_DATA_NV, (EGLAttrib)drmOutput,
|
||||
EGL_DRM_FLIP_EVENT_DATA_NV, (EGLAttrib)output,
|
||||
EGL_NONE,
|
||||
};
|
||||
if (!pEglStreamConsumerAcquireAttribNV(eglDisplay(), renderOutput.eglStream, acquireAttribs)) {
|
||||
|
@ -554,15 +547,9 @@ void EglStreamBackend::endFrame(int screenId, const QRegion &renderedRegion, con
|
|||
|
||||
QSharedPointer<DrmBuffer> EglStreamBackend::renderTestFrame(DrmAbstractOutput *drmOutput)
|
||||
{
|
||||
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
|
||||
[drmOutput] (const Output &o) {
|
||||
return o.output == drmOutput;
|
||||
}
|
||||
);
|
||||
if (it == m_outputs.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto buffer = (*it).dumbSwapchain ? (*it).dumbSwapchain->currentBuffer() : (*it).buffer;
|
||||
Q_ASSERT(m_outputs.contains(drmOutput));
|
||||
auto &output = m_outputs[drmOutput];
|
||||
auto buffer = output.dumbSwapchain ? output.dumbSwapchain->currentBuffer() : output.buffer;
|
||||
auto size = drmOutput->sourceSize();
|
||||
if (buffer->size() == size) {
|
||||
return buffer;
|
||||
|
@ -571,6 +558,11 @@ QSharedPointer<DrmBuffer> EglStreamBackend::renderTestFrame(DrmAbstractOutput *d
|
|||
}
|
||||
}
|
||||
|
||||
bool EglStreamBackend::hasOutput(AbstractOutput *output) const
|
||||
{
|
||||
return m_outputs.contains(output);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* EglTexture
|
||||
************************************************/
|
||||
|
|
|
@ -33,14 +33,11 @@ public:
|
|||
~EglStreamBackend() override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
void init() override;
|
||||
|
||||
int screenCount() const override {
|
||||
return m_outputs.count();
|
||||
}
|
||||
|
||||
bool hasOutput(AbstractOutput *output) const override;
|
||||
bool addOutput(DrmAbstractOutput *output) override;
|
||||
void removeOutput(DrmAbstractOutput *output) override;
|
||||
|
||||
|
@ -74,11 +71,11 @@ private:
|
|||
// for operation as secondary GPU
|
||||
QSharedPointer<DumbSwapchain> dumbSwapchain;
|
||||
};
|
||||
bool resetOutput(Output &output, DrmOutput *drmOutput);
|
||||
bool resetOutput(Output &output);
|
||||
bool makeContextCurrent(const Output &output);
|
||||
void cleanupOutput(Output &output);
|
||||
|
||||
QVector<Output> m_outputs;
|
||||
QMap<AbstractOutput *, Output> m_outputs;
|
||||
KWaylandServer::EglStreamControllerInterface *m_eglStreamControllerInterface;
|
||||
QHash<KWaylandServer::SurfaceInterface *, StreamTexture> m_streamTextures;
|
||||
|
||||
|
|
|
@ -45,31 +45,24 @@ void DrmQPainterBackend::initOutput(DrmAbstractOutput *output)
|
|||
Output o;
|
||||
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize());
|
||||
o.output = output;
|
||||
m_outputs << o;
|
||||
m_outputs.insert(output, o);
|
||||
connect(output, &DrmOutput::modeChanged, this,
|
||||
[output, this] {
|
||||
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
|
||||
[output] (const auto &o) {
|
||||
return o.output == output;
|
||||
}
|
||||
);
|
||||
if (it == m_outputs.end()) {
|
||||
return;
|
||||
}
|
||||
it->swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize());
|
||||
it->damageJournal.setCapacity(it->swapchain->slotCount());
|
||||
auto &o = m_outputs[output];
|
||||
o.swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize());
|
||||
o.damageJournal.setCapacity(o.swapchain->slotCount());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
QImage *DrmQPainterBackend::bufferForScreen(int screenId)
|
||||
QImage *DrmQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
{
|
||||
return m_outputs[screenId].swapchain->currentBuffer()->image();
|
||||
return m_outputs[output].swapchain->currentBuffer()->image();
|
||||
}
|
||||
|
||||
QRegion DrmQPainterBackend::beginFrame(int screenId)
|
||||
QRegion DrmQPainterBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Output *rendererOutput = &m_outputs[screenId];
|
||||
Output *rendererOutput = &m_outputs[output];
|
||||
|
||||
int bufferAge;
|
||||
rendererOutput->swapchain->acquireBuffer(&bufferAge);
|
||||
|
@ -77,9 +70,9 @@ QRegion DrmQPainterBackend::beginFrame(int screenId)
|
|||
return rendererOutput->damageJournal.accumulate(bufferAge, rendererOutput->output->geometry());
|
||||
}
|
||||
|
||||
void DrmQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Output &rendererOutput = m_outputs[screenId];
|
||||
Output &rendererOutput = m_outputs[output];
|
||||
DrmAbstractOutput *drmOutput = rendererOutput.output;
|
||||
|
||||
QSharedPointer<DrmDumbBuffer> back = rendererOutput.swapchain->currentBuffer();
|
||||
|
|
|
@ -31,9 +31,9 @@ class DrmQPainterBackend : public QPainterBackend
|
|||
public:
|
||||
DrmQPainterBackend(DrmBackend *backend, DrmGpu *gpu);
|
||||
|
||||
QImage *bufferForScreen(int screenId) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage) override;
|
||||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
void initOutput(DrmAbstractOutput *output);
|
||||
|
@ -42,7 +42,7 @@ private:
|
|||
QSharedPointer<DumbSwapchain> swapchain;
|
||||
DamageJournal damageJournal;
|
||||
};
|
||||
QVector<Output> m_outputs;
|
||||
QMap<AbstractOutput *, Output> m_outputs;
|
||||
DrmBackend *m_backend;
|
||||
DrmGpu *m_gpu;
|
||||
};
|
||||
|
|
|
@ -63,28 +63,26 @@ void FramebufferQPainterBackend::deactivate()
|
|||
|
||||
FramebufferQPainterBackend::~FramebufferQPainterBackend() = default;
|
||||
|
||||
QImage* FramebufferQPainterBackend::bufferForScreen(int screenId)
|
||||
QImage* FramebufferQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
return &m_renderBuffer;
|
||||
}
|
||||
|
||||
QRegion FramebufferQPainterBackend::beginFrame(int screenId)
|
||||
QRegion FramebufferQPainterBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
return screens()->geometry(screenId);
|
||||
return output->geometry();
|
||||
}
|
||||
|
||||
void FramebufferQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
void FramebufferQPainterBackend::endFrame(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(damage)
|
||||
|
||||
if (!kwinApp()->platform()->session()->isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FramebufferOutput *output = static_cast<FramebufferOutput *>(m_backend->findOutput(screenId));
|
||||
output->vsyncMonitor()->arm();
|
||||
static_cast<FramebufferOutput *>(output)->vsyncMonitor()->arm();
|
||||
|
||||
QPainter p(&m_backBuffer);
|
||||
p.drawImage(QPoint(0, 0), m_backend->isBGR() ? m_renderBuffer.rgbSwapped() : m_renderBuffer);
|
||||
|
|
|
@ -24,9 +24,9 @@ public:
|
|||
FramebufferQPainterBackend(FramebufferBackend *backend);
|
||||
~FramebufferQPainterBackend() override;
|
||||
|
||||
QImage *bufferForScreen(int screenId) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage) override;
|
||||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
void reactivate();
|
||||
|
|
|
@ -150,9 +150,9 @@ PlatformSurfaceTexture *EglGbmBackend::createPlatformSurfaceTextureWayland(Surfa
|
|||
return new BasicEGLSurfaceTextureWayland(this, pixmap);
|
||||
}
|
||||
|
||||
QRegion EglGbmBackend::beginFrame(int screenId)
|
||||
QRegion EglGbmBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
if (!GLRenderTarget::isRenderTargetBound()) {
|
||||
GLRenderTarget::pushRenderTarget(m_fbo);
|
||||
}
|
||||
|
@ -190,14 +190,13 @@ static void convertFromGLImage(QImage &img, int w, int h)
|
|||
img = img.mirrored();
|
||||
}
|
||||
|
||||
void EglGbmBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void EglGbmBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(renderedRegion)
|
||||
Q_UNUSED(damagedRegion)
|
||||
glFlush();
|
||||
|
||||
VirtualOutput *output = static_cast<VirtualOutput *>(m_backend->findOutput(screenId));
|
||||
output->vsyncMonitor()->arm();
|
||||
static_cast<VirtualOutput *>(output)->vsyncMonitor()->arm();
|
||||
|
||||
if (m_backend->saveFrames()) {
|
||||
QImage img = QImage(QSize(m_backBuffer->width(), m_backBuffer->height()), QImage::Format_ARGB32);
|
||||
|
|
|
@ -28,8 +28,8 @@ public:
|
|||
~EglGbmBackend() override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
void init() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -27,35 +27,35 @@ VirtualQPainterBackend::VirtualQPainterBackend(VirtualBackend *backend)
|
|||
|
||||
VirtualQPainterBackend::~VirtualQPainterBackend() = default;
|
||||
|
||||
QImage *VirtualQPainterBackend::bufferForScreen(int screen)
|
||||
QImage *VirtualQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
{
|
||||
return &m_backBuffers[screen];
|
||||
return &m_backBuffers[output];
|
||||
}
|
||||
|
||||
QRegion VirtualQPainterBackend::beginFrame(int screenId)
|
||||
QRegion VirtualQPainterBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
return screens()->geometry(screenId);
|
||||
return output->geometry();
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::createOutputs()
|
||||
{
|
||||
m_backBuffers.clear();
|
||||
for (int i = 0; i < screens()->count(); ++i) {
|
||||
QImage buffer(screens()->size(i) * screens()->scale(i), QImage::Format_RGB32);
|
||||
const auto outputs = m_backend->enabledOutputs();
|
||||
for (const auto &output : outputs) {
|
||||
QImage buffer(output->pixelSize(), QImage::Format_RGB32);
|
||||
buffer.fill(Qt::black);
|
||||
m_backBuffers << buffer;
|
||||
m_backBuffers.insert(output, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
void VirtualQPainterBackend::endFrame(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(damage)
|
||||
|
||||
VirtualOutput *output = static_cast<VirtualOutput *>(m_backend->findOutput(screenId));
|
||||
output->vsyncMonitor()->arm();
|
||||
static_cast<VirtualOutput *>(output)->vsyncMonitor()->arm();
|
||||
|
||||
if (m_backend->saveFrames()) {
|
||||
m_backBuffers[screenId].save(QStringLiteral("%1/screen%2-%3.png").arg(m_backend->screenshotDirPath(), QString::number(screenId), QString::number(m_frameCounter++)));
|
||||
m_backBuffers[output].save(QStringLiteral("%1/%s-%3.png").arg(m_backend->screenshotDirPath(), output->name(), QString::number(m_frameCounter++)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -26,14 +27,14 @@ public:
|
|||
VirtualQPainterBackend(VirtualBackend *backend);
|
||||
~VirtualQPainterBackend() override;
|
||||
|
||||
QImage *bufferForScreen(int screenId) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage) override;
|
||||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
void createOutputs();
|
||||
|
||||
QVector<QImage> m_backBuffers;
|
||||
QMap<AbstractOutput *, QImage> m_backBuffers;
|
||||
VirtualBackend *m_backend;
|
||||
int m_frameCounter = 0;
|
||||
};
|
||||
|
|
|
@ -141,11 +141,12 @@ void EglWaylandBackend::cleanupSurfaces()
|
|||
|
||||
bool EglWaylandBackend::createEglWaylandOutput(AbstractOutput *waylandOutput)
|
||||
{
|
||||
auto *output = new EglWaylandOutput(static_cast<WaylandOutput *>(waylandOutput), this);
|
||||
const auto &output = new EglWaylandOutput(static_cast<WaylandOutput *>(waylandOutput), this);
|
||||
if (!output->init(this)) {
|
||||
delete output;
|
||||
return false;
|
||||
}
|
||||
m_outputs << output;
|
||||
m_outputs.insert(waylandOutput, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -298,15 +299,16 @@ static QVector<EGLint> regionToRects(const QRegion ®ion, AbstractWaylandOutpu
|
|||
return rects;
|
||||
}
|
||||
|
||||
void EglWaylandBackend::aboutToStartPainting(int screenId, const QRegion &damagedRegion)
|
||||
void EglWaylandBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT_X(screenId != -1, "aboutToStartPainting", "not using per screen rendering");
|
||||
EglWaylandOutput *output = m_outputs.at(screenId);
|
||||
if (output->m_bufferAge > 0 && !damagedRegion.isEmpty() && supportsPartialUpdate()) {
|
||||
const QRegion region = damagedRegion & output->m_waylandOutput->geometry();
|
||||
Q_ASSERT_X(output, "aboutToStartPainting", "not using per screen rendering");
|
||||
Q_ASSERT(m_outputs.contains(output));
|
||||
const auto &eglOutput = m_outputs[output];
|
||||
if (eglOutput->m_bufferAge > 0 && !damagedRegion.isEmpty() && supportsPartialUpdate()) {
|
||||
const QRegion region = damagedRegion & eglOutput->m_waylandOutput->geometry();
|
||||
|
||||
QVector<EGLint> rects = regionToRects(region, output->m_waylandOutput);
|
||||
const bool correct = eglSetDamageRegionKHR(eglDisplay(), output->m_eglSurface,
|
||||
QVector<EGLint> rects = regionToRects(region, eglOutput->m_waylandOutput);
|
||||
const bool correct = eglSetDamageRegionKHR(eglDisplay(), eglOutput->m_eglSurface,
|
||||
rects.data(), rects.count()/4);
|
||||
if (!correct) {
|
||||
qCWarning(KWIN_WAYLAND_BACKEND) << "failed eglSetDamageRegionKHR" << eglGetError();
|
||||
|
@ -350,27 +352,29 @@ PlatformSurfaceTexture *EglWaylandBackend::createPlatformSurfaceTextureWayland(S
|
|||
return new BasicEGLSurfaceTextureWayland(this, pixmap);
|
||||
}
|
||||
|
||||
QRegion EglWaylandBackend::beginFrame(int screenId)
|
||||
QRegion EglWaylandBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(output));
|
||||
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
||||
|
||||
auto *output = m_outputs.at(screenId);
|
||||
makeContextCurrent(output);
|
||||
const auto &eglOutput = m_outputs[output];
|
||||
makeContextCurrent(eglOutput);
|
||||
if (supportsBufferAge()) {
|
||||
return output->m_damageJournal.accumulate(output->m_bufferAge, output->m_waylandOutput->geometry());
|
||||
return eglOutput->m_damageJournal.accumulate(eglOutput->m_bufferAge, eglOutput->m_waylandOutput->geometry());
|
||||
}
|
||||
return QRegion();
|
||||
}
|
||||
|
||||
void EglWaylandBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void EglWaylandBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_ASSERT(m_outputs.contains(output));
|
||||
Q_UNUSED(renderedRegion);
|
||||
EglWaylandOutput *output = m_outputs[screenId];
|
||||
QRegion damage = damagedRegion.intersected(output->m_waylandOutput->geometry());
|
||||
presentOnSurface(output, damage);
|
||||
const auto &eglOutput = m_outputs[output];
|
||||
QRegion damage = damagedRegion.intersected(eglOutput->m_waylandOutput->geometry());
|
||||
presentOnSurface(eglOutput, damage);
|
||||
|
||||
if (supportsBufferAge()) {
|
||||
output->m_damageJournal.add(damage);
|
||||
eglOutput->m_damageJournal.add(damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,15 +71,15 @@ public:
|
|||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
void init() override;
|
||||
|
||||
bool havePlatformBase() const {
|
||||
return m_havePlatformBase;
|
||||
}
|
||||
|
||||
void aboutToStartPainting(int screenId, const QRegion &damage) override;
|
||||
void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
bool initializeEgl();
|
||||
|
@ -95,7 +95,7 @@ private:
|
|||
void presentOnSurface(EglWaylandOutput *output, const QRegion &damagedRegion);
|
||||
|
||||
WaylandBackend *m_backend;
|
||||
QVector<EglWaylandOutput*> m_outputs;
|
||||
QMap<AbstractOutput *, EglWaylandOutput*> m_outputs;
|
||||
bool m_havePlatformBase;
|
||||
friend class EglWaylandTexture;
|
||||
};
|
||||
|
|
|
@ -169,25 +169,25 @@ void WaylandQPainterBackend::createOutput(AbstractOutput *waylandOutput)
|
|||
{
|
||||
auto *output = new WaylandQPainterOutput(static_cast<WaylandOutput *>(waylandOutput), this);
|
||||
output->init(m_backend->shmPool());
|
||||
m_outputs << output;
|
||||
m_outputs.insert(waylandOutput, output);
|
||||
}
|
||||
|
||||
void WaylandQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
void WaylandQPainterBackend::endFrame(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
WaylandQPainterOutput *rendererOutput = m_outputs.value(screenId);
|
||||
WaylandQPainterOutput *rendererOutput = m_outputs[output];
|
||||
Q_ASSERT(rendererOutput);
|
||||
|
||||
rendererOutput->present(rendererOutput->mapToLocal(damage));
|
||||
}
|
||||
|
||||
QImage *WaylandQPainterBackend::bufferForScreen(int screenId)
|
||||
QImage *WaylandQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
{
|
||||
return &m_outputs[screenId]->back()->image;
|
||||
return &m_outputs[output]->back()->image;
|
||||
}
|
||||
|
||||
QRegion WaylandQPainterBackend::beginFrame(int screenId)
|
||||
QRegion WaylandQPainterBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
WaylandQPainterOutput *rendererOutput = m_outputs.value(screenId);
|
||||
WaylandQPainterOutput *rendererOutput = m_outputs[output];
|
||||
Q_ASSERT(rendererOutput);
|
||||
|
||||
WaylandQPainterBufferSlot *slot = rendererOutput->acquire();
|
||||
|
|
|
@ -83,17 +83,17 @@ public:
|
|||
explicit WaylandQPainterBackend(WaylandBackend *b);
|
||||
~WaylandQPainterBackend() override;
|
||||
|
||||
QImage *bufferForScreen(int screenId) override;
|
||||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
|
||||
void endFrame(int screenId, const QRegion& damage) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion& damage) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
|
||||
private:
|
||||
void createOutput(AbstractOutput *waylandOutput);
|
||||
void frameRendered();
|
||||
|
||||
WaylandBackend *m_backend;
|
||||
QVector<WaylandQPainterOutput*> m_outputs;
|
||||
QMap<AbstractOutput *, WaylandQPainterOutput*> m_outputs;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -88,9 +88,9 @@ void EglBackend::screenGeometryChanged()
|
|||
m_bufferAge = 0;
|
||||
}
|
||||
|
||||
QRegion EglBackend::beginFrame(int screenId)
|
||||
QRegion EglBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
makeCurrent();
|
||||
|
||||
const QSize size = screens()->size();
|
||||
|
@ -106,9 +106,9 @@ QRegion EglBackend::beginFrame(int screenId)
|
|||
return repaint;
|
||||
}
|
||||
|
||||
void EglBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void EglBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
|
||||
// Start the software vsync monitor. There is no any reliable way to determine when
|
||||
// eglSwapBuffers() or eglSwapBuffersWithDamageEXT() completes.
|
||||
|
|
|
@ -31,8 +31,8 @@ public:
|
|||
void init() override;
|
||||
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *texture) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
|
||||
private:
|
||||
void screenGeometryChanged();
|
||||
|
|
|
@ -739,9 +739,9 @@ PlatformSurfaceTexture *GlxBackend::createPlatformSurfaceTextureX11(SurfacePixma
|
|||
return new GlxSurfaceTextureX11(this, pixmap);
|
||||
}
|
||||
|
||||
QRegion GlxBackend::beginFrame(int screenId)
|
||||
QRegion GlxBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
|
||||
QRegion repaint;
|
||||
makeCurrent();
|
||||
|
@ -758,9 +758,9 @@ QRegion GlxBackend::beginFrame(int screenId)
|
|||
return repaint;
|
||||
}
|
||||
|
||||
void GlxBackend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void GlxBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
|
||||
// If the GLX_INTEL_swap_event extension is not used for getting presentation feedback,
|
||||
// assume that the frame will be presented at the next vblank event, this is racy.
|
||||
|
|
|
@ -72,8 +72,8 @@ public:
|
|||
GlxBackend(Display *display, X11StandalonePlatform *backend);
|
||||
~GlxBackend() override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
bool makeCurrent() override;
|
||||
void doneCurrent() override;
|
||||
OverlayWindow* overlayWindow() const override;
|
||||
|
|
|
@ -47,12 +47,13 @@ void EglX11Backend::cleanupSurfaces()
|
|||
|
||||
bool EglX11Backend::createSurfaces()
|
||||
{
|
||||
for (int i = 0; i < screens()->count(); ++i) {
|
||||
EGLSurface s = createSurface(m_backend->windowForScreen(i));
|
||||
const auto &outputs = m_backend->outputs();
|
||||
for (const auto &output : outputs) {
|
||||
EGLSurface s = createSurface(m_backend->windowForScreen(output));
|
||||
if (s == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
m_surfaces << s;
|
||||
m_surfaces.insert(output, s);
|
||||
}
|
||||
if (m_surfaces.isEmpty()) {
|
||||
return false;
|
||||
|
@ -61,29 +62,26 @@ bool EglX11Backend::createSurfaces()
|
|||
return true;
|
||||
}
|
||||
|
||||
QRegion EglX11Backend::beginFrame(int screenId)
|
||||
QRegion EglX11Backend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
makeContextCurrent(m_surfaces.at(screenId));
|
||||
setupViewport(screenId);
|
||||
return screens()->geometry(screenId);
|
||||
makeContextCurrent(m_surfaces[output]);
|
||||
setupViewport(output);
|
||||
return output->geometry();
|
||||
}
|
||||
|
||||
void EglX11Backend::setupViewport(int screenId)
|
||||
void EglX11Backend::setupViewport(AbstractOutput *output)
|
||||
{
|
||||
qreal scale = screens()->scale(screenId);
|
||||
const QSize size = screens()->geometry(screenId).size() * scale;
|
||||
const QSize size = output->pixelSize() * output->scale();
|
||||
glViewport(0, 0, size.width(), size.height());
|
||||
}
|
||||
|
||||
void EglX11Backend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
void EglX11Backend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion)
|
||||
{
|
||||
Q_UNUSED(damagedRegion)
|
||||
|
||||
X11WindowedOutput *output = static_cast<X11WindowedOutput *>(kwinApp()->platform()->findOutput(screenId));
|
||||
output->vsyncMonitor()->arm();
|
||||
static_cast<X11WindowedOutput *>(output)->vsyncMonitor()->arm();
|
||||
|
||||
const QRect &outputGeometry = screens()->geometry(screenId);
|
||||
presentSurface(m_surfaces.at(screenId), renderedRegion, outputGeometry);
|
||||
presentSurface(m_surfaces[output], renderedRegion, output->geometry());
|
||||
}
|
||||
|
||||
void EglX11Backend::presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry)
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#define KWIN_EGL_X11_BACKEND_H
|
||||
#include "eglonxbackend.h"
|
||||
|
||||
#include <QMap>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -29,18 +31,18 @@ public:
|
|||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
void init() override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||
|
||||
protected:
|
||||
void cleanupSurfaces() override;
|
||||
bool createSurfaces() override;
|
||||
|
||||
private:
|
||||
void setupViewport(int screenId);
|
||||
void setupViewport(AbstractOutput *output);
|
||||
void presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry);
|
||||
|
||||
QVector<EGLSurface> m_surfaces;
|
||||
QMap<AbstractOutput *, EGLSurface> m_surfaces;
|
||||
X11WindowedBackend *m_backend;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,32 +35,31 @@ void X11WindowedQPainterBackend::createOutputs()
|
|||
{
|
||||
qDeleteAll(m_outputs);
|
||||
m_outputs.clear();
|
||||
for (int i = 0; i < screens()->count(); ++i) {
|
||||
const auto &outputs = m_backend->outputs();
|
||||
for (const auto &x11Output : outputs) {
|
||||
Output *output = new Output;
|
||||
output->window = m_backend->windowForScreen(i);
|
||||
output->buffer = QImage(screens()->size(i) * screens()->scale(i), QImage::Format_RGB32);
|
||||
output->window = m_backend->windowForScreen(x11Output);
|
||||
output->buffer = QImage(x11Output->pixelSize() * x11Output->scale(), QImage::Format_RGB32);
|
||||
output->buffer.fill(Qt::black);
|
||||
m_outputs << output;
|
||||
m_outputs.insert(x11Output, output);
|
||||
}
|
||||
}
|
||||
|
||||
QImage *X11WindowedQPainterBackend::bufferForScreen(int screen)
|
||||
QImage *X11WindowedQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
{
|
||||
return &m_outputs.at(screen)->buffer;
|
||||
return &m_outputs[output]->buffer;
|
||||
}
|
||||
|
||||
QRegion X11WindowedQPainterBackend::beginFrame(int screenId)
|
||||
QRegion X11WindowedQPainterBackend::beginFrame(AbstractOutput *output)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
return screens()->geometry(screenId);
|
||||
return output->geometry();
|
||||
}
|
||||
|
||||
void X11WindowedQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
void X11WindowedQPainterBackend::endFrame(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(damage)
|
||||
|
||||
X11WindowedOutput *output = static_cast<X11WindowedOutput *>(kwinApp()->platform()->findOutput(screenId));
|
||||
output->vsyncMonitor()->arm();
|
||||
static_cast<X11WindowedOutput *>(output)->vsyncMonitor()->arm();
|
||||
|
||||
xcb_connection_t *c = m_backend->connection();
|
||||
const xcb_window_t window = m_backend->window();
|
||||
|
@ -69,7 +68,7 @@ void X11WindowedQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
|||
xcb_create_gc(c, m_gc, window, 0, nullptr);
|
||||
}
|
||||
|
||||
Output *rendererOutput = m_outputs.value(screenId);
|
||||
Output *rendererOutput = m_outputs[output];
|
||||
Q_ASSERT(rendererOutput);
|
||||
|
||||
// TODO: only update changes?
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <QObject>
|
||||
#include <QImage>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
|
@ -29,9 +30,9 @@ public:
|
|||
X11WindowedQPainterBackend(X11WindowedBackend *backend);
|
||||
~X11WindowedQPainterBackend() override;
|
||||
|
||||
QImage *bufferForScreen(int screenId) override;
|
||||
QRegion beginFrame(int screenId) override;
|
||||
void endFrame(int screenId, const QRegion &damage) override;
|
||||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
void createOutputs();
|
||||
|
@ -41,7 +42,7 @@ private:
|
|||
xcb_window_t window;
|
||||
QImage buffer;
|
||||
};
|
||||
QVector<Output*> m_outputs;
|
||||
QMap<AbstractOutput *, Output*> m_outputs;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -525,12 +525,17 @@ void X11WindowedBackend::warpPointer(const QPointF &globalPos)
|
|||
xcb_flush(m_connection);
|
||||
}
|
||||
|
||||
xcb_window_t X11WindowedBackend::windowForScreen(int screen) const
|
||||
xcb_window_t X11WindowedBackend::windowForScreen(AbstractOutput *output) const
|
||||
{
|
||||
if (screen > m_outputs.count()) {
|
||||
if (!output) {
|
||||
return XCB_WINDOW_NONE;
|
||||
}
|
||||
return m_outputs.at(screen)->window();
|
||||
return static_cast<X11WindowedOutput*>(output)->window();
|
||||
}
|
||||
|
||||
xcb_window_t X11WindowedBackend::window() const
|
||||
{
|
||||
return m_outputs.first()->window();
|
||||
}
|
||||
|
||||
Outputs X11WindowedBackend::outputs() const
|
||||
|
|
|
@ -47,10 +47,8 @@ public:
|
|||
int screenNumer() const {
|
||||
return m_screenNumber;
|
||||
}
|
||||
xcb_window_t window() const {
|
||||
return windowForScreen(0);
|
||||
}
|
||||
xcb_window_t windowForScreen(int screen) const;
|
||||
xcb_window_t window() const;
|
||||
xcb_window_t windowForScreen(AbstractOutput *output) const;
|
||||
Display *display() const {
|
||||
return m_display;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "shadowitem.h"
|
||||
#include "surfaceitem.h"
|
||||
#include "windowitem.h"
|
||||
#include "abstract_output.h"
|
||||
#include <logging.h>
|
||||
|
||||
#include <cmath>
|
||||
|
@ -342,9 +343,9 @@ void SceneOpenGL2::paintCursor(const QRegion &rendered)
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void SceneOpenGL::aboutToStartPainting(int screenId, const QRegion &damage)
|
||||
void SceneOpenGL::aboutToStartPainting(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
m_backend->aboutToStartPainting(screenId, damage);
|
||||
m_backend->aboutToStartPainting(output, damage);
|
||||
}
|
||||
|
||||
static SurfaceItem *findTopMostSurface(SurfaceItem *item)
|
||||
|
@ -357,14 +358,14 @@ static SurfaceItem *findTopMostSurface(SurfaceItem *item)
|
|||
}
|
||||
}
|
||||
|
||||
void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
void SceneOpenGL::paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
RenderLoop *renderLoop)
|
||||
{
|
||||
if (m_resetOccurred) {
|
||||
return; // A graphics reset has occurred, do nothing.
|
||||
}
|
||||
|
||||
painted_screen = screenId;
|
||||
painted_screen = output;
|
||||
// actually paint the frame, flushed with the NEXT frame
|
||||
createStackingOrder(toplevels);
|
||||
|
||||
|
@ -373,9 +374,9 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
|
|||
QRegion repaint;
|
||||
QRect geo;
|
||||
qreal scaling;
|
||||
if (screenId != -1) {
|
||||
geo = screens()->geometry(screenId);
|
||||
scaling = screens()->scale(screenId);
|
||||
if (output) {
|
||||
geo = output->geometry();
|
||||
scaling = output->scale();
|
||||
} else {
|
||||
geo = screens()->geometry();
|
||||
scaling = 1;
|
||||
|
@ -391,7 +392,7 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
|
|||
for (int i = stacking_order.count() - 1; i >=0; i--) {
|
||||
Window *window = stacking_order[i];
|
||||
Toplevel *toplevel = window->window();
|
||||
if (toplevel->isOnScreen(screenId) && window->isVisible() && toplevel->opacity() > 0) {
|
||||
if (output && toplevel->isOnOutput(output) && window->isVisible() && toplevel->opacity() > 0) {
|
||||
AbstractClient *c = dynamic_cast<AbstractClient*>(toplevel);
|
||||
if (!c || !c->isFullScreen()) {
|
||||
break;
|
||||
|
@ -420,14 +421,14 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
|
|||
renderLoop->setFullscreenSurface(fullscreenSurface);
|
||||
|
||||
bool directScanout = false;
|
||||
if (m_backend->directScanoutAllowed(screenId) && !static_cast<EffectsHandlerImpl*>(effects)->blocksDirectScanout()) {
|
||||
directScanout = m_backend->scanout(screenId, fullscreenSurface);
|
||||
if (m_backend->directScanoutAllowed(output) && !static_cast<EffectsHandlerImpl*>(effects)->blocksDirectScanout()) {
|
||||
directScanout = m_backend->scanout(output, fullscreenSurface);
|
||||
}
|
||||
if (directScanout) {
|
||||
renderLoop->endFrame();
|
||||
} else {
|
||||
// prepare rendering makescontext current on the output
|
||||
repaint = m_backend->beginFrame(screenId);
|
||||
repaint = m_backend->beginFrame(output);
|
||||
|
||||
GLVertexBuffer::setVirtualScreenGeometry(geo);
|
||||
GLRenderTarget::setVirtualScreenGeometry(geo);
|
||||
|
@ -440,7 +441,7 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
|
|||
renderLoop, projectionMatrix()); // call generic implementation
|
||||
paintCursor(valid);
|
||||
|
||||
if (!GLPlatform::instance()->isGLES() && screenId == -1) {
|
||||
if (!GLPlatform::instance()->isGLES() && !output) {
|
||||
const QSize &screenSize = screens()->size();
|
||||
const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height());
|
||||
|
||||
|
@ -458,7 +459,7 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
|
|||
renderLoop->endFrame();
|
||||
|
||||
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
||||
m_backend->endFrame(screenId, valid, update);
|
||||
m_backend->endFrame(output, valid, update);
|
||||
GLVertexBuffer::streamingBuffer()->framePosted();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
class EffectFrame;
|
||||
~SceneOpenGL() override;
|
||||
bool initFailed() const override;
|
||||
void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) override;
|
||||
Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
||||
Shadow *createShadow(Toplevel *toplevel) override;
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
protected:
|
||||
SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
|
||||
void paintBackground(const QRegion ®ion) override;
|
||||
void aboutToStartPainting(int screenId, const QRegion &damage) override;
|
||||
void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override;
|
||||
void extendPaintRegion(QRegion ®ion, bool opaqueFullscreen) override;
|
||||
QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
|
||||
void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "toplevel.h"
|
||||
#include "platform.h"
|
||||
#include "windowitem.h"
|
||||
#include "abstract_output.h"
|
||||
|
||||
#include <kwineffectquickview.h>
|
||||
// Qt
|
||||
|
@ -79,18 +80,18 @@ void SceneQPainter::paintGenericScreen(int mask, const ScreenPaintData &data)
|
|||
m_painter->restore();
|
||||
}
|
||||
|
||||
void SceneQPainter::paint(int screenId, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
void SceneQPainter::paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
RenderLoop *renderLoop)
|
||||
{
|
||||
Q_ASSERT(kwinApp()->platform()->isPerScreenRenderingEnabled());
|
||||
painted_screen = screenId;
|
||||
painted_screen = output;
|
||||
|
||||
createStackingOrder(toplevels);
|
||||
|
||||
const QRegion repaint = m_backend->beginFrame(screenId);
|
||||
const QRect geometry = screens()->geometry(screenId);
|
||||
const QRegion repaint = m_backend->beginFrame(output);
|
||||
const QRect geometry = output->geometry();
|
||||
|
||||
QImage *buffer = m_backend->bufferForScreen(screenId);
|
||||
QImage *buffer = m_backend->bufferForScreen(output);
|
||||
if (buffer && !buffer->isNull()) {
|
||||
renderLoop->beginFrame();
|
||||
m_painter->begin(buffer);
|
||||
|
@ -102,7 +103,7 @@ void SceneQPainter::paint(int screenId, const QRegion &damage, const QList<Tople
|
|||
|
||||
m_painter->end();
|
||||
renderLoop->endFrame();
|
||||
m_backend->endFrame(screenId, updateRegion);
|
||||
m_backend->endFrame(output, updateRegion);
|
||||
}
|
||||
|
||||
// do cleanup
|
||||
|
@ -159,9 +160,9 @@ Shadow *SceneQPainter::createShadow(Toplevel *toplevel)
|
|||
return new SceneQPainterShadow(toplevel);
|
||||
}
|
||||
|
||||
QImage *SceneQPainter::qpainterRenderBuffer(int screenId) const
|
||||
QImage *SceneQPainter::qpainterRenderBuffer(AbstractOutput *output) const
|
||||
{
|
||||
return m_backend->bufferForScreen(screenId);
|
||||
return m_backend->bufferForScreen(output);
|
||||
}
|
||||
|
||||
//****************************************
|
||||
|
|
|
@ -24,7 +24,7 @@ class KWIN_EXPORT SceneQPainter : public Scene
|
|||
public:
|
||||
~SceneQPainter() override;
|
||||
OverlayWindow* overlayWindow() const override;
|
||||
void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) override;
|
||||
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
||||
CompositingType compositingType() const override;
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
}
|
||||
|
||||
QPainter *scenePainter() const override;
|
||||
QImage *qpainterRenderBuffer(int screenId) const override;
|
||||
QImage *qpainterRenderBuffer(AbstractOutput *output) const override;
|
||||
|
||||
QPainterBackend *backend() const {
|
||||
return m_backend.data();
|
||||
|
|
|
@ -85,11 +85,7 @@ namespace KWin
|
|||
Scene::Scene(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
connect(kwinApp()->platform(), &Platform::outputEnabled, this, &Scene::reallocRepaints);
|
||||
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Scene::reallocRepaints);
|
||||
}
|
||||
reallocRepaints();
|
||||
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Scene::removeRepaints);
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
|
@ -101,14 +97,10 @@ void Scene::addRepaint(const QRegion ®ion)
|
|||
{
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
|
||||
if (m_repaints.count() != outputs.count()) {
|
||||
return; // Repaints haven't been reallocated yet, do nothing.
|
||||
}
|
||||
for (int screenId = 0; screenId < m_repaints.count(); ++screenId) {
|
||||
AbstractOutput *output = outputs[screenId];
|
||||
for (const auto &output : outputs) {
|
||||
const QRegion dirtyRegion = region & output->geometry();
|
||||
if (!dirtyRegion.isEmpty()) {
|
||||
m_repaints[screenId] += dirtyRegion;
|
||||
m_repaints[output] += dirtyRegion;
|
||||
output->renderLoop()->scheduleRepaint();
|
||||
}
|
||||
}
|
||||
|
@ -118,27 +110,19 @@ void Scene::addRepaint(const QRegion ®ion)
|
|||
}
|
||||
}
|
||||
|
||||
QRegion Scene::repaints(int screenId) const
|
||||
QRegion Scene::repaints(AbstractOutput *output) const
|
||||
{
|
||||
const int index = screenId == -1 ? 0 : screenId;
|
||||
return m_repaints[index];
|
||||
return m_repaints.value(output, infiniteRegion());
|
||||
}
|
||||
|
||||
void Scene::resetRepaints(int screenId)
|
||||
void Scene::resetRepaints(AbstractOutput *output)
|
||||
{
|
||||
const int index = screenId == -1 ? 0 : screenId;
|
||||
m_repaints[index] = QRegion();
|
||||
m_repaints.insert(output, QRegion());
|
||||
}
|
||||
|
||||
void Scene::reallocRepaints()
|
||||
void Scene::removeRepaints(AbstractOutput *output)
|
||||
{
|
||||
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
|
||||
m_repaints.resize(kwinApp()->platform()->enabledOutputs().count());
|
||||
} else {
|
||||
m_repaints.resize(1);
|
||||
}
|
||||
|
||||
m_repaints.fill(infiniteRegion());
|
||||
m_repaints.remove(output);
|
||||
}
|
||||
|
||||
// returns mask and possibly modified region
|
||||
|
@ -164,7 +148,7 @@ void Scene::paintScreen(const QRegion &damage, const QRegion &repaint,
|
|||
|
||||
QRegion region = damage;
|
||||
|
||||
auto screen = effects->findScreen(painted_screen);
|
||||
auto screen = effects->findScreen(kwinApp()->platform()->enabledOutputs().indexOf(painted_screen));
|
||||
ScreenPrePaintData pdata;
|
||||
pdata.mask = (damage == displayRegion) ? 0 : PAINT_SCREEN_REGION;
|
||||
pdata.paint = region;
|
||||
|
@ -221,13 +205,13 @@ void Scene::finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& d
|
|||
paintSimpleScreen(mask, region);
|
||||
}
|
||||
|
||||
static void resetRepaintsHelper(Item *item, int screen)
|
||||
static void resetRepaintsHelper(Item *item, AbstractOutput *output)
|
||||
{
|
||||
item->resetRepaints(screen);
|
||||
item->resetRepaints(output);
|
||||
|
||||
const auto childItems = item->childItems();
|
||||
for (Item *childItem : childItems) {
|
||||
resetRepaintsHelper(childItem, screen);
|
||||
resetRepaintsHelper(childItem, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,14 +257,14 @@ void Scene::paintGenericScreen(int orig_mask, const ScreenPaintData &)
|
|||
}
|
||||
}
|
||||
|
||||
static void accumulateRepaints(Item *item, int screen, QRegion *repaints)
|
||||
static void accumulateRepaints(Item *item, AbstractOutput *output, QRegion *repaints)
|
||||
{
|
||||
*repaints += item->repaints(screen);
|
||||
item->resetRepaints(screen);
|
||||
*repaints += item->repaints(output);
|
||||
item->resetRepaints(output);
|
||||
|
||||
const auto childItems = item->childItems();
|
||||
for (Item *childItem : childItems) {
|
||||
accumulateRepaints(childItem, screen, repaints);
|
||||
accumulateRepaints(childItem, output, repaints);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,9 +487,9 @@ void Scene::paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPai
|
|||
static_cast<EffectsHandlerImpl*>(effects)->paintDesktop(desktop, mask, region, data);
|
||||
}
|
||||
|
||||
void Scene::aboutToStartPainting(int screenId, const QRegion &damage)
|
||||
void Scene::aboutToStartPainting(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(damage)
|
||||
}
|
||||
|
||||
|
@ -554,9 +538,9 @@ QPainter *Scene::scenePainter() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
QImage *Scene::qpainterRenderBuffer(int screenId) const
|
||||
QImage *Scene::qpainterRenderBuffer(AbstractOutput *output) const
|
||||
{
|
||||
Q_UNUSED(screenId)
|
||||
Q_UNUSED(output)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
18
src/scene.h
18
src/scene.h
|
@ -59,10 +59,10 @@ public:
|
|||
void addRepaint(const QRegion ®ion);
|
||||
|
||||
/**
|
||||
* Returns the repaints region for output with the specified @a screenId.
|
||||
* Returns the repaints region for output with the specified @a output.
|
||||
*/
|
||||
QRegion repaints(int screenId) const;
|
||||
void resetRepaints(int screenId);
|
||||
QRegion repaints(AbstractOutput *output) const;
|
||||
void resetRepaints(AbstractOutput *output);
|
||||
|
||||
// Returns true if the ctor failed to properly initialize.
|
||||
virtual bool initFailed() const = 0;
|
||||
|
@ -72,7 +72,7 @@ public:
|
|||
// The entry point for the main part of the painting pass.
|
||||
// returns the time since the last vblank signal - if there's one
|
||||
// ie. "what of this frame is lost to painting"
|
||||
virtual void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
virtual void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) = 0;
|
||||
|
||||
/**
|
||||
|
@ -159,7 +159,7 @@ public:
|
|||
* The render buffer used by a QPainter based compositor.
|
||||
* Default implementation returns @c nullptr.
|
||||
*/
|
||||
virtual QImage *qpainterRenderBuffer(int screenId) const;
|
||||
virtual QImage *qpainterRenderBuffer(AbstractOutput *output) const;
|
||||
|
||||
/**
|
||||
* The backend specific extensions (e.g. EGL/GLX extensions).
|
||||
|
@ -214,7 +214,7 @@ protected:
|
|||
*
|
||||
* @p damage contains the reported damage as suggested by windows and effects on prepaint calls.
|
||||
*/
|
||||
virtual void aboutToStartPainting(int screenId, const QRegion &damage);
|
||||
virtual void aboutToStartPainting(AbstractOutput *output, const QRegion &damage);
|
||||
// called after all effects had their paintWindow() called
|
||||
void finalPaintWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data);
|
||||
// shared implementation, starts painting the window
|
||||
|
@ -245,15 +245,15 @@ protected:
|
|||
// The dirty region before it was unioned with repaint_region
|
||||
QRegion damaged_region;
|
||||
// The screen that is being currently painted
|
||||
int painted_screen = -1;
|
||||
AbstractOutput *painted_screen = nullptr;
|
||||
|
||||
// windows in their stacking order
|
||||
QVector< Window* > stacking_order;
|
||||
private:
|
||||
void removeRepaints(AbstractOutput *output);
|
||||
std::chrono::milliseconds m_expectedPresentTimestamp = std::chrono::milliseconds::zero();
|
||||
void reallocRepaints();
|
||||
QHash< Toplevel*, Window* > m_windows;
|
||||
QVector<QRegion> m_repaints;
|
||||
QMap<AbstractOutput *, QRegion> m_repaints;
|
||||
// how many times finalPaintScreen() has been called
|
||||
int m_paintScreenCount = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue