diff options
Diffstat (limited to 'src/core/web_engine_context.cpp')
-rw-r--r-- | src/core/web_engine_context.cpp | 269 |
1 files changed, 138 insertions, 131 deletions
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index c7add160b..a49d8103c 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -130,16 +130,15 @@ #include <QOffscreenSurface> #if QT_CONFIG(opengl) # include <QOpenGLContext> +# include <qopenglcontext_platform.h> #endif #include <QQuickWindow> #include <QStringList> #include <QSurfaceFormat> -#include <QVector> #include <QNetworkProxy> #include <QtGui/qpa/qplatformintegration.h> #include <QtGui/private/qguiapplication_p.h> - -using namespace QtWebEngineCore; +#include <QLoggingCategory> #if QT_CONFIG(opengl) QT_BEGIN_NAMESPACE @@ -147,10 +146,10 @@ Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); QT_END_NAMESPACE #endif -namespace { +namespace QtWebEngineCore { #if QT_CONFIG(opengl) -bool usingANGLE() +static bool usingANGLE() { #if defined(Q_OS_WIN) if (qt_gl_global_share_context()) @@ -161,7 +160,7 @@ bool usingANGLE() #endif } -bool usingDefaultSGBackend() +static bool usingDefaultSGBackend() { const QStringList args = QGuiApplication::arguments(); @@ -182,16 +181,105 @@ bool usingDefaultSGBackend() return device.isEmpty(); } + +bool usingSoftwareDynamicGL() +{ + if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL)) + return true; +#if defined(Q_OS_WIN) + HMODULE handle = QPlatformInterface::QWGLContext::openGLModuleHandle(); + wchar_t path[MAX_PATH]; + DWORD size = GetModuleFileName(handle, path, MAX_PATH); + QFileInfo openGLModule(QString::fromWCharArray(path, size)); + return openGLModule.fileName() == QLatin1String("opengl32sw.dll"); +#else + return false; +#endif +} + +static const char *getGLType(bool enableGLSoftwareRendering) +{ + const char *glType = nullptr; + const bool tryGL = (usingDefaultSGBackend() && !usingSoftwareDynamicGL() + && QGuiApplicationPrivate::platformIntegration()->hasCapability( + QPlatformIntegration::OpenGL)) + || enableGLSoftwareRendering; + if (tryGL) { + if (!qt_gl_global_share_context() || !qt_gl_global_share_context()->isValid()) { + qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context " + "creation failed."); + } else { + const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format(); + switch (sharedFormat.renderableType()) { + case QSurfaceFormat::OpenGL: + glType = gl::kGLImplementationDesktopName; + // Check if Core profile was requested and is supported. + if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) { +#ifdef Q_OS_MACOS + glType = gl::kGLImplementationCoreProfileName; +#else + qWarning("An OpenGL Core Profile was requested, but it is not supported " + "on the current platform. Falling back to a non-Core profile. " + "Note that this might cause rendering issues."); +#endif + } + break; + case QSurfaceFormat::OpenGLES: + glType = usingANGLE() ? gl::kGLImplementationANGLEName + : gl::kGLImplementationEGLName; + break; + case QSurfaceFormat::OpenVG: + case QSurfaceFormat::DefaultRenderableType: + default: + // Shared contex created but no rederable type set. + qWarning("Unsupported rendering surface format. Please open bug report at " + "https://bugreports.qt.io"); + } + } + } + return glType; +} +#else +static cont char *getGLType(bool enableGLSoftwareRendering) +{ + return nullptr; +} #endif // QT_CONFIG(opengl) + #if QT_CONFIG(webengine_pepper_plugins) void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) { } #endif -} // namespace - -namespace QtWebEngineCore { +static void logContext(const char *glType, base::CommandLine *cmd) +{ + QLoggingCategory webEngineContextLog("qt.webenginecontext"); + if (webEngineContextLog.isInfoEnabled()) { + const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format(); + const auto profile = QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey( + sharedFormat.profile()); + const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey( + sharedFormat.renderableType()); + const base::CommandLine::SwitchMap switch_map = cmd->GetSwitches(); + QStringList params; + for (const auto &pair : switch_map) + params << " * " << toQt(pair.first) + << toQt(pair.second) << "\n"; + qCInfo(webEngineContextLog, + "\n\nGLImplementation: %s\n" + "Surface Type: %s\n" + "Surface Profile: %s\n" + "Surface Version: %d.%d\n" + "Using Default SG Backend: %s\n" + "Using Software Dynamic GL: %s\n" + "Using Angle: %s\n\n" + "Init Parameters:\n %s", + glType, type, profile, sharedFormat.majorVersion(), sharedFormat.minorVersion(), + usingDefaultSGBackend() ? "yes" : "no", usingSoftwareDynamicGL() ? "yes" : "no", + usingANGLE() ? "yes" : "no", qPrintable(params.join(" "))); + } +} #if defined(Q_OS_WIN) sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info) @@ -207,36 +295,22 @@ sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterf extern std::unique_ptr<base::MessagePump> messagePumpFactory(); -bool usingSoftwareDynamicGL() +static void setupProxyPac(base::CommandLine *commandLine) { - if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL)) - return true; -#if defined(Q_OS_WIN) && QT_CONFIG(opengl) - HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle()); - wchar_t path[MAX_PATH]; - DWORD size = GetModuleFileName(handle, path, MAX_PATH); - QFileInfo openGLModule(QString::fromWCharArray(path, size)); - return openGLModule.fileName() == QLatin1String("opengl32sw.dll"); -#else - return false; -#endif -} - -void setupProxyPac(base::CommandLine *commandLine){ if (commandLine->HasSwitch(switches::kProxyPacUrl)) { QUrl pac_url(toQt(commandLine->GetSwitchValueASCII(switches::kProxyPacUrl))); if (pac_url.isValid() && (pac_url.isLocalFile() || - !pac_url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive))) { + !pac_url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive))) { QFile file; if (pac_url.isLocalFile()) - file.setFileName(pac_url.toLocalFile()); + file.setFileName(pac_url.toLocalFile()); else - file.setFileName(pac_url.path().prepend(QChar(':'))); + file.setFileName(pac_url.path().prepend(QChar(':'))); if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QByteArray ba = file.readAll(); - commandLine->RemoveSwitch(switches::kProxyPacUrl); - commandLine->AppendSwitchASCII(switches::kProxyPacUrl, - ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); + QByteArray ba = file.readAll(); + commandLine->RemoveSwitch(switches::kProxyPacUrl); + commandLine->AppendSwitchASCII(switches::kProxyPacUrl, + ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); } } } @@ -563,12 +637,6 @@ WebEngineContext::WebEngineContext() QStringList appArgs = QCoreApplication::arguments(); - // If user requested GL support instead of using Skia rendering to - // bitmaps, use software rendering via software OpenGL. This might be less - // performant, but at least provides WebGL support. - // TODO(miklocek), check if this still works with latest chromium - bool enableGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering")); - bool useEmbeddedSwitches = false; #if defined(QTWEBENGINE_EMBEDDED_SWITCHES) useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches")); @@ -595,30 +663,6 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); -#if defined(Q_OS_WIN) - // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create - // an OpenGL Core Profile context. If the switch is not set, it would always try to create a - // Core Profile context, even if Qt uses a legacy profile, which causes - // "Could not share GL contexts" warnings, because it's not possible to share between Core and - // legacy profiles. See GLContextWGL::Initialize(). - // Given that Desktop GL Core profile is not currently supported on Windows anyway, pass this - // switch to get rid of the warnings. - // - // The switch is also used to determine which version of OpenGL ES to use (2 or 3) when using - // ANGLE. - // If the switch is not set, Chromium will always try to create an ES3 context, even if Qt uses - // an ES2 context, which causes resource sharing issues (black screen), - // see gpu::gles2::GenerateGLContextAttribs(). - // Make sure to disable ES3 context creation when using ES2. - const bool isGLES2Context = qt_gl_global_share_context() - && qt_gl_global_share_context()->isOpenGLES() - && qt_gl_global_share_context()->format().majorVersion() == 2; - const bool isDesktopGLOrSoftware = !usingANGLE(); - - if (isDesktopGLOrSoftware || isGLES2Context) - parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); -#endif - // Do not advertise a feature we have removed at compile time parsedCommandLine->AppendSwitch(switches::kDisableSpeechAPI); @@ -674,74 +718,12 @@ WebEngineContext::WebEngineContext() GLContextHelper::initialize(); - const char *glType = 0; -#if QT_CONFIG(opengl) - - const bool tryGL = (usingDefaultSGBackend() && !usingSoftwareDynamicGL() && - QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) - || enableGLSoftwareRendering; - if (tryGL) { - if (qt_gl_global_share_context() && qt_gl_global_share_context()->isValid()) { - // If the native handle is QEGLNativeContext try to use GL ES/2. - // If there is no native handle, assume we are using wayland and try GL ES/2. - // If we are using ANGLE on Windows, use OpenGL ES (2 or 3). - if (qt_gl_global_share_context()->nativeHandle().isNull() - || !strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), - "QEGLNativeContext") - || usingANGLE()) - { - if (qt_gl_global_share_context()->isOpenGLES()) { - glType = usingANGLE() ? gl::kGLImplementationANGLEName : gl::kGLImplementationEGLName; - } else { - QOpenGLContext context; - QSurfaceFormat format; - - format.setRenderableType(QSurfaceFormat::OpenGL); - format.setVersion(2, 0); - - context.setFormat(format); - context.setShareContext(qt_gl_global_share_context()); - if (context.create()) { - QOffscreenSurface surface; - - surface.setFormat(format); - surface.create(); - - if (context.makeCurrent(&surface)) { - if (context.hasExtension("GL_ARB_ES2_compatibility")) - glType = gl::kGLImplementationEGLName; - - context.doneCurrent(); - } - - surface.destroy(); - } - } - } else { - if (!qt_gl_global_share_context()->isOpenGLES()) { - // Default to Desktop non-Core profile OpenGL. - glType = gl::kGLImplementationDesktopName; - - // Check if Core profile was requested and is supported. - QSurfaceFormat globalSharedFormat = qt_gl_global_share_context()->format(); - if (globalSharedFormat.profile() == QSurfaceFormat::CoreProfile) { -#ifdef Q_OS_MACOS - glType = gl::kGLImplementationCoreProfileName; -#else - qWarning("An OpenGL Core Profile was requested, but it is not supported " - "on the current platform. Falling back to a non-Core profile. " - "Note that this might cause rendering issues."); -#endif - } - } - } - if (qt_gl_global_share_context()->format().profile() == QSurfaceFormat::CompatibilityProfile) - parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); - } else { - qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed."); - } - } -#endif // QT_CONFIG(opengl) + // If user requested GL support instead of using Skia rendering to + // bitmaps, use software rendering via software OpenGL. This might be less + // performant, but at least provides WebGL support. + // TODO(miklocek), check if this still works with latest chromium + const bool enableGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering")); + const char *glType = getGLType(enableGLSoftwareRendering); if (glType) { parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); @@ -750,6 +732,29 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpuRasterization); parsedCommandLine->AppendSwitch(switches::kIgnoreGpuBlacklist); } + const QSurfaceFormat sharedFormat = QOpenGLContext::globalShareContext()->format(); + if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile) + parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); +#if defined(Q_OS_WIN) + // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create + // an OpenGL Core Profile context. If the switch is not set, it would always try to create a + // Core Profile context, even if Qt uses a legacy profile, which causes + // "Could not share GL contexts" warnings, because it's not possible to share between Core and + // legacy profiles. See GLContextWGL::Initialize(). + // Given that Desktop GL Core profile is not currently supported on Windows anyway, pass this + // switch to get rid of the warnings. + // + // The switch is also used to determine which version of OpenGL ES to use (2 or 3) when using + // ANGLE. + // If the switch is not set, Chromium will always try to create an ES3 context, even if Qt uses + // an ES2 context, which causes resource sharing issues (black screen), + // see gpu::gles2::GenerateGLContextAttribs(). + // Make sure to disable ES3 context creation when using ES2. + const bool isGLES2Context = QOpenGLContext::globalShareContext()->isOpenGLES() + && QOpenGLContext::globalShareContext()->format().majorVersion() == 2; + if (!usingANGLE() || isGLES2Context) + parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); +#endif } else { parsedCommandLine->AppendSwitch(switches::kDisableGpu); } @@ -832,6 +837,8 @@ WebEngineContext::WebEngineContext() #endif content::WebUIControllerFactory::RegisterFactory(WebUIControllerFactoryQt::GetInstance()); + + logContext(glType, parsedCommandLine); } #if QT_CONFIG(webengine_printing_and_pdf) @@ -850,8 +857,8 @@ gpu::SyncPointManager *WebEngineContext::syncPointManager() return spm; QMutexLocker lock(&s_spmMutex); if (!s_syncPointManager) - s_syncPointManager.store(new gpu::SyncPointManager()); - return s_syncPointManager.load(); + s_syncPointManager.storeRelaxed(new gpu::SyncPointManager()); + return s_syncPointManager.loadRelaxed(); } base::CommandLine* WebEngineContext::commandLine() { |