Move Scene::Window handling methods into base class

The pure virtual methods windowAdded, windowClosed, windowDeleted and
windowGeometryShapeChanged had identical implementations in both XRender
and OpenGL scene. They were accessing the hash with Scene::Windows which
is nowhere else used except for creating the stacking order in ::paint.

The implementations are moved to the base class, the only Scene specific
code is a pure virtual factory method to create the Scene window. This
already existed in SceneOpenGL to create either a SceneOpenGL1 or 2
window.

Also the hash of windows is a Scene private member now and the creation
of the stacking order is provided by a method, so that the Scene sub
classes do no longer need to access the stacking order at all.

REVIEW: 111207
icc-effect-5.14.5
Martin Gräßlin 2013-06-24 09:53:11 +02:00
parent 1a0e586b9c
commit ef4c32f79a
6 changed files with 88 additions and 126 deletions

View File

@ -98,6 +98,9 @@ Scene::Scene(Workspace* ws)
Scene::~Scene()
{
foreach (Window *w, m_windows) {
delete w;
}
}
// returns mask and possibly modified region
@ -391,6 +394,64 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
}
}
void Scene::windowAdded(Toplevel *c)
{
assert(!m_windows.contains(c));
Scene::Window *w = createWindow(c);
m_windows[ c ] = w;
connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(windowGeometryShapeChanged(KWin::Toplevel*)));
connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(windowClosed(KWin::Toplevel*,KWin::Deleted*)));
c->effectWindow()->setSceneWindow(w);
c->getShadow();
w->updateShadow(c->shadow());
}
void Scene::windowClosed(Toplevel *c, Deleted *deleted)
{
assert(m_windows.contains(c));
if (deleted != NULL) {
// replace c with deleted
Window* w = m_windows.take(c);
w->updateToplevel(deleted);
if (w->shadow()) {
w->shadow()->setToplevel(deleted);
}
m_windows[ deleted ] = w;
} else {
delete m_windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
}
void Scene::windowDeleted(Deleted *c)
{
assert(m_windows.contains(c));
delete m_windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
void Scene::windowGeometryShapeChanged(Toplevel *c)
{
if (!m_windows.contains(c)) // this is ok, shape is not valid by default
return;
Window *w = m_windows[ c ];
w->discardShape();
}
void Scene::createStackingOrder(ToplevelList toplevels)
{
// TODO: cache the stacking_order in case it has not changed
foreach (Toplevel *c, toplevels) {
assert(m_windows.contains(c));
stacking_order.append(m_windows[ c ]);
}
}
void Scene::clearStackingOrder()
{
stacking_order.clear();
}
static Scene::Window *s_recursionCheck = NULL;
void Scene::paintWindow(Window* w, int mask, QRegion region, WindowQuadList quads)

16
scene.h
View File

@ -65,7 +65,7 @@ public:
// Used to mainly discard cached data.
// a new window has been created
virtual void windowAdded(Toplevel*) = 0;
void windowAdded(Toplevel*);
/**
* @brief Creates the Scene backend of an EffectFrame.
*
@ -123,12 +123,15 @@ public:
public Q_SLOTS:
// a window has been destroyed
virtual void windowDeleted(KWin::Deleted*) = 0;
void windowDeleted(KWin::Deleted*);
// shape/size of a window changed
virtual void windowGeometryShapeChanged(KWin::Toplevel* c) = 0;
void windowGeometryShapeChanged(KWin::Toplevel* c);
// a window has been closed
virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted) = 0;
void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted);
protected:
virtual Window *createWindow(Toplevel *toplevel) = 0;
void createStackingOrder(ToplevelList toplevels);
void clearStackingOrder();
// shared implementation, starts painting the screen
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion);
@ -168,8 +171,6 @@ protected:
int mask;
WindowQuadList quads;
};
// windows in their stacking order
QVector< Window* > stacking_order;
// The region which actually has been painted by paintScreen() and should be
// copied from the buffer to the screen. I.e. the region returned from Scene::paintScreen().
// Since prePaintWindow() can extend areas to paint, these changes would have to propagate
@ -187,6 +188,9 @@ protected:
private:
void paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacity, qreal brightness, qreal saturation);
void paintDesktopThumbnails(Scene::Window *w);
QHash< Toplevel*, Window* > m_windows;
// windows in their stacking order
QVector< Window* > stacking_order;
};
// The base class for windows representations in composite backends

View File

@ -182,9 +182,6 @@ SceneOpenGL::~SceneOpenGL()
// backend might be still needed for a different scene
delete m_backend;
}
foreach (Window * w, windows) {
delete w;
}
// do cleanup after initBuffer()
SceneOpenGL::EffectFrame::cleanup();
checkGLError("Cleanup");
@ -360,11 +357,7 @@ void SceneOpenGL::handleGraphicsReset(GLenum status)
qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
{
// actually paint the frame, flushed with the NEXT frame
foreach (Toplevel * c, toplevels) {
// TODO: cache the stacking_order in case it has not changed
assert(windows.contains(c));
stacking_order.append(windows[ c ]);
}
createStackingOrder(toplevels);
m_backend->makeCurrent();
QRegion repaint = m_backend->prepareRenderingFrame();
@ -409,7 +402,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
m_backend->endRenderingFrame(validRegion, updateRegion);
// do cleanup
stacking_order.clear();
clearStackingOrder();
checkGLError("PostPaint");
return m_backend->renderTime();
}
@ -487,51 +480,6 @@ void SceneOpenGL::extendPaintRegion(QRegion &region, bool opaqueFullscreen)
}
}
void SceneOpenGL::windowAdded(Toplevel* c)
{
assert(!windows.contains(c));
Window *w = createWindow(c);
windows[ c ] = w;
w->setScene(this);
connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(windowGeometryShapeChanged(KWin::Toplevel*)));
connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(windowClosed(KWin::Toplevel*,KWin::Deleted*)));
c->effectWindow()->setSceneWindow(windows[ c ]);
c->getShadow();
windows[ c ]->updateShadow(c->shadow());
}
void SceneOpenGL::windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted)
{
assert(windows.contains(c));
if (deleted != NULL) {
// replace c with deleted
Window* w = windows.take(c);
w->updateToplevel(deleted);
if (w->shadow()) {
w->shadow()->setToplevel(deleted);
}
windows[ deleted ] = w;
} else {
delete windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
}
void SceneOpenGL::windowDeleted(Deleted* c)
{
assert(windows.contains(c));
delete windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
void SceneOpenGL::windowGeometryShapeChanged(KWin::Toplevel* c)
{
if (!windows.contains(c)) // this is ok, shape is not valid
return; // by default
Window* w = windows[ c ];
w->discardShape();
}
SceneOpenGL::Texture *SceneOpenGL::createTexture()
{
return new Texture(m_backend);
@ -754,9 +702,11 @@ void SceneOpenGL2::doPaintBackground(const QVector< float >& vertices)
vbo->render(GL_TRIANGLES);
}
SceneOpenGL::Window *SceneOpenGL2::createWindow(Toplevel *t)
Scene::Window *SceneOpenGL2::createWindow(Toplevel *t)
{
return new SceneOpenGL2Window(t);
SceneOpenGL2Window *w = new SceneOpenGL2Window(t);
w->setScene(this);
return w;
}
void SceneOpenGL2::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data)
@ -925,9 +875,11 @@ void SceneOpenGL1::screenGeometryChanged(const QSize &size)
m_resetModelViewProjectionMatrix = true;
}
SceneOpenGL::Window *SceneOpenGL1::createWindow(Toplevel *t)
Scene::Window *SceneOpenGL1::createWindow(Toplevel *t)
{
return new SceneOpenGL1Window(t);
SceneOpenGL1Window *w = new SceneOpenGL1Window(t);
w->setScene(this);
return w;
}
#endif

View File

@ -48,8 +48,6 @@ public:
virtual bool initFailed() const;
virtual bool hasPendingFlush() const;
virtual qint64 paint(QRegion damage, ToplevelList windows);
virtual void windowAdded(Toplevel*);
virtual void windowDeleted(Deleted*);
virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame);
virtual Shadow *createShadow(Toplevel *toplevel);
virtual void screenGeometryChanged(const QSize &size);
@ -90,20 +88,15 @@ protected:
void handleGraphicsReset(GLenum status);
virtual void doPaintBackground(const QVector<float> &vertices) = 0;
virtual SceneOpenGL::Window *createWindow(Toplevel *t) = 0;
Q_SIGNALS:
void resetCompositing();
public Q_SLOTS:
virtual void windowGeometryShapeChanged(KWin::Toplevel* c);
virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted);
protected:
bool init_ok;
private:
bool viewportLimitsMatched(const QSize &size) const;
private:
QHash< Toplevel*, Window* > windows;
bool m_debug;
OpenGLBackend *m_backend;
};
@ -125,7 +118,7 @@ public:
protected:
virtual void paintGenericScreen(int mask, ScreenPaintData data);
virtual void doPaintBackground(const QVector< float >& vertices);
virtual SceneOpenGL::Window *createWindow(Toplevel *t);
virtual Scene::Window *createWindow(Toplevel *t);
virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data);
virtual void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data);
@ -159,7 +152,7 @@ public:
protected:
virtual void paintGenericScreen(int mask, ScreenPaintData data);
virtual void doPaintBackground(const QVector< float >& vertices);
virtual SceneOpenGL::Window *createWindow(Toplevel *t);
virtual Scene::Window *createWindow(Toplevel *t);
private:
void setupModelViewProjectionMatrix();

View File

@ -120,8 +120,6 @@ SceneXrender::~SceneXrender()
xcb_render_free_picture(connection(), buffer);
buffer = XCB_RENDER_PICTURE_NONE;
m_overlayWindow->destroy();
foreach (Window * w, windows)
delete w;
delete m_overlayWindow;
}
@ -185,10 +183,7 @@ qint64 SceneXrender::paint(QRegion damage, ToplevelList toplevels)
QElapsedTimer renderTimer;
renderTimer.start();
foreach (Toplevel * c, toplevels) {
assert(windows.contains(c));
stacking_order.append(windows[ c ]);
}
createStackingOrder(toplevels);
int mask = 0;
QRegion updateRegion, validRegion;
@ -199,7 +194,7 @@ qint64 SceneXrender::paint(QRegion damage, ToplevelList toplevels)
present(mask, updateRegion);
// do cleanup
stacking_order.clear();
clearStackingOrder();
return renderTimer.nsecsElapsed();
}
@ -245,47 +240,9 @@ void SceneXrender::paintBackground(QRegion region)
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, buffer, col, rects.count(), rects.data());
}
void SceneXrender::windowGeometryShapeChanged(KWin::Toplevel* c)
Scene::Window *SceneXrender::createWindow(Toplevel *toplevel)
{
if (!windows.contains(c)) // this is ok, shape is not valid by default
return;
Window* w = windows[ c ];
w->discardShape();
}
void SceneXrender::windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted)
{
assert(windows.contains(c));
if (deleted != NULL) {
// replace c with deleted
Window* w = windows.take(c);
w->updateToplevel(deleted);
if (w->shadow()) {
w->shadow()->setToplevel(deleted);
}
windows[ deleted ] = w;
} else {
delete windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
}
void SceneXrender::windowDeleted(Deleted* c)
{
assert(windows.contains(c));
delete windows.take(c);
c->effectWindow()->setSceneWindow(NULL);
}
void SceneXrender::windowAdded(Toplevel* c)
{
assert(!windows.contains(c));
windows[ c ] = new Window(c);
connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(windowGeometryShapeChanged(KWin::Toplevel*)));
connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(windowClosed(KWin::Toplevel*,KWin::Deleted*)));
c->effectWindow()->setSceneWindow(windows[ c ]);
c->getShadow();
windows[ c ]->updateShadow(c->shadow());
return new Window(toplevel);
}
Scene::EffectFrame *SceneXrender::createEffectFrame(EffectFrameImpl *frame)

View File

@ -43,8 +43,6 @@ public:
return XRenderCompositing;
}
virtual qint64 paint(QRegion damage, ToplevelList windows);
virtual void windowAdded(Toplevel*);
virtual void windowDeleted(Deleted*);
virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame);
virtual Shadow *createShadow(Toplevel *toplevel);
virtual void screenGeometryChanged(const QSize &size);
@ -53,12 +51,10 @@ public:
return m_overlayWindow;
}
protected:
virtual Scene::Window *createWindow(Toplevel *toplevel);
virtual void paintBackground(QRegion region);
virtual void paintGenericScreen(int mask, ScreenPaintData data);
virtual void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data);
public Q_SLOTS:
virtual void windowGeometryShapeChanged(KWin::Toplevel* c);
virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted);
private:
void createBuffer();
void present(int mask, QRegion damage);
@ -68,7 +64,6 @@ private:
static xcb_render_picture_t buffer;
static ScreenPaintData screen_paint;
class Window;
QHash< Toplevel*, Window* > windows;
OverlayWindow* m_overlayWindow;
bool init_ok;
};