src/opengl/qwindowsurface_x11gl.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    49 #include "qpixmapdata_x11gl_p.h"
    49 #include "qpixmapdata_x11gl_p.h"
    50 
    50 
    51 QT_BEGIN_NAMESPACE
    51 QT_BEGIN_NAMESPACE
    52 
    52 
    53 QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
    53 QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
    54     : QWindowSurface(window), m_GC(0), m_window(window)
    54     : QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window)
    55 {
    55 {
    56 }
    56 }
    57 
    57 
    58 QX11GLWindowSurface::~QX11GLWindowSurface()
    58 QX11GLWindowSurface::~QX11GLWindowSurface()
    59 {
    59 {
    60     if (m_GC)
    60     if (m_windowGC)
    61         XFree(m_GC);
    61         XFree(m_windowGC);
       
    62     if (m_pixmapGC)
       
    63         XFree(m_pixmapGC);
    62 }
    64 }
    63 
    65 
    64 QPaintDevice *QX11GLWindowSurface::paintDevice()
    66 QPaintDevice *QX11GLWindowSurface::paintDevice()
    65 {
    67 {
    66     return &m_backBuffer;
    68     return &m_backBuffer;
    68 
    70 
    69 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp
    71 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp
    70 
    72 
    71 void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
    73 void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
    72 {
    74 {
    73 //    qDebug("QX11GLWindowSurface::flush()");
    75     // We don't need to know the widget which initiated the flush. Instead we just use the offset
    74     QTime startTime = QTime::currentTime();
    76     // to translate the widgetRegion:
       
    77     Q_UNUSED(widget);
       
    78 
    75     if (m_backBuffer.isNull()) {
    79     if (m_backBuffer.isNull()) {
    76         qDebug("QHarmattanWindowSurface::flush() - backBuffer is null, not flushing anything");
    80         qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything");
    77         return;
    81         return;
    78     }
    82     }
    79 
    83 
    80     QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft();
    84     Q_ASSERT(window()->size() != m_backBuffer.size());
    81     QRegion windowRegion(widgetRegion);
    85 
    82     QRect boundingRect = widgetRegion.boundingRect();
    86     // Wait for all GL rendering to the back buffer pixmap to complete before trying to
    83     if (!widgetOffset.isNull())
    87     // copy it to the window. We do this by making sure the pixmap's context is current
    84         windowRegion.translate(-widgetOffset);
    88     // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
    85     QRect windowBoundingRect = windowRegion.boundingRect();
    89     // block, just that "All rendering calls...are guaranteed to be executed before native
       
    90     // rendering calls". This makes it potentially less expensive than glFinish.
       
    91     QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
       
    92     if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
       
    93         ctx->makeCurrent();
       
    94     eglWaitClient();
       
    95 
       
    96     if (m_windowGC == 0) {
       
    97         XGCValues attribs;
       
    98         attribs.graphics_exposures = False;
       
    99         m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs);
       
   100     }
    86 
   101 
    87     int rectCount;
   102     int rectCount;
    88     XRectangle *rects = (XRectangle *)qt_getClipRects(windowRegion, rectCount);
   103     XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount);
    89     if (rectCount <= 0)
   104     if (rectCount <= 0)
    90         return;
   105         return;
    91 //         qDebug() << "XSetClipRectangles";
   106 
    92 //         for  (int i = 0; i < num; ++i)
   107     XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
    93 //             qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
   108 
    94 
   109     QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
    95     if (m_GC == 0) {
   110     XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
    96         m_GC = XCreateGC(X11->display, m_window->handle(), 0, 0);
   111               dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
    97         XSetGraphicsExposures(X11->display, m_GC, False);
   112               dirtyRect.x(), dirtyRect.y());
    98     }
   113 
    99 
   114     // Make sure the blit of the update from the back buffer to the window completes
   100     XSetClipRectangles(X11->display, m_GC, 0, 0, rects, rectCount, YXBanded);
   115     // before allowing rendering to start again to the back buffer. Otherwise the GPU
   101     XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_GC,
   116     // might start rendering to the back buffer again while the blit takes place.
   102               boundingRect.x() + offset.x(), boundingRect.y() + offset.y(),
   117     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
   103               boundingRect.width(), boundingRect.height(),
       
   104               windowBoundingRect.x(), windowBoundingRect.y());
       
   105 }
   118 }
   106 
   119 
   107 void QX11GLWindowSurface::setGeometry(const QRect &rect)
   120 void QX11GLWindowSurface::setGeometry(const QRect &rect)
   108 {
   121 {
   109     if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
   122     if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
       
   123         QX11GLPixmapData *pd = new QX11GLPixmapData;
   110         QSize newSize = rect.size();
   124         QSize newSize = rect.size();
   111 //        QSize newSize(1024,512);
       
   112         qDebug() << "QX11GLWindowSurface::setGeometry() - creating a pixmap of size" << newSize;
       
   113         QX11GLPixmapData *pd = new QX11GLPixmapData;
       
   114         pd->resize(newSize.width(), newSize.height());
   125         pd->resize(newSize.width(), newSize.height());
   115         m_backBuffer = QPixmap(pd);
   126         m_backBuffer = QPixmap(pd);
   116     }
   127         if (window()->testAttribute(Qt::WA_TranslucentBackground))
   117 
   128             m_backBuffer.fill(Qt::transparent);
   118 //    if (gc)
   129         if (m_pixmapGC) {
   119 //        XFreeGC(X11->display, gc);
   130             XFreeGC(X11->display, m_pixmapGC);
   120 //    gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
   131             m_pixmapGC = 0;
   121 //    XSetGraphicsExposures(X11->display, gc, False);
   132         }
       
   133     }
       
   134 
   122     QWindowSurface::setGeometry(rect);
   135     QWindowSurface::setGeometry(rect);
   123 }
   136 }
   124 
   137 
   125 bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
   138 bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
   126 {
   139 {
   127     Q_UNUSED(area);
   140     if (m_backBuffer.isNull())
   128     Q_UNUSED(dx);
   141         return false;
   129     Q_UNUSED(dy);
   142 
   130     return false;
   143     Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
   131 }
   144 
   132 
   145     // Make sure all GL rendering is complete before starting the scroll operation:
   133 /*
   146     QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
   134 void QX11GLWindowSurface::beginPaint(const QRegion &region)
   147     if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
   135 {
   148         ctx->makeCurrent();
   136 }
   149     eglWaitClient();
   137 
   150 
   138 void QX11GLWindowSurface::endPaint(const QRegion &region)
   151     if (!m_pixmapGC)
   139 {
   152         m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
   140 }
   153 
   141 
   154     foreach (const QRect& rect, area.rects()) {
   142 QImage *QX11GLWindowSurface::buffer(const QWidget *widget)
   155         XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC,
   143 {
   156                   rect.x(), rect.y(), rect.width(), rect.height(),
   144 }
   157                   rect.x()+dx, rect.y()+dy);
   145 */
   158     }
       
   159 
       
   160     // Make sure the scroll operation is complete before allowing GL rendering to resume
       
   161     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
       
   162 
       
   163     return true;
       
   164 }
       
   165 
       
   166 
       
   167 QPixmap QX11GLWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const
       
   168 {
       
   169     if (!widget || m_backBuffer.isNull())
       
   170         return QPixmap();
       
   171 
       
   172     QRect srcRect;
       
   173 
       
   174     // make sure the rect is inside the widget & clip to widget's rect
       
   175     if (!rect.isEmpty())
       
   176         srcRect = rect & widget->rect();
       
   177     else
       
   178         srcRect = widget->rect();
       
   179 
       
   180     if (srcRect.isEmpty())
       
   181         return QPixmap();
       
   182 
       
   183     // If it's a child widget we have to translate the coordinates
       
   184     if (widget != window())
       
   185         srcRect.translate(widget->mapTo(window(), QPoint(0, 0)));
       
   186 
       
   187     QPixmap::x11SetDefaultScreen(widget->x11Info().screen());
       
   188 
       
   189     QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType);
       
   190     pmd->resize(srcRect.width(), srcRect.height());
       
   191     QPixmap px(pmd);
       
   192 
       
   193     GC tmpGc = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
       
   194 
       
   195     // Make sure all GL rendering is complete before copying the window
       
   196     QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.pixmapData())->context();
       
   197     if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
       
   198         ctx->makeCurrent();
       
   199     eglWaitClient();
       
   200 
       
   201     // Copy srcRect from the backing store to the new pixmap
       
   202     XSetGraphicsExposures(X11->display, tmpGc, False);
       
   203     XCopyArea(X11->display, m_backBuffer.handle(), px.handle(), tmpGc,
       
   204               srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0);
       
   205     XFreeGC(X11->display, tmpGc);
       
   206 
       
   207     // Wait until the copy has finised before allowing more rendering into the back buffer
       
   208     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
       
   209 
       
   210     return px;
       
   211 }
   146 
   212 
   147 QT_END_NAMESPACE
   213 QT_END_NAMESPACE