add offscreen render support to xrender
REVIEW: 104151 cherry-picked from b9534b4ca82973c2e99451b2e151241fd1b6e7cb
This commit is contained in:
parent
e3d2cb9a61
commit
5e2414544f
3 changed files with 99 additions and 5 deletions
|
@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||||
|
|
||||||
|
#include <QStack>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
@ -212,6 +213,55 @@ XRenderPicture::XRenderPicture(Pixmap pix, int depth)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QPixmap *s_offscreenTarget = 0;
|
||||||
|
static QStack<XRenderPicture*> s_scene_offscreenTargetStack;
|
||||||
|
static int s_renderOffscreen = 0;
|
||||||
|
|
||||||
|
void scene_setXRenderOffscreenTarget(QPixmap *pix)
|
||||||
|
{
|
||||||
|
s_offscreenTarget = pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRenderPicture *scene_xRenderOffscreenTarget()
|
||||||
|
{
|
||||||
|
return s_scene_offscreenTargetStack.isEmpty() ? 0 : s_scene_offscreenTargetStack.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setXRenderOffscreen(bool b)
|
||||||
|
{
|
||||||
|
b ? ++s_renderOffscreen : --s_renderOffscreen;
|
||||||
|
if (s_renderOffscreen < 0) {
|
||||||
|
s_renderOffscreen = 0;
|
||||||
|
qWarning("*** SOMETHING IS MESSED UP WITH YOUR setXRenderOffscreen() USAGE ***");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void xRenderPushTarget(XRenderPicture *pic)
|
||||||
|
{
|
||||||
|
s_scene_offscreenTargetStack.push(pic);
|
||||||
|
++s_renderOffscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xRenderPopTarget()
|
||||||
|
{
|
||||||
|
s_scene_offscreenTargetStack.pop();
|
||||||
|
--s_renderOffscreen;
|
||||||
|
if (s_renderOffscreen < 0) {
|
||||||
|
s_renderOffscreen = 0;
|
||||||
|
qWarning("*** SOMETHING IS MESSED UP WITH YOUR xRenderPopTarget() USAGE ***");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xRenderOffscreen()
|
||||||
|
{
|
||||||
|
return s_renderOffscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap *xRenderOffscreenTarget()
|
||||||
|
{
|
||||||
|
return s_offscreenTarget;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -126,6 +126,42 @@ KWIN_EXPORT XRenderPicture xRenderBlendPicture(double opacity);
|
||||||
KWIN_EXPORT XRenderPicture xRenderFill(const XRenderColor *c);
|
KWIN_EXPORT XRenderPicture xRenderFill(const XRenderColor *c);
|
||||||
KWIN_EXPORT XRenderPicture xRenderFill(const QColor &c);
|
KWIN_EXPORT XRenderPicture xRenderFill(const QColor &c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to render a window into a (transparent) pixmap
|
||||||
|
* NOTICE: the result can be queried as xRenderWindowOffscreenTarget()
|
||||||
|
* NOTICE: it may be 0
|
||||||
|
* NOTICE: when done call setXRenderWindowOffscreen(false) to continue normal render process
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT void setXRenderOffscreen(bool b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to define a persistent effect member as render target
|
||||||
|
* The window (including shadows) is rendered into the top left corner
|
||||||
|
* NOTICE: do NOT call setXRenderOffscreen(true) in addition!
|
||||||
|
* NOTICE: do not forget to xRenderPopTarget once you're done to continue the normal render process
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT void xRenderPushTarget(XRenderPicture *pic);
|
||||||
|
KWIN_EXPORT void xRenderPopTarget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether windows are currently rendered into an offscreen target buffer
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT bool xRenderOffscreen();
|
||||||
|
/**
|
||||||
|
* The offscreen buffer as set by the renderer because of setXRenderWindowOffscreen(true)
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT QPixmap *xRenderOffscreenTarget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTICE: HANDS OFF!!!
|
||||||
|
* scene_setXRenderWindowOffscreenTarget() is ONLY to be used by the renderer - DO NOT TOUCH!
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT void scene_setXRenderOffscreenTarget(QPixmap *pix);
|
||||||
|
/**
|
||||||
|
* scene_xRenderWindowOffscreenTarget() is used by the scene to figure the target set by an effect
|
||||||
|
*/
|
||||||
|
KWIN_EXPORT XRenderPicture *scene_xRenderOffscreenTarget();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -417,8 +417,10 @@ void SceneXrender::Window::prepareTempPixmap()
|
||||||
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
||||||
if (!temp_pixmap)
|
if (!temp_pixmap)
|
||||||
temp_pixmap = new QPixmap(r.width(), r.height());
|
temp_pixmap = new QPixmap(r.width(), r.height());
|
||||||
else if (temp_pixmap->width() < r.width() || temp_pixmap->height() < r.height())
|
else if (temp_pixmap->width() < r.width() || temp_pixmap->height() < r.height()) {
|
||||||
*temp_pixmap = QPixmap(r.width(), r.height());
|
*temp_pixmap = QPixmap(r.width(), r.height());
|
||||||
|
scene_setXRenderOffscreenTarget(0); // invalidate, better crash than cause weird results for developers
|
||||||
|
}
|
||||||
if (Extensions::nonNativePixmaps()) {
|
if (Extensions::nonNativePixmaps()) {
|
||||||
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||||
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
||||||
|
@ -532,12 +534,16 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
||||||
// the window has border
|
// the window has border
|
||||||
// This solves a number of glitches and on top of this
|
// This solves a number of glitches and on top of this
|
||||||
// it optimizes painting quite a bit
|
// it optimizes painting quite a bit
|
||||||
const bool blitInTempPixmap = scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder()));
|
const bool blitInTempPixmap = xRenderOffscreen() || (scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder())));
|
||||||
Picture renderTarget = buffer;
|
|
||||||
|
|
||||||
|
Picture renderTarget = buffer;
|
||||||
if (blitInTempPixmap) {
|
if (blitInTempPixmap) {
|
||||||
prepareTempPixmap();
|
if (scene_xRenderOffscreenTarget())
|
||||||
renderTarget = temp_pixmap->x11PictureHandle();
|
renderTarget = *scene_xRenderOffscreenTarget();
|
||||||
|
else {
|
||||||
|
prepareTempPixmap();
|
||||||
|
renderTarget = temp_pixmap->x11PictureHandle();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
XRenderSetPictureTransform(display(), pic, &xform);
|
XRenderSetPictureTransform(display(), pic, &xform);
|
||||||
if (filter == ImageFilterGood) {
|
if (filter == ImageFilterGood) {
|
||||||
|
@ -702,6 +708,8 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
||||||
XRenderChangePicture(display(), pic, CPRepeat, &attr);
|
XRenderChangePicture(display(), pic, CPRepeat, &attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (xRenderOffscreen())
|
||||||
|
scene_setXRenderOffscreenTarget(temp_pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::screenGeometryChanged(const QSize &size)
|
void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||||
|
|
Loading…
Reference in a new issue