summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-07-21 10:54:41 +0200
committerJørgen Lind <jorgen.lind@nokia.com>2011-07-21 14:56:38 +0200
commite026f767c9c600618104619d45ab6537f6988929 (patch)
treea6824f6e9f9fc3c6900d7e042c6145fb15a7e80c
parent7b3b6b5afaaf1db1bfbfa9b56fa7b955a61344bd (diff)
Handle failed SHM attach in XCB backing store.
Change-Id: I5f97c0c6030d13b68cfc17d19ba969cd78f79c3f Reviewed-on: http://codereview.qt.nokia.com/1943 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp54
1 files changed, 39 insertions, 15 deletions
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 3def577462..50407f7c9b 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -114,12 +114,18 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false));
if (error) {
- qWarning() << "QXcbBackingStore: Unable to attach to shared memory segment";
free(error);
- }
- if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1)
- qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed";
+ shmdt(m_shm_info.shmaddr);
+ shmctl(m_shm_info.shmid, IPC_RMID, 0);
+
+ m_shm_info.shmaddr = 0;
+
+ m_xcb_image->data = (uint8_t *)qMalloc(segmentSize);
+ } else {
+ if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1)
+ qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed";
+ }
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
}
@@ -127,14 +133,18 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
void QXcbShmImage::destroy()
{
const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
- if (segmentSize)
+ if (segmentSize && m_shm_info.shmaddr)
Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
xcb_image_destroy(m_xcb_image);
if (segmentSize) {
- shmdt(m_shm_info.shmaddr);
- shmctl(m_shm_info.shmid, IPC_RMID, 0);
+ if (m_shm_info.shmaddr) {
+ shmdt(m_shm_info.shmaddr);
+ shmctl(m_shm_info.shmid, IPC_RMID, 0);
+ } else {
+ qFree(m_xcb_image->data);
+ }
}
if (m_gc)
@@ -155,18 +165,32 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s
}
Q_XCB_NOOP(connection());
- xcb_image_shm_put(xcb_connection(),
+ if (m_shm_info.shmaddr) {
+ xcb_image_shm_put(xcb_connection(),
+ window,
+ m_gc,
+ m_xcb_image,
+ m_shm_info,
+ source.x(),
+ source.y(),
+ target.x(),
+ target.y(),
+ source.width(),
+ source.height(),
+ false);
+ } else {
+ xcb_image_t *subimage = xcb_image_subimage(m_xcb_image, source.x(), source.y(), source.width(), source.height(),
+ 0, 0, 0);
+ xcb_image_put(xcb_connection(),
window,
m_gc,
- m_xcb_image,
- m_shm_info,
- source.x(),
- source.y(),
+ subimage,
target.x(),
target.y(),
- source.width(),
- source.height(),
- false);
+ 0);
+
+ xcb_image_destroy(subimage);
+ }
Q_XCB_NOOP(connection());
m_dirty = m_dirty | source;