Port Magnifier Effect to XCB

First XRender effect which gets ported over. Therefore required bits are
added to CMakeLists.txt.

Port to xcb is luckily rather straight forward. Though the QPixmap usage
needs to be replaced by xcb_pixmap_t together with a XRenderPicture.
This commit is contained in:
Martin Gräßlin 2013-01-28 19:54:27 +01:00
parent d703adbdc1
commit c5bebcd809
3 changed files with 67 additions and 40 deletions

View file

@ -3,7 +3,7 @@ kde4_no_enable_final(kwineffects)
macro( KWIN4_ADD_EFFECT_BACKEND name )
kde4_add_plugin( ${name} ${ARGN} )
target_link_libraries( ${name} kwineffects ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB} ${X11_LIBRARIES})
target_link_libraries( ${name} kwineffects ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB} ${X11_LIBRARIES} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES})
endmacro( KWIN4_ADD_EFFECT_BACKEND )
# Adds effect plugin with given name. Sources are given after the name
@ -58,12 +58,12 @@ endmacro( KWIN4_ADD_EFFECT_CONFIG )
macro( KWIN4_EFFECT_LINK_XRENDER name )
if( KWIN_HAVE_XRENDER_COMPOSITING )
target_link_libraries( kwin4_effect_${name} ${X11_Xrender_LIB} )
target_link_libraries( kwin4_effect_${name} ${X11_Xrender_LIB} ${XCB_RENDER_LIBRARIES})
# if building for OpenGL and OpenGL ES we have two targets
# TODO: if building for OpenGL ES we should not build XRender support
if(OPENGLES_FOUND)
target_link_libraries( kwin4_effect_gles_${name} ${X11_Xrender_LIB} )
target_link_libraries( kwin4_effect_gles_${name} ${X11_Xrender_LIB} ${XCB_RENDER_LIBRARIES})
endif(OPENGLES_FOUND)
endif( KWIN_HAVE_XRENDER_COMPOSITING )
endmacro( KWIN4_EFFECT_LINK_XRENDER )

View file

@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwinglutils.h>
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include <kwinxrenderutils.h>
#include <xcb/render.h>
#endif
namespace KWin
@ -49,7 +50,9 @@ MagnifierEffect::MagnifierEffect()
, polling(false)
, m_texture(0)
, m_fbo(0)
, m_pixmap(0)
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
, m_pixmap(XCB_PIXMAP_NONE)
#endif
{
KActionCollection* actionCollection = new KActionCollection(this);
KAction* a;
@ -68,13 +71,26 @@ MagnifierEffect::~MagnifierEffect()
{
delete m_fbo;
delete m_texture;
delete m_pixmap;
destroyPixmap();
// Save the zoom value.
KConfigGroup conf = EffectsHandler::effectConfig("Magnifier");
conf.writeEntry("InitialZoom", target_zoom);
conf.sync();
}
void MagnifierEffect::destroyPixmap()
{
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if (effects->compositingType() != XRenderCompositing) {
return;
}
m_picture.reset();
if (m_pixmap != XCB_PIXMAP_NONE) {
xcb_free_pixmap(connection(), m_pixmap);
}
#endif
}
bool MagnifierEffect::supported()
{
return effects->compositingType() == XRenderCompositing ||
@ -106,10 +122,9 @@ void MagnifierEffect::prePaintScreen(ScreenPrePaintData& data, int time)
// zoom ended - delete FBO and texture
delete m_fbo;
delete m_texture;
delete m_pixmap;
m_fbo = NULL;
m_texture = NULL;
m_pixmap = NULL;
destroyPixmap();
}
}
}
@ -174,39 +189,46 @@ void MagnifierEffect::paintScreen(int mask, QRegion region, ScreenPaintData& dat
}
if (effects->compositingType() == XRenderCompositing) {
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if (!m_pixmap || m_pixmap->size() != srcArea.size()) {
delete m_pixmap;
m_pixmap = new QPixmap(srcArea.size());
if (m_pixmap == XCB_PIXMAP_NONE || m_pixmapSize != srcArea.size()) {
destroyPixmap();
m_pixmap = xcb_generate_id(connection());
m_pixmapSize = srcArea.size();
xcb_create_pixmap(connection(), 32, m_pixmap, rootWindow(), m_pixmapSize.width(), m_pixmapSize.height());
m_picture.reset(new XRenderPicture(m_pixmap, 32));
}
static XTransform identity = {{
{ XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) },
{ XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) },
{ XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
}
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
static xcb_render_transform_t identity = {
DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)
};
static XTransform xform = {{
{ XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) },
{ XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) },
{ XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
}
static xcb_render_transform_t xform = {
DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)
};
XRenderComposite( display(), PictOpSrc, effects->xrenderBufferPicture(), 0, m_pixmap->x11PictureHandle(),
srcArea.x(), srcArea.y(), 0, 0, 0, 0, srcArea.width(), srcArea.height() );
XFlush(display());
xform.matrix[0][0] = XDoubleToFixed(1.0/zoom);
xform.matrix[1][1] = XDoubleToFixed(1.0/zoom);
XRenderSetPictureTransform(display(), m_pixmap->x11PictureHandle(), &xform);
XRenderSetPictureFilter(display(), m_pixmap->x11PictureHandle(), const_cast<char*>("good"), NULL, 0);
XRenderComposite( display(), PictOpSrc, m_pixmap->x11PictureHandle(), 0, effects->xrenderBufferPicture(),
0, 0, 0, 0, area.x(), area.y(), area.width(), area.height() );
XRenderSetPictureFilter(display(), m_pixmap->x11PictureHandle(), const_cast<char*>("fast"), NULL, 0);
XRenderSetPictureTransform(display(), m_pixmap->x11PictureHandle(), &identity);
const XRectangle rects[4] = { { area.x()+FRAME_WIDTH, area.y(), area.width()-FRAME_WIDTH, FRAME_WIDTH},
{ area.right()-FRAME_WIDTH, area.y()+FRAME_WIDTH, FRAME_WIDTH, area.height()-FRAME_WIDTH},
{ area.x(), area.bottom()-FRAME_WIDTH, area.width()-FRAME_WIDTH, FRAME_WIDTH},
{ area.x(), area.y(), FRAME_WIDTH, area.height()-FRAME_WIDTH} };
XRenderColor c = preMultiply(QColor(0,0,0,255));
XRenderFillRectangles(display(), PictOpSrc, effects->xrenderBufferPicture(), &c, rects, 4);
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, effects->xrenderBufferPicture(), 0, *m_picture,
srcArea.x(), srcArea.y(), 0, 0, 0, 0, srcArea.width(), srcArea.height());
xcb_flush(connection());
xform.matrix11 = DOUBLE_TO_FIXED(1.0/zoom);
xform.matrix22 = DOUBLE_TO_FIXED(1.0/zoom);
#undef DOUBLE_TO_FIXED
xcb_render_set_picture_transform(connection(), *m_picture, xform);
xcb_render_set_picture_filter(connection(), *m_picture, 4, const_cast<char*>("good"), 0, NULL);
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, *m_picture, 0, effects->xrenderBufferPicture(),
0, 0, 0, 0, area.x(), area.y(), area.width(), area.height() );
xcb_render_set_picture_filter(connection(), *m_picture, 4, const_cast<char*>("fast"), 0, NULL);
xcb_render_set_picture_transform(connection(), *m_picture, identity);
const xcb_rectangle_t rects[4] = {
{ int16_t(area.x()+FRAME_WIDTH), int16_t(area.y()), uint16_t(area.width()-FRAME_WIDTH), uint16_t(FRAME_WIDTH)},
{ int16_t(area.right()-FRAME_WIDTH), int16_t(area.y()+FRAME_WIDTH), uint16_t(FRAME_WIDTH), uint16_t(area.height()-FRAME_WIDTH)},
{ int16_t(area.x()), int16_t(area.bottom()-FRAME_WIDTH), uint16_t(area.width()-FRAME_WIDTH), uint16_t(FRAME_WIDTH)},
{ int16_t(area.x()), int16_t(area.y()), uint16_t(FRAME_WIDTH), uint16_t(area.height()-FRAME_WIDTH)}
};
// TODO: remove XRenderColor
const XRenderColor xc = preMultiply(QColor(0,0,0,255));
const xcb_render_color_t c = {xc.red, xc.green, xc.blue, xc.alpha};
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, effects->xrenderBufferPicture(), c, 4, rects);
#endif
}
}
@ -254,10 +276,9 @@ void MagnifierEffect::zoomOut()
if (zoom == target_zoom) {
delete m_fbo;
delete m_texture;
delete m_pixmap;
m_fbo = NULL;
m_texture = NULL;
m_pixmap = NULL;
destroyPixmap();
}
}
effects->addRepaint(magnifierArea().adjusted(-FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH));

View file

@ -29,6 +29,7 @@ namespace KWin
class GLRenderTarget;
class GLTexture;
class XRenderPicture;
class MagnifierEffect
: public Effect
@ -60,6 +61,7 @@ private slots:
void slotMouseChanged(const QPoint& pos, const QPoint& old,
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
void destroyPixmap();
private:
QRect magnifierArea(QPoint pos = cursorPos()) const;
double zoom;
@ -68,7 +70,11 @@ private:
QSize magnifier_size;
GLTexture *m_texture;
GLRenderTarget *m_fbo;
QPixmap *m_pixmap;
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
xcb_pixmap_t m_pixmap;
QSize m_pixmapSize;
QScopedPointer<XRenderPicture> m_picture;
#endif
};
} // namespace