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) {
|
if (effects->compositingType() == XRenderCompositing) {
|
||||||
setXRenderOffscreen(true);
|
setXRenderOffscreen(true);
|
||||||
effects->drawWindow(m_scheduledScreenshot, mask, QRegion(0, 0, width, height), d);
|
effects->drawWindow(m_scheduledScreenshot, mask, QRegion(0, 0, width, height), d);
|
||||||
if (xRenderOffscreenTarget())
|
if (xRenderOffscreenTarget()) {
|
||||||
img = xRenderOffscreenTarget()->toImage().copy(0, 0, width, height);
|
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);
|
setXRenderOffscreen(false);
|
||||||
}
|
}
|
||||||
#endif
|
#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 QStack<XRenderPicture*> s_scene_offscreenTargetStack;
|
||||||
static int s_renderOffscreen = 0;
|
static int s_renderOffscreen = 0;
|
||||||
|
|
||||||
void scene_setXRenderOffscreenTarget(QPixmap *pix)
|
void scene_setXRenderOffscreenTarget(xcb_render_picture_t pix)
|
||||||
{
|
{
|
||||||
s_offscreenTarget = pix;
|
s_offscreenTarget = pix;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ bool xRenderOffscreen()
|
||||||
return s_renderOffscreen;
|
return s_renderOffscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap *xRenderOffscreenTarget()
|
xcb_render_picture_t xRenderOffscreenTarget()
|
||||||
{
|
{
|
||||||
return s_offscreenTarget;
|
return s_offscreenTarget;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,13 +184,13 @@ KWIN_EXPORT bool xRenderOffscreen();
|
||||||
/**
|
/**
|
||||||
* The offscreen buffer as set by the renderer because of setXRenderWindowOffscreen(true)
|
* 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!!!
|
* NOTICE: HANDS OFF!!!
|
||||||
* scene_setXRenderWindowOffscreenTarget() is ONLY to be used by the renderer - DO NOT TOUCH!
|
* 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
|
* scene_xRenderWindowOffscreenTarget() is used by the scene to figure the target set by an effect
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -94,6 +94,7 @@ SceneXrender::~SceneXrender()
|
||||||
m_overlayWindow->destroy();
|
m_overlayWindow->destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SceneXrender::Window::cleanup();
|
||||||
SceneXrender::EffectFrame::cleanup();
|
SceneXrender::EffectFrame::cleanup();
|
||||||
XRenderFreePicture(display(), front);
|
XRenderFreePicture(display(), front);
|
||||||
XRenderFreePicture(display(), buffer);
|
XRenderFreePicture(display(), buffer);
|
||||||
|
@ -276,7 +277,7 @@ void SceneXrender::windowAdded(Toplevel* c)
|
||||||
// SceneXrender::Window
|
// SceneXrender::Window
|
||||||
//****************************************
|
//****************************************
|
||||||
|
|
||||||
QPixmap *SceneXrender::Window::temp_pixmap = 0;
|
XRenderPicture *SceneXrender::Window::s_tempPicture = 0;
|
||||||
QRect SceneXrender::Window::temp_visibleRect;
|
QRect SceneXrender::Window::temp_visibleRect;
|
||||||
|
|
||||||
SceneXrender::Window::Window(Toplevel* c)
|
SceneXrender::Window::Window(Toplevel* c)
|
||||||
|
@ -295,6 +296,12 @@ SceneXrender::Window::~Window()
|
||||||
discardShape();
|
discardShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneXrender::Window::cleanup()
|
||||||
|
{
|
||||||
|
delete s_tempPicture;
|
||||||
|
s_tempPicture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Create XRender picture for the pixmap with the window contents.
|
// Create XRender picture for the pixmap with the window contents.
|
||||||
Picture SceneXrender::Window::picture()
|
Picture SceneXrender::Window::picture()
|
||||||
{
|
{
|
||||||
|
@ -406,21 +413,22 @@ QPoint SceneXrender::Window::mapToScreen(int mask, const WindowPaintData &data,
|
||||||
|
|
||||||
void SceneXrender::Window::prepareTempPixmap()
|
void SceneXrender::Window::prepareTempPixmap()
|
||||||
{
|
{
|
||||||
|
const QSize oldSize = temp_visibleRect.size();
|
||||||
temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
|
temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
|
||||||
|
if (s_tempPicture && (oldSize.width() < temp_visibleRect.width() || oldSize.height() < temp_visibleRect.height())) {
|
||||||
if (temp_pixmap && Extensions::nonNativePixmaps())
|
delete s_tempPicture;
|
||||||
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
s_tempPicture = NULL;
|
||||||
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());
|
|
||||||
scene_setXRenderOffscreenTarget(0); // invalidate, better crash than cause weird results for developers
|
scene_setXRenderOffscreenTarget(0); // invalidate, better crash than cause weird results for developers
|
||||||
}
|
}
|
||||||
if (Extensions::nonNativePixmaps()) {
|
if (!s_tempPicture) {
|
||||||
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
xcb_pixmap_t pix = xcb_generate_id(connection());
|
||||||
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
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
|
// paint the window
|
||||||
|
@ -543,7 +551,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
||||||
renderTarget = *scene_xRenderOffscreenTarget();
|
renderTarget = *scene_xRenderOffscreenTarget();
|
||||||
} else {
|
} else {
|
||||||
prepareTempPixmap();
|
prepareTempPixmap();
|
||||||
renderTarget = temp_pixmap->x11PictureHandle();
|
renderTarget = *s_tempPicture;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
XRenderSetPictureTransform(display(), pic, &xform);
|
XRenderSetPictureTransform(display(), pic, &xform);
|
||||||
|
@ -699,11 +707,11 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
||||||
}
|
}
|
||||||
if (blitInTempPixmap) {
|
if (blitInTempPixmap) {
|
||||||
const QRect r = mapToScreen(mask, data, temp_visibleRect);
|
const QRect r = mapToScreen(mask, data, temp_visibleRect);
|
||||||
XRenderSetPictureTransform(display(), temp_pixmap->x11PictureHandle(), &xform);
|
XRenderSetPictureTransform(display(), *s_tempPicture, &xform);
|
||||||
XRenderSetPictureFilter(display(), temp_pixmap->x11PictureHandle(), const_cast<char*>("good"), NULL, 0);
|
XRenderSetPictureFilter(display(), *s_tempPicture, const_cast<char*>("good"), NULL, 0);
|
||||||
XRenderComposite(display(), PictOpOver, temp_pixmap->x11PictureHandle(), None, buffer,
|
XRenderComposite(display(), PictOpOver, *s_tempPicture, None, buffer,
|
||||||
0, 0, 0, 0, r.x(), r.y(), r.width(), r.height());
|
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) {
|
if (scaled && !blitInTempPixmap) {
|
||||||
|
@ -716,7 +724,7 @@ XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xRenderOffscreen())
|
if (xRenderOffscreen())
|
||||||
scene_setXRenderOffscreenTarget(temp_pixmap);
|
scene_setXRenderOffscreenTarget(*s_tempPicture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::screenGeometryChanged(const QSize &size)
|
void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||||
|
|
|
@ -84,6 +84,7 @@ public:
|
||||||
void discardAlpha();
|
void discardAlpha();
|
||||||
QRegion transformedShape() const;
|
QRegion transformedShape() const;
|
||||||
void setTransformedShape(const QRegion& shape);
|
void setTransformedShape(const QRegion& shape);
|
||||||
|
static void cleanup();
|
||||||
private:
|
private:
|
||||||
Picture picture();
|
Picture picture();
|
||||||
Picture alphaMask(double opacity);
|
Picture alphaMask(double opacity);
|
||||||
|
@ -95,8 +96,8 @@ private:
|
||||||
Picture alpha;
|
Picture alpha;
|
||||||
double alpha_cached_opacity;
|
double alpha_cached_opacity;
|
||||||
QRegion transformed_shape;
|
QRegion transformed_shape;
|
||||||
static QPixmap *temp_pixmap;
|
|
||||||
static QRect temp_visibleRect;
|
static QRect temp_visibleRect;
|
||||||
|
static XRenderPicture *s_tempPicture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneXrender::EffectFrame
|
class SceneXrender::EffectFrame
|
||||||
|
|
Loading…
Reference in a new issue