src/opengl/qgl_x11egl.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include "qgl.h"
    42 #include "qgl.h"
    43 #include <private/qt_x11_p.h>
    43 #include <private/qt_x11_p.h>
    44 #include <private/qpixmap_x11_p.h>
    44 #include <private/qpixmap_x11_p.h>
       
    45 #include <private/qimagepixmapcleanuphooks_p.h>
    45 #include <private/qgl_p.h>
    46 #include <private/qgl_p.h>
    46 #include <private/qpaintengine_opengl_p.h>
    47 #include <private/qpaintengine_opengl_p.h>
    47 #include "qgl_egl_p.h"
    48 #include "qgl_egl_p.h"
    48 #include "qcolormap.h"
    49 #include "qcolormap.h"
    49 #include <QDebug>
    50 #include <QDebug>
    60 {
    61 {
    61     if (device->devType() == QInternal::Image)
    62     if (device->devType() == QInternal::Image)
    62         props.setPixelFormat(static_cast<QImage *>(device)->format());
    63         props.setPixelFormat(static_cast<QImage *>(device)->format());
    63 }
    64 }
    64 
    65 
       
    66 // Chooses the EGL config and creates the EGL context
    65 bool QGLContext::chooseContext(const QGLContext* shareContext)
    67 bool QGLContext::chooseContext(const QGLContext* shareContext)
    66 {
    68 {
    67     Q_D(QGLContext);
    69     Q_D(QGLContext);
    68 
    70 
    69     if (!device())
    71     if (!device())
    70         return false;
    72         return false;
    71 
    73 
    72     int devType = device()->devType();
    74     int devType = device()->devType();
    73 
    75 
    74     // Get the display and initialize it.
    76     // Get the display and initialize it.
    75     d->eglContext = new QEglContext();
    77     if (d->eglContext == 0) {
    76     d->eglContext->setApi(QEgl::OpenGL);
    78         d->eglContext = new QEglContext();
    77     if (!d->eglContext->openDisplay(device())) {
    79         d->eglContext->setApi(QEgl::OpenGL);
    78         delete d->eglContext;
    80         if (!d->eglContext->openDisplay(device())) {
    79         d->eglContext = 0;
    81             delete d->eglContext;
    80         return false;
    82             d->eglContext = 0;
    81     }
    83             return false;
    82 
    84         }
    83     // Construct the configuration we need for this surface.
    85 
    84     QEglProperties configProps;
    86         // Construct the configuration we need for this surface.
    85     qt_egl_set_format(configProps, devType, d->glFormat);
    87         QEglProperties configProps;
    86     qt_egl_add_platform_config(configProps, device());
    88         qt_egl_set_format(configProps, devType, d->glFormat);
    87     configProps.setRenderableType(QEgl::OpenGL);
    89         qt_egl_add_platform_config(configProps, device());
    88 
    90         configProps.setRenderableType(QEgl::OpenGL);
    89     QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
    91 
    90     if (device()->depth() == 16) {
    92 #if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
    91         configProps.setValue(EGL_RED_SIZE, 5);
    93         if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
    92         configProps.setValue(EGL_GREEN_SIZE, 6);
    94             qDebug("Setting EGL_BUFFER_SIZE to 16");
    93         configProps.setValue(EGL_BLUE_SIZE, 5);
    95             configProps.setValue(EGL_BUFFER_SIZE, 16);
    94         configProps.setValue(EGL_ALPHA_SIZE, 0);
    96             configProps.setValue(EGL_ALPHA_SIZE, 0);
    95         matchType = QEgl::ExactPixelFormat;
    97         }
    96     }
    98 
    97     configProps.setRenderableType(QEgl::OpenGL);
    99         if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
    98 
   100             delete d->eglContext;
    99     // Search for a matching configuration, reducing the complexity
   101             d->eglContext = 0;
   100     // each time until we get something that matches.
   102             return false;
   101     if (!d->eglContext->chooseConfig(configProps, matchType)) {
   103         }
   102         delete d->eglContext;
   104 #else
   103         d->eglContext = 0;
   105         QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
   104         return false;
   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
   105     }
   141     }
   106 
   142 
   107     // Inform the higher layers about the actual format properties.
   143     // Inform the higher layers about the actual format properties.
   108     qt_egl_update_format(*(d->eglContext), d->glFormat);
   144     qt_egl_update_format(*(d->eglContext), d->glFormat);
   109 
       
   110     // Create a new context for the configuration.
       
   111     if (!d->eglContext->createContext
       
   112             (shareContext ? shareContext->d_func()->eglContext : 0)) {
       
   113         delete d->eglContext;
       
   114         d->eglContext = 0;
       
   115         return false;
       
   116     }
       
   117 
       
   118 #if defined(EGL_VERSION_1_1)
       
   119     if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
       
   120         eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
       
   121 #endif
       
   122 
   145 
   123     return true;
   146     return true;
   124 }
   147 }
   125 
   148 
   126 void QGLWidget::resizeEvent(QResizeEvent *)
   149 void QGLWidget::resizeEvent(QResizeEvent *)
   148 void QGLWidget::updateOverlayGL()
   171 void QGLWidget::updateOverlayGL()
   149 {
   172 {
   150     //handle overlay
   173     //handle overlay
   151 }
   174 }
   152 
   175 
       
   176 //#define QT_DEBUG_X11_VISUAL_SELECTION 1
       
   177 
   153 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
   178 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
   154 {
   179 {
   155     bool foundVisualIsArgb = useArgbVisual;
   180     bool foundVisualIsArgb = useArgbVisual;
   156 
   181 
       
   182 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
       
   183     qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
       
   184 #endif
       
   185 
   157     memset(&vi, 0, sizeof(XVisualInfo));
   186     memset(&vi, 0, sizeof(XVisualInfo));
       
   187 
       
   188     EGLint eglConfigColorSize;
       
   189     eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
   158 
   190 
   159     // Check to see if EGL is suggesting an appropriate visual id:
   191     // Check to see if EGL is suggesting an appropriate visual id:
   160     EGLint nativeVisualId;
   192     EGLint nativeVisualId;
   161     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
   193     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
   162     vi.visualid = nativeVisualId;
   194     vi.visualid = nativeVisualId;
   171             if (useArgbVisual) {
   203             if (useArgbVisual) {
   172                 // Check to make sure the visual provided by EGL is ARGB
   204                 // Check to make sure the visual provided by EGL is ARGB
   173                 XRenderPictFormat *format;
   205                 XRenderPictFormat *format;
   174                 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
   206                 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
   175                 if (format->type == PictTypeDirect && format->direct.alphaMask) {
   207                 if (format->type == PictTypeDirect && format->direct.alphaMask) {
   176 //                    qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
   208 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
       
   209                     qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
       
   210 #endif
   177                     foundVisualIsArgb = true;
   211                     foundVisualIsArgb = true;
   178                     vi = *chosenVisualInfo;
   212                     vi = *chosenVisualInfo;
   179                 }
   213                 }
   180                 else {
   214                 else {
   181                     qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
   215                     qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
   183                     vi.visualid = 0;
   217                     vi.visualid = 0;
   184                 }
   218                 }
   185             } else
   219             } else
   186 #endif
   220 #endif
   187             {
   221             {
   188 //                qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
   222                 if (eglConfigColorSize == chosenVisualInfo->depth) {
   189                 vi = *chosenVisualInfo;
   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);
   190             }
   230             }
   191             XFree(chosenVisualInfo);
   231             XFree(chosenVisualInfo);
   192         }
   232         }
   193         else {
   233         else {
   194             qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
   234             qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
   216             XRenderPictFormat *format;
   256             XRenderPictFormat *format;
   217             format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
   257             format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
   218             if (format->type == PictTypeDirect && format->direct.alphaMask) {
   258             if (format->type == PictTypeDirect && format->direct.alphaMask) {
   219                 vi = matchingVisuals[i];
   259                 vi = matchingVisuals[i];
   220                 foundVisualIsArgb = true;
   260                 foundVisualIsArgb = true;
   221 //                qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
   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
   222                 break;
   264                 break;
   223             }
   265             }
   224         }
   266         }
   225         XFree(matchingVisuals);
   267         XFree(matchingVisuals);
   226     }
   268     }
   240                 qWarning("Error: Couldn't get any matching X visual!");
   282                 qWarning("Error: Couldn't get any matching X visual!");
   241                 return false;
   283                 return false;
   242             } else
   284             } else
   243                 qWarning("         - Falling back to X11 suggested depth (%d)", depth);
   285                 qWarning("         - Falling back to X11 suggested depth (%d)", depth);
   244         }
   286         }
   245 //        else
   287 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
   246 //            qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
   288         else
       
   289             qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
       
   290 #endif
   247 
   291 
   248         // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
   292         // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
   249         if (useArgbVisual)
   293         if (useArgbVisual)
   250             foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
   294             foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
   251     }
   295     }
   252 
   296 
   253 //    qDebug("Visual Info:");
   297 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
   254 //    qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
   298     qDebug("Visual Info:");
   255 //    qDebug("   red_mask=0x%x", vi.red_mask);
   299     qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
   256 //    qDebug("   green_mask=0x%x", vi.green_mask);
   300     qDebug("   red_mask=0x%x", vi.red_mask);
   257 //    qDebug("   blue_mask=0x%x", vi.blue_mask);
   301     qDebug("   green_mask=0x%x", vi.green_mask);
   258 //    qDebug("   colormap_size=%d", vi.colormap_size);
   302     qDebug("   blue_mask=0x%x", vi.blue_mask);
   259 //    qDebug("   c_class=%d", vi.c_class);
   303     qDebug("   colormap_size=%d", vi.colormap_size);
   260 //    qDebug("   depth=%d", vi.depth);
   304     qDebug("   c_class=%d", vi.c_class);
   261 //    qDebug("   screen=%d", vi.screen);
   305     qDebug("   depth=%d", vi.depth);
   262 //    qDebug("   visualid=%d", vi.visualid);
   306     qDebug("   screen=%d", vi.screen);
       
   307     qDebug("   visualid=%d", vi.visualid);
       
   308 #endif
   263     return foundVisualIsArgb;
   309     return foundVisualIsArgb;
   264 }
   310 }
   265 
   311 
   266 void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
   312 void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
   267 {
   313 {
   288     }
   334     }
   289 
   335 
   290     // If the application has set WA_TranslucentBackground and not explicitly set
   336     // If the application has set WA_TranslucentBackground and not explicitly set
   291     // the alpha buffer size to zero, modify the format so it have an alpha channel
   337     // the alpha buffer size to zero, modify the format so it have an alpha channel
   292     QGLFormat& fmt = d->glcx->d_func()->glFormat;
   338     QGLFormat& fmt = d->glcx->d_func()->glFormat;
   293     const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground);
   339     const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
   294     if (tryArgbVisual && fmt.alphaBufferSize() == -1)
   340     if (tryArgbVisual && fmt.alphaBufferSize() == -1)
   295         fmt.setAlphaBufferSize(1);
   341         fmt.setAlphaBufferSize(1);
   296 
   342 
   297     bool createFailed = false;
   343     bool createFailed = false;
   298     if (!d->glcx->isValid()) {
   344     if (!d->glcx->isValid()) {
       
   345         // Create the QGLContext here, which in turn chooses the EGL config
       
   346         // and creates the EGL context:
   299         if (!d->glcx->create(shareContext ? shareContext : oldcx))
   347         if (!d->glcx->create(shareContext ? shareContext : oldcx))
   300             createFailed = true;
   348             createFailed = true;
   301     }
   349     }
   302     if (createFailed) {
   350     if (createFailed) {
   303         if (deleteOldContext)
   351         if (deleteOldContext)
   529         doneOnce = true;
   577         doneOnce = true;
   530     }
   578     }
   531 
   579 
   532     Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
   580     Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
   533     pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
   581     pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
   534     pixmapData->is_cached = true; // Make sure the cleanup hook gets called
   582     QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
   535 
   583 
   536     return true;
   584     return true;
   537 }
   585 }
   538 
   586 
   539 
   587 
   587 
   635 
   588     Q_ASSERT(pixmapData->gl_surface);
   636     Q_ASSERT(pixmapData->gl_surface);
   589 
   637 
   590     GLuint textureId;
   638     GLuint textureId;
   591     glGenTextures(1, &textureId);
   639     glGenTextures(1, &textureId);
   592     glEnable(GL_TEXTURE_2D);
       
   593     glBindTexture(GL_TEXTURE_2D, textureId);
   640     glBindTexture(GL_TEXTURE_2D, textureId);
   594 
   641 
   595     // bind the egl pixmap surface to a texture
   642     // bind the egl pixmap surface to a texture
   596     EGLBoolean success;
   643     EGLBoolean success;
   597     success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
   644     success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);