Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/opengl/qwindowsurface_x11gl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 201 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation ([email protected])
     
    5252
    5353QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
    54     : QWindowSurface(window), m_GC(0), m_window(window)
     54    : QWindowSurface(window), m_GC(0), m_window(window)
    5555{
    5656}
     
    5858QX11GLWindowSurface::~QX11GLWindowSurface()
    5959{
    60     if (m_GC)
    61         XFree(m_GC);
     60    if (m_windowGC)
     61        XFree(m_windowGC);
     62    if (m_pixmapGC)
     63        XFree(m_pixmapGC);
    6264}
    6365
     
    7173void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
    7274{
    73 //    qDebug("QX11GLWindowSurface::flush()");
    74     QTime startTime = QTime::currentTime();
     75    // We don't need to know the widget which initiated the flush. Instead we just use the offset
     76    // to translate the widgetRegion:
     77    Q_UNUSED(widget);
     78
    7579    if (m_backBuffer.isNull()) {
    76         qDebug("QHarmattanWindowSurface::flush() - backBuffer is null, not flushing anything");
     80        qDebug("QWindowSurface::flush() - backBuffer is null, not flushing anything");
    7781        return;
    7882    }
    7983
    80     QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft();
    81     QRegion windowRegion(widgetRegion);
    82     QRect boundingRect = widgetRegion.boundingRect();
    83     if (!widgetOffset.isNull())
    84         windowRegion.translate(-widgetOffset);
    85     QRect windowBoundingRect = windowRegion.boundingRect();
     84    Q_ASSERT(window()->size() != m_backBuffer.size());
     85
     86    // Wait for all GL rendering to the back buffer pixmap to complete before trying to
     87    // copy it to the window. We do this by making sure the pixmap's context is current
     88    // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
     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    }
    86101
    87102    int rectCount;
    88     XRectangle *rects = (XRectangle *)qt_getClipRects(windowRegion, rectCount);
     103    XRectangle *rects = (XRectangle *)qt_getClipRects(wiRegion, rectCount);
    89104    if (rectCount <= 0)
    90105        return;
    91 //         qDebug() << "XSetClipRectangles";
    92 //         for  (int i = 0; i < num; ++i)
    93 //             qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
    94 
    95     if (m_GC == 0) {
    96         m_GC = XCreateGC(X11->display, m_window->handle(), 0, 0);
    97         XSetGraphicsExposures(X11->display, m_GC, False);
    98     }
    99 
    100     XSetClipRectangles(X11->display, m_GC, 0, 0, rects, rectCount, YXBanded);
    101     XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_GC,
    102               boundingRect.x() + offset.x(), boundingRect.y() + offset.y(),
    103               boundingRect.width(), boundingRect.height(),
    104               windowBoundingRect.x(), windowBoundingRect.y());
     106
     107    XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
     108
     109    QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
     110    XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
     111              dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
     112              dirtyRect.x(), dirtyRect.y());
     113
     114    // Make sure the blit of the update from the back buffer to the window completes
     115    // before allowing rendering to start again to the back buffer. Otherwise the GPU
     116    // might start rendering to the back buffer again while the blit takes place.
     117    eglWaitNative(EGL_CORE_NATIVE_ENGINE);
    105118}
    106119
     
    108121{
    109122    if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
     123
    110124        QSize newSize = rect.size();
    111 //        QSize newSize(1024,512);
    112         qDebug() << "QX11GLWindowSurface::setGeometry() - creating a pixmap of size" << newSize;
    113         QX11GLPixmapData *pd = new QX11GLPixmapData;
    114125        pd->resize(newSize.width(), newSize.height());
    115126        m_backBuffer = QPixmap(pd);
    116     }
    117 
    118 //    if (gc)
    119 //        XFreeGC(X11->display, gc);
    120 //    gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
    121 //    XSetGraphicsExposures(X11->display, gc, False);
     127        if (window()->testAttribute(Qt::WA_TranslucentBackground))
     128            m_backBuffer.fill(Qt::transparent);
     129        if (m_pixmapGC) {
     130            XFreeGC(X11->display, m_pixmapGC);
     131            m_pixmapGC = 0;
     132        }
     133    }
     134
    122135    QWindowSurface::setGeometry(rect);
    123136}
     
    125138bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
    126139{
    127     Q_UNUSED(area);
    128     Q_UNUSED(dx);
    129     Q_UNUSED(dy);
    130     return false;
    131 }
    132 
    133 /*
    134 void QX11GLWindowSurface::beginPaint(const QRegion &region)
    135 {
    136 }
    137 
    138 void QX11GLWindowSurface::endPaint(const QRegion &region)
    139 {
    140 }
    141 
    142 QImage *QX11GLWindowSurface::buffer(const QWidget *widget)
    143 {
    144 }
    145 */
     140    if (m_backBuffer.isNull())
     141        return false;
     142
     143    Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
     144
     145    // Make sure all GL rendering is complete before starting the scroll operation:
     146    QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
     147    if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
     148        ctx->makeCurrent();
     149    eglWaitClient();
     150
     151    if (!m_pixmapGC)
     152        m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
     153
     154    foreach (const QRect& rect, area.rects()) {
     155        XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC,
     156                  rect.x(), rect.y(), rect.width(), rect.height(),
     157                  rect.x()+dx, rect.y()+dy);
     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
     167QPixmap 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}
    146212
    147213QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.