QXcbBackingStore: Fix scrolling when backed with native X Pixmap
Change-Id: I7c6618783996c814dc6873b950e2c35e95680f11 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
This commit is contained in:
parent
3439705c2d
commit
4706e2c533
@ -68,6 +68,8 @@ public:
|
|||||||
QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format);
|
QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format);
|
||||||
~QXcbShmImage() { destroy(); }
|
~QXcbShmImage() { destroy(); }
|
||||||
|
|
||||||
|
bool scroll(const QRegion &area, int dx, int dy);
|
||||||
|
|
||||||
QImage *image() { return &m_qimage; }
|
QImage *image() { return &m_qimage; }
|
||||||
QPlatformGraphicsBuffer *graphicsBuffer() { return m_graphics_buffer; }
|
QPlatformGraphicsBuffer *graphicsBuffer() { return m_graphics_buffer; }
|
||||||
|
|
||||||
@ -76,12 +78,13 @@ public:
|
|||||||
bool hasAlpha() const { return m_hasAlpha; }
|
bool hasAlpha() const { return m_hasAlpha; }
|
||||||
bool hasShm() const { return m_shm_info.shmaddr != nullptr; }
|
bool hasShm() const { return m_shm_info.shmaddr != nullptr; }
|
||||||
|
|
||||||
void put(xcb_window_t window, const QRegion ®ion, const QPoint &offset);
|
void put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset);
|
||||||
void preparePaint(const QRegion ®ion);
|
void preparePaint(const QRegion ®ion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
|
void ensureGC(xcb_drawable_t dst);
|
||||||
void flushPixmap(const QRegion ®ion);
|
void flushPixmap(const QRegion ®ion);
|
||||||
void setClip(const QRegion ®ion);
|
void setClip(const QRegion ®ion);
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ private:
|
|||||||
QPlatformGraphicsBuffer *m_graphics_buffer;
|
QPlatformGraphicsBuffer *m_graphics_buffer;
|
||||||
|
|
||||||
xcb_gcontext_t m_gc;
|
xcb_gcontext_t m_gc;
|
||||||
xcb_window_t m_gc_window;
|
xcb_drawable_t m_gc_drawable;
|
||||||
|
|
||||||
// When using shared memory this is the region currently shared with the server
|
// When using shared memory this is the region currently shared with the server
|
||||||
QRegion m_dirtyShm;
|
QRegion m_dirtyShm;
|
||||||
@ -142,7 +145,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
|
|||||||
: QXcbObject(screen->connection())
|
: QXcbObject(screen->connection())
|
||||||
, m_graphics_buffer(Q_NULLPTR)
|
, m_graphics_buffer(Q_NULLPTR)
|
||||||
, m_gc(0)
|
, m_gc(0)
|
||||||
, m_gc_window(0)
|
, m_gc_drawable(0)
|
||||||
, m_xcb_pixmap(0)
|
, m_xcb_pixmap(0)
|
||||||
{
|
{
|
||||||
Q_XCB_NOOP(connection());
|
Q_XCB_NOOP(connection());
|
||||||
@ -207,6 +210,39 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
|
||||||
|
|
||||||
|
bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
|
||||||
|
{
|
||||||
|
if (image()->isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hasShm())
|
||||||
|
preparePaint(area);
|
||||||
|
|
||||||
|
const QPoint delta(dx, dy);
|
||||||
|
foreach (const QRect &rect, area.rects())
|
||||||
|
qt_scrollRectInImage(*image(), rect, delta);
|
||||||
|
|
||||||
|
if (m_xcb_pixmap) {
|
||||||
|
flushPixmap(area);
|
||||||
|
ensureGC(m_xcb_pixmap);
|
||||||
|
const QRect bounds(QPoint(0, 0), size());
|
||||||
|
foreach (const QRect &src, area.rects()) {
|
||||||
|
const QRect dst = src.translated(delta).intersected(bounds);
|
||||||
|
Q_XCB_CALL(xcb_copy_area(xcb_connection(),
|
||||||
|
m_xcb_pixmap,
|
||||||
|
m_xcb_pixmap,
|
||||||
|
m_gc,
|
||||||
|
src.x(), src.y(),
|
||||||
|
dst.x(), dst.y(),
|
||||||
|
dst.width(), dst.height()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void QXcbShmImage::destroy()
|
void QXcbShmImage::destroy()
|
||||||
{
|
{
|
||||||
const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
|
const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
|
||||||
@ -235,6 +271,22 @@ void QXcbShmImage::destroy()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QXcbShmImage::ensureGC(xcb_drawable_t dst)
|
||||||
|
{
|
||||||
|
if (m_gc_drawable != dst) {
|
||||||
|
if (m_gc)
|
||||||
|
Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
|
||||||
|
|
||||||
|
static const uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES;
|
||||||
|
static const uint32_t values[] = { 0 };
|
||||||
|
|
||||||
|
m_gc = xcb_generate_id(xcb_connection());
|
||||||
|
Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, dst, mask, values));
|
||||||
|
|
||||||
|
m_gc_drawable = dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QXcbShmImage::flushPixmap(const QRegion ®ion)
|
void QXcbShmImage::flushPixmap(const QRegion ®ion)
|
||||||
{
|
{
|
||||||
const QVector<QRect> rects = m_pendingFlush.intersected(region).rects();
|
const QVector<QRect> rects = m_pendingFlush.intersected(region).rects();
|
||||||
@ -320,25 +372,11 @@ void QXcbShmImage::setClip(const QRegion ®ion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbShmImage::put(xcb_window_t window, const QRegion ®ion, const QPoint &offset)
|
void QXcbShmImage::put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset)
|
||||||
{
|
{
|
||||||
Q_XCB_NOOP(connection());
|
Q_XCB_NOOP(connection());
|
||||||
|
|
||||||
if (m_gc_window != window) {
|
ensureGC(dst);
|
||||||
if (m_gc)
|
|
||||||
Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
|
|
||||||
|
|
||||||
static const uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES;
|
|
||||||
static const uint32_t values[] = { 0 };
|
|
||||||
|
|
||||||
m_gc = xcb_generate_id(xcb_connection());
|
|
||||||
Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, mask, values));
|
|
||||||
|
|
||||||
m_gc_window = window;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_XCB_NOOP(connection());
|
|
||||||
|
|
||||||
setClip(region);
|
setClip(region);
|
||||||
|
|
||||||
const QRect bounds = region.boundingRect();
|
const QRect bounds = region.boundingRect();
|
||||||
@ -347,7 +385,7 @@ void QXcbShmImage::put(xcb_window_t window, const QRegion ®ion, const QPoint
|
|||||||
|
|
||||||
if (hasShm()) {
|
if (hasShm()) {
|
||||||
Q_XCB_CALL(xcb_shm_put_image(xcb_connection(),
|
Q_XCB_CALL(xcb_shm_put_image(xcb_connection(),
|
||||||
window,
|
dst,
|
||||||
m_gc,
|
m_gc,
|
||||||
m_xcb_image->width,
|
m_xcb_image->width,
|
||||||
m_xcb_image->height,
|
m_xcb_image->height,
|
||||||
@ -364,7 +402,7 @@ void QXcbShmImage::put(xcb_window_t window, const QRegion ®ion, const QPoint
|
|||||||
flushPixmap(region);
|
flushPixmap(region);
|
||||||
Q_XCB_CALL(xcb_copy_area(xcb_connection(),
|
Q_XCB_CALL(xcb_copy_area(xcb_connection(),
|
||||||
m_xcb_pixmap,
|
m_xcb_pixmap,
|
||||||
window,
|
dst,
|
||||||
m_gc,
|
m_gc,
|
||||||
source.x(), source.y(),
|
source.x(), source.y(),
|
||||||
target.x(), target.y(),
|
target.x(), target.y(),
|
||||||
@ -533,20 +571,12 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
|
|||||||
Q_XCB_NOOP(connection());
|
Q_XCB_NOOP(connection());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
|
|
||||||
|
|
||||||
bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
|
bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
|
||||||
{
|
{
|
||||||
if (!m_image || m_image->image()->isNull())
|
if (m_image)
|
||||||
return false;
|
return m_image->scroll(area, dx, dy);
|
||||||
|
|
||||||
m_image->preparePaint(area);
|
return false;
|
||||||
|
|
||||||
QPoint delta(dx, dy);
|
|
||||||
const QVector<QRect> rects = area.rects();
|
|
||||||
for (int i = 0; i < rects.size(); ++i)
|
|
||||||
qt_scrollRectInImage(*m_image->image(), rects.at(i), delta);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user