Move direct scanout management to Compositor
The responsibilities of the Scene must be reduced to painting only so we can move forward with the layer-based compositing. This change moves direct scanout logic from the opengl scene to the base scene class and the compositor. It makes the opengl scene less overloaded and allows to share direct scanout logic.
This commit is contained in:
parent
886173cabe
commit
203d7b3b8a
15 changed files with 164 additions and 197 deletions
|
@ -306,11 +306,6 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output
|
|||
return m_surfaces[output]->texture();
|
||||
}
|
||||
|
||||
bool EglGbmBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
return !output->usesSoftwareCursor() && !output->directScanoutInhibited();
|
||||
}
|
||||
|
||||
GbmFormat EglGbmBackend::gbmFormatForDrmFormat(uint32_t format) const
|
||||
{
|
||||
// TODO use a hardcoded lookup table where needed instead?
|
||||
|
|
|
@ -69,8 +69,6 @@ public:
|
|||
|
||||
QSharedPointer<GLTexture> textureForOutput(AbstractOutput *requestedOutput) const override;
|
||||
|
||||
bool directScanoutAllowed(AbstractOutput *output) const override;
|
||||
|
||||
QSharedPointer<DrmBuffer> testBuffer(DrmAbstractOutput *output);
|
||||
EGLConfig config(uint32_t format) const;
|
||||
GbmFormat gbmFormatForDrmFormat(uint32_t format) const;
|
||||
|
|
|
@ -591,38 +591,6 @@ void Compositor::handleFrameRequested(RenderLoop *renderLoop)
|
|||
composite(renderLoop);
|
||||
}
|
||||
|
||||
QList<Toplevel *> Compositor::windowsToRender() const
|
||||
{
|
||||
// Create a list of all windows in the stacking order
|
||||
QList<Toplevel *> windows = Workspace::self()->xStackingOrder();
|
||||
|
||||
// Move elevated windows to the top of the stacking order
|
||||
const QList<EffectWindow *> elevatedList = static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows();
|
||||
for (EffectWindow *c : elevatedList) {
|
||||
Toplevel *t = static_cast<EffectWindowImpl *>(c)->window();
|
||||
windows.removeAll(t);
|
||||
windows.append(t);
|
||||
}
|
||||
|
||||
// Skip windows that are not yet ready for being painted and if screen is locked skip windows
|
||||
// that are neither lockscreen nor inputmethod windows.
|
||||
//
|
||||
// TODO? This cannot be used so carelessly - needs protections against broken clients, the
|
||||
// window should not get focus before it's displayed, handle unredirected windows properly and
|
||||
// so on.
|
||||
for (Toplevel *win : windows) {
|
||||
if (!win->readyForPainting()) {
|
||||
windows.removeAll(win);
|
||||
}
|
||||
if (waylandServer() && waylandServer()->isScreenLocked()) {
|
||||
if(!win->isLockScreen() && !win->isInputMethod()) {
|
||||
windows.removeAll(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
return windows;
|
||||
}
|
||||
|
||||
void Compositor::composite(RenderLoop *renderLoop)
|
||||
{
|
||||
if (m_backend->checkGraphicsReset()) {
|
||||
|
@ -635,39 +603,31 @@ void Compositor::composite(RenderLoop *renderLoop)
|
|||
AbstractOutput *output = findOutput(renderLoop);
|
||||
fTraceDuration("Paint (", output->name(), ")");
|
||||
|
||||
const auto windows = windowsToRender();
|
||||
|
||||
const QRegion repaints = m_scene->repaints(output);
|
||||
const QRegion damage = m_scene->repaints(output);
|
||||
m_scene->resetRepaints(output);
|
||||
m_scene->prePaint(output);
|
||||
|
||||
m_scene->paint(output, repaints, windows, renderLoop);
|
||||
SurfaceItem *scanoutCandidate = m_scene->scanoutCandidate();
|
||||
renderLoop->setFullscreenSurface(scanoutCandidate);
|
||||
|
||||
if (waylandServer()) {
|
||||
const std::chrono::milliseconds frameTime =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(renderLoop->lastPresentationTimestamp());
|
||||
|
||||
for (Toplevel *window : windows) {
|
||||
if (!window->readyForPainting()) {
|
||||
continue;
|
||||
}
|
||||
if (waylandServer()->isScreenLocked() &&
|
||||
!(window->isLockScreen() || window->isInputMethod())) {
|
||||
continue;
|
||||
}
|
||||
if (!window->isOnOutput(output)) {
|
||||
continue;
|
||||
}
|
||||
if (auto surface = window->surface()) {
|
||||
surface->frameRendered(frameTime.count());
|
||||
}
|
||||
}
|
||||
if (!Cursors::self()->isCursorHidden()) {
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
if (cursor->geometry().intersects(output->geometry())) {
|
||||
cursor->markAsRendered(frameTime);
|
||||
}
|
||||
renderLoop->beginFrame();
|
||||
bool directScanout = false;
|
||||
if (scanoutCandidate) {
|
||||
if (!output->usesSoftwareCursor() && !output->directScanoutInhibited()) {
|
||||
directScanout = m_backend->scanout(output, scanoutCandidate);
|
||||
}
|
||||
}
|
||||
if (directScanout) {
|
||||
renderLoop->endFrame();
|
||||
} else {
|
||||
QRegion update, valid;
|
||||
const QRegion repaint = m_backend->beginFrame(output);
|
||||
m_scene->paint(damage, repaint, update, valid);
|
||||
renderLoop->endFrame();
|
||||
m_backend->endFrame(output, valid, update);
|
||||
}
|
||||
|
||||
m_scene->postPaint();
|
||||
}
|
||||
|
||||
bool Compositor::isActive()
|
||||
|
|
|
@ -84,7 +84,6 @@ public:
|
|||
// for delayed supportproperty management of effects
|
||||
void keepSupportProperty(xcb_atom_t atom);
|
||||
void removeSupportProperty(xcb_atom_t atom);
|
||||
QList<Toplevel *> windowsToRender() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void compositingToggled(bool active);
|
||||
|
|
|
@ -1776,7 +1776,7 @@ void EffectsHandlerImpl::slotOutputDisabled(AbstractOutput *output)
|
|||
void EffectsHandlerImpl::renderScreen(EffectScreen *screen)
|
||||
{
|
||||
auto output = static_cast<EffectScreenImpl *>(screen)->platformOutput();
|
||||
scene()->paintScreen(output, Compositor::self()->windowsToRender());
|
||||
scene()->paintScreen(output);
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::isCursorHidden() const
|
||||
|
|
|
@ -43,13 +43,6 @@ void OpenGLBackend::setFailed(const QString &reason)
|
|||
m_failed = true;
|
||||
}
|
||||
|
||||
bool OpenGLBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem)
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(surfaceItem)
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenGLBackend::copyPixels(const QRegion ®ion)
|
||||
{
|
||||
const int height = screens()->size().height();
|
||||
|
@ -75,13 +68,6 @@ void OpenGLBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &
|
|||
Q_UNUSED(damage)
|
||||
}
|
||||
|
||||
|
||||
bool OpenGLBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
Q_UNUSED(output);
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceTexture *OpenGLBackend::createSurfaceTextureInternal(SurfacePixmapInternal *pixmap)
|
||||
{
|
||||
Q_UNUSED(pixmap)
|
||||
|
|
|
@ -63,11 +63,6 @@ public:
|
|||
virtual void aboutToStartPainting(AbstractOutput *output, const QRegion &damage);
|
||||
virtual bool makeCurrent() = 0;
|
||||
virtual void doneCurrent() = 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(AbstractOutput *output, SurfaceItem *surfaceItem);
|
||||
|
||||
/**
|
||||
* @brief Whether the creation of the Backend failed.
|
||||
|
@ -109,7 +104,6 @@ public:
|
|||
{
|
||||
return m_haveNativeFence;
|
||||
}
|
||||
virtual bool directScanoutAllowed(AbstractOutput *output) const;
|
||||
|
||||
/**
|
||||
* The backend specific extensions (e.g. EGL/GLX extensions).
|
||||
|
|
|
@ -24,4 +24,11 @@ bool RenderBackend::checkGraphicsReset()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RenderBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem)
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(surfaceItem)
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace KWin
|
|||
|
||||
class AbstractOutput;
|
||||
class OverlayWindow;
|
||||
class SurfaceItem;
|
||||
|
||||
/**
|
||||
* The RenderBackend class is the base class for all rendering backends.
|
||||
|
@ -33,6 +34,12 @@ public:
|
|||
|
||||
virtual QRegion beginFrame(AbstractOutput *output) = 0;
|
||||
virtual void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) = 0;
|
||||
|
||||
/**
|
||||
* Tries to directly scan out a surface to the screen
|
||||
* Returns @c true if scanout succeeds, @c false if rendering is necessary
|
||||
*/
|
||||
virtual bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem);
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
116
src/scene.cpp
116
src/scene.cpp
|
@ -76,6 +76,8 @@
|
|||
#include "composite.h"
|
||||
#include <QtMath>
|
||||
|
||||
#include <KWaylandServer/surface_interface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -186,6 +188,84 @@ void Scene::removeRepaints(AbstractOutput *output)
|
|||
m_repaints.remove(output);
|
||||
}
|
||||
|
||||
static SurfaceItem *findTopMostSurface(SurfaceItem *item)
|
||||
{
|
||||
const QList<Item *> children = item->childItems();
|
||||
if (children.isEmpty()) {
|
||||
return item;
|
||||
} else {
|
||||
return findTopMostSurface(static_cast<SurfaceItem *>(children.constLast()));
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceItem *Scene::scanoutCandidate() const
|
||||
{
|
||||
SurfaceItem *candidate = nullptr;
|
||||
if (!static_cast<EffectsHandlerImpl*>(effects)->blocksDirectScanout()) {
|
||||
for (int i = stacking_order.count() - 1; i >=0; i--) {
|
||||
Window *window = stacking_order[i];
|
||||
Toplevel *toplevel = window->window();
|
||||
if (painted_screen && toplevel->isOnOutput(painted_screen) && window->isVisible() && toplevel->opacity() > 0) {
|
||||
AbstractClient *c = dynamic_cast<AbstractClient*>(toplevel);
|
||||
if (!c || !c->isFullScreen()) {
|
||||
break;
|
||||
}
|
||||
if (!window->surfaceItem()) {
|
||||
break;
|
||||
}
|
||||
SurfaceItem *topMost = findTopMostSurface(window->surfaceItem());
|
||||
auto pixmap = topMost->pixmap();
|
||||
if (!pixmap) {
|
||||
break;
|
||||
}
|
||||
pixmap->update();
|
||||
// the subsurface has to be able to cover the whole window
|
||||
if (topMost->position() != QPoint(0, 0)) {
|
||||
break;
|
||||
}
|
||||
// and it has to be completely opaque
|
||||
if (!window->isOpaque() && !topMost->opaque().contains(QRect(0, 0, window->width(), window->height()))) {
|
||||
break;
|
||||
}
|
||||
candidate = topMost;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
void Scene::prePaint(AbstractOutput *output)
|
||||
{
|
||||
createStackingOrder();
|
||||
painted_screen = output;
|
||||
}
|
||||
|
||||
void Scene::postPaint()
|
||||
{
|
||||
if (waylandServer()) {
|
||||
const std::chrono::milliseconds frameTime =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(painted_screen->renderLoop()->lastPresentationTimestamp());
|
||||
|
||||
for (Window *window : std::as_const(m_windows)) {
|
||||
Toplevel *toplevel = window->window();
|
||||
if (!toplevel->isOnOutput(painted_screen)) {
|
||||
continue;
|
||||
}
|
||||
if (auto surface = toplevel->surface()) {
|
||||
surface->frameRendered(frameTime.count());
|
||||
}
|
||||
}
|
||||
if (!Cursors::self()->isCursorHidden()) {
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
if (cursor->geometry().intersects(painted_screen->geometry())) {
|
||||
cursor->markAsRendered(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearStackingOrder();
|
||||
}
|
||||
|
||||
static QMatrix4x4 createProjectionMatrix(const QRect &rect)
|
||||
{
|
||||
|
@ -252,9 +332,9 @@ QRegion Scene::mapToRenderTarget(const QRegion ®ion) const
|
|||
return result;
|
||||
}
|
||||
|
||||
void Scene::paintScreen(AbstractOutput *output, const QList<Toplevel *> &toplevels)
|
||||
void Scene::paintScreen(AbstractOutput *output)
|
||||
{
|
||||
createStackingOrder(toplevels);
|
||||
createStackingOrder();
|
||||
painted_screen = output;
|
||||
|
||||
QRegion update, valid;
|
||||
|
@ -594,10 +674,38 @@ void Scene::windowClosed(Toplevel *toplevel, Deleted *deleted)
|
|||
m_windows[deleted] = window;
|
||||
}
|
||||
|
||||
void Scene::createStackingOrder(const QList<Toplevel *> &toplevels)
|
||||
void Scene::createStackingOrder()
|
||||
{
|
||||
// Create a list of all windows in the stacking order
|
||||
QList<Toplevel *> windows = Workspace::self()->xStackingOrder();
|
||||
|
||||
// Move elevated windows to the top of the stacking order
|
||||
const QList<EffectWindow *> elevatedList = static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows();
|
||||
for (EffectWindow *c : elevatedList) {
|
||||
Toplevel *t = static_cast<EffectWindowImpl *>(c)->window();
|
||||
windows.removeAll(t);
|
||||
windows.append(t);
|
||||
}
|
||||
|
||||
// Skip windows that are not yet ready for being painted and if screen is locked skip windows
|
||||
// that are neither lockscreen nor inputmethod windows.
|
||||
//
|
||||
// TODO? This cannot be used so carelessly - needs protections against broken clients, the
|
||||
// window should not get focus before it's displayed, handle unredirected windows properly and
|
||||
// so on.
|
||||
for (Toplevel *win : windows) {
|
||||
if (!win->readyForPainting()) {
|
||||
windows.removeAll(win);
|
||||
}
|
||||
if (waylandServer() && waylandServer()->isScreenLocked()) {
|
||||
if(!win->isLockScreen() && !win->isInputMethod()) {
|
||||
windows.removeAll(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cache the stacking_order in case it has not changed
|
||||
for (Toplevel *c : toplevels) {
|
||||
for (Toplevel *c : std::as_const(windows)) {
|
||||
Q_ASSERT(m_windows.contains(c));
|
||||
stacking_order.append(m_windows[ c ]);
|
||||
}
|
||||
|
|
14
src/scene.h
14
src/scene.h
|
@ -74,15 +74,13 @@ public:
|
|||
// Returns true if the ctor failed to properly initialize.
|
||||
virtual bool initFailed() const = 0;
|
||||
|
||||
// Repaints the given screen areas, windows provides the stacking order.
|
||||
// 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(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) = 0;
|
||||
SurfaceItem *scanoutCandidate() const;
|
||||
|
||||
void prePaint(AbstractOutput *output);
|
||||
void postPaint();
|
||||
virtual void paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid) = 0;
|
||||
|
||||
void paintScreen(AbstractOutput *output, const QList<Toplevel *> &toplevels);
|
||||
void paintScreen(AbstractOutput *output);
|
||||
|
||||
/**
|
||||
* Adds the Toplevel to the Scene.
|
||||
|
@ -205,7 +203,7 @@ public Q_SLOTS:
|
|||
void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted);
|
||||
protected:
|
||||
virtual Window *createWindow(Toplevel *toplevel) = 0;
|
||||
void createStackingOrder(const QList<Toplevel *> &toplevels);
|
||||
void createStackingOrder();
|
||||
void clearStackingOrder();
|
||||
// shared implementation, starts painting the screen
|
||||
void paintScreen(const QRegion &damage, const QRegion &repaint,
|
||||
|
|
|
@ -174,83 +174,12 @@ void SceneOpenGL::aboutToStartPainting(AbstractOutput *output, const QRegion &da
|
|||
m_backend->aboutToStartPainting(output, damage);
|
||||
}
|
||||
|
||||
static SurfaceItem *findTopMostSurface(SurfaceItem *item)
|
||||
void SceneOpenGL::paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid)
|
||||
{
|
||||
const QList<Item *> children = item->childItems();
|
||||
if (children.isEmpty()) {
|
||||
return item;
|
||||
} else {
|
||||
return findTopMostSurface(static_cast<SurfaceItem *>(children.constLast()));
|
||||
}
|
||||
}
|
||||
|
||||
void SceneOpenGL::paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
RenderLoop *renderLoop)
|
||||
{
|
||||
painted_screen = output;
|
||||
// actually paint the frame, flushed with the NEXT frame
|
||||
createStackingOrder(toplevels);
|
||||
|
||||
QRegion update;
|
||||
QRegion valid;
|
||||
QRegion repaint;
|
||||
|
||||
renderLoop->beginFrame();
|
||||
|
||||
SurfaceItem *fullscreenSurface = nullptr;
|
||||
for (int i = stacking_order.count() - 1; i >=0; i--) {
|
||||
Window *window = stacking_order[i];
|
||||
Toplevel *toplevel = window->window();
|
||||
if (output && toplevel->isOnOutput(output) && window->isVisible() && toplevel->opacity() > 0) {
|
||||
AbstractClient *c = dynamic_cast<AbstractClient*>(toplevel);
|
||||
if (!c || !c->isFullScreen()) {
|
||||
break;
|
||||
}
|
||||
if (!window->surfaceItem()) {
|
||||
break;
|
||||
}
|
||||
SurfaceItem *topMost = findTopMostSurface(window->surfaceItem());
|
||||
auto pixmap = topMost->pixmap();
|
||||
if (!pixmap) {
|
||||
break;
|
||||
}
|
||||
pixmap->update();
|
||||
// the subsurface has to be able to cover the whole window
|
||||
if (topMost->position() != QPoint(0, 0)) {
|
||||
break;
|
||||
}
|
||||
// and it has to be completely opaque
|
||||
if (!window->isOpaque() && !topMost->opaque().contains(QRect(0, 0, window->width(), window->height()))) {
|
||||
break;
|
||||
}
|
||||
fullscreenSurface = topMost;
|
||||
break;
|
||||
}
|
||||
}
|
||||
renderLoop->setFullscreenSurface(fullscreenSurface);
|
||||
|
||||
bool directScanout = false;
|
||||
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(output);
|
||||
GLVertexBuffer::streamingBuffer()->beginFrame();
|
||||
|
||||
paintScreen(damage, repaint, &update, &valid);
|
||||
paintCursor(output, valid);
|
||||
|
||||
renderLoop->endFrame();
|
||||
|
||||
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
||||
m_backend->endFrame(output, valid, update);
|
||||
}
|
||||
|
||||
// do cleanup
|
||||
clearStackingOrder();
|
||||
GLVertexBuffer::streamingBuffer()->beginFrame();
|
||||
paintScreen(damage, repaint, &update, &valid);
|
||||
paintCursor(painted_screen, valid);
|
||||
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
||||
}
|
||||
|
||||
QMatrix4x4 SceneOpenGL::transformation(int mask, const ScreenPaintData &data) const
|
||||
|
|
|
@ -33,8 +33,7 @@ public:
|
|||
explicit SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
|
||||
~SceneOpenGL() override;
|
||||
bool initFailed() const override;
|
||||
void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) override;
|
||||
void paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid) override;
|
||||
Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
||||
Shadow *createShadow(Toplevel *toplevel) override;
|
||||
bool makeOpenGLContextCurrent() override;
|
||||
|
|
|
@ -68,34 +68,22 @@ void SceneQPainter::paintGenericScreen(int mask, const ScreenPaintData &data)
|
|||
m_painter->restore();
|
||||
}
|
||||
|
||||
void SceneQPainter::paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &toplevels,
|
||||
RenderLoop *renderLoop)
|
||||
void SceneQPainter::paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid)
|
||||
{
|
||||
Q_ASSERT(kwinApp()->platform()->isPerScreenRenderingEnabled());
|
||||
painted_screen = output;
|
||||
|
||||
createStackingOrder(toplevels);
|
||||
|
||||
const QRegion repaint = m_backend->beginFrame(output);
|
||||
const QRect geometry = output->geometry();
|
||||
|
||||
QImage *buffer = m_backend->bufferForScreen(output);
|
||||
QImage *buffer = m_backend->bufferForScreen(painted_screen);
|
||||
if (buffer && !buffer->isNull()) {
|
||||
renderLoop->beginFrame();
|
||||
const QRect geometry = painted_screen->geometry();
|
||||
m_painter->begin(buffer);
|
||||
m_painter->setWindow(geometry);
|
||||
|
||||
QRegion updateRegion, validRegion;
|
||||
paintScreen(damage, repaint, &updateRegion, &validRegion);
|
||||
paintCursor(output, updateRegion);
|
||||
paintCursor(painted_screen, updateRegion);
|
||||
|
||||
m_painter->end();
|
||||
renderLoop->endFrame();
|
||||
m_backend->endFrame(output, validRegion, updateRegion);
|
||||
}
|
||||
|
||||
// do cleanup
|
||||
clearStackingOrder();
|
||||
}
|
||||
|
||||
void SceneQPainter::paintBackground(const QRegion ®ion)
|
||||
|
|
|
@ -23,8 +23,7 @@ class KWIN_EXPORT SceneQPainter : public Scene
|
|||
|
||||
public:
|
||||
~SceneQPainter() override;
|
||||
void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
|
||||
RenderLoop *renderLoop) override;
|
||||
void paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid) override;
|
||||
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
||||
bool initFailed() const override;
|
||||
EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
||||
|
|
Loading…
Reference in a new issue