src/opengl/qgl_x11egl.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/opengl/qgl_x11egl.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/opengl/qgl_x11egl.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -42,6 +42,7 @@
 #include "qgl.h"
 #include <private/qt_x11_p.h>
 #include <private/qpixmap_x11_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
 #include <private/qgl_p.h>
 #include <private/qpaintengine_opengl_p.h>
 #include "qgl_egl_p.h"
@@ -62,6 +63,7 @@
         props.setPixelFormat(static_cast<QImage *>(device)->format());
 }
 
+// Chooses the EGL config and creates the EGL context
 bool QGLContext::chooseContext(const QGLContext* shareContext)
 {
     Q_D(QGLContext);
@@ -72,54 +74,75 @@
     int devType = device()->devType();
 
     // Get the display and initialize it.
-    d->eglContext = new QEglContext();
-    d->eglContext->setApi(QEgl::OpenGL);
-    if (!d->eglContext->openDisplay(device())) {
-        delete d->eglContext;
-        d->eglContext = 0;
-        return false;
-    }
+    if (d->eglContext == 0) {
+        d->eglContext = new QEglContext();
+        d->eglContext->setApi(QEgl::OpenGL);
+        if (!d->eglContext->openDisplay(device())) {
+            delete d->eglContext;
+            d->eglContext = 0;
+            return false;
+        }
 
-    // Construct the configuration we need for this surface.
-    QEglProperties configProps;
-    qt_egl_set_format(configProps, devType, d->glFormat);
-    qt_egl_add_platform_config(configProps, device());
-    configProps.setRenderableType(QEgl::OpenGL);
+        // Construct the configuration we need for this surface.
+        QEglProperties configProps;
+        qt_egl_set_format(configProps, devType, d->glFormat);
+        qt_egl_add_platform_config(configProps, device());
+        configProps.setRenderableType(QEgl::OpenGL);
+
+#if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
+        if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
+            qDebug("Setting EGL_BUFFER_SIZE to 16");
+            configProps.setValue(EGL_BUFFER_SIZE, 16);
+            configProps.setValue(EGL_ALPHA_SIZE, 0);
+        }
 
-    QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
-    if (device()->depth() == 16) {
-        configProps.setValue(EGL_RED_SIZE, 5);
-        configProps.setValue(EGL_GREEN_SIZE, 6);
-        configProps.setValue(EGL_BLUE_SIZE, 5);
-        configProps.setValue(EGL_ALPHA_SIZE, 0);
-        matchType = QEgl::ExactPixelFormat;
-    }
-    configProps.setRenderableType(QEgl::OpenGL);
+        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
+            delete d->eglContext;
+            d->eglContext = 0;
+            return false;
+        }
+#else
+        QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
+        if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
+            configProps.setValue(EGL_RED_SIZE, 5);
+            configProps.setValue(EGL_GREEN_SIZE, 6);
+            configProps.setValue(EGL_BLUE_SIZE, 5);
+            configProps.setValue(EGL_ALPHA_SIZE, 0);
+            matchType = QEgl::ExactPixelFormat;
+        }
 
-    // Search for a matching configuration, reducing the complexity
-    // each time until we get something that matches.
-    if (!d->eglContext->chooseConfig(configProps, matchType)) {
-        delete d->eglContext;
-        d->eglContext = 0;
-        return false;
+        // Search for a matching configuration, reducing the complexity
+        // each time until we get something that matches.
+        if (!d->eglContext->chooseConfig(configProps, matchType)) {
+            delete d->eglContext;
+            d->eglContext = 0;
+            return false;
+        }
+#endif
+
+//        qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
+//        qDebug() << QEglProperties(d->eglContext->config()).toString();
+
+        // Create a new context for the configuration.
+        if (!d->eglContext->createContext
+                (shareContext ? shareContext->d_func()->eglContext : 0)) {
+            delete d->eglContext;
+            d->eglContext = 0;
+            return false;
+        }
+        d->sharing = d->eglContext->isSharing();
+        if (d->sharing && shareContext)
+            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
+
+#if defined(EGL_VERSION_1_1)
+        if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
+            eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
+#endif
     }
 
     // Inform the higher layers about the actual format properties.
     qt_egl_update_format(*(d->eglContext), d->glFormat);
 
-    // Create a new context for the configuration.
-    if (!d->eglContext->createContext
-            (shareContext ? shareContext->d_func()->eglContext : 0)) {
-        delete d->eglContext;
-        d->eglContext = 0;
-        return false;
-    }
-
-#if defined(EGL_VERSION_1_1)
-    if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
-        eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
-#endif
-
     return true;
 }
 
@@ -150,12 +173,21 @@
     //handle overlay
 }
 
+//#define QT_DEBUG_X11_VISUAL_SELECTION 1
+
 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
 {
     bool foundVisualIsArgb = useArgbVisual;
 
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+    qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
+#endif
+
     memset(&vi, 0, sizeof(XVisualInfo));
 
+    EGLint eglConfigColorSize;
+    eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
+
     // Check to see if EGL is suggesting an appropriate visual id:
     EGLint nativeVisualId;
     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
@@ -173,7 +205,9 @@
                 XRenderPictFormat *format;
                 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
                 if (format->type == PictTypeDirect && format->direct.alphaMask) {
-//                    qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+                    qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
+#endif
                     foundVisualIsArgb = true;
                     vi = *chosenVisualInfo;
                 }
@@ -185,8 +219,14 @@
             } else
 #endif
             {
-//                qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
-                vi = *chosenVisualInfo;
+                if (eglConfigColorSize == chosenVisualInfo->depth) {
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+                    qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
+#endif
+                    vi = *chosenVisualInfo;
+                } else
+                    qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
+                             nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
             }
             XFree(chosenVisualInfo);
         }
@@ -218,7 +258,9 @@
             if (format->type == PictTypeDirect && format->direct.alphaMask) {
                 vi = matchingVisuals[i];
                 foundVisualIsArgb = true;
-//                qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+                qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
+#endif
                 break;
             }
         }
@@ -242,24 +284,28 @@
             } else
                 qWarning("         - Falling back to X11 suggested depth (%d)", depth);
         }
-//        else
-//            qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+        else
+            qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
+#endif
 
         // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
         if (useArgbVisual)
             foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
     }
 
-//    qDebug("Visual Info:");
-//    qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
-//    qDebug("   red_mask=0x%x", vi.red_mask);
-//    qDebug("   green_mask=0x%x", vi.green_mask);
-//    qDebug("   blue_mask=0x%x", vi.blue_mask);
-//    qDebug("   colormap_size=%d", vi.colormap_size);
-//    qDebug("   c_class=%d", vi.c_class);
-//    qDebug("   depth=%d", vi.depth);
-//    qDebug("   screen=%d", vi.screen);
-//    qDebug("   visualid=%d", vi.visualid);
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+    qDebug("Visual Info:");
+    qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
+    qDebug("   red_mask=0x%x", vi.red_mask);
+    qDebug("   green_mask=0x%x", vi.green_mask);
+    qDebug("   blue_mask=0x%x", vi.blue_mask);
+    qDebug("   colormap_size=%d", vi.colormap_size);
+    qDebug("   c_class=%d", vi.c_class);
+    qDebug("   depth=%d", vi.depth);
+    qDebug("   screen=%d", vi.screen);
+    qDebug("   visualid=%d", vi.visualid);
+#endif
     return foundVisualIsArgb;
 }
 
@@ -290,12 +336,14 @@
     // If the application has set WA_TranslucentBackground and not explicitly set
     // the alpha buffer size to zero, modify the format so it have an alpha channel
     QGLFormat& fmt = d->glcx->d_func()->glFormat;
-    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground);
+    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
     if (tryArgbVisual && fmt.alphaBufferSize() == -1)
         fmt.setAlphaBufferSize(1);
 
     bool createFailed = false;
     if (!d->glcx->isValid()) {
+        // Create the QGLContext here, which in turn chooses the EGL config
+        // and creates the EGL context:
         if (!d->glcx->create(shareContext ? shareContext : oldcx))
             createFailed = true;
     }
@@ -531,7 +579,7 @@
 
     Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
     pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
-    pixmapData->is_cached = true; // Make sure the cleanup hook gets called
+    QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
 
     return true;
 }
@@ -589,7 +637,6 @@
 
     GLuint textureId;
     glGenTextures(1, &textureId);
-    glEnable(GL_TEXTURE_2D);
     glBindTexture(GL_TEXTURE_2D, textureId);
 
     // bind the egl pixmap surface to a texture