Port xRenderOffscreenTarget away from QPixmap
Instead of having a pointer to a QPixmap the offscreen target holds an xcb_render_picture_t. To make this possible in SceneWindow the tempPixmap is changed from a QPixmap* to a XRenderPicture*. QPixmap was only used for convenience. ScreenShot Effect as only user of the offscreen target is adjusted but as it needs a QImage, still uses a QPixmap wrapper.
This commit is contained in:
parent
2dcbbd6a3a
commit
f20ec15053
5 changed files with 43 additions and 26 deletions
|
@ -132,8 +132,16 @@ void ScreenShotEffect::postPaintScreen()
|
|||
if (effects->compositingType() == XRenderCompositing) {
|
||||
setXRenderOffscreen(true);
|
||||
effects->drawWindow(m_scheduledScreenshot, mask, QRegion(0, 0, width, height), d);
|
||||
if (xRenderOffscreenTarget())
|
||||
img = xRenderOffscreenTarget()->toImage().copy(0, 0, width, height);
|
||||
if (xRenderOffscreenTarget()) {
|
||||
xcb_pixmap_t xpix = xcb_generate_id(connection());
|
||||
xcb_create_pixmap(connection(), 32, xpix, rootWindow(), width, height);
|
||||
// TODO: Qt5 - convert from xpixmap to QImage without a QPixmap
|
||||
QPixmap pixmap = QPixmap::fromX11Pixmap(xpix);
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, xRenderOffscreenTarget(),
|
||||
XCB_RENDER_PICTURE_NONE, pixmap.x11PictureHandle(), 0, 0, 0, 0, 0, 0, width, height);
|
||||
img = pixmap.toImage().copy(0, 0, width, height);
|
||||
xcb_free_pixmap(connection(), xpix);
|
||||
}
|
||||
setXRenderOffscreen(false);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -132,11 +132,11 @@ XRenderPicture::XRenderPicture(Pixmap pix, int depth)
|
|||
{
|
||||
}
|
||||
|
||||
static QPixmap *s_offscreenTarget = 0;
|
||||
static xcb_render_picture_t s_offscreenTarget = XCB_RENDER_PICTURE_NONE;
|
||||
static QStack<XRenderPicture*> s_scene_offscreenTargetStack;
|
||||
static int s_renderOffscreen = 0;
|
||||
|
||||
void scene_setXRenderOffscreenTarget(QPixmap *pix)
|
||||
void scene_setXRenderOffscreenTarget(xcb_render_picture_t pix)
|
||||
{
|
||||
s_offscreenTarget = pix;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ bool xRenderOffscreen()
|
|||
return s_renderOffscreen;
|
||||
}
|
||||
|
||||
QPixmap *xRenderOffscreenTarget()
|
||||
xcb_render_picture_t xRenderOffscreenTarget()
|
||||
{
|
||||
return s_offscreenTarget;
|
||||
}
|
||||
|
|
|
@ -184,13 +184,13 @@ KWIN_EXPORT bool xRenderOffscreen();
|
|||
/**
|
||||
* The offscreen buffer as set by the renderer because of setXRenderWindowOffscreen(true)
|
||||
*/
|
||||
KWIN_EXPORT QPixmap *xRenderOffscreenTarget();
|
||||
KWIN_EXPORT xcb_render_picture_t xRenderOffscreenTarget();
|
||||
|
||||
/**
|
||||
* NOTICE: HANDS OFF!!!
|
||||
* scene_setXRenderWindowOffscreenTarget() is ONLY to be used by the renderer - DO NOT TOUCH!
|
||||
*/
|
||||
KWIN_EXPORT void scene_setXRenderOffscreenTarget(QPixmap *pix);
|
||||
KWIN_EXPORT void scene_setXRenderOffscreenTarget(xcb_render_picture_t pix);
|
||||
/**
|
||||
* scene_xRenderWindowOffscreenTarget() is used by the scene to figure the target set by an effect
|
||||
*/
|
||||
|
|
|
@ -94,6 +94,7 @@ SceneXrender::~SceneXrender()
|
|||
m_overlayWindow->destroy();
|
||||
return;
|
||||
}
|
||||
SceneXrender::Window::cleanup();
|
||||
SceneXrender::EffectFrame::cleanup();
|
||||
XRenderFreePicture(display(), front);
|
||||
XRenderFreePicture(display(), buffer);
|
||||
|
@ -276,7 +277,7 @@ void SceneXrender::windowAdded(Toplevel* c)
|
|||
// SceneXrender::Window
|
||||
//****************************************
|
||||
|
||||
QPixmap *SceneXrender::Window::temp_pixmap = 0;
|
||||
XRenderPicture *SceneXrender::Window::s_tempPicture = 0;
|
||||
QRect SceneXrender::Window::temp_visibleRect;
|
||||
|
||||
SceneXrender::Window::Window(Toplevel* c)
|
||||
|
@ -295,6 +296,12 @@ SceneXrender::Window::~Window()
|
|||
discardShape();
|
||||
}
|
||||
|
||||
void SceneXrender::Window::cleanup()
|
||||
{
|
||||
delete s_tempPicture;
|
||||
s_tempPicture = NULL;
|
||||
}
|
||||
|
||||
// Create XRender picture for the pixmap with the window contents.
|
||||
Picture SceneXrender::Window::picture()
|
||||
{
|
||||
|
@ -406,21 +413,22 @@ QPoint SceneXrender::Window::mapToScreen(int mask, const WindowPaintData &data,
|
|||
|
||||
void SceneXrender::Window::prepareTempPixmap()
|
||||
{
|
||||
const QSize oldSize = temp_visibleRect.size();
|
||||
temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
|
||||
|
||||
if (temp_pixmap && Extensions::nonNativePixmaps())
|
||||
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
||||
if (!temp_pixmap)
|
||||
temp_pixmap = new QPixmap(temp_visibleRect.size());
|
||||
else if (temp_pixmap->width() < temp_visibleRect.width() || temp_pixmap->height() < temp_visibleRect.height()) {
|
||||
*temp_pixmap = QPixmap(temp_visibleRect.size());
|
||||
if (s_tempPicture && (oldSize.width() < temp_visibleRect.width() || oldSize.height() < temp_visibleRect.height())) {
|
||||
delete s_tempPicture;
|
||||
s_tempPicture = NULL;
|
||||
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);
|
||||
if (!s_tempPicture) {
|
||||
xcb_pixmap_t pix = xcb_generate_id(connection());
|
||||
xcb_create_pixmap(connection(), 32, pix, rootWindow(), temp_visibleRect.width(), temp_visibleRect.height());
|
||||
s_tempPicture = new XRenderPicture(pix, 32);
|
||||
xcb_free_pixmap(connection(), pix);
|
||||
}
|
||||
temp_pixmap->fill(Qt::transparent);
|
||||
const xcb_render_color_t transparent = {0, 0, 0, 0};
|
||||
const xcb_rectangle_t rect = {0, 0, uint16_t(temp_visibleRect.width()), uint16_t(temp_visibleRect.height())};
|
||||
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, *s_tempPicture, transparent, 1, &rect);
|
||||
}
|
||||
|
||||
// paint the window
|
||||
|
@ -543,7 +551,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
|||
renderTarget = *scene_xRenderOffscreenTarget();
|
||||
} else {
|
||||
prepareTempPixmap();
|
||||
renderTarget = temp_pixmap->x11PictureHandle();
|
||||
renderTarget = *s_tempPicture;
|
||||
}
|
||||
} else {
|
||||
XRenderSetPictureTransform(display(), pic, &xform);
|
||||
|
@ -699,11 +707,11 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
|||
}
|
||||
if (blitInTempPixmap) {
|
||||
const QRect r = mapToScreen(mask, data, temp_visibleRect);
|
||||
XRenderSetPictureTransform(display(), temp_pixmap->x11PictureHandle(), &xform);
|
||||
XRenderSetPictureFilter(display(), temp_pixmap->x11PictureHandle(), const_cast<char*>("good"), NULL, 0);
|
||||
XRenderComposite(display(), PictOpOver, temp_pixmap->x11PictureHandle(), None, buffer,
|
||||
XRenderSetPictureTransform(display(), *s_tempPicture, &xform);
|
||||
XRenderSetPictureFilter(display(), *s_tempPicture, const_cast<char*>("good"), NULL, 0);
|
||||
XRenderComposite(display(), PictOpOver, *s_tempPicture, None, buffer,
|
||||
0, 0, 0, 0, r.x(), r.y(), r.width(), r.height());
|
||||
XRenderSetPictureTransform(display(), temp_pixmap->x11PictureHandle(), &identity);
|
||||
XRenderSetPictureTransform(display(), *s_tempPicture, &identity);
|
||||
}
|
||||
}
|
||||
if (scaled && !blitInTempPixmap) {
|
||||
|
@ -716,7 +724,7 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
|||
}
|
||||
}
|
||||
if (xRenderOffscreen())
|
||||
scene_setXRenderOffscreenTarget(temp_pixmap);
|
||||
scene_setXRenderOffscreenTarget(*s_tempPicture);
|
||||
}
|
||||
|
||||
void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
void discardAlpha();
|
||||
QRegion transformedShape() const;
|
||||
void setTransformedShape(const QRegion& shape);
|
||||
static void cleanup();
|
||||
private:
|
||||
Picture picture();
|
||||
Picture alphaMask(double opacity);
|
||||
|
@ -95,8 +96,8 @@ private:
|
|||
Picture alpha;
|
||||
double alpha_cached_opacity;
|
||||
QRegion transformed_shape;
|
||||
static QPixmap *temp_pixmap;
|
||||
static QRect temp_visibleRect;
|
||||
static XRenderPicture *s_tempPicture;
|
||||
};
|
||||
|
||||
class SceneXrender::EffectFrame
|
||||
|
|
Loading…
Reference in a new issue