Move paint method from SceneWindow to Scene

That's the next step in allowing to reuse surface painting code between
the workspace and the cursor layer.
This commit is contained in:
Vlad Zahorodnii 2022-05-07 11:42:41 +03:00
parent 683a222233
commit bc1f808f0f
11 changed files with 65 additions and 131 deletions

View file

@ -198,6 +198,11 @@ DecorationRenderer *DecorationItem::renderer() const
return m_renderer.data();
}
Window *DecorationItem::window() const
{
return m_window;
}
WindowQuad buildQuad(const QRect &partRect, const QPoint &textureOffset,
const qreal devicePixelRatio, bool rotated)
{

View file

@ -81,6 +81,7 @@ public:
explicit DecorationItem(KDecoration2::Decoration *decoration, Window *window, Item *parent = nullptr);
DecorationRenderer *renderer() const;
Window *window() const;
private Q_SLOTS:
void handleFrameGeometryChanged();

View file

@ -7,6 +7,7 @@
#include "windowscreencastsource.h"
#include "screencastutils.h"
#include "composite.h"
#include "deleted.h"
#include "effects.h"
#include "kwineffects.h"
@ -16,6 +17,7 @@
#include "renderloop.h"
#include "scene.h"
#include "window.h"
#include "windowitem.h"
namespace KWin
{
@ -59,7 +61,7 @@ void WindowScreenCastSource::render(GLFramebuffer *target)
GLFramebuffer::pushFramebuffer(target);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
m_window->sceneWindow()->performPaint(Scene::PAINT_WINDOW_TRANSFORMED, infiniteRegion(), data);
Compositor::self()->scene()->render(m_window->windowItem(), Scene::PAINT_WINDOW_TRANSFORMED, infiniteRegion(), data);
GLFramebuffer::popFramebuffer();
}

View file

@ -600,7 +600,7 @@ void Scene::finalPaintWindow(EffectWindowImpl *w, int mask, const QRegion &regio
// will be eventually called from drawWindow()
void Scene::finalDrawWindow(EffectWindowImpl *w, int mask, const QRegion &region, WindowPaintData &data)
{
w->sceneWindow()->performPaint(mask, region, data);
render(w->sceneWindow()->windowItem(), mask, region, data);
}
bool Scene::makeOpenGLContextCurrent()

View file

@ -103,17 +103,6 @@ public:
void postPaint();
virtual void paint(RenderTarget *renderTarget, const QRegion &region) = 0;
/**
* Adds the Window to the Scene.
*
* If the window gets deleted, then the scene will try automatically
* to re-bind an underlying scene window to the corresponding Deleted.
*
* @param window The window to be added.
* @note You can add a window to scene only once.
*/
virtual SceneWindow *createWindow(Window *window) = 0;
/**
* @brief Creates the Scene backend of an EffectFrame.
*
@ -197,6 +186,8 @@ public:
QRegion mapToRenderTarget(const QRegion &region) const;
virtual void render(Item *item, int mask, const QRegion &region, const WindowPaintData &data) = 0;
Q_SIGNALS:
void frameRendered();
@ -268,8 +259,6 @@ class SceneWindow : public QObject
public:
explicit SceneWindow(Window *client, QObject *parent = nullptr);
~SceneWindow() override;
// perform the actual painting of the window
virtual void performPaint(int mask, const QRegion &region, const WindowPaintData &data) = 0;
int x() const;
int y() const;
int width() const;

View file

@ -292,26 +292,7 @@ void SceneOpenGL::doPaintBackground(const QVector<float> &vertices)
vbo->render(GL_TRIANGLES);
}
SceneWindow *SceneOpenGL::createWindow(Window *t)
{
return new OpenGLWindow(t, this);
}
//****************************************
// OpenGLWindow
//****************************************
OpenGLWindow::OpenGLWindow(Window *window, SceneOpenGL *scene)
: SceneWindow(window)
, m_scene(scene)
{
}
OpenGLWindow::~OpenGLWindow()
{
}
QVector4D OpenGLWindow::modulate(float opacity, float brightness) const
QVector4D SceneOpenGL::modulate(float opacity, float brightness) const
{
const float a = opacity;
const float rgb = opacity * brightness;
@ -319,7 +300,7 @@ QVector4D OpenGLWindow::modulate(float opacity, float brightness) const
return QVector4D(rgb, rgb, rgb, a);
}
void OpenGLWindow::setBlendEnabled(bool enabled)
void SceneOpenGL::setBlendEnabled(bool enabled)
{
if (enabled && !m_blendingEnabled) {
glEnable(GL_BLEND);
@ -359,7 +340,7 @@ static GLTexture *bindSurfaceTexture(SurfaceItem *surfaceItem)
return platformSurfaceTexture->texture();
}
static WindowQuadList clipQuads(const Item *item, const OpenGLWindow::RenderContext *context)
static WindowQuadList clipQuads(const Item *item, const SceneOpenGL::RenderContext *context)
{
const WindowQuadList quads = item->quads();
if (context->clip != infiniteRegion() && !context->hardwareClipping) {
@ -390,7 +371,7 @@ static WindowQuadList clipQuads(const Item *item, const OpenGLWindow::RenderCont
return quads;
}
void OpenGLWindow::createRenderNode(Item *item, RenderContext *context)
void SceneOpenGL::createRenderNode(Item *item, RenderContext *context)
{
const QList<Item *> sortedChildItems = item->sortedChildItems();
@ -466,7 +447,7 @@ void OpenGLWindow::createRenderNode(Item *item, RenderContext *context)
context->transforms.pop();
}
QMatrix4x4 OpenGLWindow::modelViewProjectionMatrix(int mask, const WindowPaintData &data) const
QMatrix4x4 SceneOpenGL::modelViewProjectionMatrix(int mask, const WindowPaintData &data) const
{
const QMatrix4x4 pMatrix = data.projectionMatrix();
const QMatrix4x4 mvMatrix = data.modelViewMatrix();
@ -484,10 +465,10 @@ QMatrix4x4 OpenGLWindow::modelViewProjectionMatrix(int mask, const WindowPaintDa
// with the default projection matrix. If the effect hasn't specified a
// model-view matrix, mvMatrix will be the identity matrix.
if (mask & Scene::PAINT_SCREEN_TRANSFORMED) {
return m_scene->screenProjectionMatrix() * mvMatrix;
return screenProjectionMatrix() * mvMatrix;
}
return m_scene->renderTargetProjectionMatrix() * mvMatrix;
return renderTargetProjectionMatrix() * mvMatrix;
}
static QMatrix4x4 transformForPaintData(int mask, const WindowPaintData &data)
@ -517,7 +498,7 @@ static QMatrix4x4 transformForPaintData(int mask, const WindowPaintData &data)
return matrix;
}
void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPaintData &data)
void SceneOpenGL::render(Item *item, int mask, const QRegion &region, const WindowPaintData &data)
{
if (region.isEmpty()) {
return;
@ -531,9 +512,9 @@ void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPai
renderContext.transforms.push(QMatrix4x4());
windowItem()->setTransform(transformForPaintData(mask, data));
item->setTransform(transformForPaintData(mask, data));
createRenderNode(windowItem(), &renderContext);
createRenderNode(item, &renderContext);
int quadCount = 0;
for (const RenderNode &node : qAsConst(renderContext.renderNodes)) {
@ -605,7 +586,7 @@ void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPai
// The scissor region must be in the render target local coordinate system.
QRegion scissorRegion = infiniteRegion();
if (renderContext.hardwareClipping) {
scissorRegion = m_scene->mapToRenderTarget(region);
scissorRegion = mapToRenderTarget(region);
}
const QMatrix4x4 modelViewProjection = modelViewProjectionMatrix(mask, data);

View file

@ -28,6 +28,27 @@ class KWIN_EXPORT SceneOpenGL
{
Q_OBJECT
public:
struct RenderNode
{
GLTexture *texture = nullptr;
WindowQuadList quads;
QMatrix4x4 transformMatrix;
int firstVertex = 0;
int vertexCount = 0;
qreal opacity = 1;
bool hasAlpha = false;
TextureCoordinateType coordinateType = UnnormalizedCoordinates;
};
struct RenderContext
{
QVector<RenderNode> renderNodes;
QStack<QMatrix4x4> transforms;
const QRegion clip;
const WindowPaintData &paintData;
const bool hardwareClipping;
};
class EffectFrame;
explicit SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
~SceneOpenGL() override;
@ -43,6 +64,7 @@ public:
SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
SurfaceTexture *createSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
void render(Item *item, int mask, const QRegion &region, const WindowPaintData &data) override;
OpenGLBackend *backend() const
{
@ -67,55 +89,18 @@ protected:
void paintSimpleScreen(int mask, const QRegion &region) override;
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
SceneWindow *createWindow(Window *t) override;
private:
void doPaintBackground(const QVector<float> &vertices);
bool init_ok = true;
OpenGLBackend *m_backend;
QMatrix4x4 m_screenProjectionMatrix;
GLuint vao = 0;
};
class OpenGLWindow final : public SceneWindow
{
Q_OBJECT
public:
struct RenderNode
{
GLTexture *texture = nullptr;
WindowQuadList quads;
QMatrix4x4 transformMatrix;
int firstVertex = 0;
int vertexCount = 0;
qreal opacity = 1;
bool hasAlpha = false;
TextureCoordinateType coordinateType = UnnormalizedCoordinates;
};
struct RenderContext
{
QVector<RenderNode> renderNodes;
QStack<QMatrix4x4> transforms;
const QRegion clip;
const WindowPaintData &paintData;
const bool hardwareClipping;
};
OpenGLWindow(Window *window, SceneOpenGL *scene);
~OpenGLWindow() override;
void performPaint(int mask, const QRegion &region, const WindowPaintData &data) override;
private:
QMatrix4x4 modelViewProjectionMatrix(int mask, const WindowPaintData &data) const;
QVector4D modulate(float opacity, float brightness) const;
void setBlendEnabled(bool enabled);
void createRenderNode(Item *item, RenderContext *context);
SceneOpenGL *m_scene;
bool init_ok = true;
OpenGLBackend *m_backend;
QMatrix4x4 m_screenProjectionMatrix;
GLuint vao = 0;
bool m_blendingEnabled = false;
};

View file

@ -98,11 +98,6 @@ void SceneQPainter::paintOffscreenQuickView(OffscreenQuickView *w)
painter->restore();
}
SceneWindow *SceneQPainter::createWindow(Window *window)
{
return new SceneQPainterWindow(this, window);
}
Scene::EffectFrame *SceneQPainter::createEffectFrame(EffectFrameImpl *frame)
{
return new QPainterEffectFrame(frame, this);
@ -113,24 +108,11 @@ Shadow *SceneQPainter::createShadow(Window *window)
return new SceneQPainterShadow(window);
}
//****************************************
// SceneQPainterWindow
//****************************************
SceneQPainterWindow::SceneQPainterWindow(SceneQPainter *scene, Window *c)
: SceneWindow(c)
, m_scene(scene)
{
}
SceneQPainterWindow::~SceneQPainterWindow()
{
}
void SceneQPainterWindow::performPaint(int mask, const QRegion &_region, const WindowPaintData &data)
void SceneQPainter::render(Item *item, int mask, const QRegion &_region, const WindowPaintData &data)
{
QRegion region = _region;
const QRect boundingRect = windowItem()->mapToGlobal(windowItem()->boundingRect());
const QRect boundingRect = item->mapToGlobal(item->boundingRect());
if (!(mask & (Scene::PAINT_WINDOW_TRANSFORMED | Scene::PAINT_SCREEN_TRANSFORMED))) {
region &= boundingRect;
}
@ -139,8 +121,7 @@ void SceneQPainterWindow::performPaint(int mask, const QRegion &_region, const W
return;
}
QPainter *scenePainter = m_scene->scenePainter();
QPainter *painter = scenePainter;
QPainter *painter = scenePainter();
painter->save();
painter->setClipRegion(region);
painter->setClipping(true);
@ -163,7 +144,7 @@ void SceneQPainterWindow::performPaint(int mask, const QRegion &_region, const W
painter = &tempPainter;
}
renderItem(painter, windowItem());
renderItem(painter, item);
if (!opaque) {
tempPainter.restore();
@ -172,14 +153,14 @@ void SceneQPainterWindow::performPaint(int mask, const QRegion &_region, const W
translucent.setAlphaF(data.opacity());
tempPainter.fillRect(QRect(QPoint(0, 0), boundingRect.size()), translucent);
tempPainter.end();
painter = scenePainter;
painter = scenePainter();
painter->drawImage(boundingRect.topLeft(), tempImage);
}
painter->restore();
}
void SceneQPainterWindow::renderItem(QPainter *painter, Item *item) const
void SceneQPainter::renderItem(QPainter *painter, Item *item) const
{
const QList<Item *> sortedChildItems = item->sortedChildItems();
@ -214,7 +195,7 @@ void SceneQPainterWindow::renderItem(QPainter *painter, Item *item) const
painter->restore();
}
void SceneQPainterWindow::renderSurfaceItem(QPainter *painter, SurfaceItem *surfaceItem) const
void SceneQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *surfaceItem) const
{
const SurfacePixmap *surfaceTexture = surfaceItem->pixmap();
if (!surfaceTexture || !surfaceTexture->isValid()) {
@ -241,11 +222,11 @@ void SceneQPainterWindow::renderSurfaceItem(QPainter *painter, SurfaceItem *surf
}
}
void SceneQPainterWindow::renderDecorationItem(QPainter *painter, DecorationItem *decorationItem) const
void SceneQPainter::renderDecorationItem(QPainter *painter, DecorationItem *decorationItem) const
{
const auto renderer = static_cast<const SceneQPainterDecorationRenderer *>(decorationItem->renderer());
QRect dtr, dlr, drr, dbr;
m_window->layoutDecorationRects(dlr, dtr, drr, dbr);
decorationItem->window()->layoutDecorationRects(dlr, dtr, drr, dbr);
painter->drawImage(dtr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Top));
painter->drawImage(dlr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Left));

View file

@ -32,6 +32,7 @@ public:
DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
void render(Item *item, int mask, const QRegion &region, const WindowPaintData &data) override;
bool animationsSupported() const override
{
@ -49,29 +50,17 @@ public:
protected:
void paintBackground(const QRegion &region) override;
SceneWindow *createWindow(Window *window) override;
void paintOffscreenQuickView(OffscreenQuickView *w) override;
private:
explicit SceneQPainter(QPainterBackend *backend, QObject *parent = nullptr);
QPainterBackend *m_backend;
QScopedPointer<QPainter> m_painter;
};
class SceneQPainterWindow : public SceneWindow
{
Q_OBJECT
public:
SceneQPainterWindow(SceneQPainter *scene, Window *c);
~SceneQPainterWindow() override;
void performPaint(int mask, const QRegion &region, const WindowPaintData &data) override;
private:
void renderSurfaceItem(QPainter *painter, SurfaceItem *surfaceItem) const;
void renderDecorationItem(QPainter *painter, DecorationItem *decorationItem) const;
void renderItem(QPainter *painter, Item *item) const;
SceneQPainter *m_scene;
QPainterBackend *m_backend;
QScopedPointer<QPainter> m_painter;
};
class QPainterEffectFrame : public Scene::EffectFrame

View file

@ -15,6 +15,7 @@
#include "scripting_logging.h"
#include "virtualdesktops.h"
#include "window.h"
#include "windowitem.h"
#include "workspace.h"
#include <kwingltexture.h>
@ -438,7 +439,7 @@ void WindowThumbnailItem::updateOffscreenTexture()
// shared across contexts. Unfortunately, this also introduces a latency of 1
// frame, which is not ideal, but it is acceptable for things such as thumbnails.
const int mask = Scene::PAINT_WINDOW_TRANSFORMED;
m_client->sceneWindow()->performPaint(mask, infiniteRegion(), data);
Compositor::self()->scene()->render(m_client->windowItem(), mask, infiniteRegion(), data);
GLFramebuffer::popFramebuffer();
// The fence is needed to avoid the case where qtquick renderer starts using

View file

@ -349,7 +349,7 @@ bool Window::setupCompositing()
m_effectWindow = new EffectWindowImpl(this);
updateShadow();
m_sceneWindow = Compositor::self()->scene()->createWindow(this);
m_sceneWindow = new SceneWindow(this);
m_effectWindow->setSceneWindow(m_sceneWindow);
connect(windowItem(), &WindowItem::positionChanged, this, &Window::visibleGeometryChanged);