diff options
Diffstat (limited to 'src/plugins/platforms/mirclient/qmirclientscreen.cpp')
-rw-r--r-- | src/plugins/platforms/mirclient/qmirclientscreen.cpp | 278 |
1 files changed, 117 insertions, 161 deletions
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp index 0a2253e9e2..cc8db830aa 100644 --- a/src/plugins/platforms/mirclient/qmirclientscreen.cpp +++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014-2015 Canonical, Ltd. +** Copyright (C) 2014-2016 Canonical, Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -42,11 +42,12 @@ #include "qmirclientscreen.h" #include "qmirclientlogging.h" #include "qmirclientorientationchangeevent_p.h" +#include "qmirclientnativeinterface.h" #include <mir_toolkit/mir_client_library.h> // Qt -#include <QCoreApplication> +#include <QGuiApplication> #include <QtCore/qmath.h> #include <QScreen> #include <QThread> @@ -55,9 +56,7 @@ #include <memory> -static const int kSwapInterval = 1; - -#if !defined(QT_NO_DEBUG) +static const int overrideDevicePixelRatio = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt(); static const char *orientationToStr(Qt::ScreenOrientation orientation) { switch (orientation) { @@ -71,173 +70,33 @@ static const char *orientationToStr(Qt::ScreenOrientation orientation) { return "inverted portrait"; case Qt::InvertedLandscapeOrientation: return "inverted landscape"; - default: - return "INVALID!"; } + Q_UNREACHABLE(); } -static void printEglConfig(EGLDisplay display, EGLConfig config) { - DASSERT(display != EGL_NO_DISPLAY); - DASSERT(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); - LOG("EGL vendor: %s", string); - string = eglQueryString(display, EGL_VERSION); - LOG("EGL version: %s", string); - string = eglQueryString(display, EGL_EXTENSIONS); - LOG("EGL extensions: %s", string); - LOG("EGL configuration attibutes:"); - for (int index = 0; kAttribs[index].attrib != -1; index++) { - EGLint value; - if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value)) - LOG(" %s: %d", kAttribs[index].name, static_cast<int>(value)); - } -} -#endif - - const QEvent::Type OrientationChangeEvent::mType = static_cast<QEvent::Type>(QEvent::registerEventType()); -static const MirDisplayOutput *find_active_output( - const MirDisplayConfiguration *conf) -{ - const MirDisplayOutput *output = NULL; - for (uint32_t d = 0; d < conf->num_outputs; d++) - { - const MirDisplayOutput *out = conf->outputs + d; - - if (out->used && - out->connected && - out->num_modes && - out->current_mode < out->num_modes) - { - output = out; - break; - } - } - - return output; -} -QMirClientScreen::QMirClientScreen(MirConnection *connection) - : mFormat(QImage::Format_RGB32) +QMirClientScreen::QMirClientScreen(const MirOutput *output, MirConnection *connection) + : mDevicePixelRatio(1.0) + , mFormat(QImage::Format_RGB32) , mDepth(32) + , mDpi{0} + , mFormFactor{mir_form_factor_unknown} + , mScale{1.0} , mOutputId(0) - , mSurfaceFormat() - , mEglDisplay(EGL_NO_DISPLAY) - , mEglConfig(nullptr) , mCursor(connection) { - // Initialize EGL. - ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE); - - mEglNativeDisplay = mir_connection_get_egl_native_display(connection); - ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY); - ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE); - - // Configure EGL buffers format. - 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); - DLOG("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); - - #if !defined(QT_NO_DEBUG) - printEglConfig(mEglDisplay, mEglConfig); - #endif - - // Set vblank swap interval. - int swapInterval = kSwapInterval; - QByteArray swapIntervalString = qgetenv("QTUBUNTU_SWAPINTERVAL"); - if (!swapIntervalString.isEmpty()) { - bool ok; - swapInterval = swapIntervalString.toInt(&ok); - if (!ok) - swapInterval = kSwapInterval; - } - DLOG("ubuntumirclient: setting swap interval to %d", swapInterval); - eglSwapInterval(mEglDisplay, swapInterval); - - // Get screen resolution. - auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); }; - using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>; - configUp displayConfig(mir_connection_create_display_config(connection), configDeleter); - ASSERT(displayConfig != nullptr); - - auto const displayOutput = find_active_output(displayConfig.get()); - ASSERT(displayOutput != nullptr); - - mOutputId = displayOutput->output_id; - - mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm); - DLOG("ubuntumirclient: screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height()); - - const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode]; - const int kScreenWidth = mode->horizontal_resolution; - const int kScreenHeight = mode->vertical_resolution; - DASSERT(kScreenWidth > 0 && kScreenHeight > 0); - - DLOG("ubuntumirclient: screen resolution: %dx%d", kScreenWidth, kScreenHeight); - - mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight); - - DLOG("QQMirClientScreen::QQMirClientScreen (this=%p)", this); - - // Set the default orientation based on the initial screen dimmensions. - mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation; - - // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait - mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation; + setMirOutput(output); } QMirClientScreen::~QMirClientScreen() { - eglTerminate(mEglDisplay); } void QMirClientScreen::customEvent(QEvent* event) { - DASSERT(QThread::currentThread() == thread()); + Q_ASSERT(QThread::currentThread() == thread()); OrientationChangeEvent* oReadingEvent = static_cast<OrientationChangeEvent*>(event); switch (oReadingEvent->mOrientation) { @@ -261,14 +120,10 @@ void QMirClientScreen::customEvent(QEvent* event) { Qt::InvertedLandscapeOrientation : Qt::InvertedPortraitOrientation; break; } - default: { - DLOG("QMirClientScreen::customEvent - Unknown orientation."); - return; - } } // Raise the event signal so that client apps know the orientation changed - DLOG("QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation)); + qCDebug(mirclient, "QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation)); QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation); } @@ -289,7 +144,7 @@ void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeig mGeometry.setWidth(currGeometry.height()); mGeometry.setHeight(currGeometry.width()); - DLOG("QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)", + qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)", mGeometry.width(), mGeometry.height()); QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry /* newGeometry */, @@ -300,7 +155,108 @@ void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeig } else { mCurrentOrientation = Qt::LandscapeOrientation; } - DLOG("QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation)); + qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation)); QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation); } } + +void QMirClientScreen::setMirOutput(const MirOutput *output) +{ + // Physical screen size (in mm) + mPhysicalSize.setWidth(mir_output_get_physical_width_mm(output)); + mPhysicalSize.setHeight(mir_output_get_physical_height_mm(output)); + + // Pixel Format +// mFormat = qImageFormatFromMirPixelFormat(mir_output_get_current_pixel_format(output)); // GERRY: TODO + + // Pixel depth + mDepth = 8 * MIR_BYTES_PER_PIXEL(mir_output_get_current_pixel_format(output)); + + // Mode = Resolution & refresh rate + const MirOutputMode *mode = mir_output_get_current_mode(output); + mNativeGeometry.setX(mir_output_get_position_x(output)); + mNativeGeometry.setY(mir_output_get_position_y(output)); + mNativeGeometry.setWidth(mir_output_mode_get_width(mode)); + mNativeGeometry.setHeight(mir_output_mode_get_height(mode)); + + mRefreshRate = mir_output_mode_get_refresh_rate(mode); + + // UI scale & DPR + mScale = mir_output_get_scale_factor(output); + if (overrideDevicePixelRatio > 0) { + mDevicePixelRatio = overrideDevicePixelRatio; + } else { + mDevicePixelRatio = 1.0; // FIXME - need to determine suitable DPR for the specified scale + } + + mFormFactor = mir_output_get_form_factor(output); + + mOutputId = mir_output_get_id(output); + + mGeometry.setX(mNativeGeometry.x()); + mGeometry.setY(mNativeGeometry.y()); + mGeometry.setWidth(mNativeGeometry.width()); + mGeometry.setHeight(mNativeGeometry.height()); + + // Set the default orientation based on the initial screen dimensions. + mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation; + + // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait + mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation; +} + +void QMirClientScreen::updateMirOutput(const MirOutput *output) +{ + auto oldRefreshRate = mRefreshRate; + auto oldScale = mScale; + auto oldFormFactor = mFormFactor; + auto oldGeometry = mGeometry; + + setMirOutput(output); + + // Emit change signals in particular order + if (oldGeometry != mGeometry) { + QWindowSystemInterface::handleScreenGeometryChange(screen(), + mGeometry /* newGeometry */, + mGeometry /* newAvailableGeometry */); + } + + if (!qFuzzyCompare(mRefreshRate, oldRefreshRate)) { + QWindowSystemInterface::handleScreenRefreshRateChange(screen(), mRefreshRate); + } + + auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface()); + if (!qFuzzyCompare(mScale, oldScale)) { + nativeInterface->screenPropertyChanged(this, QStringLiteral("scale")); + } + if (mFormFactor != oldFormFactor) { + nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor")); + } +} + +void QMirClientScreen::setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi) +{ + if (mDpi != dpi) { + mDpi = dpi; + QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), dpi, dpi); + } + + auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface()); + if (!qFuzzyCompare(mScale, scale)) { + mScale = scale; + nativeInterface->screenPropertyChanged(this, QStringLiteral("scale")); + } + if (mFormFactor != formFactor) { + mFormFactor = formFactor; + nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor")); + } +} + +QDpi QMirClientScreen::logicalDpi() const +{ + if (mDpi > 0) { + return QDpi(mDpi, mDpi); + } else { + return QPlatformScreen::logicalDpi(); + } +} |