=== modified file 'README'
--- README	2016-06-20 08:37:56 +0000
+++ README	2016-06-22 12:37:34 +0000
@@ -23,13 +23,10 @@
     $ qmlscene -platform ubuntumirclient Foo.qml
     $ QT_QPA_PLATFORM=ubuntumirclient qmlscene Foo.qml
 
-  The QPA plugins expose the following environment variables:
-
-    QTUBUNTU_SWAPINTERVAL: Specifies the required swap interval as an
-                           integer. 1 by default.
-
-    QTUBUNTU_MULTISAMPLE: Enables multisampling with using 4 samples
-                          per fragment.
+  This QPA plugin exposes the following environment variables:
+
+    QT_QPA_EGLFS_SWAPINTERVAL: Specifies the required swap interval as an
+                               integer. 1 by default.
 
     QTUBUNTU_NO_THREADED_OPENGL: Disables QtQuick threaded OpenGL
                                  rendering.
@@ -51,6 +48,8 @@
   * ubuntumirclient.swapBuffers - Messages related to surface buffer swapping.
   * ubuntumirclient             - For all other messages.
 
+  The QT_QPA_EGLFS_DEBUG environment variable prints a little more information
+  from Qt's internals.
 
 4. Building
 -----------

=== modified file 'src/ubuntumirclient/glcontext.cpp'
--- src/ubuntumirclient/glcontext.cpp	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/glcontext.cpp	2016-06-22 12:37:34 +0000
@@ -25,58 +25,12 @@
 
 namespace {
 
-void printOpenGLESConfig() {
-    static bool once = true;
-    if (once) {
-        const char* string = (const char*) glGetString(GL_VENDOR);
-        qCDebug(ubuntumirclient, "OpenGL ES vendor: %s", string);
-        string = (const char*) glGetString(GL_RENDERER);
-        qCDebug(ubuntumirclient, "OpenGL ES renderer: %s", string);
-        string = (const char*) glGetString(GL_VERSION);
-        qCDebug(ubuntumirclient, "OpenGL ES version: %s", string);
-        string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
-        qCDebug(ubuntumirclient, "OpenGL ES Shading Language version: %s", string);
-        string = (const char*) glGetString(GL_EXTENSIONS);
-        qCDebug(ubuntumirclient, "OpenGL ES extensions: %s", string);
-        once = false;
-    }
-}
-
-void printEglConfig(EGLDisplay display, EGLConfig config) {
+void printEglConfig(EGLDisplay display, EGLConfig config)
+{
     Q_ASSERT(display != EGL_NO_DISPLAY);
     Q_ASSERT(config != nullptr);
 
-    static const struct { const EGLint attrib; const char* name; } kAttribs[] = {
-        { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" },
-        { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" },
-        { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" },
-        { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" },
-        { EGL_RED_SIZE, "EGL_RED_SIZE" },
-        { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" },
-        { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" },
-        { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" },
-        { EGL_CONFIG_ID, "EGL_CONFIG_ID" },
-        { EGL_LEVEL, "EGL_LEVEL" },
-        { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" },
-        { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" },
-        { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" },
-        { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" },
-        { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" },
-        { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" },
-        { EGL_SAMPLES, "EGL_SAMPLES" },
-        { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" },
-        { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" },
-        { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" },
-        { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" },
-        { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" },
-        { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" },
-        { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" },
-        { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" },
-        { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" },
-        { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" },
-        { -1, NULL }
-    };
-    const char* string = eglQueryString(display, EGL_VENDOR);
+    const char *string = eglQueryString(display, EGL_VENDOR);
     qCDebug(ubuntumirclient, "EGL vendor: %s", string);
 
     string = eglQueryString(display, EGL_VERSION);
@@ -85,93 +39,19 @@
     string = eglQueryString(display, EGL_EXTENSIONS);
     qCDebug(ubuntumirclient, "EGL extensions: %s", string);
 
-    qCDebug(ubuntumirclient, "EGL configuration attibutes:");
-    for (int index = 0; kAttribs[index].attrib != -1; index++) {
-        EGLint value;
-        if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value))
-            qCDebug(ubuntumirclient, "  %s: %d", kAttribs[index].name, static_cast<int>(value));
-    }
-}
-
-QString eglErrorToString(EGLint errorNumber)
-{
-    #define EGL_ERROR_CASE(error) case error: return QString(#error);
-
-    switch (errorNumber) {
-        EGL_ERROR_CASE(EGL_SUCCESS)
-        EGL_ERROR_CASE(EGL_NOT_INITIALIZED)
-        EGL_ERROR_CASE(EGL_BAD_ACCESS)
-        EGL_ERROR_CASE(EGL_BAD_ALLOC)
-        EGL_ERROR_CASE(EGL_BAD_ATTRIBUTE)
-        EGL_ERROR_CASE(EGL_BAD_CONTEXT)
-        EGL_ERROR_CASE(EGL_BAD_CONFIG)
-        EGL_ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
-        EGL_ERROR_CASE(EGL_BAD_DISPLAY)
-        EGL_ERROR_CASE(EGL_BAD_SURFACE)
-        EGL_ERROR_CASE(EGL_BAD_MATCH)
-        EGL_ERROR_CASE(EGL_BAD_PARAMETER)
-        EGL_ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
-        EGL_ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
-        EGL_ERROR_CASE(EGL_CONTEXT_LOST)
-        default:
-            return QString("?");
-    }
-
-    #undef EGL_ERROR_CASE
-}
-
-EGLenum api_in_use()
-{
-    #ifdef QTUBUNTU_USE_OPENGL
-    return EGL_OPENGL_API;
-    #else
-    return EGL_OPENGL_ES_API;
-    #endif
-}
-
-const int kSwapInterval = 1;
-
-int qGetEnvIntValue(const char *varName, bool *ok)
-{
-    return qgetenv(varName).toInt(ok);
+    qCDebug(ubuntumirclient, "EGL configuration attributes:");
+    q_printEglConfig(display, config);
 }
 
 } // anonymous namespace
 
-UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share,
-                                         EGLDisplay display, EGLConfig config)
-    : mSurfaceFormat(surfaceFormat)
-    , mEglDisplay(display)
+UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+                                         EGLDisplay display)
+    : QEGLPlatformContext(format, share, display, 0)
 {
-    // Create an OpenGL ES 2 context.
-    QVector<EGLint> attribs;
-    attribs.append(EGL_CONTEXT_CLIENT_VERSION);
-    attribs.append(2);
-    attribs.append(EGL_NONE);
-    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
-
     if (ubuntumirclient().isDebugEnabled()) {
-        printEglConfig(mEglDisplay, config);
+        printEglConfig(display, eglConfig());
     }
-
-    // Set vblank swap interval.
-    bool ok;
-    int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok);
-    if (!ok)
-        swapInterval = kSwapInterval;
-
-    qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval);
-    eglSwapInterval(mEglDisplay, swapInterval);
-
-    mEglContext = eglCreateContext(mEglDisplay, config, share ? share->eglContext() : EGL_NO_CONTEXT,
-                                   attribs.constData());
-
-    Q_ASSERT(mEglContext != EGL_NO_CONTEXT);
-}
-
-UbuntuOpenGLContext::~UbuntuOpenGLContext()
-{
-    ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE);
 }
 
 static bool needsFBOReadBackWorkaround()
@@ -179,7 +59,7 @@
     static bool set = false;
     static bool needsWorkaround = false;
 
-    if (!set) {
+    if (Q_UNLIKELY(!set)) {
         const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
         needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0
                           || qstrncmp(rendererString, "Mali-T7", 7) == 0
@@ -202,47 +82,42 @@
         }
         return offscreen->buffer()->bind();
     } else {
-        EGLSurface eglSurface = static_cast<UbuntuWindow*>(surface)->eglSurface();
-        ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
-
-        EGLBoolean result = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
-        if (result == EGL_FALSE) {
-            qCCritical(ubuntumirclient, "eglMakeCurrent() failed with %s",
-                    qPrintable(eglErrorToString(eglGetError())));
-            return false;
-        }
-
-        QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
-        if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
-            ctx_d->workaround_brokenFBOReadBack = true;
-        }
-
-        if (ubuntumirclient().isDebugEnabled()) {
-            printOpenGLESConfig();
-        }
-        return true;
-    }
-}
-
-void UbuntuOpenGLContext::doneCurrent()
-{
-    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
-    ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE);
-}
-
-void UbuntuOpenGLContext::swapBuffers(QPlatformSurface* surface)
-{
-    UbuntuWindow *ubuntuWindow = static_cast<UbuntuWindow*>(surface);
-
-    EGLSurface eglSurface = ubuntuWindow->eglSurface();
-    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
-    ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
-
+        const bool ret = QEGLPlatformContext::makeCurrent(surface);
+
+        if (Q_LIKELY(ret)) {
+            QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
+            if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
+                ctx_d->workaround_brokenFBOReadBack = true;
+            }
+        }
+
+        return ret;
+    }
+}
+
+// WORKAROUND for bug 1594198 - avoid having Qt use GLESv3
+QSurfaceFormat UbuntuOpenGLContext::format() const
+{
+    auto format = QEGLPlatformContext::format();
+    if (format.renderableType() == QSurfaceFormat::OpenGLES && format.majorVersion() > 2) {
+        format.setMajorVersion(2);
+    }
+    return format;
+}
+
+// Following method used internally in the base class QEGLPlatformContext to access
+// the egl surface of a QPlatformSurface/UbuntuWindow
+EGLSurface UbuntuOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+{
+    auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
+    return ubuntuWindow->eglSurface();
+}
+
+void UbuntuOpenGLContext::swapBuffers(QPlatformSurface *surface)
+{
+    QEGLPlatformContext::swapBuffers(surface);
+
+    // notify window on swap completion
+    auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
     ubuntuWindow->onSwapBuffersDone();
 }
-
-void (*UbuntuOpenGLContext::getProcAddress(const QByteArray& procName)) ()
-{
-    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
-    return eglGetProcAddress(procName.constData());
-}

=== modified file 'src/ubuntumirclient/glcontext.h'
--- src/ubuntumirclient/glcontext.h	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/glcontext.h	2016-06-22 12:37:34 +0000
@@ -18,30 +18,24 @@
 #define UBUNTU_OPENGL_CONTEXT_H
 
 #include <qpa/qplatformopenglcontext.h>
+#include <private/qeglplatformcontext_p.h>
 
 #include <EGL/egl.h>
 
-class UbuntuOpenGLContext : public QPlatformOpenGLContext
+class UbuntuOpenGLContext : public QEGLPlatformContext
 {
 public:
-    UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share,
-                        EGLDisplay display, EGLConfig config);
-    virtual ~UbuntuOpenGLContext();
-
-    // QPlatformOpenGLContext methods.
-    QSurfaceFormat format() const override { return mSurfaceFormat; }
-    void swapBuffers(QPlatformSurface *surface) override;
-    bool makeCurrent(QPlatformSurface *surface) override;
-    void doneCurrent() override;
-    bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; }
-    void (*getProcAddress(const QByteArray& procName)) () override;
-
-    EGLContext eglContext() const { return mEglContext; }
-
-private:
-    const QSurfaceFormat mSurfaceFormat;
-    EGLContext mEglContext;
-    EGLDisplay mEglDisplay;
+    UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+                        EGLDisplay display);
+
+    // QEGLPlatformContext methods.
+    void swapBuffers(QPlatformSurface *surface) final;
+    bool makeCurrent(QPlatformSurface *surface) final;
+
+    QSurfaceFormat format() const final;
+
+protected:
+    EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final;
 };
 
 #endif // UBUNTU_OPENGL_CONTEXT_H

=== modified file 'src/ubuntumirclient/integration.cpp'
--- src/ubuntumirclient/integration.cpp	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/integration.cpp	2016-06-22 12:37:34 +0000
@@ -30,7 +30,6 @@
 // Qt
 #include <QFileInfo>
 #include <QGuiApplication>
-#include <private/qguiapplication_p.h>
 #include <qpa/qplatformnativeinterface.h>
 #include <qpa/qplatforminputcontextfactory_p.h>
 #include <qpa/qplatforminputcontext.h>
@@ -95,31 +94,17 @@
 
     mMirConnection = u_application_instance_get_mir_connection(mInstance);
 
+    // Choose the default surface format suited to the Mir platform
+    QSurfaceFormat defaultFormat;
+    defaultFormat.setRedBufferSize(8);
+    defaultFormat.setGreenBufferSize(8);
+    defaultFormat.setBlueBufferSize(8);
+    QSurfaceFormat::setDefaultFormat(defaultFormat);
+
     // Initialize EGL.
-    ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE);
-
     mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection);
     ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
     ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
-
-    // Configure EGL buffers format for all Windows.
-    mSurfaceFormat.setRedBufferSize(8);
-    mSurfaceFormat.setGreenBufferSize(8);
-    mSurfaceFormat.setBlueBufferSize(8);
-    mSurfaceFormat.setAlphaBufferSize(8);
-    mSurfaceFormat.setDepthBufferSize(24);
-    mSurfaceFormat.setStencilBufferSize(8);
-    if (!qEnvironmentVariableIsEmpty("QTUBUNTU_MULTISAMPLE")) {
-        mSurfaceFormat.setSamples(4);
-        qCDebug(ubuntumirclient, "setting MSAA to 4 samples");
-    }
-#ifdef QTUBUNTU_USE_OPENGL
-    mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
-#else
-    mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
-#endif
-
-    mEglConfig = q_configFromGLFormat(mEglDisplay, mSurfaceFormat, true);
 }
 
 void UbuntuClientIntegration::initialize()
@@ -226,7 +211,7 @@
 
 QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window) const
 {
-    return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mEglConfig, mMirConnection);
+    return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mMirConnection);
 }
 
 bool UbuntuClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -269,8 +254,25 @@
 QPlatformOpenGLContext* UbuntuClientIntegration::createPlatformOpenGLContext(
         QOpenGLContext* context) const
 {
-    return new UbuntuOpenGLContext(mSurfaceFormat, static_cast<UbuntuOpenGLContext*>(context->shareHandle()),
-                                   mEglDisplay, mEglConfig);
+    QSurfaceFormat format(context->format());
+
+    auto platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay);
+    if (!platformContext->isValid()) {
+        // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
+        // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
+        // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to
+        // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
+        // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
+        static const bool isMesa = QString(eglQueryString(mEglDisplay, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
+        if (isMesa) {
+            qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
+            format.setMajorVersion(1);
+            format.setMinorVersion(4);
+            delete platformContext;
+            platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay);
+        }
+    }
+    return platformContext;
 }
 
 QStringList UbuntuClientIntegration::themeNames() const

=== modified file 'src/ubuntumirclient/integration.h'
--- src/ubuntumirclient/integration.h	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/integration.h	2016-06-22 12:37:34 +0000
@@ -62,9 +62,7 @@
 
     // New methods.
     MirConnection *mirConnection() const { return mMirConnection; }
-    QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; }
     EGLDisplay eglDisplay() const { return mEglDisplay; }
-    EGLConfig eglConfig() const { return mEglConfig; }
     EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
     UbuntuScreenObserver *screenObserver() const { return mScreenObserver.data(); }
 
@@ -97,9 +95,7 @@
 
     // EGL related
     EGLDisplay mEglDisplay{EGL_NO_DISPLAY};
-    EGLConfig mEglConfig{nullptr};
     EGLNativeDisplayType mEglNativeDisplay;
-    QSurfaceFormat mSurfaceFormat;
 };
 
 #endif // UBUNTU_CLIENT_INTEGRATION_H

=== modified file 'src/ubuntumirclient/window.cpp'
--- src/ubuntumirclient/window.cpp	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/window.cpp	2016-06-22 12:37:34 +0000
@@ -29,6 +29,7 @@
 #include <QMutexLocker>
 #include <QSize>
 #include <QtMath>
+#include <private/qeglconvenience_p.h>
 
 // Platform API
 #include <ubuntu/application/instance.h>
@@ -101,6 +102,24 @@
     }
 }
 
+const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
+{
+    switch (pixelFormat) {
+    case mir_pixel_format_invalid:   return "invalid";
+    case mir_pixel_format_abgr_8888: return "ABGR8888";
+    case mir_pixel_format_xbgr_8888: return "XBGR8888";
+    case mir_pixel_format_argb_8888: return "ARGB8888";
+    case mir_pixel_format_xrgb_8888: return "XRGB8888";
+    case mir_pixel_format_bgr_888:   return "BGR888";
+    case mir_pixel_format_rgb_888:   return "RGB888";
+    case mir_pixel_format_rgb_565:   return "RGB565";
+    case mir_pixel_format_rgba_5551: return "RGBA5551";
+    case mir_pixel_format_rgba_4444: return "RGBA4444";
+    case mir_pixel_formats:
+    default:                         return "???";
+    }
+}
+
 MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
 {
     switch (state) {
@@ -124,14 +143,6 @@
     return id++;
 }
 
-MirPixelFormat defaultPixelFormatFor(MirConnection *connection)
-{
-    MirPixelFormat format;
-    unsigned int nformats;
-    mir_connection_get_available_surface_formats(connection, &format, 1, &nformats);
-    return format;
-}
-
 UAUiWindowRole roleFor(QWindow *window)
 {
     QVariant roleVariant = window->property("role");
@@ -151,12 +162,11 @@
     return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr;
 }
 
-Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)
+Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirPixelFormat pixelFormat, MirConnection *connection)
 {
     const auto geom = window->geometry();
     const int width = geom.width() > 0 ? geom.width() : 1;
     const int height = geom.height() > 0 ? geom.height() : 1;
-    const auto pixelFormat = defaultPixelFormatFor(connection);
 
     if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
         qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
@@ -217,11 +227,11 @@
     }
 }
 
-MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input,
+MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, MirPixelFormat pixelFormat,
                              MirConnection *connection, mir_surface_event_callback inputCallback,
                              void* inputContext)
 {
-    auto spec = makeSurfaceSpec(window, input, connection);
+    auto spec = makeSurfaceSpec(window, input, pixelFormat, connection);
 
     // Install event handler as early as possible
     mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
@@ -244,6 +254,18 @@
     return surface;
 }
 
+MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
+{
+    switch(pixelFormat) {
+    case mir_pixel_format_abgr_8888:
+        return mir_pixel_format_xbgr_8888;
+    case mir_pixel_format_argb_8888:
+        return mir_pixel_format_xrgb_8888;
+    default: // can do nothing, leave it alone
+        return pixelFormat;
+    }
+}
+
 // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
 // we need to guess the panel height (3GU)
 int panelHeight()
@@ -266,8 +288,7 @@
 class UbuntuSurface
 {
 public:
-    UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, EGLConfig config, int mirOutputId,
-                  UbuntuInput *input, MirConnection *connection)
+    UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection)
         : mWindow(platformWindow->window())
         , mPlatformWindow(platformWindow)
         , mInput(input)
@@ -275,9 +296,44 @@
         , mEglDisplay(display)
         , mNeedsRepaint(false)
         , mParented(mWindow->transientParent() || mWindow->parent())
+        , mFormat(mWindow->requestedFormat())
         , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
     {
-        mMirSurface = createMirSurface(mWindow, mirOutputId, input, connection, surfaceEventCallback, this);
+        // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it
+        EGLConfig config = q_configFromGLFormat(display, mFormat, true);
+        if (config == 0) {
+            // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
+            // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
+            // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to
+            // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
+            // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
+            static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
+            if (isMesa) {
+                qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
+                mFormat.setMajorVersion(1);
+                mFormat.setMinorVersion(4);
+                config = q_configFromGLFormat(display, mFormat, true);
+            }
+        }
+        if (config == 0) {
+            qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat;
+        }
+
+        mFormat = q_glFormatFromConfig(display, config, mFormat);
+
+        // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
+        // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
+        auto pixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
+        // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
+        // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
+        // This is an optimisation for the compositor, as it can avoid blending this surface.
+        if (mWindow->requestedFormat().alphaBufferSize() < 0) {
+            pixelFormat = disableAlphaBufferIfPossible(pixelFormat);
+        }
+
+        const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId();
+
+        mMirSurface = createMirSurface(mWindow, outputId, input, pixelFormat, connection, surfaceEventCallback, this);
         mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr);
 
         // Window manager can give us a final size different from what we asked for
@@ -299,8 +355,11 @@
         platformWindow->QPlatformWindow::setGeometry(geom);
         QWindowSystemInterface::handleGeometryChange(mWindow, geom);
 
-        qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n",
-             geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow));
+        qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
+                                 << "role:" << roleFor(mWindow)
+                                 << "\nRequested format:" << mWindow->requestedFormat()
+                                 << "\nActual format:" << mFormat
+                                 << "with associated Mir pixel format:" << mirPixelFormatToStr(pixelFormat);
     }
 
     ~UbuntuSurface()
@@ -335,6 +394,8 @@
     void setSurfaceParent(MirSurface*);
     bool hasParent() const { return mParented; }
 
+    QSurfaceFormat format() const { return mFormat; }
+
 private:
     static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
     void postEvent(const MirEvent *event);
@@ -351,6 +412,7 @@
     bool mNeedsRepaint;
     bool mParented;
     QSize mBufferSize;
+    QSurfaceFormat mFormat;
 
     QMutex mTargetSizeMutex;
     QSize mTargetSize;
@@ -509,8 +571,7 @@
 }
 
 UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
-                           UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay,
-                           EGLConfig eglConfig, MirConnection *mirConnection)
+                           UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay, MirConnection *mirConnection)
     : QObject(nullptr)
     , QPlatformWindow(w)
     , mId(makeId())
@@ -520,8 +581,7 @@
     , mWindowVisible(false)
     , mWindowExposed(true)
     , mNativeInterface(native)
-    , mSurface(new UbuntuSurface{this, eglDisplay, eglConfig,
-               static_cast<UbuntuScreen*>(w->screen()->handle())->mirOutputId(), input, mirConnection})
+    , mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection})
     , mScale(1.0)
     , mFormFactor(mir_form_factor_unknown)
 {
@@ -709,6 +769,11 @@
     return mWindowVisible && mWindowExposed;
 }
 
+QSurfaceFormat UbuntuWindow::format() const
+{
+    return mSurface->format();
+}
+
 void* UbuntuWindow::eglSurface() const
 {
     return mSurface->eglSurface();

=== modified file 'src/ubuntumirclient/window.h'
--- src/ubuntumirclient/window.h	2016-06-20 08:37:56 +0000
+++ src/ubuntumirclient/window.h	2016-06-22 12:37:34 +0000
@@ -40,7 +40,7 @@
     Q_OBJECT
 public:
     UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
-                 UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay, EGLConfig eglConfig,
+                 UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay,
                  MirConnection *mirConnection);
     virtual ~UbuntuWindow();
 
@@ -54,6 +54,8 @@
     void propagateSizeHints() override;
     bool isExposed() const override;
 
+    QSurfaceFormat format() const override;
+
     // Additional Window properties exposed by NativeInterface
     MirFormFactor formFactor() const { return mFormFactor; }
     float scale() const { return mScale; }

