summaryrefslogtreecommitdiffstats
path: root/src/opengl/qwindowsurface_x11gl.cpp
diff options
context:
space:
mode:
authorTom Cooksey <thomas.cooksey@nokia.com>2010-04-21 15:59:40 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2010-04-22 14:38:08 (GMT)
commit0c77187652b976c3b9a17e95311bda3e3d8a6fbe (patch)
treeb6df8fd0c7b0c16d3f504a41a0264f85389958b7 /src/opengl/qwindowsurface_x11gl.cpp
parent1a00c7dec743c05b0f64bcacc03b3d2c90ac881d (diff)
downloadQt-0c77187652b976c3b9a17e95311bda3e3d8a6fbe.zip
Qt-0c77187652b976c3b9a17e95311bda3e3d8a6fbe.tar.gz
Qt-0c77187652b976c3b9a17e95311bda3e3d8a6fbe.tar.bz2
QX11GL: Cleanup the window surface & remove some synchronisation
Previously we were calling all manor of synchronisation calls to make sure there were no issues. These have been sanitised to just use eglWaitClient and eglWaitNative and only in places which need it. There is still a bug where small updates will sometimes result in small horizontal streaks. However, this has been confirmed to be a cache flush bug in the X server 2D driver. The driver bug is tracked in Meamo bugzilla as bug 164941. Hopefully it will be fixed soon. Reviewed-By: TrustMe
Diffstat (limited to 'src/opengl/qwindowsurface_x11gl.cpp')
-rw-r--r--src/opengl/qwindowsurface_x11gl.cpp92
1 files changed, 41 insertions, 51 deletions
diff --git a/src/opengl/qwindowsurface_x11gl.cpp b/src/opengl/qwindowsurface_x11gl.cpp
index 7befe03..e5a1760 100644
--- a/src/opengl/qwindowsurface_x11gl.cpp
+++ b/src/opengl/qwindowsurface_x11gl.cpp
@@ -72,63 +72,66 @@ extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11
void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
{
-// qDebug("QX11GLWindowSurface::flush()");
- QTime startTime = QTime::currentTime();
+ // We don't need to know the widget which initiated the flush. Instead we just use the offset
+ // to translate the widgetRegion:
+ Q_UNUSED(widget);
+
if (m_backBuffer.isNull()) {
- qDebug("QHarmattanWindowSurface::flush() - backBuffer is null, not flushing anything");
+ qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything");
return;
}
- QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft();
- QRegion windowRegion(widgetRegion);
- QRect boundingRect = widgetRegion.boundingRect();
- if (!widgetOffset.isNull())
- windowRegion.translate(-widgetOffset);
- QRect windowBoundingRect = windowRegion.boundingRect();
+ Q_ASSERT(window()->size() != m_backBuffer.size());
- int rectCount;
- XRectangle *rects = (XRectangle *)qt_getClipRects(windowRegion, rectCount);
- if (rectCount <= 0)
- return;
-// qDebug() << "XSetClipRectangles";
-// for (int i = 0; i < num; ++i)
-// qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
+ // Wait for all GL rendering to the back buffer pixmap to complete before trying to
+ // copy it to the window. We do this by making sure the pixmap's context is current
+ // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
+ // block, just that "All rendering calls...are guaranteed to be executed before native
+ // rendering calls". This makes it potentially less expensive than glFinish.
+ QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
+ if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
+ ctx->makeCurrent();
+ eglWaitClient();
if (m_windowGC == 0) {
- m_windowGC = XCreateGC(X11->display, m_window->handle(), 0, 0);
- XSetGraphicsExposures(X11->display, m_windowGC, False);
+ XGCValues attribs;
+ attribs.graphics_exposures = False;
+ m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs);
}
+ int rectCount;
+ XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount);
+ if (rectCount <= 0)
+ return;
+
XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
+
+ QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
- boundingRect.x() + offset.x(), boundingRect.y() + offset.y(),
- boundingRect.width(), boundingRect.height(),
- windowBoundingRect.x(), windowBoundingRect.y());
-
- QX11GLPixmapData* pmd = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data());
- Q_ASSERT(pmd->context());
- pmd->context()->makeCurrent();
- XSync(X11->display, False);
+ dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
+ dirtyRect.x(), dirtyRect.y());
+
+ // Make sure the blit of the update from the back buffer to the window completes
+ // before allowing rendering to start again to the back buffer. Otherwise the GPU
+ // might start rendering to the back buffer again while the blit takes place.
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
}
void QX11GLWindowSurface::setGeometry(const QRect &rect)
{
if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
- QSize newSize = rect.size();
-// QSize newSize(1024,512);
- qDebug() << "QX11GLWindowSurface::setGeometry() - creating a pixmap of size" << newSize;
QX11GLPixmapData *pd = new QX11GLPixmapData;
+ QSize newSize = rect.size();
pd->resize(newSize.width(), newSize.height());
m_backBuffer = QPixmap(pd);
if (window()->testAttribute(Qt::WA_TranslucentBackground))
m_backBuffer.fill(Qt::transparent);
+ if (m_pixmapGC) {
+ XFreeGC(X11->display, m_pixmapGC);
+ m_pixmapGC = 0;
+ }
}
-// if (gc)
-// XFreeGC(X11->display, gc);
-// gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
-// XSetGraphicsExposures(X11->display, gc, False);
QWindowSurface::setGeometry(rect);
}
@@ -139,10 +142,10 @@ bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
- QX11GLPixmapData* pmd = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data());
- Q_ASSERT(pmd->context());
- pmd->context()->makeCurrent();
- glFinish();
+ // Make sure all GL rendering is complete before starting the scroll operation:
+ QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
+ if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
+ ctx->makeCurrent();
eglWaitClient();
if (!m_pixmapGC)
@@ -154,24 +157,11 @@ bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
rect.x()+dx, rect.y()+dy);
}
- XSync(X11->display, False);
+ // Make sure the scroll operation is complete before allowing GL rendering to resume
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
return true;
}
-/*
-void QX11GLWindowSurface::beginPaint(const QRegion &region)
-{
-}
-
-void QX11GLWindowSurface::endPaint(const QRegion &region)
-{
-}
-
-QImage *QX11GLWindowSurface::buffer(const QWidget *widget)
-{
-}
-*/
QT_END_NAMESPACE