Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/opengl/qgl_x11egl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242#include "qgl.h"
    4343#include <private/qt_x11_p.h>
     44#include <private/qpixmap_x11_p.h>
     45#include <private/qimagepixmapcleanuphooks_p.h>
    4446#include <private/qgl_p.h>
    4547#include <private/qpaintengine_opengl_p.h>
    4648#include "qgl_egl_p.h"
    4749#include "qcolormap.h"
     50#include <QDebug>
    4851
    4952
    5053QT_BEGIN_NAMESPACE
    51 
    52 
    53 bool QGLFormat::hasOpenGL()
    54 {
    55     return true;
    56 }
    5754
    5855bool QGLFormat::hasOpenGLOverlays()
     
    6764}
    6865
     66// Chooses the EGL config and creates the EGL context
    6967bool QGLContext::chooseContext(const QGLContext* shareContext)
    7068{
     
    7775
    7876    // Get the display and initialize it.
    79     d->eglContext = new QEglContext();
    80     d->eglContext->setApi(QEglContext::OpenGL);
    81     if (!d->eglContext->openDisplay(device())) {
    82         delete d->eglContext;
    83         d->eglContext = 0;
    84         return false;
    85     }
    86 
    87     // Construct the configuration we need for this surface.
    88     QEglProperties configProps;
    89     qt_egl_set_format(configProps, devType, d->glFormat);
    90     qt_egl_add_platform_config(configProps, device());
    91     configProps.setRenderableType(QEglContext::OpenGL);
    92 
    93     // Search for a matching configuration, reducing the complexity
    94     // each time until we get something that matches.
    95     if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
    96         delete d->eglContext;
    97         d->eglContext = 0;
    98         return false;
     77    if (d->eglContext == 0) {
     78        d->eglContext = new QEglContext();
     79        d->eglContext->setApi(QEgl::OpenGL);
     80        if (!d->eglContext->openDisplay(device())) {
     81            delete d->eglContext;
     82            d->eglContext = 0;
     83            return false;
     84        }
     85
     86        // Construct the configuration we need for this surface.
     87        QEglProperties configProps;
     88        qt_egl_set_format(configProps, devType, d->glFormat);
     89        qt_egl_add_platform_config(configProps, device());
     90        configProps.setRenderableType(QEgl::OpenGL);
     91
     92#if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
     93        if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
     94            qDebug("Setting EGL_BUFFER_SIZE to 16");
     95            configProps.setValue(EGL_BUFFER_SIZE, 16);
     96            configProps.setValue(EGL_ALPHA_SIZE, 0);
     97        }
     98
     99        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
     100            delete d->eglContext;
     101            d->eglContext = 0;
     102            return false;
     103        }
     104#else
     105        QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
     106        if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
     107            configProps.setValue(EGL_RED_SIZE, 5);
     108            configProps.setValue(EGL_GREEN_SIZE, 6);
     109            configProps.setValue(EGL_BLUE_SIZE, 5);
     110            configProps.setValue(EGL_ALPHA_SIZE, 0);
     111            matchType = QEgl::ExactPixelFormat;
     112        }
     113
     114        // Search for a matching configuration, reducing the complexity
     115        // each time until we get something that matches.
     116        if (!d->eglContext->chooseConfig(configProps, matchType)) {
     117            delete d->eglContext;
     118            d->eglContext = 0;
     119            return false;
     120        }
     121#endif
     122
     123//        qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
     124//        qDebug() << QEglProperties(d->eglContext->config()).toString();
     125
     126        // Create a new context for the configuration.
     127        if (!d->eglContext->createContext
     128                (shareContext ? shareContext->d_func()->eglContext : 0)) {
     129            delete d->eglContext;
     130            d->eglContext = 0;
     131            return false;
     132        }
     133        d->sharing = d->eglContext->isSharing();
     134        if (d->sharing && shareContext)
     135            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
     136
     137#if defined(EGL_VERSION_1_1)
     138        if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
     139            eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
     140#endif
    99141    }
    100142
     
    102144    qt_egl_update_format(*(d->eglContext), d->glFormat);
    103145
    104     // Create a new context for the configuration.
    105     if (!d->eglContext->createContext
    106             (shareContext ? shareContext->d_func()->eglContext : 0)) {
    107         delete d->eglContext;
    108         d->eglContext = 0;
    109         return false;
    110     }
    111 
    112 #if defined(EGL_VERSION_1_1)
    113     if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
    114         eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
    115 #endif
    116 
    117     // Create the EGL surface to draw into.
    118     if (!d->eglContext->createSurface(device())) {
    119         delete d->eglContext;
    120         d->eglContext = 0;
    121         return false;
    122     }
    123 
    124146    return true;
    125147}
    126 
    127 
    128 void QGLContext::reset()
    129 {
    130     Q_D(QGLContext);
    131     if (!d->valid)
    132         return;
    133     d->cleanup();
    134     doneCurrent();
    135     if (d->eglContext) {
    136         delete d->eglContext;
    137         d->eglContext = 0;
    138     }
    139     d->crWin = false;
    140     d->sharing = false;
    141     d->valid = false;
    142     d->transpColor = QColor();
    143     d->initDone = false;
    144     qgl_share_reg()->removeShare(this);
    145 }
    146 
    147 void QGLContext::makeCurrent()
    148 {
    149     Q_D(QGLContext);
    150     if(!d->valid || !d->eglContext) {
    151         qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
    152         return;
    153     }
    154 
    155     if (d->eglContext->makeCurrent()) {
    156         if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
    157             qgl_context_storage.setLocalData(new QGLThreadContext);
    158         if (qgl_context_storage.hasLocalData())
    159             qgl_context_storage.localData()->context = this;
    160         currentCtx = this;
    161     }
    162 }
    163 
    164 void QGLContext::doneCurrent()
    165 {
    166     Q_D(QGLContext);
    167     if (d->eglContext)
    168         d->eglContext->doneCurrent();
    169 
    170     if (qgl_context_storage.hasLocalData())
    171         qgl_context_storage.localData()->context = 0;
    172     currentCtx = 0;
    173 }
    174 
    175 
    176 void QGLContext::swapBuffers() const
    177 {
    178     Q_D(const QGLContext);
    179     if(!d->valid || !d->eglContext)
    180         return;
    181 
    182     d->eglContext->swapBuffers();
    183 }
    184 
    185 QColor QGLContext::overlayTransparentColor() const
    186 {
    187     return QColor(0, 0, 0);                // Invalid color
    188 }
    189 
    190 uint QGLContext::colorIndex(const QColor &c) const
    191 {
    192     //### color index doesn't work on egl
    193     Q_UNUSED(c);
    194     return 0;
    195 }
    196 
    197 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
    198 {
    199     Q_UNUSED(fnt);
    200     Q_UNUSED(listBase);
    201 }
    202 
    203 void *QGLContext::getProcAddress(const QString &proc) const
    204 {
    205     return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));
    206 }
    207 
    208 void QGLWidget::setMouseTracking(bool enable)
    209 {
    210     QWidget::setMouseTracking(enable);
    211 }
    212 
    213148
    214149void QGLWidget::resizeEvent(QResizeEvent *)
     
    239174}
    240175
     176//#define QT_DEBUG_X11_VISUAL_SELECTION 1
     177
     178bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
     179{
     180    bool foundVisualIsArgb = useArgbVisual;
     181
     182#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     183    qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
     184#endif
     185
     186    memset(&vi, 0, sizeof(XVisualInfo));
     187
     188    EGLint eglConfigColorSize;
     189    eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
     190
     191    // Check to see if EGL is suggesting an appropriate visual id:
     192    EGLint nativeVisualId;
     193    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
     194    vi.visualid = nativeVisualId;
     195
     196    if (vi.visualid) {
     197        // EGL has suggested a visual id, so get the rest of the visual info for that id:
     198        XVisualInfo *chosenVisualInfo;
     199        int matchingCount = 0;
     200        chosenVisualInfo = XGetVisualInfo(x11Info.display(), VisualIDMask, &vi, &matchingCount);
     201        if (chosenVisualInfo) {
     202#if !defined(QT_NO_XRENDER)
     203            if (useArgbVisual) {
     204                // Check to make sure the visual provided by EGL is ARGB
     205                XRenderPictFormat *format;
     206                format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
     207                if (format->type == PictTypeDirect && format->direct.alphaMask) {
     208#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     209                    qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
     210#endif
     211                    foundVisualIsArgb = true;
     212                    vi = *chosenVisualInfo;
     213                }
     214                else {
     215                    qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
     216                             nativeVisualId, (int)config);
     217                    vi.visualid = 0;
     218                }
     219            } else
     220#endif
     221            {
     222                if (eglConfigColorSize == chosenVisualInfo->depth) {
     223#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     224                    qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
     225#endif
     226                    vi = *chosenVisualInfo;
     227                } else
     228                    qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
     229                             nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
     230            }
     231            XFree(chosenVisualInfo);
     232        }
     233        else {
     234            qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
     235                     nativeVisualId, (int)config);
     236            vi.visualid = 0;
     237        }
     238    }
     239
     240    // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
     241    // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
     242         
     243#if !defined(QT_NO_XRENDER)
     244    if (vi.visualid == 0 && useArgbVisual) {
     245        // Try to use XRender to find an ARGB visual we can use
     246        vi.screen  = x11Info.screen();
     247        vi.depth   = 32; //### We might at some point (soon) get ARGB4444
     248        vi.c_class = TrueColor;
     249        XVisualInfo *matchingVisuals;
     250        int matchingCount = 0;
     251        matchingVisuals = XGetVisualInfo(x11Info.display(),
     252                                         VisualScreenMask|VisualDepthMask|VisualClassMask,
     253                                         &vi, &matchingCount);
     254
     255        for (int i = 0; i < matchingCount; ++i) {
     256            XRenderPictFormat *format;
     257            format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
     258            if (format->type == PictTypeDirect && format->direct.alphaMask) {
     259                vi = matchingVisuals[i];
     260                foundVisualIsArgb = true;
     261#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     262                qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
     263#endif
     264                break;
     265            }
     266        }
     267        XFree(matchingVisuals);
     268    }
     269#endif
     270
     271    if (vi.visualid == 0) {
     272        EGLint depth;
     273        eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &depth);
     274        int err;
     275        err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
     276        if (err == 0) {
     277            qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!",
     278                     (int)config, depth);
     279            depth = x11Info.depth();
     280            err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
     281            if (err == 0) {
     282                qWarning("Error: Couldn't get any matching X visual!");
     283                return false;
     284            } else
     285                qWarning("         - Falling back to X11 suggested depth (%d)", depth);
     286        }
     287#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     288        else
     289            qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
     290#endif
     291
     292        // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
     293        if (useArgbVisual)
     294            foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
     295    }
     296
     297#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     298    qDebug("Visual Info:");
     299    qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
     300    qDebug("   red_mask=0x%x", vi.red_mask);
     301    qDebug("   green_mask=0x%x", vi.green_mask);
     302    qDebug("   blue_mask=0x%x", vi.blue_mask);
     303    qDebug("   colormap_size=%d", vi.colormap_size);
     304    qDebug("   c_class=%d", vi.c_class);
     305    qDebug("   depth=%d", vi.depth);
     306    qDebug("   screen=%d", vi.screen);
     307    qDebug("   visualid=%d", vi.visualid);
     308#endif
     309    return foundVisualIsArgb;
     310}
     311
    241312void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
    242313{
     
    263334    }
    264335
    265     bool visible = isVisible();
    266     if (visible)
    267         hide();
    268 
    269     XVisualInfo vi;
    270 
    271     int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi);
    272     if (err == 0) {
    273         qWarning("Error: Couldn't get a matching X visual for format");
    274         return;
    275     }
    276 
    277     XSetWindowAttributes a;
    278 
    279     Window p = RootWindow(X11->display, vi.screen);
    280     if (parentWidget())
    281         p = parentWidget()->winId();
    282 
    283     QColormap colmap = QColormap::instance(vi.screen);
    284     a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
    285     a.border_pixel = colmap.pixel(Qt::black);
    286 
    287     Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
    288                               0, vi.depth, InputOutput, vi.visual,
    289                               CWBackPixel|CWBorderPixel, &a);
    290 
    291     if (deleteOldContext)
    292         delete oldcx;
    293     oldcx = 0;
    294 
    295     create(w); // Create with the ID of the window we've just created
    296 
    297     d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
    298 
    299     if (visible)
    300         show();
     336    // If the application has set WA_TranslucentBackground and not explicitly set
     337    // the alpha buffer size to zero, modify the format so it have an alpha channel
     338    QGLFormat& fmt = d->glcx->d_func()->glFormat;
     339    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
     340    if (tryArgbVisual && fmt.alphaBufferSize() == -1)
     341        fmt.setAlphaBufferSize(1);
    301342
    302343    bool createFailed = false;
    303344    if (!d->glcx->isValid()) {
     345        // Create the QGLContext here, which in turn chooses the EGL config
     346        // and creates the EGL context:
    304347        if (!d->glcx->create(shareContext ? shareContext : oldcx))
    305348            createFailed = true;
     
    317360    }
    318361
     362    bool visible = isVisible();
     363    if (visible)
     364        hide();
     365
     366    XVisualInfo vi;
     367    QEglContext *eglContext = d->glcx->d_func()->eglContext;
     368    bool usingArgbVisual = qt_egl_setup_x11_visual(vi, eglContext->display(), eglContext->config(),
     369                                                   x11Info(), tryArgbVisual);
     370
     371    XSetWindowAttributes a;
     372
     373    Window p = RootWindow(x11Info().display(), x11Info().screen());
     374    if (parentWidget())
     375        p = parentWidget()->winId();
     376
     377    QColormap colmap = QColormap::instance(vi.screen);
     378    a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
     379    a.border_pixel = colmap.pixel(Qt::black);
     380
     381    unsigned int valueMask = CWBackPixel|CWBorderPixel;
     382    if (usingArgbVisual) {
     383        a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone);
     384        valueMask |= CWColormap;
     385    }
     386
     387    Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(),
     388                             0, vi.depth, InputOutput, vi.visual, valueMask, &a);
     389
     390    if (deleteOldContext)
     391        delete oldcx;
     392    oldcx = 0;
     393
     394    create(w); // Create with the ID of the window we've just created
     395
     396
     397    // Create the EGL surface to draw into.
     398    QGLContextPrivate *ctxpriv = d->glcx->d_func();
     399    ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(this);
     400    if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
     401        delete ctxpriv->eglContext;
     402        ctxpriv->eglContext = 0;
     403        return;
     404    }
     405
     406    d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
     407
     408    if (visible)
     409        show();
     410
     411    XFlush(X11->display);
    319412    d->glcx->setWindowCreated(true);
    320413}
     
    332425}
    333426
    334 bool QGLWidgetPrivate::renderCxPm(QPixmap*)
    335 {
    336     return false;
    337 }
    338 
    339427void QGLWidgetPrivate::cleanupColormaps()
    340428{
     
    357445        return;
    358446    init_done = true;
     447
     448    // We need a context current to initialize the extensions.
     449    QGLWidget tmpWidget;
     450    tmpWidget.makeCurrent();
     451
    359452    init_extensions();
     453
     454    tmpWidget.doneCurrent();
    360455}
    361456
     
    369464    if ( force || (currentId != eglSurfaceWindowId) ) {
    370465        // The window id has changed so we need to re-create the EGL surface
    371         if (!glcx->d_func()->eglContext->recreateSurface(q))
     466        QEglContext *ctx = glcx->d_func()->eglContext;
     467        EGLSurface surface = glcx->d_func()->eglSurface;
     468        if (surface != EGL_NO_SURFACE)
     469            ctx->destroySurface(surface); // Will force doneCurrent() if nec.
     470        surface = ctx->createSurface(q);
     471        if (surface == EGL_NO_SURFACE)
    372472            qWarning("Error creating EGL window surface: 0x%x", eglGetError());
     473        glcx->d_func()->eglSurface = surface;
    373474
    374475        eglSurfaceWindowId = currentId;
     
    376477}
    377478
     479// Selects which configs should be used
     480EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly)
     481{
     482    // Cache the configs we select as they wont change:
     483    static EGLConfig roPixmapRGBConfig = 0;
     484    static EGLConfig roPixmapRGBAConfig = 0;
     485    static EGLConfig rwPixmapRGBConfig = 0;
     486    static EGLConfig rwPixmapRGBAConfig = 0;
     487
     488    EGLConfig* targetConfig;
     489
     490    if (hasAlpha) {
     491        if (readOnly)
     492            targetConfig = &roPixmapRGBAConfig;
     493        else
     494            targetConfig = &rwPixmapRGBAConfig;
     495    }
     496    else {
     497        if (readOnly)
     498            targetConfig = &roPixmapRGBConfig;
     499        else
     500            targetConfig = &rwPixmapRGBConfig;
     501    }
     502
     503    if (*targetConfig == 0) {
     504        QEglProperties configAttribs;
     505        configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
     506        configAttribs.setRenderableType(QEgl::OpenGL);
     507        if (hasAlpha)
     508            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
     509        else
     510            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
     511
     512        // If this is going to be a render target, it needs to have a depth, stencil & sample buffer
     513        if (!readOnly) {
     514            configAttribs.setValue(EGL_DEPTH_SIZE, 1);
     515            configAttribs.setValue(EGL_STENCIL_SIZE, 1);
     516            configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
     517        }
     518
     519        EGLint configCount = 0;
     520        do {
     521            eglChooseConfig(QEglContext::defaultDisplay(0), configAttribs.properties(), targetConfig, 1, &configCount);
     522            if (configCount > 0) {
     523                // Got one
     524                qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
     525                         << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
     526
     527//                QEglProperties configProps(*targetConfig);
     528//                qDebug() << configProps.toString();
     529                break;
     530            }
     531            qWarning("choosePixmapConfig() - No suitible config found, reducing requirements");
     532        } while (configAttribs.reduceConfiguration());
     533    }
     534
     535    if (*targetConfig == 0)
     536        qWarning("choosePixmapConfig() - Couldn't find a suitable config");
     537
     538    return *targetConfig;
     539}
     540
     541bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly)
     542{
     543    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     544    QX11PixmapData* pixmapData = static_cast<QX11PixmapData*>(pmd);
     545
     546    bool hasAlpha = pixmapData->hasAlphaChannel();
     547
     548    EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly);
     549
     550    QEglProperties pixmapAttribs;
     551
     552    // If the pixmap can't be bound to a texture, it's pretty useless
     553    pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
     554    if (hasAlpha)
     555        pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
     556    else
     557        pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
     558
     559    EGLSurface pixmapSurface;
     560    pixmapSurface = eglCreatePixmapSurface(QEglContext::defaultDisplay(0),
     561                                           pixmapConfig,
     562                                           (EGLNativePixmapType) pixmapData->handle(),
     563                                           pixmapAttribs.properties());
     564//    qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
     565//           pixmapSurface, pixmapData->handle());
     566    if (pixmapSurface == EGL_NO_SURFACE) {
     567        qWarning() << "Failed to create a pixmap surface using config" << (int)pixmapConfig
     568                   << ":" << QEglContext::errorString(eglGetError());
     569        return false;
     570    }
     571
     572    static bool doneOnce = false;
     573    if (!doneOnce) {
     574        // Make sure QGLTextureCache is instanciated so it can install cleanup hooks
     575        // which cleanup the EGL surface.
     576        QGLTextureCache::instance();
     577        doneOnce = true;
     578    }
     579
     580    Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
     581    pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
     582    QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
     583
     584    return true;
     585}
     586
     587
     588QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key,
     589                                                           QGLContext::BindOptions options)
     590{
     591    Q_Q(QGLContext);
     592
     593    // The EGL texture_from_pixmap has no facility to invert the y coordinate
     594    if (!(options & QGLContext::CanFlipNativePixmapBindOption))
     595        return 0;
     596
     597    Q_ASSERT(pd->classId() == QPixmapData::X11Class);
     598
     599    static bool checkedForTFP = false;
     600    static bool haveTFP = false;
     601
     602    if (!checkedForTFP) {
     603        // Check for texture_from_pixmap egl extension
     604        checkedForTFP = true;
     605        if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
     606            eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
     607        {
     608            qDebug("Found texture_from_pixmap EGL extension!");
     609            haveTFP = true;
     610        }
     611    }
     612
     613    if (!haveTFP)
     614        return 0;
     615
     616    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
     617
     618    bool hasAlpha = pixmapData->hasAlphaChannel();
     619
     620    // Check to see if the surface is still valid
     621    if (pixmapData->gl_surface &&
     622        hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
     623    {
     624        // Surface is invalid!
     625        destroyGlSurfaceForPixmap(pixmapData);
     626    }
     627
     628    if (pixmapData->gl_surface == 0) {
     629        bool success = qt_createEGLSurfaceForPixmap(pixmapData, true);
     630        if (!success) {
     631            haveTFP = false;
     632            return 0;
     633        }
     634    }
     635
     636    Q_ASSERT(pixmapData->gl_surface);
     637
     638    GLuint textureId;
     639    glGenTextures(1, &textureId);
     640    glBindTexture(GL_TEXTURE_2D, textureId);
     641
     642    // bind the egl pixmap surface to a texture
     643    EGLBoolean success;
     644    success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
     645    if (success == EGL_FALSE) {
     646        qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
     647        eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface);
     648        pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
     649        haveTFP = false;
     650        return 0;
     651    }
     652
     653    QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
     654    pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
     655
     656    // We assume the cost of bound pixmaps is zero
     657    QGLTextureCache::instance()->insert(q, key, texture, 0);
     658
     659    glBindTexture(GL_TEXTURE_2D, textureId);
     660    return texture;
     661}
     662
     663void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
     664{
     665    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     666    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     667    if (pixmapData->gl_surface) {
     668        EGLBoolean success;
     669        success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
     670        if (success == EGL_FALSE) {
     671            qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
     672                       << QEglContext::errorString(eglGetError());
     673        }
     674        pixmapData->gl_surface = 0;
     675    }
     676}
     677
     678void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
     679{
     680    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     681    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     682    if (pixmapData->gl_surface) {
     683        EGLBoolean success;
     684        success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
     685                                     (EGLSurface)pixmapData->gl_surface,
     686                                     EGL_BACK_BUFFER);
     687        if (success == EGL_FALSE) {
     688            qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
     689                       << QEglContext::errorString(eglGetError());
     690        }
     691    }
     692}
     693
    378694QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.