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/qgl_egl.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)
     
    4141
    4242#include <QtOpenGL/qgl.h>
     43#include <QtOpenGL/qglpixelbuffer.h>
    4344#include "qgl_p.h"
    4445#include "qgl_egl_p.h"
     46#include "qglpixelbuffer_p.h"
     47
     48#ifdef Q_WS_X11
     49#include <QtGui/private/qpixmap_x11_p.h>
     50#endif
    4551
    4652QT_BEGIN_NAMESPACE
    4753
    48 // Set device configuration attributes from a QGLFormat instance.
    49 void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f)
    50 {
    51     if (deviceType == QInternal::Pixmap || deviceType == QInternal::Image)
    52         props.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
    53     else if (deviceType == QInternal::Pbuffer)
    54         props.setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
    55     else
    56         props.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
    57 
    58     // Set the pixel format to that contained in the QGLFormat
    59     // if the system hasn't already chosen a fixed format to
    60     // match the pixmap, widget, etc.
    61     if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1)
    62         props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize());
    63     if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1)
    64         props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize());
    65     if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1)
    66         props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize());
    67     if (f.alpha()) {
    68         if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1)
    69             props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize());
    70     }
    71 
    72     if (f.depth())
    73         props.setValue(EGL_DEPTH_SIZE, f.depthBufferSize() == -1 ? 1 : f.depthBufferSize());
    74     if (f.stencil())
    75         props.setValue(EGL_STENCIL_SIZE, f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize());
    76     if (f.sampleBuffers()) {
    77         props.setValue(EGL_SAMPLE_BUFFERS, 1);
    78         props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples());
    79     } else {
    80         props.setValue(EGL_SAMPLE_BUFFERS, 0);
    81     }
    82     if (deviceType == QInternal::Widget)
    83         props.setValue(EGL_LEVEL, f.plane());
     54void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat)
     55{
     56    int redSize     = glFormat.redBufferSize();
     57    int greenSize   = glFormat.greenBufferSize();
     58    int blueSize    = glFormat.blueBufferSize();
     59    int alphaSize   = glFormat.alphaBufferSize();
     60    int depthSize   = glFormat.depthBufferSize();
     61    int stencilSize = glFormat.stencilBufferSize();
     62    int sampleCount = glFormat.samples();
     63
     64    // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
     65    // type has been requested. So we must check QGLFormat's booleans too if size is -1:
     66    if (glFormat.alpha() && alphaSize <= 0)
     67        alphaSize = 1;
     68    if (glFormat.depth() && depthSize <= 0)
     69        depthSize = 1;
     70    if (glFormat.stencil() && stencilSize <= 0)
     71        stencilSize = 1;
     72    if (glFormat.sampleBuffers() && sampleCount <= 0)
     73        sampleCount = 1;
     74
     75    // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
     76    // the best performance. The EGL config selection algorithm is a bit stange in this regard:
     77    // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
     78    // 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
     79    // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
     80    // order is special and described as "by larger _total_ number of color bits.". So EGL will
     81    // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
     82    // to say "If the requested number of bits in attrib_list for a particular component is 0,
     83    // then the number of bits for that component is not considered". This part of the spec also
     84    // seems to imply that setting the red/green/blue bits to zero means none of the components
     85    // are considered and EGL disregards the entire sorting rule. It then looks to the next
     86    // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
     87    // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
     88    // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
     89    // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
     90    // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will
     91    // probably get a 32-bit config, even when there's an RGB565 config available. Oh well.
     92
     93    // Now normalize the values so -1 becomes 0
     94    redSize   = redSize   > 0 ? redSize   : 0;
     95    greenSize = greenSize > 0 ? greenSize : 0;
     96    blueSize  = blueSize  > 0 ? blueSize  : 0;
     97    alphaSize = alphaSize > 0 ? alphaSize : 0;
     98    depthSize = depthSize > 0 ? depthSize : 0;
     99    stencilSize = stencilSize > 0 ? stencilSize : 0;
     100    sampleCount = sampleCount > 0 ? sampleCount : 0;
     101
     102    eglProperties.setValue(EGL_RED_SIZE,   redSize);
     103    eglProperties.setValue(EGL_GREEN_SIZE, greenSize);
     104    eglProperties.setValue(EGL_BLUE_SIZE,  blueSize);
     105    eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize);
     106    eglProperties.setValue(EGL_DEPTH_SIZE, depthSize);
     107    eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize);
     108    eglProperties.setValue(EGL_SAMPLES, sampleCount);
     109    eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0);
    84110}
    85111
    86112// Updates "format" with the parameters of the selected configuration.
    87 void qt_egl_update_format(const QEglContext& context, QGLFormat& format)
    88 {
    89     EGLint value = 0;
    90 
    91     if (context.configAttrib(EGL_RED_SIZE, &value))
    92         format.setRedBufferSize(value);
    93     if (context.configAttrib(EGL_GREEN_SIZE, &value))
    94         format.setGreenBufferSize(value);
    95     if (context.configAttrib(EGL_BLUE_SIZE, &value))
    96         format.setBlueBufferSize(value);
    97     if (context.configAttrib(EGL_ALPHA_SIZE, &value)) {
    98         format.setAlpha(value != 0);
    99         if (format.alpha())
    100             format.setAlphaBufferSize(value);
    101     }
    102 
    103     if (context.configAttrib(EGL_DEPTH_SIZE, &value)) {
    104         format.setDepth(value != 0);
    105         if (format.depth())
    106             format.setDepthBufferSize(value);
    107     }
    108 
    109     if (context.configAttrib(EGL_LEVEL, &value))
    110         format.setPlane(value);
    111 
    112     if (context.configAttrib(EGL_SAMPLE_BUFFERS, &value)) {
    113         format.setSampleBuffers(value != 0);
    114         if (format.sampleBuffers()) {
    115             context.configAttrib(EGL_SAMPLES, &value);
    116             format.setSamples(value);
    117         }
    118     }
    119 
    120     if (context.configAttrib(EGL_STENCIL_SIZE, &value)) {
    121         format.setStencil(value != 0);
    122         if (format.stencil())
    123             format.setStencilBufferSize(value);
    124     }
     113void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config)
     114{
     115    EGLint redSize     = 0;
     116    EGLint greenSize   = 0;
     117    EGLint blueSize    = 0;
     118    EGLint alphaSize   = 0;
     119    EGLint depthSize   = 0;
     120    EGLint stencilSize = 0;
     121    EGLint sampleCount = 0;
     122    EGLint level       = 0;
     123
     124    EGLDisplay display = QEgl::display();
     125    eglGetConfigAttrib(display, config, EGL_RED_SIZE,     &redSize);
     126    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE,   &greenSize);
     127    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,    &blueSize);
     128    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE,   &alphaSize);
     129    eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE,   &depthSize);
     130    eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
     131    eglGetConfigAttrib(display, config, EGL_SAMPLES,      &sampleCount);
     132    eglGetConfigAttrib(display, config, EGL_LEVEL,        &level);
     133
     134    format.setRedBufferSize(redSize);
     135    format.setGreenBufferSize(greenSize);
     136    format.setBlueBufferSize(blueSize);
     137    format.setAlphaBufferSize(alphaSize);
     138    format.setDepthBufferSize(depthSize);
     139    format.setStencilBufferSize(stencilSize);
     140    format.setSamples(sampleCount);
     141    format.setPlane(level);
     142    format.setDirectRendering(true); // All EGL contexts are direct-rendered
     143    format.setRgba(true);            // EGL doesn't support colour index rendering
     144    format.setStereo(false);         // EGL doesn't support stereo buffers
     145    format.setAccumBufferSize(0);    // EGL doesn't support accululation buffers
     146    format.setDoubleBuffer(true);    // We don't support single buffered EGL contexts
    125147
    126148    // Clear the EGL error state because some of the above may
    127149    // have errored out because the attribute is not applicable
    128150    // to the surface type.  Such errors don't matter.
    129     context.clearError();
     151    eglGetError();
    130152}
    131153
     
    142164    d->cleanup();
    143165    doneCurrent();
    144     if (d->eglContext) {
     166    if (d->eglContext && d->ownsEglContext) {
    145167        d->destroyEglSurfaceForDevice();
    146168        delete d->eglContext;
    147169    }
     170    d->ownsEglContext = false;
    148171    d->eglContext = 0;
    149172    d->eglSurface = EGL_NO_SURFACE;
     
    159182{
    160183    Q_D(QGLContext);
    161     if (!d->valid || !d->eglContext || d->eglSurface == EGL_NO_SURFACE) {
     184    if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) {
    162185        qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
    163186        return;
    164187    }
    165188
    166     if (d->eglContext->makeCurrent(d->eglSurface))
     189    if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) {
    167190        QGLContextPrivate::setCurrentContext(this);
     191        if (!d->workaroundsCached) {
     192            d->workaroundsCached = true;
     193            const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
     194            if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) {
     195                // PowerVR MBX/SGX chips needs to clear all buffers when starting to render
     196                // a new frame, otherwise there will be a performance penalty to pay for
     197                // each frame.
     198                d->workaround_needsFullClearOnEveryFrame = true;
     199
     200                // Older PowerVR SGX drivers (like the one in the N900) have a
     201                // bug which prevents glCopyTexSubImage2D() to work with a POT
     202                // or GL_ALPHA texture bound to an FBO. The only way to
     203                // identify that driver is to check the EGL version number for it.
     204                const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION);
     205                if (egl_version && strstr(egl_version, "1.3"))
     206                    d->workaround_brokenFBOReadBack = true;
     207                else if (egl_version && strstr(egl_version, "1.4"))
     208                    d->workaround_brokenTexSubImage = true;
     209            }
     210        }
     211    }
    168212}
    169213
     
    184228        return;
    185229
    186     d->eglContext->swapBuffers(d->eglSurface);
     230    d->eglContext->swapBuffers(d->eglSurfaceForDevice());
    187231}
    188232
     
    190234{
    191235    if (eglSurface != EGL_NO_SURFACE) {
     236#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN)
     237        // Make sure we don't call eglDestroySurface on a surface which
     238        // was created for a different winId. This applies only to QGLWidget
     239        // paint device, so make sure this is the one we're operating on
     240        // (as opposed to a QGLWindowSurface use case).
     241        if (paintDevice && paintDevice->devType() == QInternal::Widget) {
     242            QWidget *w = static_cast<QWidget *>(paintDevice);
     243            if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) {
     244                if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) {
     245                    qWarning("WARNING: Potential EGL surface leak! Not destroying surface.");
     246                    eglSurface = EGL_NO_SURFACE;
     247                    return;
     248                }
     249            }
     250        }
     251#endif
     252        eglDestroySurface(eglContext->display(), eglSurface);
     253        eglSurface = EGL_NO_SURFACE;
     254    }
     255}
     256
     257EGLSurface QGLContextPrivate::eglSurfaceForDevice() const
     258{
     259    // If a QPixmapData had to create the QGLContext, we don't have a paintDevice
     260    if (!paintDevice)
     261        return eglSurface;
     262
    192263#ifdef Q_WS_X11
    193         // Make sure we don't call eglDestroySurface on a surface which
    194         // was created for a different winId:
    195         if (paintDevice->devType() == QInternal::Widget) {
    196             QGLWidget* w = static_cast<QGLWidget*>(paintDevice);
    197 
    198             if (w->d_func()->eglSurfaceWindowId == w->winId())
    199                 eglDestroySurface(eglContext->display(), eglSurface);
    200             else
    201                 qWarning("WARNING: Potential EGL surface leak!");
    202         } else
     264    if (paintDevice->devType() == QInternal::Pixmap) {
     265        QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data();
     266        if (pmd->classId() == QPixmapData::X11Class) {
     267            QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd);
     268            return (EGLSurface)x11PixmapData->gl_surface;
     269        }
     270    }
    203271#endif
    204             eglDestroySurface(eglContext->display(), eglSurface);
    205         eglSurface = EGL_NO_SURFACE;
    206     }
     272
     273    if (paintDevice->devType() == QInternal::Pbuffer) {
     274        QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice);
     275        return pbuf->d_func()->pbuf;
     276    }
     277
     278    return eglSurface;
     279}
     280
     281void QGLContextPrivate::swapRegion(const QRegion &region)
     282{
     283    if (!valid || !eglContext)
     284        return;
     285
     286    eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), &region);
    207287}
    208288
Note: See TracChangeset for help on using the changeset viewer.