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_gl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8383#endif
    8484
    85 #ifdef QT_OPENGL_ES_1_CL
    86 #include "qgl_cl_p.h"
    87 #endif
    88 
    89 #ifdef QT_OPENGL_ES
    90 #include <private/qegl_p.h>
     85#ifndef QT_NO_EGL
     86#include <private/qeglcontext_p.h>
    9187#endif
    9288
     
    9995extern Q_GUI_EXPORT bool qt_win_owndc_required;
    10096#endif
    101 QGLGraphicsSystem::QGLGraphicsSystem()
    102     : QGraphicsSystem()
     97QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL)
     98    : QGraphicsSystem(), m_useX11GL(useX11GL)
    10399{
    104100#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     
    195191        if (!initializing && !widget && !cleanedUp) {
    196192            initializing = true;
    197             widget = new QGLWidget;
    198             // We dont need this internal widget to appear in QApplication::topLevelWidgets()
     193
     194            widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer));
     195            widget->resize(1, 1);
     196
     197            // We don't need this internal widget to appear in QApplication::topLevelWidgets()
    199198            if (QWidgetPrivate::allWidgets)
    200199                QWidgetPrivate::allWidgets->remove(widget);
     
    204203    }
    205204
     205    // destroys the share widget and prevents recreation
    206206    void cleanup() {
    207207        QGLWidget *w = widget;
     
    211211    }
    212212
     213    // destroys the share widget, but allows it to be recreated later on
     214    void destroy() {
     215        if (cleanedUp)
     216            return;
     217
     218        QGLWidget *w = widget;
     219
     220        // prevent potential recursions
     221        cleanedUp = true;
     222        widget = 0;
     223        delete w;
     224        cleanedUp = false;
     225    }
     226
    213227    static bool cleanedUp;
    214228
     
    238252}
    239253
     254void qt_destroy_gl_share_widget()
     255{
     256    _qt_gl_share_widget()->destroy();
     257}
    240258
    241259struct QGLWindowSurfacePrivate
     
    250268    int destructive_swap_buffers : 1;
    251269    int geometry_updated : 1;
     270    int did_paint : 1;
    252271
    253272    QGLContext *ctx;
     
    257276    QRegion paintedRegion;
    258277    QSize size;
     278
     279    QSize textureSize;
    259280
    260281    QList<QImage> buffers;
     
    264285
    265286QGLFormat QGLWindowSurface::surfaceFormat;
     287QGLWindowSurface::SwapMode QGLWindowSurface::swapBehavior = QGLWindowSurface::AutomaticSwap;
    266288
    267289void QGLWindowSurfaceGLPaintDevice::endPaint()
     
    299321    d_ptr->fbo = 0;
    300322    d_ptr->ctx = 0;
     323    d_ptr->tex_id = 0;
    301324#if defined (QT_OPENGL_ES_2)
    302325    d_ptr->tried_fbo = true;
     
    310333    d_ptr->q_ptr = this;
    311334    d_ptr->geometry_updated = false;
     335    d_ptr->did_paint = false;
    312336}
    313337
     
    328352void QGLWindowSurface::deleted(QObject *object)
    329353{
    330     // Make sure that the fbo is destroyed before destroying its context.
    331     delete d_ptr->fbo;
    332     d_ptr->fbo = 0;
    333 
    334354    QWidget *widget = qobject_cast<QWidget *>(object);
    335355    if (widget) {
     356        if (widget == window()) {
     357            // Make sure that the fbo is destroyed before destroying its context.
     358            delete d_ptr->fbo;
     359            d_ptr->fbo = 0;
     360        }
     361
    336362        QWidgetPrivate *widgetPrivate = widget->d_func();
    337363        if (widgetPrivate->extraData()) {
     
    355381        return;
    356382
    357     QGLContext *ctx = new QGLContext(surfaceFormat, widget);
     383    QGLContext *ctx = NULL;
     384
     385    // For translucent top-level widgets we need alpha in the format.
     386    if (widget->testAttribute(Qt::WA_TranslucentBackground)) {
     387        QGLFormat modFormat(surfaceFormat);
     388        modFormat.setSampleBuffers(false);
     389        modFormat.setSamples(0);
     390        modFormat.setAlpha(true);
     391        ctx = new QGLContext(modFormat, widget);
     392    } else
     393        ctx = new QGLContext(surfaceFormat, widget);
     394
    358395    ctx->create(qt_gl_share_widget()->context());
    359396
    360 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
    361     // Create the EGL surface to draw into.  QGLContext::chooseContext()
    362     // does not do this for X11/EGL, but does do it for other platforms.
    363     // This probably belongs in qgl_x11egl.cpp.
    364     QGLContextPrivate *ctxpriv = ctx->d_func();
    365     ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(widget);
    366     if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
    367         qWarning() << "hijackWindow() could not create EGL surface";
    368     }
    369     qDebug("QGLWindowSurface - using EGLConfig %d", reinterpret_cast<int>(ctxpriv->eglContext->config()));
     397#ifndef QT_NO_EGL
     398    static bool checkedForNOKSwapRegion = false;
     399    static bool haveNOKSwapRegion = false;
     400
     401    if (!checkedForNOKSwapRegion) {
     402        haveNOKSwapRegion = QEgl::hasExtension("EGL_NOK_swap_region2");
     403        checkedForNOKSwapRegion = true;
     404
     405        if (haveNOKSwapRegion)
     406            qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates.";
     407    }
     408
     409    if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED &&
     410        ! haveNOKSwapRegion)
     411        setPartialUpdateSupport(false); // Force full-screen updates
     412    else
     413        setPartialUpdateSupport(true);
    370414#endif
    371415
     
    398442    QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
    399443    ctx->makeCurrent();
     444
     445    Q_ASSERT(d_ptr->fbo);
    400446    return d_ptr->fbo;
    401447}
     
    405451void QGLWindowSurface::beginPaint(const QRegion &)
    406452{
     453    if (!context())
     454        return;
     455
     456    int clearFlags = 0;
     457
     458    if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
     459        clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
     460    else if (context()->format().alpha())
     461        clearFlags = GL_COLOR_BUFFER_BIT;
     462
     463    if (clearFlags) {
     464        glClearColor(0.0, 0.0, 0.0, 0.0);
     465        glClear(clearFlags);
     466    }
     467
     468    d_ptr->did_paint = true;
    407469}
    408470
     
    415477}
    416478
     479static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect)
     480{
     481    glDisable(GL_DEPTH_TEST);
     482    glDisable(GL_SCISSOR_TEST);
     483    glDisable(GL_BLEND);
     484
     485    glViewport(0, 0, viewport.width(), viewport.height());
     486
     487    QGLShaderProgram *blitProgram =
     488        QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
     489    blitProgram->bind();
     490    blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
     491
     492    // The shader manager's blit program does not multiply the
     493    // vertices by the pmv matrix, so we need to do the effect
     494    // of the orthographic projection here ourselves.
     495    QRectF r;
     496    qreal w = viewport.width();
     497    qreal h = viewport.height();
     498    r.setLeft((targetRect.left() / w) * 2.0f - 1.0f);
     499    if (targetRect.right() == (viewport.width() - 1))
     500        r.setRight(1.0f);
     501    else
     502        r.setRight((targetRect.right() / w) * 2.0f - 1.0f);
     503    r.setBottom((targetRect.top() / h) * 2.0f - 1.0f);
     504    if (targetRect.bottom() == (viewport.height() - 1))
     505        r.setTop(1.0f);
     506    else
     507        r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f);
     508
     509    drawTexture(r, texture, texSize, sourceRect);
     510}
     511
     512
    417513void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
    418514{
    419     if (context() && widget != window()) {
    420         qWarning("No native child widget support in GL window surface without FBOs or pixel buffers");
    421         return;
    422     }
    423 
    424515    //### Find out why d_ptr->geometry_updated isn't always false.
    425516    // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either
     
    428519        return;
    429520
     521    // did_paint is set to true in ::beginPaint. ::beginPaint means that we
     522    // at least cleared the background (= painted something). In EGL API it's a
     523    // mistake to call swapBuffers if nothing was painted unless
     524    // EGL_BUFFER_PRESERVED is set. This check protects the flush func from
     525    // being executed if it's for nothing.
     526    if (!hasPartialUpdateSupport() && !d_ptr->did_paint)
     527        return;
     528
    430529    QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
    431530    Q_ASSERT(parent);
     
    444543    const GLenum target = GL_TEXTURE_2D;
    445544    Q_UNUSED(target);
     545
     546    if (QGLWindowSurface::swapBehavior == QGLWindowSurface::KillSwap)
     547        return;
    446548
    447549    if (context()) {
     
    492594            }
    493595#endif
     596            bool doingPartialUpdate = false;
     597            if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AutomaticSwap)
     598                doingPartialUpdate = hasPartialUpdateSupport() && br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2;
     599            else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysFullSwap)
     600                doingPartialUpdate = false;
     601            else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysPartialSwap)
     602                doingPartialUpdate = hasPartialUpdateSupport();
     603
     604            QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext);
     605            if (widget != window()) {
     606                if (initializeOffscreenTexture(window()->size()))
     607                    qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss";
     608                glBindTexture(target, d_ptr->tex_id);
     609
     610                const uint bottom = window()->height() - (br.y() + br.height());
     611                glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
     612
     613                glBindTexture(target, 0);
     614
     615                ctx->makeCurrent();
     616                if (doingPartialUpdate)
     617                    blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br);
     618                else
     619                    blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset));
     620            }
     621
     622            if (doingPartialUpdate)
     623                ctx->d_func()->swapRegion(br);
     624            else
     625                ctx->swapBuffers();
     626
    494627            d_ptr->paintedRegion = QRegion();
    495             context()->swapBuffers();
    496628        } else {
    497629            glFlush();
     
    534666
    535667        if (window() == parent || d_ptr->fbo->format().samples() <= 1) {
    536             // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     668            if (ctx->d_ptr->current_fbo != 0)
     669                glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     670
    537671            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle());
    538672
     
    567701            qgl_fbo_pool()->release(temp);
    568702        }
     703
     704        ctx->d_ptr->current_fbo = 0;
    569705    }
    570706#if !defined(QT_OPENGL_ES_2)
     
    613749        Q_UNUSED(target);
    614750
    615         GLuint texture = d_ptr->fbo->texture();
    616 
    617         glDisable(GL_DEPTH_TEST);
    618 
    619751        if (d_ptr->fbo->isBound())
    620752            d_ptr->fbo->release();
    621753
    622         glViewport(0, 0, size.width(), size.height());
    623 
    624         QGLShaderProgram *blitProgram =
    625             QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
    626         blitProgram->bind();
    627         blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
    628 
    629         // The shader manager's blit program does not multiply the
    630         // vertices by the pmv matrix, so we need to do the effect
    631         // of the orthographic projection here ourselves.
    632         QRectF r;
    633         qreal w = size.width() ? size.width() : 1.0f;
    634         qreal h = size.height() ? size.height() : 1.0f;
    635         r.setLeft((rect.left() / w) * 2.0f - 1.0f);
    636         if (rect.right() == (size.width() - 1))
    637             r.setRight(1.0f);
    638         else
    639             r.setRight((rect.right() / w) * 2.0f - 1.0f);
    640         r.setBottom((rect.top() / h) * 2.0f - 1.0f);
    641         if (rect.bottom() == (size.height() - 1))
    642             r.setTop(1.0f);
    643         else
    644             r.setTop((rect.bottom() / w) * 2.0f - 1.0f);
    645 
    646         drawTexture(r, texture, window()->size(), br);
     754        blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br);
    647755    }
    648756#endif
     
    652760    else
    653761        glFlush();
     762
     763    d_ptr->did_paint = false;
    654764}
    655765
     
    667777    d_ptr->geometry_updated = false;
    668778
    669 
    670779    QRect rect = geometry();
    671780    hijackWindow(window());
     
    688797    if (d_ptr->ctx) {
    689798#ifndef QT_OPENGL_ES_2
    690         if (d_ptr->destructive_swap_buffers) {
    691             glBindTexture(target, d_ptr->tex_id);
    692             glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    693             glBindTexture(target, 0);
    694         }
     799        if (d_ptr->destructive_swap_buffers)
     800            initializeOffscreenTexture(rect.size());
    695801#endif
    696802        return;
     
    772878
    773879#ifndef QT_OPENGL_ES_2
    774     if (d_ptr->destructive_swap_buffers) {
    775         glGenTextures(1, &d_ptr->tex_id);
    776         glBindTexture(target, d_ptr->tex_id);
    777         glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    778 
    779         glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    780         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    781         glBindTexture(target, 0);
    782     }
     880    if (d_ptr->destructive_swap_buffers)
     881        initializeOffscreenTexture(rect.size());
    783882#endif
    784883
     
    786885    d_ptr->ctx = ctx;
    787886    d_ptr->ctx->d_ptr->internal_context = true;
     887}
     888
     889bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size)
     890{
     891    if (size == d_ptr->textureSize)
     892        return false;
     893
     894    glGenTextures(1, &d_ptr->tex_id);
     895    glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id);
     896    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
     897
     898    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     899    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     900    glBindTexture(GL_TEXTURE_2D, 0);
     901
     902    d_ptr->textureSize = size;
     903    return true;
    788904}
    789905
     
    839955    }
    840956
    841     const q_vertexType tx1 = f2vt(src.left());
    842     const q_vertexType tx2 = f2vt(src.right());
    843     const q_vertexType ty1 = f2vt(src.top());
    844     const q_vertexType ty2 = f2vt(src.bottom());
    845 
    846     q_vertexType texCoordArray[4*2] = {
     957    const GLfloat tx1 = src.left();
     958    const GLfloat tx2 = src.right();
     959    const GLfloat ty1 = src.top();
     960    const GLfloat ty2 = src.bottom();
     961
     962    GLfloat texCoordArray[4*2] = {
    847963        tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1
    848964    };
    849965
    850     q_vertexType vertexArray[4*2];
    851     extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array); // qpaintengine_opengl.cpp
     966    GLfloat vertexArray[4*2];
     967    extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); // qpaintengine_opengl.cpp
    852968    qt_add_rect_to_array(rect, vertexArray);
    853969
    854970#if !defined(QT_OPENGL_ES_2)
    855     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    856     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     971    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     972    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
    857973
    858974    glBindTexture(target, tex_id);
Note: See TracChangeset for help on using the changeset viewer.