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
|
||||
|
||||
#include <QStack>
|
||||
#include <QVector>
|
||||
#include <QPixmap>
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -126,6 +126,42 @@ KWIN_EXPORT XRenderPicture xRenderBlendPicture(double opacity);
|
|||
KWIN_EXPORT XRenderPicture xRenderFill(const XRenderColor *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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -417,8 +417,10 @@ void SceneXrender::Window::prepareTempPixmap()
|
|||
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
||||
if (!temp_pixmap)
|
||||
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());
|
||||
scene_setXRenderOffscreenTarget(0); // invalidate, better crash than cause weird results for developers
|
||||
}
|
||||
if (Extensions::nonNativePixmaps()) {
|
||||
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
||||
|
@ -532,12 +534,16 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
|||
// the window has border
|
||||
// This solves a number of glitches and on top of this
|
||||
// it optimizes painting quite a bit
|
||||
const bool blitInTempPixmap = scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder()));
|
||||
Picture renderTarget = buffer;
|
||||
const bool blitInTempPixmap = xRenderOffscreen() || (scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder())));
|
||||
|
||||
Picture renderTarget = buffer;
|
||||
if (blitInTempPixmap) {
|
||||
prepareTempPixmap();
|
||||
renderTarget = temp_pixmap->x11PictureHandle();
|
||||
if (scene_xRenderOffscreenTarget())
|
||||
renderTarget = *scene_xRenderOffscreenTarget();
|
||||
else {
|
||||
prepareTempPixmap();
|
||||
renderTarget = temp_pixmap->x11PictureHandle();
|
||||
}
|
||||
} else {
|
||||
XRenderSetPictureTransform(display(), pic, &xform);
|
||||
if (filter == ImageFilterGood) {
|
||||
|
@ -702,6 +708,8 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
|||
XRenderChangePicture(display(), pic, CPRepeat, &attr);
|
||||
}
|
||||
}
|
||||
if (xRenderOffscreen())
|
||||
scene_setXRenderOffscreenTarget(temp_pixmap);
|
||||
}
|
||||
|
||||
void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||
|
|
Loading…
Reference in a new issue