~gerboland/qtubuntu/graphics-logging-category

« back to all changes in this revision

Viewing changes to src/ubuntumirclient/window.cpp

  • Committer: Bileto Bot
  • Author(s): Gerry Boland
  • Date: 2016-06-14 08:33:44 UTC
  • mfrom: (316.4.25 adopt-more-eglconvenience2)
  • Revision ID: ci-train-bot@canonical.com-20160614083344-8hi0fudgq8cszo6b
Convert UbuntuOpenGLContext to use QEGLPlatformContext, and allow clients to customize chosen GLConfig (LP: #1507817, #1549455)

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <QMutexLocker>
30
30
#include <QSize>
31
31
#include <QtMath>
 
32
#include <private/qeglconvenience_p.h>
32
33
 
33
34
// Platform API
34
35
#include <ubuntu/application/instance.h>
101
102
    }
102
103
}
103
104
 
 
105
const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
 
106
{
 
107
    switch (pixelFormat) {
 
108
    case mir_pixel_format_invalid:   return "invalid";
 
109
    case mir_pixel_format_abgr_8888: return "ABGR8888";
 
110
    case mir_pixel_format_xbgr_8888: return "XBGR8888";
 
111
    case mir_pixel_format_argb_8888: return "ARGB8888";
 
112
    case mir_pixel_format_xrgb_8888: return "XRGB8888";
 
113
    case mir_pixel_format_bgr_888:   return "BGR888";
 
114
    case mir_pixel_format_rgb_888:   return "RGB888";
 
115
    case mir_pixel_format_rgb_565:   return "RGB565";
 
116
    case mir_pixel_format_rgba_5551: return "RGBA5551";
 
117
    case mir_pixel_format_rgba_4444: return "RGBA4444";
 
118
    case mir_pixel_formats:
 
119
    default:                         return "???";
 
120
    }
 
121
}
 
122
 
104
123
MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
105
124
{
106
125
    switch (state) {
124
143
    return id++;
125
144
}
126
145
 
127
 
MirPixelFormat defaultPixelFormatFor(MirConnection *connection)
128
 
{
129
 
    MirPixelFormat format;
130
 
    unsigned int nformats;
131
 
    mir_connection_get_available_surface_formats(connection, &format, 1, &nformats);
132
 
    return format;
133
 
}
134
 
 
135
146
UAUiWindowRole roleFor(QWindow *window)
136
147
{
137
148
    QVariant roleVariant = window->property("role");
151
162
    return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr;
152
163
}
153
164
 
154
 
Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)
 
165
Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirPixelFormat pixelFormat, MirConnection *connection)
155
166
{
156
167
    const auto geom = window->geometry();
157
168
    const int width = geom.width() > 0 ? geom.width() : 1;
158
169
    const int height = geom.height() > 0 ? geom.height() : 1;
159
 
    const auto pixelFormat = defaultPixelFormatFor(connection);
160
170
 
161
171
    if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
162
172
        qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
217
227
    }
218
228
}
219
229
 
220
 
MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input,
 
230
MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, MirPixelFormat pixelFormat,
221
231
                             MirConnection *connection, mir_surface_event_callback inputCallback,
222
232
                             void* inputContext)
223
233
{
224
 
    auto spec = makeSurfaceSpec(window, input, connection);
 
234
    auto spec = makeSurfaceSpec(window, input, pixelFormat, connection);
225
235
 
226
236
    // Install event handler as early as possible
227
237
    mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
244
254
    return surface;
245
255
}
246
256
 
 
257
MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
 
258
{
 
259
    switch(pixelFormat) {
 
260
    case mir_pixel_format_abgr_8888:
 
261
        return mir_pixel_format_xbgr_8888;
 
262
    case mir_pixel_format_argb_8888:
 
263
        return mir_pixel_format_xrgb_8888;
 
264
    default: // can do nothing, leave it alone
 
265
        return pixelFormat;
 
266
    }
 
267
}
 
268
 
247
269
// FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
248
270
// we need to guess the panel height (3GU)
249
271
int panelHeight()
266
288
class UbuntuSurface
267
289
{
268
290
public:
269
 
    UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, EGLConfig config, int mirOutputId,
270
 
                  UbuntuInput *input, MirConnection *connection)
 
291
    UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection)
271
292
        : mWindow(platformWindow->window())
272
293
        , mPlatformWindow(platformWindow)
273
294
        , mInput(input)
275
296
        , mEglDisplay(display)
276
297
        , mNeedsRepaint(false)
277
298
        , mParented(mWindow->transientParent() || mWindow->parent())
 
299
        , mFormat(mWindow->requestedFormat())
278
300
        , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
279
301
    {
280
 
        mMirSurface = createMirSurface(mWindow, mirOutputId, input, connection, surfaceEventCallback, this);
 
302
        // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it
 
303
        EGLConfig config = q_configFromGLFormat(display, mFormat, true);
 
304
        if (config == 0) {
 
305
            // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
 
306
            // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
 
307
            // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to
 
308
            // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
 
309
            // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
 
310
            static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
 
311
            if (isMesa) {
 
312
                qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
 
313
                mFormat.setMajorVersion(1);
 
314
                mFormat.setMinorVersion(4);
 
315
                config = q_configFromGLFormat(display, mFormat, true);
 
316
            }
 
317
        }
 
318
        if (config == 0) {
 
319
            qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat;
 
320
        }
 
321
 
 
322
        mFormat = q_glFormatFromConfig(display, config, mFormat);
 
323
 
 
324
        // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
 
325
        // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
 
326
        auto pixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
 
327
        // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
 
328
        // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
 
329
        // This is an optimisation for the compositor, as it can avoid blending this surface.
 
330
        if (mWindow->requestedFormat().alphaBufferSize() < 0) {
 
331
            pixelFormat = disableAlphaBufferIfPossible(pixelFormat);
 
332
        }
 
333
 
 
334
        const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId();
 
335
 
 
336
        mMirSurface = createMirSurface(mWindow, outputId, input, pixelFormat, connection, surfaceEventCallback, this);
281
337
        mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr);
282
338
 
283
339
        // Window manager can give us a final size different from what we asked for
299
355
        platformWindow->QPlatformWindow::setGeometry(geom);
300
356
        QWindowSystemInterface::handleGeometryChange(mWindow, geom);
301
357
 
302
 
        qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n",
303
 
             geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow));
 
358
        qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
 
359
                                 << "role:" << roleFor(mWindow)
 
360
                                 << "\nRequested format:" << mWindow->requestedFormat()
 
361
                                 << "\nActual format:" << mFormat
 
362
                                 << "with associated Mir pixel format:" << mirPixelFormatToStr(pixelFormat);
304
363
    }
305
364
 
306
365
    ~UbuntuSurface()
335
394
    void setSurfaceParent(MirSurface*);
336
395
    bool hasParent() const { return mParented; }
337
396
 
 
397
    QSurfaceFormat format() const { return mFormat; }
 
398
 
338
399
private:
339
400
    static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
340
401
    void postEvent(const MirEvent *event);
351
412
    bool mNeedsRepaint;
352
413
    bool mParented;
353
414
    QSize mBufferSize;
 
415
    QSurfaceFormat mFormat;
354
416
 
355
417
    QMutex mTargetSizeMutex;
356
418
    QSize mTargetSize;
509
571
}
510
572
 
511
573
UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
512
 
                           UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay,
513
 
                           EGLConfig eglConfig, MirConnection *mirConnection)
 
574
                           UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay, MirConnection *mirConnection)
514
575
    : QObject(nullptr)
515
576
    , QPlatformWindow(w)
516
577
    , mId(makeId())
520
581
    , mWindowVisible(false)
521
582
    , mWindowExposed(true)
522
583
    , mNativeInterface(native)
523
 
    , mSurface(new UbuntuSurface{this, eglDisplay, eglConfig,
524
 
               static_cast<UbuntuScreen*>(w->screen()->handle())->mirOutputId(), input, mirConnection})
 
584
    , mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection})
525
585
    , mScale(1.0)
526
586
    , mFormFactor(mir_form_factor_unknown)
527
587
{
709
769
    return mWindowVisible && mWindowExposed;
710
770
}
711
771
 
 
772
QSurfaceFormat UbuntuWindow::format() const
 
773
{
 
774
    return mSurface->format();
 
775
}
 
776
 
712
777
void* UbuntuWindow::eglSurface() const
713
778
{
714
779
    return mSurface->eglSurface();