summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdiel Janulgue <abdiel.janulgue@nokia.com>2010-11-17 16:46:23 +0200
committerKimmo Hämäläinen <kimmo.hamalainen@nokia.com>2010-11-29 13:13:36 +0200
commit9ca8330eee668bcaebe5d1eb8825476fe116820c (patch)
treee95cc86537e070bad5a39ee10e65b7503c105975
parent3b7b0d20f4104dc29c1453480cc6c8cd1d011ddd (diff)
Changes: Initial implementation for composite window groups
Details: Add the MCompositeWindowGroup class. MCompositeWindowGroup allows a collection of windows to be rendered as a single texture. This patch adds support for the compositor paint engine to render windows that are indirectly rendered to FBO's. Introduced some refactoring to the EGL backend as well to support render to texture functionality. Some fixes were necessary in the MCompositeWindowShaderEffect class to allow effects to be rendered to MComositeWindowGroup items as well RevBy: TrustMe
-rw-r--r--src/mcompositescene.cpp38
-rw-r--r--src/mcompositewindow.cpp6
-rw-r--r--src/mcompositewindow.h14
-rw-r--r--src/mcompositewindowgroup.cpp302
-rw-r--r--src/mcompositewindowgroup.h67
-rw-r--r--src/mcompositewindowshadereffect.cpp19
-rw-r--r--src/mtexturepixmapitem.h4
-rw-r--r--src/mtexturepixmapitem_egl.cpp25
-rw-r--r--src/mtexturepixmapitem_p.cpp9
-rw-r--r--src/mtexturepixmapitem_p.h2
-rw-r--r--src/src.pro6
11 files changed, 457 insertions, 35 deletions
diff --git a/src/mcompositescene.cpp b/src/mcompositescene.cpp
index 63321d5..593e075 100644
--- a/src/mcompositescene.cpp
+++ b/src/mcompositescene.cpp
@@ -27,6 +27,7 @@
#include "mcompositewindow.h"
#include "mcompositescene.h"
+#include "mcompositewindowgroup.h"
#include <X11/extensions/Xfixes.h>
#ifdef HAVE_SHAPECONST
@@ -87,20 +88,22 @@ void MCompositeScene::drawItems(QPainter *painter, int numItems, QGraphicsItem *
for (int i = numItems - 1; i >= 0; --i) {
MCompositeWindow *cw = (MCompositeWindow *) items[i];
- if (!cw->propertyCache()) // this window is dead
- continue;
- if (cw->hasTransitioningWindow() && cw->propertyCache()->isDecorator())
- // if we have a transition animation, don't draw the decorator
- // lest we can have it drawn with the transition (especially
- // when desktop window is not yet shown, NB#192454)
- continue;
- if (cw->isDirectRendered() || !cw->isVisible()
- || !(cw->propertyCache()->isMapped() || cw->isWindowTransitioning())
- || cw->propertyCache()->isInputOnly())
- continue;
- if (visible.isEmpty())
- // nothing below is visible anymore
- break;
+ if (cw->type() != MCompositeWindowGroup::Type) {
+ if (!cw->propertyCache()) // this window is dead
+ continue;
+ if (cw->hasTransitioningWindow() && cw->propertyCache()->isDecorator())
+ // if we have a transition animation, don't draw the decorator
+ // lest we can have it drawn with the transition (especially
+ // when desktop window is not yet shown, NB#192454)
+ continue;
+ if (cw->isDirectRendered() || !cw->isVisible()
+ || !(cw->propertyCache()->isMapped() || cw->isWindowTransitioning())
+ || cw->propertyCache()->isInputOnly())
+ continue;
+ if (visible.isEmpty())
+ // nothing below is visible anymore
+ break;
+ }
// Ensure that intersects() still work, otherwise, painting a window
// is skipped when another window above it is scaled or moved to an
@@ -110,7 +113,8 @@ void MCompositeScene::drawItems(QPainter *painter, int numItems, QGraphicsItem *
// transitioning window can be smaller than shapeRegion(), so paint
// all transitioning windows
- if (cw->isWindowTransitioning() || visible.intersects(r)) {
+ if (cw->isWindowTransitioning() || visible.intersects(r)
+ || cw->type() == MCompositeWindowGroup::Type) {
if (size >= 9)
to_paint.resize(to_paint.size()+1);
to_paint[size++] = i;
@@ -121,7 +125,9 @@ void MCompositeScene::drawItems(QPainter *painter, int numItems, QGraphicsItem *
// subtract opaque regions
if (!cw->isWindowTransitioning()
- && !cw->propertyCache()->hasAlpha() && cw->opacity() == 1.0)
+ && !cw->propertyCache()->hasAlpha()
+ && cw->opacity() == 1.0
+ && !cw->windowGroup()) // window is renderered off-screen)
visible -= r;
}
if (size > 0) {
diff --git a/src/mcompositewindow.cpp b/src/mcompositewindow.cpp
index 624943b..40af5de 100644
--- a/src/mcompositewindow.cpp
+++ b/src/mcompositewindow.cpp
@@ -24,6 +24,7 @@
#include "mtexturepixmapitem.h"
#include "mdecoratorframe.h"
#include "mcompositemanagerextension.h"
+#include "mcompositewindowgroup.h"
#include <QX11Info>
#include <QGraphicsScene>
@@ -792,3 +793,8 @@ bool MCompositeWindow::isMapped() const
{
return pc ? pc->isMapped() : false;
}
+
+MCompositeWindowGroup* MCompositeWindow::windowGroup() const
+{
+ return renderer()->current_window_group;
+}
diff --git a/src/mcompositewindow.h b/src/mcompositewindow.h
index ed558a2..a7b480c 100644
--- a/src/mcompositewindow.h
+++ b/src/mcompositewindow.h
@@ -27,6 +27,8 @@
#include "mwindowpropertycache.h"
class MCompWindowAnimator;
+class MTexturePixmapPrivate;
+class MCompositeWindowGroup;
/*!
* This is the base class for composited window items. It provided general
@@ -302,6 +304,12 @@ public:
* Returns whatever window is directly behind this window. 0 if there is none.
*/
MCompositeWindow* behind() const { return behind_window; }
+
+ /*!
+ * Returns a pointer to this window's group if it belongs to a group and 0
+ * if 0 if not a member
+ */
+ MCompositeWindowGroup* windowGroup() const;
/*! Disabled alpha-blending for a dim-effect instead */
void setDimmedEffect(bool dimmed) { dimmed_effect = dimmed; }
@@ -379,8 +387,11 @@ protected:
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual QPainterPath shape() const;
-
+
private:
+ /* re-implemented in GL/GLES2 backends for internal interaction
+ between shader effects */
+ virtual MTexturePixmapPrivate* renderer() const = 0;
void findBehindWindow();
QPointer<MWindowPropertyCache> pc;
@@ -421,6 +432,7 @@ private:
Qt::HANDLE win_id;
friend class MTexturePixmapPrivate;
+ friend class MCompositeWindowShaderEffect;
};
#endif
diff --git a/src/mcompositewindowgroup.cpp b/src/mcompositewindowgroup.cpp
new file mode 100644
index 0000000..bace393
--- /dev/null
+++ b/src/mcompositewindowgroup.cpp
@@ -0,0 +1,302 @@
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui@nokia.com)
+**
+** This file is part of mcompositor.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui@nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation
+** and appearing in the file LICENSE.LGPL included in the packaging
+** of this file.
+**
+****************************************************************************/
+/*!
+ \class MCompositeWindowGroup
+ \brief MCompositeWindowGroup allows a collection of windows to be rendered
+ as a single texture.
+
+ This class is useful for rendering a list of windows that needs to
+ be treated as one item with transformations applied only to a single texture.
+ Unlike QGraphicsItemGroup where each item is rendered separately for each
+ frame, MCompositeWindowGroup can pre-render all items to an off-screen buffer
+ before a frame starts and can render the resulting texture afterwards as a
+ single quad which reduces GPU load and helps performance especially in panning
+ and scaling transformations.
+
+ Use this class to render a main window with its transient windows. Another
+ use case is for a window that needs to have similar transformations to a
+ main window. The addChildWindow() function adds windows that need to
+ animate synchronously with the main window. The removeChildWindow() function
+ removes a window from the group.
+
+ Implementation is hw-dependent. It relies on framebuffer objects on GLES2
+ and the GL_EXT_framebuffer_object extension on the desktop.
+*/
+
+#include <QtOpenGL>
+#include <QGLFramebufferObject>
+#include <QList>
+#include <mcompositewindowgroup.h>
+
+#include <mtexturepixmapitem.h>
+#include <mcompositemanager.h>
+
+#ifdef GLES2_VERSION
+#define FORMAT GL_RGBA
+#else
+#define FORMAT GL_RGBA8
+#endif
+
+class MCompositeWindowGroupPrivate
+{
+public:
+ MCompositeWindowGroupPrivate(MTexturePixmapItem* mainWindow)
+ :main_window(mainWindow),
+ texture(0),
+ fbo(0),
+ valid(false),
+ renderer(new MTexturePixmapPrivate(0, mainWindow))
+ {
+
+ }
+ MTexturePixmapItem* main_window;
+ GLuint texture;
+ GLuint fbo;
+
+ bool valid;
+ QList<MTexturePixmapItem*> win_groups;
+ MTexturePixmapPrivate* renderer;
+};
+
+/*!
+ Creates a window group object. Specify the main window
+ with \a mainWindow
+ */
+MCompositeWindowGroup::MCompositeWindowGroup(MTexturePixmapItem* mainWindow)
+ :MCompositeWindow(0, new MWindowPropertyCache(0)),
+ d_ptr(new MCompositeWindowGroupPrivate(mainWindow))
+{
+ MCompositeManager *p = (MCompositeManager *) qApp;
+ p->scene()->addItem(this);
+
+ mainWindow->d->current_window_group = this;
+ connect(mainWindow, SIGNAL(destroyed()), SLOT(deleteLater()));
+ init();
+ updateWindowPixmap();
+ setZValue(mainWindow->zValue() - 1);
+ stackBefore(mainWindow);
+}
+
+/*!
+ Destroys this window group and frees resources. All windows that are within
+ this group revert back to directly rendering its own texture.
+ */
+MCompositeWindowGroup::~MCompositeWindowGroup()
+{
+ Q_D(MCompositeWindowGroup);
+
+ if (!QGLContext::currentContext()) {
+ qWarning("MCompositeWindowGroup::%s(): no current GL context",
+ __func__);
+ return;
+ }
+
+ GLuint texture = d->texture;
+ glDeleteTextures(1, &texture);
+ GLuint fbo = d->fbo;
+ glDeleteFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ update();
+}
+
+void MCompositeWindowGroup::init()
+{
+ Q_D(MCompositeWindowGroup);
+
+ if (!QGLContext::currentContext()) {
+ qWarning("MCompositeWindowGroup::%s(): no current GL context",
+ __func__);
+ d->valid = false;
+ return;
+ }
+ d->renderer->current_window_group = this;
+
+ // no renderbuffer because we dont need the stencil and depthbuffer attachment
+ glGenFramebuffers(1, &d->fbo);
+ glBindFramebuffer(GL_RENDERBUFFER, d->fbo);
+
+ glGenTextures(1, &d->texture);
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, d->fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, d->texture, 0);
+
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, FORMAT,
+ d->main_window->boundingRect().width(),
+ d->main_window->boundingRect().height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ GLenum ret = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (ret == GL_FRAMEBUFFER_COMPLETE)
+ d->valid = true;
+ else
+ qWarning("MCompositeWindowGroup::%s(): incomplete FBO attachment 0x%x",
+ __func__, ret);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+static bool behindCompare(MTexturePixmapItem* a, MTexturePixmapItem* b)
+{
+ return a->indexInStack() < b->indexInStack();
+}
+
+/*!
+ Adds the given \a window to this group. The window's transformations will
+ remain unmodified
+ */
+void MCompositeWindowGroup::addChildWindow(MTexturePixmapItem* window)
+{
+ Q_D(MCompositeWindowGroup);
+ window->d->current_window_group = this;
+ connect(window, SIGNAL(destroyed()), SLOT(q_removeWindow()));
+ d->win_groups.append(window);
+
+ // ensure group windows are already stacked in proper order in advance
+ // for back to front rendering. Could use depth buffer attachment at some
+ // point so this might be unecessary
+ qSort(d->win_groups.begin(), d->win_groups.end(), behindCompare);
+ updateWindowPixmap();
+}
+
+/*!
+ Removes the given \a window to from group.
+ */
+void MCompositeWindowGroup::removeChildWindow(MTexturePixmapItem* window)
+{
+ Q_D(MCompositeWindowGroup);
+ window->d->current_window_group = 0;
+ d->win_groups.removeAll(window);
+}
+
+void MCompositeWindowGroup::q_removeWindow()
+{
+ Q_D(MCompositeWindowGroup);
+ MTexturePixmapItem* w = qobject_cast<MTexturePixmapItem*>(sender());
+ if (w)
+ d->win_groups.removeAll(w);
+}
+
+void MCompositeWindowGroup::saveBackingStore() {}
+
+void MCompositeWindowGroup::resize(int , int) {}
+
+void MCompositeWindowGroup::clearTexture() {}
+
+bool MCompositeWindowGroup::isDirectRendered() const { return false; }
+
+QRectF MCompositeWindowGroup::boundingRect() const
+{
+ Q_D(const MCompositeWindowGroup);
+ return d->main_window->boundingRect();
+}
+
+void MCompositeWindowGroup::paint(QPainter* painter,
+ const QStyleOptionGraphicsItem* options,
+ QWidget* widget)
+{
+ Q_D(MCompositeWindowGroup);
+ Q_UNUSED(options)
+ Q_UNUSED(widget)
+
+#if QT_VERSION < 0x040600
+ if (painter->paintEngine()->type() != QPaintEngine::OpenGL)
+ return;
+#else
+ if (painter->paintEngine()->type() != QPaintEngine::OpenGL2) {
+ return;
+ }
+#endif
+
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ if (d->main_window->propertyCache()->hasAlpha() ||
+ (opacity() < 1.0f && !dimmedEffect()) ) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ d->renderer->drawTexture(painter->combinedTransform(), boundingRect(),
+ opacity());
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+}
+
+void MCompositeWindowGroup::windowRaised()
+{
+}
+
+void MCompositeWindowGroup::updateWindowPixmap(XRectangle *rects, int num,
+ Time t)
+{
+ Q_UNUSED(rects)
+ Q_UNUSED(num)
+ Q_UNUSED(t)
+ Q_D(MCompositeWindowGroup);
+
+ if (!d->valid) {
+ qDebug() << "invalid fbo";
+ return;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, d->fbo);
+ GLenum ret = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (ret == GL_FRAMEBUFFER_COMPLETE)
+ d->valid = true;
+ else {
+ qWarning("MCompositeWindowGroup::%s(): incomplete FBO attachment 0x%x",
+ __func__, ret);
+ d->valid = false;
+ }
+ d->main_window->d->inverted_texture = false;
+ d->main_window->renderTexture(d->main_window->sceneTransform());
+ d->main_window->d->inverted_texture = true;
+ for (int i = 0; i < d->win_groups.size(); ++i) {
+ MTexturePixmapItem* item = d->win_groups[i];
+ item->d->inverted_texture = false;
+ item->renderTexture(item->sceneTransform());
+ item->d->inverted_texture = true;
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+// internal re-implementation from MCompositeWindow
+MTexturePixmapPrivate* MCompositeWindowGroup::renderer() const
+{
+ Q_D(const MCompositeWindowGroup);
+ return d->renderer;
+}
+
+/*!
+ \return Returns the texture used by the off-screen buffer
+*/
+GLuint MCompositeWindowGroup::texture()
+{
+ Q_D(MCompositeWindowGroup);
+ return d->texture;
+}
+
+
diff --git a/src/mcompositewindowgroup.h b/src/mcompositewindowgroup.h
new file mode 100644
index 0000000..709b07d
--- /dev/null
+++ b/src/mcompositewindowgroup.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui@nokia.com)
+**
+** This file is part of mcompositor.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui@nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation
+** and appearing in the file LICENSE.LGPL included in the packaging
+** of this file.
+**
+****************************************************************************/
+
+#ifndef MCOMPOSITEWINDOWGROUP_H
+#define MCOMPOSITEWINDOWGROUP_H
+
+#include <mcompositewindow.h>
+
+class MTexturePixmapItem;
+class MCompositeWindowGroupPrivate;
+
+class MCompositeWindowGroup: public MCompositeWindow
+{
+ Q_OBJECT
+ public:
+ enum { Type = UserType + 2 };
+
+ MCompositeWindowGroup(MTexturePixmapItem* mainWindow);
+ virtual ~MCompositeWindowGroup();
+
+ void addChildWindow(MTexturePixmapItem* window);
+ void removeChildWindow(MTexturePixmapItem* window);
+ GLuint texture();
+
+ //! \reimp
+ virtual void windowRaised();
+ virtual void updateWindowPixmap(XRectangle *rects = 0, int num = 0,
+ Time = 0);
+ virtual void saveBackingStore();
+ virtual void resize(int , int);
+ virtual void clearTexture();
+ virtual bool isDirectRendered() const;
+ virtual QRectF boundingRect() const;
+ virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);
+ //virtual Pixmap windowPixmap() const ( return 0; }
+ //! \reimp_end
+
+ virtual int type () const { return Type; }
+
+ private slots:
+ void q_removeWindow();
+
+ private:
+ Q_DECLARE_PRIVATE(MCompositeWindowGroup)
+ void init();
+ virtual MTexturePixmapPrivate* renderer() const;
+
+ QScopedPointer<MCompositeWindowGroupPrivate> d_ptr;
+};
+
+#endif // MCOMPOSITEWINDOWGROUP_H
diff --git a/src/mcompositewindowshadereffect.cpp b/src/mcompositewindowshadereffect.cpp
index d52f1cd..16aae02 100644
--- a/src/mcompositewindowshadereffect.cpp
+++ b/src/mcompositewindowshadereffect.cpp
@@ -35,6 +35,7 @@
#include "mtexturepixmapitem.h"
#include "mcompositewindowshadereffect.h"
#include "mtexturepixmapitem_p.h"
+#include "mcompositewindowgroup.h"
#include <QByteArray>
static const char default_frag[] = "\
@@ -110,8 +111,12 @@ GLuint MCompositeWindowShaderEffect::installShaderFragment(const QByteArray& cod
GLuint MCompositeWindowShaderEffect::texture() const
{
// TODO: This assumes we have always have hadware TFP support
- if (d->priv_render)
- return d->priv_render->textureId;
+ if (d->priv_render) {
+ if (!d->priv_render->current_window_group)
+ return d->priv_render->textureId;
+ else
+ return d->priv_render->current_window_group->texture();
+ }
return 0;
}
@@ -172,13 +177,12 @@ void MCompositeWindowShaderEffect::drawSource(const QTransform &transform,
*/
void MCompositeWindowShaderEffect::installEffect(MCompositeWindow* window)
{
- if (!window->isValid())
+ if (!window->isValid() && (window->type() != MCompositeWindowGroup::Type))
return;
// only happens with GL. sorry n800 guys :p
#ifdef QT_OPENGL_LIB
- MTexturePixmapItem* item = (MTexturePixmapItem*) window;
- item->d->installEffect(this);
+ window->renderer()->installEffect(this);
#endif
}
@@ -188,12 +192,11 @@ void MCompositeWindowShaderEffect::installEffect(MCompositeWindow* window)
*/
void MCompositeWindowShaderEffect::removeEffect(MCompositeWindow* window)
{
- if (!window->isValid())
+ if (!window->isValid() && (window->type() != MCompositeWindowGroup::Type))
return;
#ifdef QT_OPENGL_LIB
- MTexturePixmapItem* item = (MTexturePixmapItem*) window;
- item->d->installEffect(0);
+ window->renderer()->installEffect(0);
#endif
}
diff --git a/src/mtexturepixmapitem.h b/src/mtexturepixmapitem.h
index f433dd7..42b4ba6 100644
--- a/src/mtexturepixmapitem.h
+++ b/src/mtexturepixmapitem.h
@@ -41,6 +41,7 @@ class MTexturePixmapPrivate;
*/
class MTexturePixmapItem: public MCompositeWindow
{
+ Q_OBJECT
public:
/*!
* Constructs a MTexturePixmapItem
@@ -101,16 +102,19 @@ protected:
virtual void windowRaised();
private:
+ virtual MTexturePixmapPrivate* renderer() const;
void init();
void initCustomTfp();
void cleanup();
void rebindPixmap();
void doTFP();
+ void renderTexture(const QTransform& transform);
MTexturePixmapPrivate *const d;
friend class MTexturePixmapPrivate;
friend class MCompositeManagerPrivate;
friend class MCompositeWindowShaderEffect;
+ friend class MCompositeWindowGroupPrivate;
friend class MCompositeWindowGroup;
};
diff --git a/src/mtexturepixmapitem_egl.cpp b/src/mtexturepixmapitem_egl.cpp
index b60a28b..b75cbec 100644
--- a/src/mtexturepixmapitem_egl.cpp
+++ b/src/mtexturepixmapitem_egl.cpp
@@ -19,6 +19,7 @@
#include "mtexturepixmapitem.h"
#include "mtexturepixmapitem_p.h"
+#include "mcompositewindowgroup.h"
#include <QPainterPath>
#include <QRect>
@@ -309,8 +310,8 @@ void MTexturePixmapItem::updateWindowPixmap(XRectangle *rects, int num,
}
void MTexturePixmapItem::paint(QPainter *painter,
- const QStyleOptionGraphicsItem *option,
- QWidget *widget)
+ const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
@@ -332,6 +333,14 @@ void MTexturePixmapItem::paint(QPainter *painter,
if (!d->ctx)
d->ctx = const_cast<QGLContext *>(gl->context());
+ if (!d->current_window_group)
+ renderTexture(painter->combinedTransform());
+ else
+ d->current_window_group->updateWindowPixmap();
+}
+
+void MTexturePixmapItem::renderTexture(const QTransform& transform)
+{
if (propertyCache()->hasAlpha() || (opacity() < 1.0f && !dimmedEffect()) ) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -357,7 +366,7 @@ void MTexturePixmapItem::paint(QPainter *painter,
d->damageRegion.rects().at(i).height()),
d->damageRegion.rects().at(i).width(),
d->damageRegion.rects().at(i).height());
- d->drawTexture(painter->combinedTransform(), boundingRect(), opacity());
+ d->drawTexture(transform, boundingRect(), opacity());
}
} else if (shape_on) {
// draw a shaped window using glScissor
@@ -368,11 +377,10 @@ void MTexturePixmapItem::paint(QPainter *painter,
shape.rects().at(i).height()),
shape.rects().at(i).width(),
shape.rects().at(i).height());
- d->drawTexture(painter->combinedTransform(),
- boundingRect(), opacity());
+ d->drawTexture(transform, boundingRect(), opacity());
}
} else
- d->drawTexture(painter->combinedTransform(), boundingRect(), opacity());
+ d->drawTexture(transform, boundingRect(), opacity());
if (scissor_on)
glDisable(GL_SCISSOR_TEST);
@@ -442,3 +450,8 @@ void MTexturePixmapItem::doTFP()
}
}
}
+
+MTexturePixmapPrivate* MTexturePixmapItem::renderer() const
+{
+ return d;
+}
diff --git a/src/mtexturepixmapitem_p.cpp b/src/mtexturepixmapitem_p.cpp
index 4c1e4c3..eb5438f 100644
--- a/src/mtexturepixmapitem_p.cpp
+++ b/src/mtexturepixmapitem_p.cpp
@@ -441,7 +441,8 @@ MTexturePixmapPrivate::~MTexturePixmapPrivate()
void MTexturePixmapPrivate::saveBackingStore()
{
if ((item->propertyCache()->is_valid && !item->propertyCache()->isMapped())
- || item->propertyCache()->isInputOnly())
+ || item->propertyCache()->isInputOnly()
+ || !window)
return;
if (windowp)
@@ -452,11 +453,15 @@ void MTexturePixmapPrivate::saveBackingStore()
void MTexturePixmapPrivate::windowRaised()
{
- XRaiseWindow(QX11Info::display(), item->window());
+ if (item->window())
+ XRaiseWindow(QX11Info::display(), item->window());
}
void MTexturePixmapPrivate::resize(int w, int h)
{
+ if (!window)
+ return;
+
if (!brect.isEmpty() && !item->isDirectRendered() && (brect.width() != w || brect.height() != h)) {
item->saveBackingStore();
item->updateWindowPixmap();
diff --git a/src/mtexturepixmapitem_p.h b/src/mtexturepixmapitem_p.h
index cd4c086..eaf4c03 100644
--- a/src/mtexturepixmapitem_p.h
+++ b/src/mtexturepixmapitem_p.h
@@ -43,6 +43,7 @@ class QGLContext;
class QTransform;
class MGLResourceManager;
class MCompositeWindowShaderEffect;
+class MCompositeWindowGroup;
/*! Internal private implementation of MTexturePixmapItem
Warning! Interface here may change at any time!
@@ -87,6 +88,7 @@ public:
MTexturePixmapItem *item;
QPointer<MCompositeWindowShaderEffect> current_effect;
+ QPointer<MCompositeWindowGroup> current_window_group;
const MCompositeWindowShaderEffect *prev_effect;
// Contains a limited number of server times we received damage
diff --git a/src/src.pro b/src/src.pro
index cf3ac74..46527c3 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -40,7 +40,8 @@ HEADERS += \
mdecoratorframe.h \
mcompositemanagerextension.h \
mcompositewindowshadereffect.h \
- mcompmgrextensionfactory.h
+ mcompmgrextensionfactory.h \
+ mcompositewindowgroup.h
SOURCES += \
mtexturepixmapitem_p.cpp \
@@ -53,7 +54,8 @@ SOURCES += \
mdevicestate.cpp \
mdecoratorframe.cpp \
mcompositemanagerextension.cpp \
- mcompositewindowshadereffect.cpp
+ mcompositewindowshadereffect.cpp \
+ mcompositewindowgroup.cpp
RESOURCES = tools.qrc