diff --git a/krita/main.cc b/krita/main.cc index 38971b80b1..ca43acecd3 100644 --- a/krita/main.cc +++ b/krita/main.cc @@ -1,467 +1,478 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2015 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050900 #include #endif #include #include #include #include #include #include "data/splash/splash_screen.xpm" #include "data/splash/splash_holidays.xpm" #include "data/splash/splash_screen_x2.xpm" #include "data/splash/splash_holidays_x2.xpm" #include "KisDocument.h" #include "kis_splash_screen.h" #include "KisPart.h" #include "KisApplicationArguments.h" #include #include "input/KisQtWidgetsTweaker.h" #if defined Q_OS_WIN #include #include #include #include #elif defined HAVE_X11 #include "config_use_qt_xcb.h" #ifndef USE_QT_XCB #include #endif #endif #if defined HAVE_KCRASH #include #elif defined USE_DRMINGW namespace { void tryInitDrMingw() { wchar_t path[MAX_PATH]; QString pathStr = QCoreApplication::applicationDirPath().replace(L'/', L'\\') + QStringLiteral("\\exchndl.dll"); if (pathStr.size() > MAX_PATH - 1) { return; } int pathLen = pathStr.toWCharArray(path); path[pathLen] = L'\0'; // toWCharArray doesn't add NULL terminator HMODULE hMod = LoadLibraryW(path); if (!hMod) { return; } // No need to call ExcHndlInit since the crash handler is installed on DllMain auto myExcHndlSetLogFileNameA = reinterpret_cast(GetProcAddress(hMod, "ExcHndlSetLogFileNameA")); if (!myExcHndlSetLogFileNameA) { return; } // Set the log file path to %LocalAppData%\kritacrash.log QString logFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation).replace(L'/', L'\\') + QStringLiteral("\\kritacrash.log"); myExcHndlSetLogFileNameA(logFile.toLocal8Bit()); } typedef enum ORIENTATION_PREFERENCE { ORIENTATION_PREFERENCE_NONE = 0x0, ORIENTATION_PREFERENCE_LANDSCAPE = 0x1, ORIENTATION_PREFERENCE_PORTRAIT = 0x2, ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED = 0x4, ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED = 0x8 } ORIENTATION_PREFERENCE; typedef BOOL WINAPI (*pSetDisplayAutoRotationPreferences_t)( ORIENTATION_PREFERENCE orientation ); void resetRotation() { QLibrary user32Lib("user32"); if (!user32Lib.load()) { qWarning() << "Failed to load user32.dll! This really should not happen."; return; } pSetDisplayAutoRotationPreferences_t pSetDisplayAutoRotationPreferences = reinterpret_cast(user32Lib.resolve("SetDisplayAutoRotationPreferences")); if (!pSetDisplayAutoRotationPreferences) { dbgKrita << "Failed to load function SetDisplayAutoRotationPreferences"; return; } bool result = pSetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE); dbgKrita << "SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE) returned" << result; } } // namespace #endif extern "C" int main(int argc, char **argv) { // The global initialization of the random generator qsrand(time(0)); bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty(); #if defined HAVE_X11 qputenv("QT_QPA_PLATFORM", "xcb"); #endif // Workaround a bug in QNetworkManager qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1)); // A per-user unique string, without /, because QLocalServer cannot use names with a / in it QString key = "Krita4" + QStandardPaths::writableLocation(QStandardPaths::HomeLocation).replace("/", "_"); key = key.replace(":", "_").replace("\\","_"); QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #if QT_VERSION >= 0x050900 QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache, true); #endif const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); bool singleApplication = true; bool enableOpenGLDebug = false; bool openGLDebugSynchronous = false; { QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); singleApplication = kritarc.value("EnableSingleApplication", true).toBool(); #if QT_VERSION >= 0x050600 if (kritarc.value("EnableHiDPI", true).toBool()) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } if (!qgetenv("KRITA_HIDPI").isEmpty()) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } #endif if (!qgetenv("KRITA_OPENGL_DEBUG").isEmpty()) { enableOpenGLDebug = true; } else { enableOpenGLDebug = kritarc.value("EnableOpenGLDebug", false).toBool(); } if (enableOpenGLDebug && (qgetenv("KRITA_OPENGL_DEBUG") == "sync" || kritarc.value("OpenGLDebugSynchronous", false).toBool())) { openGLDebugSynchronous = true; } - KisOpenGL::setDefaultFormat(enableOpenGLDebug, openGLDebugSynchronous, &kritarc); + KisConfig::RootSurfaceFormat rootSurfaceFormat = KisConfig::rootSurfaceFormat(&kritarc); + KisOpenGL::OpenGLRenderer preferredRenderer = KisOpenGL::RendererAuto; #ifdef Q_OS_WIN - QString preferredOpenGLRenderer = kritarc.value("OpenGLRenderer", "auto").toString(); + const QString preferredRendererString = kritarc.value("OpenGLRenderer", "auto").toString(); + preferredRenderer = KisOpenGL::convertConfigToOpenGLRenderer(preferredRendererString); // Force ANGLE to use Direct3D11. D3D9 doesn't support OpenGL ES 3 and WARP // might get weird crashes atm. qputenv("QT_ANGLE_PLATFORM", "d3d11"); +#endif - // Probe QPA auto OpenGL detection - char *fakeArgv[2] = { argv[0], nullptr }; // Prevents QCoreApplication from modifying the real argc/argv - KisOpenGL::probeWindowsQpaOpenGL(1, fakeArgv, preferredOpenGLRenderer); + const QSurfaceFormat format = + KisOpenGL::selectSurfaceFormat(preferredRenderer, rootSurfaceFormat, enableOpenGLDebug); + if (format.renderableType() == QSurfaceFormat::OpenGLES) { + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true); + } else { + QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true); + } + KisOpenGL::setDefaultSurfaceFormat(format); + KisOpenGL::setDebugSynchronous(openGLDebugSynchronous); + +#ifdef Q_OS_WIN // HACK: https://bugs.kde.org/show_bug.cgi?id=390651 resetRotation(); #endif } QString root; QString language; { // Create a temporary application to get the root QCoreApplication app(argc, argv); Q_UNUSED(app); root = KoResourcePaths::getApplicationRoot(); QSettings languageoverride(configPath + QStringLiteral("/klanguageoverridesrc"), QSettings::IniFormat); languageoverride.beginGroup(QStringLiteral("Language")); language = languageoverride.value(qAppName(), "").toString(); } #ifdef Q_OS_LINUX { QByteArray originalXdgDataDirs = qgetenv("XDG_DATA_DIRS"); if (originalXdgDataDirs.isEmpty()) { // We don't want to completely override the default originalXdgDataDirs = "/usr/local/share/:/usr/share/"; } qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share") + ":" + originalXdgDataDirs); } #else qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share")); #endif dbgKrita << "Setting XDG_DATA_DIRS" << qgetenv("XDG_DATA_DIRS"); // Now that the paths are set, set the language. First check the override from the language // selection dialog. dbgKrita << "Override language:" << language; bool rightToLeft = false; if (!language.isEmpty()) { KLocalizedString::setLanguages(language.split(":")); // And override Qt's locale, too qputenv("LANG", language.split(":").first().toLocal8Bit()); QLocale locale(language.split(":").first()); QLocale::setDefault(locale); const QStringList rtlLanguages = QStringList() << "ar" << "dv" << "he" << "ha" << "ku" << "fa" << "ps" << "ur" << "yi"; if (rtlLanguages.contains(language.split(':').first())) { rightToLeft = true; } } else { dbgKrita << "Qt UI languages:" << QLocale::system().uiLanguages() << qgetenv("LANG"); // And if there isn't one, check the one set by the system. QLocale locale = QLocale::system(); if (locale.name() != QStringLiteral("en")) { QStringList uiLanguages = locale.uiLanguages(); for (QString &uiLanguage : uiLanguages) { // This list of language codes that can have a specifier should // be extended whenever we have translations that need it; right // now, only en, pt, zh are in this situation. if (uiLanguage.startsWith("en") || uiLanguage.startsWith("pt")) { uiLanguage.replace(QChar('-'), QChar('_')); } else if (uiLanguage.startsWith("zh-Hant") || uiLanguage.startsWith("zh-TW")) { uiLanguage = "zh_TW"; } else if (uiLanguage.startsWith("zh-Hans") || uiLanguage.startsWith("zh-CN")) { uiLanguage = "zh_CN"; } } for (int i = 0; i < uiLanguages.size(); i++) { QString uiLanguage = uiLanguages[i]; // Strip the country code int idx = uiLanguage.indexOf(QChar('-')); if (idx != -1) { uiLanguage = uiLanguage.left(idx); uiLanguages.replace(i, uiLanguage); } } dbgKrita << "Converted ui languages:" << uiLanguages; qputenv("LANG", uiLanguages.first().toLocal8Bit()); #ifdef Q_OS_MAC // See https://bugs.kde.org/show_bug.cgi?id=396370 KLocalizedString::setLanguages(QStringList() << uiLanguages.first()); #else KLocalizedString::setLanguages(QStringList() << uiLanguages); #endif } } // first create the application so we can create a pixmap KisApplication app(key, argc, argv); if (!language.isEmpty()) { if (rightToLeft) { app.setLayoutDirection(Qt::RightToLeft); } else { app.setLayoutDirection(Qt::LeftToRight); } } KLocalizedString::setApplicationDomain("krita"); dbgKrita << "Available translations" << KLocalizedString::availableApplicationTranslations(); dbgKrita << "Available domain translations" << KLocalizedString::availableDomainTranslations("krita"); #ifdef Q_OS_WIN QDir appdir(KoResourcePaths::getApplicationRoot()); QString path = qgetenv("PATH"); qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";" + appdir.absolutePath() + "/lib" + ";" + appdir.absolutePath() + "/Frameworks" + ";" + appdir.absolutePath() + ";" + path)); dbgKrita << "PATH" << qgetenv("PATH"); #endif if (qApp->applicationDirPath().contains(KRITA_BUILD_DIR)) { qFatal("FATAL: You're trying to run krita from the build location. You can only run Krita from the installation location."); } #if defined HAVE_KCRASH KCrash::initialize(); #elif defined USE_DRMINGW tryInitDrMingw(); #endif // If we should clear the config, it has to be done as soon as possible after // KisApplication has been created. Otherwise the config file may have been read // and stored in a KConfig object we have no control over. app.askClearConfig(); KisApplicationArguments args(app); if (singleApplication && app.isRunning()) { // only pass arguments to main instance if they are not for batch processing // any batch processing would be done in this separate instance const bool batchRun = args.exportAs(); if (!batchRun) { QByteArray ba = args.serialize(); if (app.sendMessage(ba)) { return 0; } } } if (!runningInKDE) { // Icons in menus are ugly and distracting app.setAttribute(Qt::AA_DontShowIconsInMenus); } #if defined HAVE_X11 #ifndef USE_QT_XCB app.installNativeEventFilter(KisXi2EventFilter::instance()); #endif #endif app.installEventFilter(KisQtWidgetsTweaker::instance()); if (!args.noSplash()) { // then create the pixmap from an xpm: we cannot get the // location of our datadir before we've started our components, // so use an xpm. QDate currentDate = QDate::currentDate(); QWidget *splash = 0; if (currentDate > QDate(currentDate.year(), 12, 4) || currentDate < QDate(currentDate.year(), 1, 9)) { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm), QPixmap(splash_holidays_x2_xpm)); } else { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm), QPixmap(splash_screen_x2_xpm)); } app.setSplashScreen(splash); } #if defined Q_OS_WIN KisConfig cfg(false); bool supportedWindowsVersion = true; #if QT_VERSION >= 0x050900 QOperatingSystemVersion osVersion = QOperatingSystemVersion::current(); if (osVersion.type() == QOperatingSystemVersion::Windows) { if (osVersion.majorVersion() >= QOperatingSystemVersion::Windows7.majorVersion()) { supportedWindowsVersion = true; } else { supportedWindowsVersion = false; if (cfg.readEntry("WarnedAboutUnsupportedWindows", false)) { QMessageBox::information(0, i18nc("@title:window", "Krita: Warning"), i18n("You are running an unsupported version of Windows: %1.\n" "This is not recommended. Do not report any bugs.\n" "Please update to a supported version of Windows: Windows 7, 8, 8.1 or 10.", osVersion.name())); cfg.writeEntry("WarnedAboutUnsupportedWindows", true); } } } #endif { if (cfg.useWin8PointerInput() && !KisTabletSupportWin8::isAvailable()) { cfg.setUseWin8PointerInput(false); } if (!cfg.useWin8PointerInput()) { bool hasWinTab = KisTabletSupportWin::init(); if (!hasWinTab && supportedWindowsVersion) { if (KisTabletSupportWin8::isPenDeviceAvailable()) { // Use WinInk automatically cfg.setUseWin8PointerInput(true); } else if (!cfg.readEntry("WarnedAboutMissingWinTab", false)) { if (KisTabletSupportWin8::isAvailable()) { QMessageBox::information(nullptr, i18n("Krita Tablet Support"), i18n("Cannot load WinTab driver and no Windows Ink pen devices are found. If you have a drawing tablet, please make sure the tablet driver is properly installed."), QMessageBox::Ok, QMessageBox::Ok); } else { QMessageBox::information(nullptr, i18n("Krita Tablet Support"), i18n("Cannot load WinTab driver. If you have a drawing tablet, please make sure the tablet driver is properly installed."), QMessageBox::Ok, QMessageBox::Ok); } cfg.writeEntry("WarnedAboutMissingWinTab", true); } } } if (cfg.useWin8PointerInput()) { KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8(); if (penFilter->init()) { // penFilter.registerPointerDeviceNotifications(); app.installNativeEventFilter(penFilter); dbgKrita << "Using Win8 Pointer Input for tablet support"; } else { dbgKrita << "No Win8 Pointer Input available"; delete penFilter; } } } #endif if (!app.start(args)) { return 1; } #if QT_VERSION >= 0x050700 app.setAttribute(Qt::AA_CompressHighFrequencyEvents, false); #endif // Set up remote arguments. QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)), &app, SLOT(remoteArguments(QByteArray,QObject*))); QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), &app, SLOT(fileOpenRequested(QString))); int state = app.exec(); { QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("canvasState", "OPENGL_SUCCESS"); } return state; } diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 8e78c73c17..5ed17e893b 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,597 +1,596 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) find_library(APPKIT_LIBRARY AppKit) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp canvas/KisSnapPointStrategy.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_stroke_selection_properties.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp dialogs/kis_delayed_save_dialog.cpp dialogs/KisSessionManagerDialog.cpp dialogs/KisNewWindowLayoutDialog.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp brushhud/kis_uniform_paintop_property_widget.cpp brushhud/kis_brush_hud.cpp brushhud/kis_round_hud_button.cpp brushhud/kis_dlg_brush_hud_config.cpp brushhud/kis_brush_hud_properties_list.cpp brushhud/kis_brush_hud_properties_config.cpp kis_aspect_ratio_locker.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc KisPaintopPropertiesBase.cpp kis_canvas_resource_provider.cpp kis_derived_resources.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc KisOcioConfiguration.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_cursor_cache.cpp kis_custom_pattern.cc kis_file_layer.cpp kis_change_file_layer_command.h kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc KisImageBarrierLockerWithFeedback.cpp kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp KisNodeDisplayModeAdapter.cpp kis_node_model.cpp kis_node_filter_proxy_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp KisDecorationsManager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp KisResourceServerProvider.cpp KisResourceBundleServerProvider.cpp KisSelectedShapesProxy.cpp kis_selection_decoration.cc kis_selection_manager.cc KisSelectionActionsAdapter.cpp kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp KisActionPlugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_stopgradient_editor.cpp KisWelcomePageWidget.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_canvas_debugger.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp opengl/kis_opengl_shader_loader.cpp opengl/kis_texture_tile_info_pool.cpp opengl/KisOpenGLUpdateInfoBuilder.cpp opengl/KisOpenGLModeProber.cpp opengl/KisScreenInformationAdapter.cpp kis_fps_decoration.cpp tool/KisToolChangesTracker.cpp tool/KisToolChangesTrackerData.cpp tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_stabilized_events_sampler.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/KisStabilizerDelayedPaintHelper.cpp tool/KisStrokeSpeedMonitor.cpp tool/strokes/freehand_stroke.cpp tool/strokes/KisStrokeEfficiencyMeasurer.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp tool/strokes/KisFreehandStrokeInfo.cpp tool/strokes/KisMaskedFreehandStrokePainter.cpp tool/strokes/KisMaskingBrushRenderer.cpp tool/strokes/KisMaskingBrushCompositeOpFactory.cpp tool/strokes/move_stroke_strategy.cpp tool/KisSelectionToolFactoryBase.cpp tool/KisToolPaintFactoryBase.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_advanced_color_space_selector.cc widgets/kis_cie_tongue_widget.cpp widgets/kis_tone_curve_widget.cpp widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_paintop_presets_save.cpp widgets/kis_paintop_preset_icon_library.cpp widgets/kis_pattern_chooser.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_slider_spin_box.cpp widgets/KisSelectionPropertySlider.cpp widgets/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp widgets/kis_lod_availability_widget.cpp widgets/kis_color_label_selector_widget.cpp widgets/kis_color_filter_combo.cpp widgets/kis_elided_label.cpp widgets/kis_stopgradient_slider_widget.cpp widgets/kis_preset_live_preview_view.cpp widgets/KisScreenColorPicker.cpp widgets/KoDualColorButton.cpp widgets/KoStrokeConfigWidget.cpp widgets/KoFillConfigWidget.cpp KisPaletteEditor.cpp dialogs/KisDlgPaletteEditor.cpp widgets/KisNewsWidget.cpp widgets/KisGamutMaskToolbar.cpp utils/kis_document_aware_spin_box_unit_manager.cpp input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_native_gesture_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp input/KisQtWidgetsTweaker.cpp input/KisInputActionGroup.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp actions/KisPasteActionFactory.cpp actions/KisTransformToolActivationCommand.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisCloneDocumentStroke.cpp KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisImportExportFilter.cpp KisFilterEntry.cpp KisImportExportManager.cpp KisImportExportUtils.cpp kis_async_action_feedback.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoActionsUpdateManager.cpp KisView.cpp thememanager.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp KisResourceBundle.cpp KisResourceBundleManifest.cpp kis_md5_generator.cpp KisApplicationArguments.cpp KisNetworkAccessManager.cpp KisMultiFeedRSSModel.cpp KisRemoteFileFetcher.cpp KisSaveGroupVisitor.cpp KisWindowLayoutResource.cpp KisWindowLayoutManager.cpp KisSessionResource.cpp KisReferenceImagesDecoration.cpp KisReferenceImage.cpp flake/KisReferenceImagesLayer.cpp flake/KisReferenceImagesLayer.h ) if(WIN32) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp input/wintab/kis_tablet_support_win8.cpp - opengl/kis_opengl_win.cpp ) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp KisAsyncAnimationRendererBase.cpp KisAsyncAnimationCacheRenderer.cpp KisAsyncAnimationFramesSavingRenderer.cpp dialogs/KisAsyncAnimationRenderDialogBase.cpp dialogs/KisAsyncAnimationCacheRenderDialog.cpp dialogs/KisAsyncAnimationFramesSaveDialog.cpp canvas/kis_animation_player.cpp kis_animation_importer.cpp KisSyncedAudioPlayback.cpp KisFrameDataSerializer.cpp KisFrameCacheStore.cpp KisFrameCacheSwapper.cpp KisAbstractFrameCacheSwapper.cpp KisInMemoryFrameCacheSwapper.cpp input/wintab/drawpile_tablettester/tablettester.cpp input/wintab/drawpile_tablettester/tablettest.cpp ) if (UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} qtlockedfile/qtlockedfile_unix.cpp ) if(NOT USE_QT_XCB) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support.cpp ) endif() if(NOT APPLE AND NOT USE_QT_XCB) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() if(APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} osx.mm ) endif() ki18n_wrap_ui(kritaui_LIB_SRCS widgets/KoFillConfigWidget.ui widgets/KoStrokeConfigWidget.ui forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgsavebrushpreset.ui forms/wdgpreseticonlibrary.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/wdgstrokeselectionproperties.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui forms/wdgstopgradienteditor.ui forms/wdgsessionmanager.ui forms/wdgnewwindowlayout.ui forms/KisWelcomePage.ui forms/WdgDlgPaletteEditor.ui forms/KisNewsPage.ui forms/wdgGamutMaskToolbar.ui brushhud/kis_dlg_brush_hud_config.ui dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui input/wintab/drawpile_tablettester/tablettest.ui ) QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h) add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} ) generate_export_header(kritaui BASE_NAME kritaui) target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_QT_MULTIMEDIA) target_link_libraries(kritaui Qt5::Multimedia) endif() if (NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${X11_X11_LIB} ${X11_Xinput_LIB} ${XCB_LIBRARIES}) endif() if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) target_link_libraries(kritaui ${APPKIT_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() target_include_directories(kritaui PUBLIC $ $ $ $ $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc index 1ec8887846..eea61e117e 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -1,1550 +1,1553 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoID.h" #include #include #include #include #include #include #include "kis_action_registry.h" #include #include #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorConversionTransformation.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_color_manager.h" #include "KisProofingConfiguration.h" #include "kis_image_config.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include #include "input/config/kis_input_configuration_page.h" #include "input/wintab/drawpile_tablettester/tablettester.h" #ifdef Q_OS_WIN # include #endif GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg(true); // // Cursor Tab // m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbCursorShape->addItem(i18n("Black Pixel")); m_cmbCursorShape->addItem(i18n("White Pixel")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline()); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor()); cursorColorBtutton->setColor(cursorColor); // // Window Tab // m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor()); m_mdiColor->setColor(mdiColor); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); m_chkHiDPI->setChecked(kritarc.value("EnableHiDPI", true).toBool()); m_chkSingleApplication->setChecked(kritarc.value("EnableSingleApplication", true).toBool()); // // Tools tab // m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas()); chkEnableTranformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste()); m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled()); m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag")); m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag")); m_cmbKineticScrollingGesture->addItem(i18n("On Middle-Click Drag")); //m_cmbKineticScrollingGesture->addItem(i18n("On Right Click Drag")); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture()); m_kineticScrollingSensitivitySlider->setRange(0, 100); m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity()); m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars()); // // Miscellaneous // cmbStartupSession->addItem(i18n("Open default window")); cmbStartupSession->addItem(i18n("Load previous session")); cmbStartupSession->addItem(i18n("Show session manager")); cmbStartupSession->setCurrentIndex(cfg.sessionOnStartup()); chkSaveSessionOnQuit->setChecked(cfg.saveSessionOnQuit(false)); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_chkCompressKra->setChecked(cfg.compressKra()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); m_undoStackSize->setValue(cfg.undoStackLimit()); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); chkShowRootLayer->setChecked(cfg.showRootLayer()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); bool dontUseNative = true; #ifdef Q_OS_UNIX if (qgetenv("XDG_CURRENT_DESKTOP") == "KDE") { dontUseNative = false; } #endif #ifdef Q_OS_WIN dontUseNative = false; #endif m_chkNativeFileDialog->setChecked(!group.readEntry("DontUseNativeFileDialog", dontUseNative)); intMaxBrushSize->setValue(cfg.readEntry("maximumBrushSize", 1000)); } void GeneralTab::setDefault() { KisConfig cfg(true); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline(true)); m_chkNativeFileDialog->setChecked(false); intMaxBrushSize->setValue(1000); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor(true)); m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_chkHiDPI->setChecked(false); m_chkSingleApplication->setChecked(true); m_chkHiDPI->setChecked(true); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled(true)); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true)); m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity(true)); m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true)); chkEnableTranformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor(true)); cursorColorBtutton->setColor(cursorColor); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } KisConfig::SessionOnStartup GeneralTab::sessionOnStartup() const { return (KisConfig::SessionOnStartup)cmbStartupSession->currentIndex(); } bool GeneralTab::saveSessionOnQuit() const { return chkSaveSessionOnQuit->isChecked(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value() * 60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } bool GeneralTab::kineticScrollingEnabled() { return m_groupBoxKineticScrollingSettings->isChecked(); } int GeneralTab::kineticScrollingGesture() { return m_cmbKineticScrollingGesture->currentIndex(); } int GeneralTab::kineticScrollingSensitivity() { return m_kineticScrollingSensitivitySlider->value(); } bool GeneralTab::kineticScrollingHiddenScrollbars() { return m_chkKineticScrollingHideScrollbars->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); } bool GeneralTab::convertToImageColorspaceOnImport() { return m_chkConvertOnImport->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.filename(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } #include "kactioncollection.h" #include "KisActionsSnapshot.h" ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgShortcutSettings(this); l->addWidget(m_page, 0, 0); m_snapshot.reset(new KisActionsSnapshot); KActionCollection *collection = KisPart::instance()->currentMainwindow()->actionCollection(); Q_FOREACH (QAction *action, collection->actions()) { m_snapshot->addAction(action->objectName(), action); } QMap sortedCollections = m_snapshot->actionCollections(); for (auto it = sortedCollections.constBegin(); it != sortedCollections.constEnd(); ++it) { m_page->addCollection(it.value(), it.key()); } } ShortcutSettingsTab::~ShortcutSettingsTab() { } void ShortcutSettingsTab::setDefault() { m_page->allDefault(); } void ShortcutSettingsTab::saveChanges() { m_page->save(); KisActionRegistry::instance()->settingsPageSaved(); } void ShortcutSettingsTab::cancelChanges() { m_page->undo(); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg(true); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); QFormLayout *monitorProfileGrid = new QFormLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); cmb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); monitorProfileGrid->addRow(lbl, cmb); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors()); KisImageConfig cfgImage(true); KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel, proofingConfig->proofingDepth, proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); } void ColorSettingsTab::installProfile() { KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile"); QStringList profileNames = dialog.filenames(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KoResourcePaths::saveLocation("icc_profiles"); Q_FOREACH (const QString &profileName, profileNames) { if (!QFile::copy(profileName, saveLocation + QFileInfo(profileName).fileName())) { qWarning() << "Could not install profile!" << saveLocation + QFileInfo(profileName).fileName(); continue; } iccEngine->addProfile(saveLocation + QFileInfo(profileName).fileName()); } KisConfig cfg(true); refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { KisConfig cfg(true); if (useSystemProfile) { QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); Q_FOREACH (const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); refillMonitorProfiles(KoID("RGBA")); KisConfig cfg(true); KisImageConfig cfgImage(true); KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_page->sldAdaptationState->setValue(0); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & colorSpaceId) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } QMap profileList; Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(colorSpaceId.id())) { profileList[profile->name()] = profile; } Q_FOREACH (const KoColorProfile *profile, profileList.values()) { //qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId.id())); } } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { KisConfig cfg(true); m_page->radioWintab->setChecked(!cfg.useWin8PointerInput(true)); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput(true)); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); } #endif } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg(true); KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { m_page->radioWintab->setChecked(!cfg.useWin8PointerInput()); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput()); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); m_page->grpTabletApi->setVisible(false); } #else m_page->grpTabletApi->setVisible(false); #endif connect(m_page->btnTabletTest, SIGNAL(clicked()), SLOT(slotTabletTest())); } void TabletSettingsTab::slotTabletTest() { TabletTestDialog tabletTestDialog(this); tabletTestDialog.exec(); } //--------------------------------------------------------------------------------------------------- #include "kis_acyclic_signal_connector.h" int getTotalRAM() { return KisImageConfig(true).totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg(true); const double totalRAM = cfg.totalRAM(); lblTotalMemory->setText(KFormat().formatByteSize(totalRAM * 1024 * 1024, 0, KFormat::IECBinaryDialect, KFormat::UnitMegaByte)); sliderMemoryLimit->setSuffix(i18n(" %")); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(i18n(" %")); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(i18n(" %")); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, std::bind(&KisIntParseSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, std::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); sliderThreadsLimit->setRange(1, QThread::idealThreadCount()); sliderFrameClonesLimit->setRange(1, QThread::idealThreadCount()); sliderFpsLimit->setRange(20, 100); sliderFpsLimit->setSuffix(i18n(" fps")); connect(sliderThreadsLimit, SIGNAL(valueChanged(int)), SLOT(slotThreadsLimitChanged(int))); connect(sliderFrameClonesLimit, SIGNAL(valueChanged(int)), SLOT(slotFrameClonesLimitChanged(int))); intCachedFramesSizeLimit->setRange(1, 10000); intCachedFramesSizeLimit->setSuffix(i18n(" px")); intCachedFramesSizeLimit->setSingleStep(1); intCachedFramesSizeLimit->setPageStep(1000); intRegionOfInterestMargin->setRange(1, 100); intRegionOfInterestMargin->setSuffix(i18n(" %")); intRegionOfInterestMargin->setSingleStep(1); intRegionOfInterestMargin->setPageStep(10); connect(chkCachedFramesSizeLimit, SIGNAL(toggled(bool)), intCachedFramesSizeLimit, SLOT(setEnabled(bool))); connect(chkUseRegionOfInterest, SIGNAL(toggled(bool)), intRegionOfInterestMargin, SLOT(setEnabled(bool))); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg(true); sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); m_lastUsedThreadsLimit = cfg.maxNumberOfThreads(requestDefault); m_lastUsedClonesLimit = cfg.frameRenderingClones(requestDefault); sliderThreadsLimit->setValue(m_lastUsedThreadsLimit); sliderFrameClonesLimit->setValue(m_lastUsedClonesLimit); sliderFpsLimit->setValue(cfg.fpsLimit(requestDefault)); { KisConfig cfg2(true); chkOpenGLFramerateLogging->setChecked(cfg2.enableOpenGLFramerateLogging(requestDefault)); chkBrushSpeedLogging->setChecked(cfg2.enableBrushSpeedLogging(requestDefault)); chkDisableVectorOptimizations->setChecked(cfg2.enableAmdVectorizationWorkaround(requestDefault)); chkBackgroundCacheGeneration->setChecked(cfg2.calculateAnimationCacheInBackground(requestDefault)); } if (cfg.useOnDiskAnimationCacheSwapping(requestDefault)) { optOnDisk->setChecked(true); } else { optInMemory->setChecked(true); } chkCachedFramesSizeLimit->setChecked(cfg.useAnimationCacheFrameSizeLimit(requestDefault)); intCachedFramesSizeLimit->setValue(cfg.animationCacheFrameSizeLimit(requestDefault)); intCachedFramesSizeLimit->setEnabled(chkCachedFramesSizeLimit->isChecked()); chkUseRegionOfInterest->setChecked(cfg.useAnimationCacheRegionOfInterest(requestDefault)); intRegionOfInterestMargin->setValue(cfg.animationCacheRegionOfInterestMargin(requestDefault) * 100.0); intRegionOfInterestMargin->setEnabled(chkUseRegionOfInterest->isChecked()); } void PerformanceTab::save() { KisImageConfig cfg(false); cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setEnableProgressReporting(chkProgressReporting->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); cfg.setMaxNumberOfThreads(sliderThreadsLimit->value()); cfg.setFrameRenderingClones(sliderFrameClonesLimit->value()); cfg.setFpsLimit(sliderFpsLimit->value()); { KisConfig cfg2(true); cfg2.setEnableOpenGLFramerateLogging(chkOpenGLFramerateLogging->isChecked()); cfg2.setEnableBrushSpeedLogging(chkBrushSpeedLogging->isChecked()); cfg2.setEnableAmdVectorizationWorkaround(chkDisableVectorOptimizations->isChecked()); cfg2.setCalculateAnimationCacheInBackground(chkBackgroundCacheGeneration->isChecked()); } cfg.setUseOnDiskAnimationCacheSwapping(optOnDisk->isChecked()); cfg.setUseAnimationCacheFrameSizeLimit(chkCachedFramesSizeLimit->isChecked()); cfg.setAnimationCacheFrameSizeLimit(intCachedFramesSizeLimit->value()); cfg.setUseAnimationCacheRegionOfInterest(chkUseRegionOfInterest->isChecked()); cfg.setAnimationCacheRegionOfInterestMargin(intRegionOfInterestMargin->value() / 100.0); } void PerformanceTab::selectSwapDir() { KisImageConfig cfg(true); QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); if (swapDir.isEmpty()) { return; } lblSwapFileLocation->setText(swapDir); } void PerformanceTab::slotThreadsLimitChanged(int value) { KisSignalsBlocker b(sliderFrameClonesLimit); sliderFrameClonesLimit->setValue(qMin(m_lastUsedClonesLimit, value)); m_lastUsedThreadsLimit = value; } void PerformanceTab::slotFrameClonesLimitChanged(int value) { KisSignalsBlocker b(sliderThreadsLimit); sliderThreadsLimit->setValue(qMax(m_lastUsedThreadsLimit, value)); m_lastUsedClonesLimit = value; } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" #include "opengl/KisOpenGLModeProber.h" #include "opengl/KisScreenInformationAdapter.h" #include #include QString colorSpaceString(QSurfaceFormat::ColorSpace cs, int depth) { const QString csString = cs == QSurfaceFormat::bt2020PQColorSpace ? "Rec. 2020 PQ" : cs == QSurfaceFormat::scRGBColorSpace ? "Rec. 709 Linear" : cs == QSurfaceFormat::sRGBColorSpace ? "sRGB" : cs == QSurfaceFormat::DefaultColorSpace ? "sRGB" : "Unknown Color Space"; return QString("%1 (%2 bit)").arg(csString).arg(depth); } int formatToIndex(KisConfig::RootSurfaceFormat fmt) { return fmt == KisConfig::BT2020_PQ ? 1 : fmt == KisConfig::BT709_G10 ? 2 : 0; } KisConfig::RootSurfaceFormat indexToFormat(int value) { return value == 1 ? KisConfig::BT2020_PQ : value == 2 ? KisConfig::BT709_G10 : KisConfig::BT709_G22; } DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg(true); const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL"); #ifdef Q_OS_WIN const QString rendererAngleText = i18nc("canvas renderer", "Direct3D 11 via ANGLE"); - cmbRenderer->clear(); + + lblCurrentRenderer->setText(KisOpenGL::hasOpenGLES() ? rendererAngleText : rendererOpenGLText); + + cmbPreferredRenderer->clear(); QString qtPreferredRendererText; - if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererAngle) { + if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererOpenGLES) { qtPreferredRendererText = rendererAngleText; } else { qtPreferredRendererText = rendererOpenGLText; } - cmbRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto); - cmbRenderer->setCurrentIndex(0); + cmbPreferredRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto); + cmbPreferredRenderer->setCurrentIndex(0); if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererDesktopGL) { - cmbRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL); - if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererDesktopGL) { - cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); + cmbPreferredRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL); + if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererDesktopGL) { + cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1); } } - if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererAngle) { - cmbRenderer->addItem(rendererAngleText, KisOpenGL::RendererAngle); - if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererAngle) { - cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); + if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererOpenGLES) { + cmbPreferredRenderer->addItem(rendererAngleText, KisOpenGL::RendererOpenGLES); + if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererOpenGLES) { + cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1); } } #else - lblRenderer->setEnabled(false); - cmbRenderer->setEnabled(false); - cmbRenderer->clear(); - cmbRenderer->addItem(rendererOpenGLText); - cmbRenderer->setCurrentIndex(0); + lblPreferredRenderer->setEnabled(false); + cmbPreferredRenderer->setEnabled(false); + cmbPreferredRenderer->clear(); + cmbPreferredRenderer->addItem(rendererOpenGLText); + cmbPreferredRenderer->setCurrentIndex(0); + + const QString rendererOpenGLESText = i18nc("canvas renderer", "OpenGL ES"); + lblCurrentRenderer->setText(KisOpenGL::hasOpenGLES() ? rendererOpenGLESText : rendererOpenGLText); #endif #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & - (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { + (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererOpenGLES))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsLoD()) { cmbFilterMode->removeItem(3); } } lblCurrentDisplayFormat->setText(""); lblCurrentRootSurfaceFormat->setText(""); lblHDRWarning->setText(""); cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::sRGBColorSpace, 8)); cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::bt2020PQColorSpace, 10)); cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::scRGBColorSpace, 16)); cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22)); slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); QOpenGLContext *context = QOpenGLContext::currentContext(); if (context) { QScreen *screen = QGuiApplication::screenAt(rect().center()); KisScreenInformationAdapter adapter(context); if (screen && adapter.isValid()) { KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen); if (info.isValid()) { QStringList toolTip; toolTip << i18n("Display Id: %1", info.screen->name()); toolTip << i18n("Display Name: %1 %2", info.screen->manufacturer(), info.screen->model()); toolTip << i18n("Min Luminance: %1", info.minLuminance); toolTip << i18n("Max Luminance: %1", info.maxLuminance); toolTip << i18n("Max Full Frame Luminance: %1", info.maxFullFrameLuminance); toolTip << i18n("Red Primary: %1, %2", info.redPrimary[0], info.redPrimary[1]); toolTip << i18n("Green Primary: %1, %2", info.greenPrimary[0], info.greenPrimary[1]); toolTip << i18n("Blue Primary: %1, %2", info.bluePrimary[0], info.bluePrimary[1]); toolTip << i18n("White Point: %1, %2", info.whitePoint[0], info.whitePoint[1]); lblCurrentDisplayFormat->setToolTip(toolTip.join('\n')); lblCurrentDisplayFormat->setText(colorSpaceString(info.colorSpace, info.bitsPerColor)); } else { lblCurrentDisplayFormat->setToolTip(""); lblCurrentDisplayFormat->setText(i18n("Unknown")); } - grpHDRSettings->setEnabled(info.isValid()); - - const QSurfaceFormat currentFormat = KisOpenGLModeProber::instance()->surfaceformatInUse(); - lblCurrentRootSurfaceFormat->setText(colorSpaceString(currentFormat.colorSpace(), currentFormat.redBufferSize())); - cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(cfg.rootSurfaceFormat())); - - connect(cmbPreferedRootSurfaceFormat, SIGNAL(currentIndexChanged(int)), SLOT(slotPreferredSurfaceFormatChanged(int))); - slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); } else { - grpHDRSettings->setEnabled(false); + lblCurrentDisplayFormat->setToolTip(""); + lblCurrentDisplayFormat->setText(i18n("Unknown")); } + + const QSurfaceFormat currentFormat = KisOpenGLModeProber::instance()->surfaceformatInUse(); + lblCurrentRootSurfaceFormat->setText(colorSpaceString(currentFormat.colorSpace(), currentFormat.redBufferSize())); + cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(cfg.rootSurfaceFormat())); + + connect(cmbPreferedRootSurfaceFormat, SIGNAL(currentIndexChanged(int)), SLOT(slotPreferredSurfaceFormatChanged(int))); + slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); } const QStringList openglWarnings = KisOpenGL::getOpenGLWarnings(); if (openglWarnings.isEmpty()) { lblOpenGLWarnings->setVisible(false); } else { QString text(" "); text.append(i18n("Warning(s):")); text.append("
    "); Q_FOREACH (const QString &warning, openglWarnings) { text.append("
  • "); text.append(warning.toHtmlEscaped()); text.append("
  • "); } text.append("
"); lblOpenGLWarnings->setText(text); lblOpenGLWarnings->setVisible(true); } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } KisImageConfig imageCfg(false); KoColor c; c.fromQColor(imageCfg.selectionOverlayMaskColor()); c.setOpacity(1.0); btnSelectionOverlayColor->setColor(c); sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2); sldSelectionOverlayOpacity->setSingleStep(0.05); sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor().alphaF()); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1()); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2()); colorChecks2->setColor(ck2); KoColor cb(KoColorSpaceRegistry::instance()->rgb8()); cb.fromQColor(cfg.canvasBorderColor()); canvasBorder->setColor(cb); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor()); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold() * 100); } void DisplaySettingsTab::setDefault() { KisConfig cfg(true); - cmbRenderer->setCurrentIndex(0); + cmbPreferredRenderer->setCurrentIndex(0); #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & - (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { + (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererOpenGLES))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1(true)); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2(true)); colorChecks2->setColor(ck2); KoColor cvb(KoColorSpaceRegistry::instance()->rgb8()); cvb.fromQColor(cfg.canvasBorderColor(true)); canvasBorder->setColor(cvb); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor(true)); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold(true) * 100); cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22)); slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { chkUseTextureBuffer->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); } void DisplaySettingsTab::slotPreferredSurfaceFormatChanged(int index) { Q_UNUSED(index); QOpenGLContext *context = QOpenGLContext::currentContext(); if (context) { QScreen *screen = QGuiApplication::screenAt(rect().center()); KisScreenInformationAdapter adapter(context); if (adapter.isValid()) { KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen); if (info.isValid()) { if (cmbPreferedRootSurfaceFormat->currentIndex() != formatToIndex(KisConfig::BT709_G22) && info.colorSpace == QSurfaceFormat::sRGBColorSpace) { lblHDRWarning->setText(i18n("WARNING: current display doesn't support HDR rendering")); } else { lblHDRWarning->setText(""); } } } } } //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg(true); chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg(true); chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setWindowTitle(i18n("Configure Krita")); setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); setFaceType(KPageDialog::Tree); // General KoVBox *vbox = new KoVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); page->setIcon(KisIconUtils::loadIcon("go-home")); m_pages << page; addPage(page); m_general = new GeneralTab(vbox); // Shortcuts vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts")); page->setObjectName("shortcuts"); page->setHeader(i18n("Shortcuts")); page->setIcon(KisIconUtils::loadIcon("document-export")); m_pages << page; addPage(page); m_shortcutSettings = new ShortcutSettingsTab(vbox); connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_shortcutSettings, SLOT(cancelChanges())); // Canvas input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); page->setIcon(KisIconUtils::loadIcon("configure")); m_pages << page; // Display vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); m_pages << page; addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); m_pages << page; addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); page->setIcon(KisIconUtils::loadIcon("applications-system")); m_pages << page; addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Tablet vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); page->setIcon(KisIconUtils::loadIcon("document-edit")); m_pages << page; addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); page->setIcon(KisIconUtils::loadIcon("folder-pictures")); m_pages << page; addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); page->setIcon(KisIconUtils::loadIcon("im-user")); m_pages << page; QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults); restoreDefaultsButton->setText(i18nc("@action:button", "Restore Defaults")); connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); Q_FOREACH (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KoVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault())); KisConfig cfg(true); QString currentPageName = cfg.readEntry("KisDlgPreferences/CurrentPage"); Q_FOREACH(KPageWidgetItem *page, m_pages) { if (page->objectName() == currentPageName) { setCurrentPage(page); break; } } } KisDlgPreferences::~KisDlgPreferences() { KisConfig cfg(true); cfg.writeEntry("KisDlgPreferences/CurrentPage", currentPage()->objectName()); } void KisDlgPreferences::showEvent(QShowEvent *event){ KPageDialog::showEvent(event); button(QDialogButtonBox::Cancel)->setAutoDefault(false); button(QDialogButtonBox::Ok)->setAutoDefault(false); button(QDialogButtonBox::RestoreDefaults)->setAutoDefault(false); button(QDialogButtonBox::Cancel)->setDefault(false); button(QDialogButtonBox::Ok)->setDefault(false); button(QDialogButtonBox::RestoreDefaults)->setDefault(false); } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "general") { m_general->setDefault(); } else if (currentPage()->objectName() == "shortcuts") { m_shortcutSettings->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg(false); cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setForceAlwaysFullSizedOutline(!dialog->m_general->m_changeBrushOutline->isChecked()); cfg.setSessionOnStartup(dialog->m_general->sessionOnStartup()); cfg.setSaveSessionOnQuit(dialog->m_general->saveSessionOnQuit()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); group.writeEntry("DontUseNativeFileDialog", !dialog->m_general->m_chkNativeFileDialog->isChecked()); cfg.writeEntry("maximumBrushSize", dialog->m_general->intMaxBrushSize->value()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color().toQColor()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("EnableHiDPI", dialog->m_general->m_chkHiDPI->isChecked()); kritarc.setValue("EnableSingleApplication", dialog->m_general->m_chkSingleApplication->isChecked()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); cfg.setKineticScrollingEnabled(dialog->m_general->kineticScrollingEnabled()); cfg.setKineticScrollingGesture(dialog->m_general->kineticScrollingGesture()); cfg.setKineticScrollingSensitivity(dialog->m_general->kineticScrollingSensitivity()); cfg.setKineticScrollingHideScrollbars(dialog->m_general->kineticScrollingHiddenScrollbars()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setDisableTouchOnCanvas(!dialog->m_general->chkEnableTouch->isChecked()); cfg.setActivateTransformToolAfterPaste(dialog->m_general->chkEnableTranformToolAfterPaste->isChecked()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); KisImageConfig cfgImage(false); cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_page->gamutAlarm->color(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setForcePaletteColors(dialog->m_colorSettings->m_page->chkForcePaletteColor->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { cfg.setUseWin8PointerInput(dialog->m_tabletSettings->m_page->radioWin8PointerInput->isChecked()); } #endif dialog->m_performanceSettings->save(); #ifdef Q_OS_WIN { KisOpenGL::OpenGLRenderer renderer = static_cast( - dialog->m_displaySettings->cmbRenderer->itemData( - dialog->m_displaySettings->cmbRenderer->currentIndex()).toInt()); - KisOpenGL::setNextUserOpenGLRendererConfig(renderer); - const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); - QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); - kritarc.setValue("OpenGLRenderer", KisOpenGL::convertOpenGLRendererToConfig(renderer)); + dialog->m_displaySettings->cmbPreferredRenderer->itemData( + dialog->m_displaySettings->cmbPreferredRenderer->currentIndex()).toInt()); + KisOpenGL::setUserPreferredOpenGLRendererConfig(renderer); } #endif if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); cfg.setRootSurfaceFormat(&kritarc, indexToFormat(dialog->m_displaySettings->cmbPreferedRootSurfaceFormat->currentIndex())); cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color().toQColor()); cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color().toQColor()); cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color().toQColor()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); KoColor c = dialog->m_displaySettings->btnSelectionOverlayColor->color(); c.setOpacity(dialog->m_displaySettings->sldSelectionOverlayOpacity->value()); cfgImage.setSelectionOverlayMaskColor(c.toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); cfg.setCursorMainColor(dialog->m_general->cursorColorBtutton->color().toQColor()); cfg.setPixelGridColor(dialog->m_displaySettings->pixelGridColorButton->color().toQColor()); cfg.setPixelGridDrawingThreshold(dialog->m_displaySettings->pixelGridDrawingThresholdBox->value() / 100); dialog->m_authorPage->apply(); } delete dialog; return baccept; } diff --git a/libs/ui/forms/wdgdisplaysettings.ui b/libs/ui/forms/wdgdisplaysettings.ui index 642c087abd..98488f3c91 100644 --- a/libs/ui/forms/wdgdisplaysettings.ui +++ b/libs/ui/forms/wdgdisplaysettings.ui @@ -1,538 +1,552 @@ WdgDisplaySettings 0 0 598 - 546 + 595 0 0 Display 15 0 0 Canvas &Graphics Acceleration true - - - - - 0 - 0 - - - - 0 - - - - Nearest Neighbour - - - - - Bilinear Filtering - - - - - Trilinear Filtering - - - - - High Quality Filtering - - - - - + 0 0 <html><head/><body><p>Try to disable vsync for Krita. This makes painting more responsive. Uncheck only when experiencing crashes with some GPU/driver combinations.</p></body></html> Disable vsync (needs restart) true - + 0 0 <html><head/><body><p>Use Texture Buffering. This can be faster on some GPU/Driver combinations (like Intel) or broken on some others (like AMD/Radeon).</p></body></html> Use texture buffer - + 0 0 Scaling Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + - + 0 0 - - Renderer (needs restart): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0 + + + Nearest Neighbour + + + + + Bilinear Filtering + + + + + Trilinear Filtering + + + + + High Quality Filtering + + - - + + 0 0 - + OpenGL Warnings Qt::RichText true + + + + + 0 + 0 + + + + Preferred Renderer (needs restart): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Unknown + + + + + + + Current Renderer: + + + HDR false Display Format: Current Display Format Current Output Format: Current Surface Value Preferred Output Format: HDR Warning.................................. 15 7 Si&ze: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intCheckSize px 256 32 Qt::Horizontal 40 20 Start showing at: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 % 9999.000000000000000 Qt::Horizontal 40 20 Opacity: 0 0 50 20 Pixel Grid: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Selection Overlay: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Transparency Checkerboard: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Canvas Border Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 20 0 10 Hide Window Scrollbars false Hide layer thumbnail popup Enable curve anti-aliasing Color channels in color false Enable selection outline anti-aliasing If checked, the checkers will move when scrolling the canvas. Determines whether the checks will stay put or whether they will scroll together with the canvas &Move checkers when scrolling true Qt::Vertical 20 40 KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisColorButton QPushButton
kis_color_button.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/libs/ui/opengl/KisOpenGLModeProber.cpp b/libs/ui/opengl/KisOpenGLModeProber.cpp index c95f89500a..9f39896952 100644 --- a/libs/ui/opengl/KisOpenGLModeProber.cpp +++ b/libs/ui/opengl/KisOpenGLModeProber.cpp @@ -1,89 +1,215 @@ #include "KisOpenGLModeProber.h" +#include +#include +#include +#include + #include Q_GLOBAL_STATIC(KisOpenGLModeProber, s_instance) KisOpenGLModeProber::KisOpenGLModeProber() { } KisOpenGLModeProber::~KisOpenGLModeProber() { } KisOpenGLModeProber *KisOpenGLModeProber::instance() { return s_instance; } bool KisOpenGLModeProber::useHDRMode() const { return isFormatHDR(QSurfaceFormat::defaultFormat()); } QSurfaceFormat KisOpenGLModeProber::surfaceformatInUse() const { - return QSurfaceFormat::defaultFormat(); + // TODO: use information provided by KisOpenGL instead + QOpenGLContext *sharedContext = QOpenGLContext::globalShareContext(); + QSurfaceFormat format = sharedContext ? sharedContext->format() : QSurfaceFormat::defaultFormat(); + return format; } const KoColorProfile *KisOpenGLModeProber::rootSurfaceColorProfile() const { const QSurfaceFormat::ColorSpace surfaceColorSpace = surfaceformatInUse().colorSpace(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->p709SRGBProfile(); if (surfaceColorSpace == QSurfaceFormat::sRGBColorSpace) { // use the default one! } else if (surfaceColorSpace == QSurfaceFormat::scRGBColorSpace) { profile = KoColorSpaceRegistry::instance()->p709G10Profile(); } else if (surfaceColorSpace == QSurfaceFormat::bt2020PQColorSpace) { profile = KoColorSpaceRegistry::instance()->p2020PQProfile(); } return profile; } +namespace { +struct AppAttributeSetter +{ + AppAttributeSetter(Qt::ApplicationAttribute attribute, bool useOpenGLES) + : m_attribute(attribute), + m_oldValue(QCoreApplication::testAttribute(attribute)) + { + QCoreApplication::setAttribute(attribute, useOpenGLES); + } + + ~AppAttributeSetter() { + QCoreApplication::setAttribute(m_attribute, m_oldValue); + } + +private: + Qt::ApplicationAttribute m_attribute; + bool m_oldValue = false; +}; + +struct SurfaceFormatSetter +{ + SurfaceFormatSetter(const QSurfaceFormat &format) + : m_oldFormat(QSurfaceFormat::defaultFormat()) + { + QSurfaceFormat::setDefaultFormat(format); + } + + ~SurfaceFormatSetter() { + QSurfaceFormat::setDefaultFormat(m_oldFormat); + } + +private: + QSurfaceFormat m_oldFormat; +}; + +} + +boost::optional +KisOpenGLModeProber::probeFormat(const QSurfaceFormat &format, bool adjustGlobalState) +{ + QScopedPointer sharedContextSetter; + QScopedPointer glSetter; + QScopedPointer glesSetter; + QScopedPointer formatSetter; + QScopedPointer application; + + if (adjustGlobalState) { + sharedContextSetter.reset(new AppAttributeSetter(Qt::AA_ShareOpenGLContexts, false)); + + if (format.renderableType() != QSurfaceFormat::DefaultRenderableType) { + glSetter.reset(new AppAttributeSetter(Qt::AA_UseDesktopOpenGL, format.renderableType() != QSurfaceFormat::OpenGLES)); + glesSetter.reset(new AppAttributeSetter(Qt::AA_UseOpenGLES, format.renderableType() == QSurfaceFormat::OpenGLES)); + } + + formatSetter.reset(new SurfaceFormatSetter(format)); + + int argc = 1; + QByteArray data("krita"); + char *argv = data.data(); + application.reset(new QApplication(argc, &argv)); + } + + QWindow surface; + surface.setFormat(format); + surface.setSurfaceType(QSurface::OpenGLSurface); + surface.create(); + QOpenGLContext context; + context.setFormat(format); + + + if (!context.create()) { + dbgOpenGL << "OpenGL context cannot be created"; + return boost::none; + } + if (!context.isValid()) { + dbgOpenGL << "OpenGL context is not valid while checking Qt's OpenGL status"; + return boost::none; + } + if (!context.makeCurrent(&surface)) { + dbgOpenGL << "OpenGL context cannot be made current"; + return boost::none; + } + + if (!fuzzyCompareColorSpaces(context.format().colorSpace(), format.colorSpace())) { + dbgOpenGL << "Failed to create an OpenGL context with requested color space. Requested:" << format.colorSpace() << "Actual:" << context.format().colorSpace(); + return boost::none; + } + + return Result(context); +} + +bool KisOpenGLModeProber::fuzzyCompareColorSpaces(const QSurfaceFormat::ColorSpace &lhs, const QSurfaceFormat::ColorSpace &rhs) +{ + return lhs == rhs || + ((lhs == QSurfaceFormat::DefaultColorSpace || + lhs == QSurfaceFormat::sRGBColorSpace) && + (rhs == QSurfaceFormat::DefaultColorSpace || + rhs == QSurfaceFormat::sRGBColorSpace)); +} + void KisOpenGLModeProber::initSurfaceFormatFromConfig(KisConfig::RootSurfaceFormat config, QSurfaceFormat *format) { if (config == KisConfig::BT2020_PQ) { format->setRedBufferSize(10); format->setGreenBufferSize(10); format->setBlueBufferSize(10); format->setAlphaBufferSize(2); format->setColorSpace(QSurfaceFormat::bt2020PQColorSpace); } else if (config == KisConfig::BT709_G10) { format->setRedBufferSize(16); format->setGreenBufferSize(16); format->setBlueBufferSize(16); format->setAlphaBufferSize(16); format->setColorSpace(QSurfaceFormat::scRGBColorSpace); } else { format->setRedBufferSize(8); format->setGreenBufferSize(8); format->setBlueBufferSize(8); format->setAlphaBufferSize(8); // TODO: check if we can use real sRGB space here format->setColorSpace(QSurfaceFormat::DefaultColorSpace); } } bool KisOpenGLModeProber::isFormatHDR(const QSurfaceFormat &format) { bool isBt2020PQ = format.colorSpace() == QSurfaceFormat::bt2020PQColorSpace && format.redBufferSize() == 10 && format.greenBufferSize() == 10 && format.blueBufferSize() == 10 && format.alphaBufferSize() == 2; bool isBt709G10 = format.colorSpace() == QSurfaceFormat::scRGBColorSpace && format.redBufferSize() == 16 && format.greenBufferSize() == 16 && format.blueBufferSize() == 16 && format.alphaBufferSize() == 16; return isBt2020PQ || isBt709G10; } + +KisOpenGLModeProber::Result::Result(QOpenGLContext &context) { + if (!context.isValid()) { + return; + } + + QOpenGLFunctions *funcs = context.functions(); // funcs is ready to be used + + m_rendererString = QString(reinterpret_cast(funcs->glGetString(GL_RENDERER))); + m_driverVersionString = QString(reinterpret_cast(funcs->glGetString(GL_VERSION))); + m_vendorString = QString(reinterpret_cast(funcs->glGetString(GL_VENDOR))); + m_shadingLanguageString = QString(reinterpret_cast(funcs->glGetString(GL_SHADING_LANGUAGE_VERSION))); + m_glMajorVersion = context.format().majorVersion(); + m_glMinorVersion = context.format().minorVersion(); + m_supportsDeprecatedFunctions = (context.format().options() & QSurfaceFormat::DeprecatedFunctions); + m_isOpenGLES = context.isOpenGLES(); + m_format = context.format(); +} diff --git a/libs/ui/opengl/KisOpenGLModeProber.h b/libs/ui/opengl/KisOpenGLModeProber.h index 4f7b1a6c53..26f4a0bf38 100644 --- a/libs/ui/opengl/KisOpenGLModeProber.h +++ b/libs/ui/opengl/KisOpenGLModeProber.h @@ -1,29 +1,125 @@ #ifndef KISOPENGLMODEPROBER_H #define KISOPENGLMODEPROBER_H #include "kritaui_export.h" #include "kis_config.h" #include +#include class KoColorProfile; class KRITAUI_EXPORT KisOpenGLModeProber { +public: + class Result; + public: KisOpenGLModeProber(); ~KisOpenGLModeProber(); static KisOpenGLModeProber* instance(); bool useHDRMode() const; QSurfaceFormat surfaceformatInUse() const; const KoColorProfile *rootSurfaceColorProfile() const; + boost::optional probeFormat(const QSurfaceFormat &format, + bool adjustGlobalState = true); + + static bool fuzzyCompareColorSpaces(const QSurfaceFormat::ColorSpace &lhs, + const QSurfaceFormat::ColorSpace &rhs); + public: static void initSurfaceFormatFromConfig(KisConfig::RootSurfaceFormat config, QSurfaceFormat *format); static bool isFormatHDR(const QSurfaceFormat &format); }; +class KisOpenGLModeProber::Result { +public: + Result(QOpenGLContext &context); + + int glMajorVersion() const { + return m_glMajorVersion; + } + + int glMinorVersion() const { + return m_glMinorVersion; + } + + bool supportsDeprecatedFunctions() const { + return m_supportsDeprecatedFunctions; + } + + bool isOpenGLES() const { + return m_isOpenGLES; + } + + QString rendererString() const { + return m_rendererString; + } + + QString driverVersionString() const { + return m_driverVersionString; + } + + bool isSupportedVersion() const { + return +#ifdef Q_OS_OSX + ((m_glMajorVersion * 100 + m_glMinorVersion) >= 302) +#else + (m_glMajorVersion >= 3 && (m_supportsDeprecatedFunctions || m_isOpenGLES)) || + ((m_glMajorVersion * 100 + m_glMinorVersion) == 201) +#endif + ; + } + + bool supportsLoD() const { + return (m_glMajorVersion * 100 + m_glMinorVersion) >= 300; + } + + bool hasOpenGL3() const { + return (m_glMajorVersion * 100 + m_glMinorVersion) >= 302; + } + + bool supportsFenceSync() const { + return m_glMajorVersion >= 3; + } + +#ifdef Q_OS_WIN + // This is only for detecting whether ANGLE is being used. + // For detecting generic OpenGL ES please check isOpenGLES + bool isUsingAngle() const { + return m_rendererString.startsWith("ANGLE", Qt::CaseInsensitive); + } +#endif + + QString shadingLanguageString() const + { + return m_shadingLanguageString; + } + + QString vendorString() const + { + return m_vendorString; + } + + QSurfaceFormat format() const + { + return m_format; + } + +private: + int m_glMajorVersion = 0; + int m_glMinorVersion = 0; + bool m_supportsDeprecatedFunctions = false; + bool m_isOpenGLES = false; + QString m_rendererString; + QString m_driverVersionString; + QString m_vendorString; + QString m_shadingLanguageString; + QSurfaceFormat m_format; +}; + #endif // KISOPENGLMODEPROBER_H diff --git a/libs/ui/opengl/kis_opengl.cpp b/libs/ui/opengl/kis_opengl.cpp index 984c635dfd..c9878302d8 100644 --- a/libs/ui/opengl/kis_opengl.cpp +++ b/libs/ui/opengl/kis_opengl.cpp @@ -1,312 +1,703 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "opengl/kis_opengl.h" #include "opengl/kis_opengl_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisOpenGLModeProber.h" #include +#include "kis_assert.h" +#include +#include #ifndef GL_RENDERER # define GL_RENDERER 0x1F01 #endif using namespace KisOpenGLPrivate; namespace { - bool defaultFormatIsSet = false; - bool isDebugEnabled = false; - bool isDebugSynchronous = false; + // config option, set manually by main() + bool g_isDebugSynchronous = false; - boost::optional openGLCheckResult; + bool g_sanityDefaultFormatIsSet = false; - bool NeedsFenceWorkaround = false; - bool NeedsPixmapCacheWorkaround = false; + boost::optional openGLCheckResult; - QString debugText("OpenGL Info\n **OpenGL not initialized**"); + bool g_needsFenceWorkaround = false; + bool g_needsPixmapCacheWorkaround = false; - QVector openglWarningStrings; + QString g_surfaceFormatDetectionLog; + QString g_debugText("OpenGL Info\n **OpenGL not initialized**"); + + QVector g_openglWarningStrings; + KisOpenGL::OpenGLRenderers g_supportedRenderers; + KisOpenGL::OpenGLRenderer g_rendererPreferredByQt; + + void overrideSupportedRenderers(KisOpenGL::OpenGLRenderers supportedRenderers, KisOpenGL::OpenGLRenderer preferredByQt) { + g_supportedRenderers = supportedRenderers; + g_rendererPreferredByQt = preferredByQt; + } void openglOnMessageLogged(const QOpenGLDebugMessage& debugMessage) { qDebug() << "OpenGL:" << debugMessage; } } KisOpenGLPrivate::OpenGLCheckResult::OpenGLCheckResult(QOpenGLContext &context) { if (!context.isValid()) { return; } QOpenGLFunctions *funcs = context.functions(); // funcs is ready to be used m_rendererString = QString(reinterpret_cast(funcs->glGetString(GL_RENDERER))); m_driverVersionString = QString(reinterpret_cast(funcs->glGetString(GL_VERSION))); m_glMajorVersion = context.format().majorVersion(); m_glMinorVersion = context.format().minorVersion(); m_supportsDeprecatedFunctions = (context.format().options() & QSurfaceFormat::DeprecatedFunctions); m_isOpenGLES = context.isOpenGLES(); } void KisOpenGLPrivate::appendOpenGLWarningString(KLocalizedString warning) { - openglWarningStrings << warning; + g_openglWarningStrings << warning; } -bool KisOpenGLPrivate::isDefaultFormatSet() { - return defaultFormatIsSet; +void KisOpenGLPrivate::overrideOpenGLWarningString(QVector warnings) +{ + g_openglWarningStrings = warnings; } + void KisOpenGL::initialize() { if (openGLCheckResult) return; - KIS_SAFE_ASSERT_RECOVER(defaultFormatIsSet) { - qWarning() << "Default OpenGL format was not set before calling KisOpenGL::initialize. This might be a BUG!"; - setDefaultFormat(); - } - - // we need a QSurface active to get our GL functions from the context - QWindow surface; - surface.setSurfaceType( QSurface::OpenGLSurface ); - surface.create(); + KIS_SAFE_ASSERT_RECOVER_NOOP(g_sanityDefaultFormatIsSet); - QOpenGLContext context; - if (!context.create()) { - qDebug() << "OpenGL context cannot be created"; - return; - } - if (!context.isValid()) { - qDebug() << "OpenGL context is not valid"; - return; - } - - if (!context.makeCurrent(&surface)) { - qDebug() << "OpenGL context cannot be made current"; - return; - } + openGLCheckResult = + KisOpenGLModeProber::instance()->probeFormat(QSurfaceFormat::defaultFormat(), false); - QOpenGLFunctions *funcs = context.functions(); - openGLCheckResult = OpenGLCheckResult(context); - debugText.clear(); - QDebug debugOut(&debugText); + g_debugText.clear(); + QDebug debugOut(&g_debugText); debugOut << "OpenGL Info"; - debugOut << "\n Vendor: " << reinterpret_cast(funcs->glGetString(GL_VENDOR)); + debugOut << "\n Vendor: " << openGLCheckResult->vendorString(); debugOut << "\n Renderer: " << openGLCheckResult->rendererString(); debugOut << "\n Version: " << openGLCheckResult->driverVersionString(); - debugOut << "\n Shading language: " << reinterpret_cast(funcs->glGetString(GL_SHADING_LANGUAGE_VERSION)); + debugOut << "\n Shading language: " << openGLCheckResult->shadingLanguageString(); debugOut << "\n Requested format: " << QSurfaceFormat::defaultFormat(); - debugOut << "\n Current format: " << context.format(); + debugOut << "\n Current format: " << openGLCheckResult->format(); debugOut.nospace(); debugOut << "\n Version: " << openGLCheckResult->glMajorVersion() << "." << openGLCheckResult->glMinorVersion(); debugOut.resetFormat(); debugOut << "\n Supports deprecated functions" << openGLCheckResult->supportsDeprecatedFunctions(); debugOut << "\n is OpenGL ES:" << openGLCheckResult->isOpenGLES(); - appendPlatformOpenGLDebugText(debugOut); - dbgOpenGL.noquote() << debugText; +#ifdef Q_OS_WIN + debugOut << "\n\nQPA OpenGL Detection Info"; + debugOut << "\n supportsDesktopGL:" << bool(g_supportedRenderers & RendererDesktopGL); + debugOut << "\n supportsAngleD3D11:" << bool(g_supportedRenderers & RendererOpenGLES); + debugOut << "\n isQtPreferAngle:" << bool(g_rendererPreferredByQt == RendererOpenGLES); + debugOut << "\n== log ==\n"; + debugOut.noquote(); + debugOut << g_surfaceFormatDetectionLog; + debugOut.resetFormat(); + debugOut << "\n== end log =="; +#endif + + dbgOpenGL.noquote().nospace() << g_debugText; + + // Check if we have a bugged driver that needs fence workaround + bool isOnX11 = false; +#ifdef HAVE_X11 + isOnX11 = true; +#endif + + KisConfig cfg(true); + if ((isOnX11 && openGLCheckResult->rendererString().startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) { + g_needsFenceWorkaround = true; + } + + /** + * NVidia + Qt's openGL don't play well together and one cannot + * draw a pixmap on a widget more than once in one rendering cycle. + * + * It can be workarounded by drawing strictly via QPixmapCache and + * only when the pixmap size in bigger than doubled size of the + * display framebuffer. That is for 8-bit HD display, you should have + * a cache bigger than 16 MiB. Don't ask me why. (DK) + * + * See bug: https://bugs.kde.org/show_bug.cgi?id=361709 + * + * TODO: check if this workaround is still needed after merging + * Qt5+openGL3 branch. + */ + + if (openGLCheckResult->vendorString().toUpper().contains("NVIDIA")) { + g_needsPixmapCacheWorkaround = true; + + const QRect screenSize = QApplication::desktop()->screenGeometry(); + const int minCacheSize = 20 * 1024; + const int cacheSize = 2048 + 2 * 4 * screenSize.width() * screenSize.height() / 1024; //KiB + + QPixmapCache::setCacheLimit(qMax(minCacheSize, cacheSize)); + } } void KisOpenGL::initializeContext(QOpenGLContext *ctx) { KisConfig cfg(true); initialize(); + const bool isDebugEnabled = ctx->format().testOption(QSurfaceFormat::DebugContext); + dbgUI << "OpenGL: Opening new context"; if (isDebugEnabled) { // Passing ctx for ownership management only, not specifying context. // QOpenGLDebugLogger only function on the current active context. // FIXME: Do we need to make sure ctx is the active context? QOpenGLDebugLogger* openglLogger = new QOpenGLDebugLogger(ctx); if (openglLogger->initialize()) { qDebug() << "QOpenGLDebugLogger is initialized. Check whether you get a message below."; QObject::connect(openglLogger, &QOpenGLDebugLogger::messageLogged, &openglOnMessageLogged); - openglLogger->startLogging(isDebugSynchronous ? QOpenGLDebugLogger::SynchronousLogging : QOpenGLDebugLogger::AsynchronousLogging); + openglLogger->startLogging(g_isDebugSynchronous ? QOpenGLDebugLogger::SynchronousLogging : QOpenGLDebugLogger::AsynchronousLogging); openglLogger->logMessage(QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("QOpenGLDebugLogger is logging."))); } else { qDebug() << "QOpenGLDebugLogger cannot be initialized."; delete openglLogger; } } // Double check we were given the version we requested QSurfaceFormat format = ctx->format(); QOpenGLFunctions *f = ctx->functions(); f->initializeOpenGLFunctions(); QFile log(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/krita-opengl.txt"); log.open(QFile::WriteOnly); QString vendor((const char*)f->glGetString(GL_VENDOR)); log.write(vendor.toLatin1()); log.write(", "); log.write(openGLCheckResult->rendererString().toLatin1()); log.write(", "); QString version((const char*)f->glGetString(GL_VERSION)); log.write(version.toLatin1()); log.close(); - - // Check if we have a bugged driver that needs fence workaround - bool isOnX11 = false; -#ifdef HAVE_X11 - isOnX11 = true; -#endif - - if ((isOnX11 && openGLCheckResult->rendererString().startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) { - NeedsFenceWorkaround = true; - } - - - /** - * NVidia + Qt's openGL don't play well together and one cannot - * draw a pixmap on a widget more than once in one rendering cycle. - * - * It can be workarounded by drawing strictly via QPixmapCache and - * only when the pixmap size in bigger than doubled size of the - * display framebuffer. That is for 8-bit HD display, you should have - * a cache bigger than 16 MiB. Don't ask me why. (DK) - * - * See bug: https://bugs.kde.org/show_bug.cgi?id=361709 - * - * TODO: check if this workaround is still needed after merging - * Qt5+openGL3 branch. - */ - - if (vendor.toUpper().contains("NVIDIA")) { - NeedsPixmapCacheWorkaround = true; - - const QRect screenSize = QApplication::desktop()->screenGeometry(); - const int minCacheSize = 20 * 1024; - const int cacheSize = 2048 + 2 * 4 * screenSize.width() * screenSize.height() / 1024; //KiB - - QPixmapCache::setCacheLimit(qMax(minCacheSize, cacheSize)); - } - - } const QString &KisOpenGL::getDebugText() { initialize(); - return debugText; + return g_debugText; } QStringList KisOpenGL::getOpenGLWarnings() { QStringList strings; - Q_FOREACH (const KLocalizedString &item, openglWarningStrings) { + Q_FOREACH (const KLocalizedString &item, g_openglWarningStrings) { strings << item.toString(); } return strings; } // XXX Temporary function to allow LoD on OpenGL3 without triggering // all of the other 3.2 functionality, can be removed once we move to Qt5.7 bool KisOpenGL::supportsLoD() { initialize(); return openGLCheckResult->supportsLoD(); } bool KisOpenGL::hasOpenGL3() { initialize(); return openGLCheckResult->hasOpenGL3(); } bool KisOpenGL::hasOpenGLES() { initialize(); return openGLCheckResult->isOpenGLES(); } bool KisOpenGL::supportsFenceSync() { initialize(); return openGLCheckResult->supportsFenceSync(); } bool KisOpenGL::needsFenceWorkaround() { initialize(); - return NeedsFenceWorkaround; + return g_needsFenceWorkaround; } bool KisOpenGL::needsPixmapCacheWorkaround() { initialize(); - return NeedsPixmapCacheWorkaround; + return g_needsPixmapCacheWorkaround; } -void KisOpenGL::setDefaultFormat(bool enableDebug, bool debugSynchronous, QSettings *kritadisplayrc) +void KisOpenGL::testingInitializeDefaultSurfaceFormat() { - if (defaultFormatIsSet) { - return; + setDefaultSurfaceFormat(selectSurfaceFormat(KisOpenGL::RendererAuto, KisConfig::BT709_G22, false)); +} + +void KisOpenGL::setDebugSynchronous(bool value) +{ + g_isDebugSynchronous = value; +} + +KisOpenGL::OpenGLRenderer KisOpenGL::getCurrentOpenGLRenderer() +{ + const QSurfaceFormat::RenderableType renderer = QSurfaceFormat::defaultFormat().renderableType(); + + return renderer == QSurfaceFormat::OpenGLES ? RendererOpenGLES : + renderer == QSurfaceFormat::OpenGL ? RendererDesktopGL : + RendererAuto; +} + +KisOpenGL::OpenGLRenderer KisOpenGL::getQtPreferredOpenGLRenderer() +{ + return g_rendererPreferredByQt; +} + +KisOpenGL::OpenGLRenderers KisOpenGL::getSupportedOpenGLRenderers() +{ + return g_supportedRenderers; +} + +KisOpenGL::OpenGLRenderer KisOpenGL::getUserPreferredOpenGLRendererConfig() +{ + const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); + QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); + return convertConfigToOpenGLRenderer(kritarc.value("OpenGLRenderer", "auto").toString()); +} + +void KisOpenGL::setUserPreferredOpenGLRendererConfig(KisOpenGL::OpenGLRenderer renderer) +{ + const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); + QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); + kritarc.setValue("OpenGLRenderer", KisOpenGL::convertOpenGLRendererToConfig(renderer)); +} + +QString KisOpenGL::convertOpenGLRendererToConfig(KisOpenGL::OpenGLRenderer renderer) +{ + switch (renderer) { + case RendererDesktopGL: + return QStringLiteral("desktop"); + case RendererOpenGLES: + return QStringLiteral("angle"); + default: + return QStringLiteral("auto"); + } +} + +KisOpenGL::OpenGLRenderer KisOpenGL::convertConfigToOpenGLRenderer(QString renderer) +{ + if (renderer == "desktop") { + return RendererDesktopGL; + } else if (renderer == "angle") { + return RendererOpenGLES; + } else { + return RendererAuto; } - defaultFormatIsSet = true; +} + +namespace { + +QSurfaceFormat generateSurfaceFormat(QSurfaceFormat::RenderableType renderer, + KisConfig::RootSurfaceFormat rootSurfaceFormat, + bool debugContext) +{ QSurfaceFormat format; #ifdef Q_OS_OSX format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); #else // XXX This can be removed once we move to Qt5.7 format.setVersion(3, 0); format.setProfile(QSurfaceFormat::CompatibilityProfile); format.setOptions(QSurfaceFormat::DeprecatedFunctions); #endif format.setDepthBufferSize(24); format.setStencilBufferSize(8); - if (kritadisplayrc) { - KisConfig::RootSurfaceFormat rootSurfaceFormat = KisConfig::rootSurfaceFormat(kritadisplayrc); - KisOpenGLModeProber::initSurfaceFormatFromConfig(rootSurfaceFormat, &format); - } + KisOpenGLModeProber::initSurfaceFormatFromConfig(rootSurfaceFormat, &format); + format.setRenderableType(renderer); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); format.setSwapInterval(0); // Disable vertical refresh syncing - isDebugEnabled = enableDebug; - if (enableDebug) { + if (debugContext) { format.setOption(QSurfaceFormat::DebugContext, true); - isDebugSynchronous = debugSynchronous; - qDebug() << "QOpenGLDebugLogger will be enabled, synchronous:" << debugSynchronous; } + + return format; +} + +bool isOpenGLRendererBlacklisted(const QString &rendererString, + const QString &driverVersionString, + QVector *warningMessage) +{ + bool isBlacklisted = false; + + // Special blacklisting of OpenGL/ANGLE is tracked on: + // https://phabricator.kde.org/T7411 + + // HACK: Specifically detect for Intel driver build number + // See https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html + if (rendererString.startsWith("Intel")) { + KLocalizedString knownBadIntelWarning = ki18n("The Intel graphics driver in use is known to have issues with OpenGL."); + KLocalizedString grossIntelWarning = ki18n( + "Intel graphics drivers tend to have issues with OpenGL so ANGLE will be used by default. " + "You may manually switch to OpenGL but it is not guaranteed to work properly." + ); + QRegularExpression regex("\\b\\d{2}\\.\\d{2}\\.\\d{2}\\.(\\d{4})\\b"); + QRegularExpressionMatch match = regex.match(driverVersionString); + if (match.hasMatch()) { + int driverBuild = match.captured(1).toInt(); + if (driverBuild > 4636 && driverBuild < 4729) { + // Make ANGLE the preferred renderer for Intel driver versions + // between build 4636 and 4729 (exclusive) due to an UI offset bug. + // See https://communities.intel.com/thread/116003 + // (Build 4636 is known to work from some test results) + qDebug() << "Detected Intel driver build between 4636 and 4729, making ANGLE the preferred renderer"; + isBlacklisted = true; + *warningMessage << knownBadIntelWarning; + } else if (driverBuild == 4358) { + // There are several reports on a bug where the canvas is not being + // updated properly which has debug info pointing to this build. + qDebug() << "Detected Intel driver build 4358, making ANGLE the preferred renderer"; + isBlacklisted = true; + *warningMessage << knownBadIntelWarning; + } else { + // Intel tends to randomly break OpenGL in some of their new driver + // builds, therefore we just shouldn't use OpenGL by default to + // reduce bug report noises. + qDebug() << "Detected Intel driver, making ANGLE the preferred renderer"; + isBlacklisted = true; + *warningMessage << grossIntelWarning; + } + } + } + + return isBlacklisted; +} + +boost::optional orderPreference(bool lhs, bool rhs) +{ + if (lhs == rhs) return boost::none; + if (lhs && !rhs) return true; + if (!lhs && rhs) return false; + return false; +} + +#define ORDER_BY(lhs, rhs) if (auto res = orderPreference((lhs), (rhs))) { return *res; } + +class FormatPositionLess +{ +public: + + FormatPositionLess() + { + } + + bool operator()(const QSurfaceFormat &lhs, const QSurfaceFormat &rhs) const { + KIS_SAFE_ASSERT_RECOVER_NOOP(m_preferredColorSpace != QSurfaceFormat::DefaultColorSpace); + + ORDER_BY(isPreferredColorSpace(lhs.colorSpace()), + isPreferredColorSpace(rhs.colorSpace())); + + + if (doPreferHDR()) { + ORDER_BY(isHDRFormat(lhs), isHDRFormat(rhs)); + } else { + ORDER_BY(!isHDRFormat(lhs), !isHDRFormat(rhs)); + } + + if (m_preferredRendererByUser != QSurfaceFormat::DefaultRenderableType) { + ORDER_BY(lhs.renderableType() == m_preferredRendererByUser, + rhs.renderableType() == m_preferredRendererByUser); + } + + ORDER_BY(!isBlacklisted(lhs), !isBlacklisted(rhs)); + + if (doPreferHDR() && + m_preferredRendererByHDR != QSurfaceFormat::DefaultRenderableType) { + + ORDER_BY(lhs.renderableType() == m_preferredRendererByHDR, + rhs.renderableType() == m_preferredRendererByHDR); + + } + + KIS_SAFE_ASSERT_RECOVER_NOOP(m_preferredRendererByQt != QSurfaceFormat::DefaultRenderableType); + + ORDER_BY(lhs.renderableType() == m_preferredRendererByQt, + rhs.renderableType() == m_preferredRendererByQt); + + return false; + } + + +public: + void setPreferredColorSpace(const QSurfaceFormat::ColorSpace &preferredColorSpace) { + m_preferredColorSpace = preferredColorSpace; + } + + void setPreferredRendererByQt(const QSurfaceFormat::RenderableType &preferredRendererByQt) { + m_preferredRendererByQt = preferredRendererByQt; + } + + void setPreferredRendererByUser(const QSurfaceFormat::RenderableType &preferredRendererByUser) { + m_preferredRendererByUser = preferredRendererByUser; + } + + void setPreferredRendererByHDR(const QSurfaceFormat::RenderableType &preferredRendererByHDR) { + m_preferredRendererByHDR = preferredRendererByHDR; + } + + void setOpenGLBlacklisted(bool openGLBlacklisted) { + m_openGLBlacklisted = openGLBlacklisted; + } + + void setOpenGLESBlacklisted(bool openGLESBlacklisted) { + m_openGLESBlacklisted = openGLESBlacklisted; + } + + QSurfaceFormat::ColorSpace preferredColorSpace() const { + return m_preferredColorSpace; + } + + QSurfaceFormat::RenderableType preferredRendererByUser() const { + return m_preferredRendererByUser; + } + +private: + bool isHDRFormat(const QSurfaceFormat &f) const { + return f.colorSpace() == QSurfaceFormat::bt2020PQColorSpace || + f.colorSpace() == QSurfaceFormat::scRGBColorSpace; + } + + bool isBlacklisted(const QSurfaceFormat &f) const { + KIS_SAFE_ASSERT_RECOVER_NOOP(f.renderableType() == QSurfaceFormat::OpenGL || + f.renderableType() == QSurfaceFormat::OpenGLES); + + return (f.renderableType() == QSurfaceFormat::OpenGL && m_openGLBlacklisted) || + (f.renderableType() == QSurfaceFormat::OpenGLES && m_openGLESBlacklisted); + } + + bool doPreferHDR() const { + return m_preferredColorSpace == QSurfaceFormat::bt2020PQColorSpace || + m_preferredColorSpace == QSurfaceFormat::scRGBColorSpace; + } + + bool isPreferredColorSpace(const QSurfaceFormat::ColorSpace cs) const { + return KisOpenGLModeProber::fuzzyCompareColorSpaces(m_preferredColorSpace, cs); + return false; + } + +private: + QSurfaceFormat::ColorSpace m_preferredColorSpace = QSurfaceFormat::DefaultColorSpace; + QSurfaceFormat::RenderableType m_preferredRendererByQt = QSurfaceFormat::OpenGL; + QSurfaceFormat::RenderableType m_preferredRendererByUser = QSurfaceFormat::DefaultRenderableType; + QSurfaceFormat::RenderableType m_preferredRendererByHDR = QSurfaceFormat::DefaultRenderableType; + bool m_openGLBlacklisted = false; + bool m_openGLESBlacklisted = false; +}; + +struct DetectionDebug : public QDebug +{ + DetectionDebug(QString *string) + : QDebug(string), + m_string(string), + m_originalSize(string->size()) + {} + ~DetectionDebug() { dbgOpenGL << m_string->right(m_string->size() - m_originalSize); *this << endl; } + + QString *m_string; + int m_originalSize; +}; +} + +#define dbgDetection() DetectionDebug(&g_surfaceFormatDetectionLog) + +QSurfaceFormat KisOpenGL::selectSurfaceFormat(KisOpenGL::OpenGLRenderer preferredRenderer, + KisConfig::RootSurfaceFormat preferredRootSurfaceFormat, + bool enableDebug) +{ + QVector warningMessages; + + using Info = boost::optional; + + QVector renderers({QSurfaceFormat::OpenGLES, QSurfaceFormat::OpenGL}); + QVector formatSymbols({KisConfig::BT709_G22, KisConfig::BT709_G10, KisConfig::BT2020_PQ}); + + QVector preferredFormats; + Q_FOREACH (const QSurfaceFormat::RenderableType renderer, renderers) { + Q_FOREACH (const KisConfig::RootSurfaceFormat formatSymbol, formatSymbols) { + preferredFormats << generateSurfaceFormat(renderer, formatSymbol, enableDebug); + } + } + + QSurfaceFormat defaultFormat = generateSurfaceFormat(QSurfaceFormat::DefaultRenderableType, + KisConfig::BT709_G22, false); + Info info = KisOpenGLModeProber::instance()->probeFormat(defaultFormat); + + KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(info, QSurfaceFormat()); + + FormatPositionLess compareOp; + compareOp.setPreferredRendererByQt(info->isOpenGLES() ? QSurfaceFormat::OpenGLES : QSurfaceFormat::OpenGL); + compareOp.setPreferredColorSpace(preferredRootSurfaceFormat == KisConfig::BT709_G22 ? QSurfaceFormat::sRGBColorSpace : + preferredRootSurfaceFormat == KisConfig::BT709_G10 ? QSurfaceFormat::scRGBColorSpace : + QSurfaceFormat::bt2020PQColorSpace); +#ifdef Q_OS_WIN + compareOp.setPreferredRendererByHDR(QSurfaceFormat::OpenGLES); +#endif + compareOp.setPreferredRendererByUser(preferredRenderer == KisOpenGL::RendererDesktopGL ? QSurfaceFormat::OpenGL : + preferredRenderer == KisOpenGL::RendererOpenGLES ? QSurfaceFormat::OpenGLES : + QSurfaceFormat::DefaultRenderableType); + compareOp.setOpenGLESBlacklisted(false); // We cannot blacklist ES drivers atm + + OpenGLRenderers supportedRenderers = RendererNone; + OpenGLRenderer preferredByQt = info->isOpenGLES() ? RendererOpenGLES : RendererDesktopGL; + + if (!info->isOpenGLES()) { + compareOp.setOpenGLBlacklisted(isOpenGLRendererBlacklisted(info->rendererString(), + info->driverVersionString(), + &warningMessages)); + + supportedRenderers |= RendererDesktopGL; + + info = KisOpenGLModeProber::instance()-> + probeFormat(generateSurfaceFormat(QSurfaceFormat::OpenGLES, + KisConfig::BT709_G22, false)); + if (info) { + supportedRenderers |= RendererOpenGLES; + } + } else { + supportedRenderers |= RendererOpenGLES; + + info = KisOpenGLModeProber::instance()-> + probeFormat(generateSurfaceFormat(QSurfaceFormat::OpenGL, + KisConfig::BT709_G22, false)); + + if (!info || info->isOpenGLES()) { + compareOp.setOpenGLBlacklisted(true); + } else { + compareOp.setOpenGLBlacklisted(isOpenGLRendererBlacklisted(info->rendererString(), + info->driverVersionString(), + &warningMessages)); + + supportedRenderers |= RendererDesktopGL; + } + } + + std::stable_sort(preferredFormats.begin(), preferredFormats.end(), compareOp); + + dbgDetection() << "Supported renderers:" << supportedRenderers; + + dbgDetection() << "Surface format preference list:"; + Q_FOREACH (const QSurfaceFormat &format, preferredFormats) { + dbgDetection() << "*" << format; + dbgDetection() << " " << format.renderableType(); + } + + QSurfaceFormat resultFormat = defaultFormat; + + Q_FOREACH (const QSurfaceFormat &format, preferredFormats) { + dbgDetection() <<"Probing format..." << format.colorSpace() << format.renderableType(); + + Info info = KisOpenGLModeProber::instance()->probeFormat(format); + + if (info && info->isSupportedVersion()) { + // HACK: Block ANGLE with Direct3D9 + // Direct3D9 does not give OpenGL ES 3.0 + // Some versions of ANGLE returns OpenGL version 3.0 incorrectly + + if (info->isUsingAngle() && + info->rendererString().contains("Direct3D9", Qt::CaseInsensitive)) { + + dbgDetection() << "Skipping Direct3D 9 Angle implementation, it shouldn't have happened."; + + continue; + } + + dbgDetection() << "Found format:" << format; + dbgDetection() << " " << format.renderableType(); + + resultFormat = format; + break; + } + } + + { + const bool colorSpaceIsCorrect = + KisOpenGLModeProber::fuzzyCompareColorSpaces(compareOp.preferredColorSpace(), + resultFormat.colorSpace()); + + const bool rendererIsCorrect = + compareOp.preferredRendererByUser() == QSurfaceFormat::DefaultRenderableType || + compareOp.preferredRendererByUser() == resultFormat.renderableType(); + + if (!rendererIsCorrect && colorSpaceIsCorrect) { + warningMessages << ki18n("Preferred renderer doesn't support requested surface format. Another renderer has been selected."); + } else if (!colorSpaceIsCorrect) { + warningMessages << ki18n("Preferred output format is not supported by available renderers"); + } + + } + + overrideSupportedRenderers(supportedRenderers, preferredByQt); + overrideOpenGLWarningString(warningMessages); + + return resultFormat; +} + +void KisOpenGL::setDefaultSurfaceFormat(const QSurfaceFormat &format) +{ + KIS_SAFE_ASSERT_RECOVER_NOOP(!g_sanityDefaultFormatIsSet); + + g_sanityDefaultFormatIsSet = true; QSurfaceFormat::setDefaultFormat(format); } bool KisOpenGL::hasOpenGL() { return openGLCheckResult->isSupportedVersion(); } diff --git a/libs/ui/opengl/kis_opengl.h b/libs/ui/opengl/kis_opengl.h index 136d953e63..eede52ef0d 100644 --- a/libs/ui/opengl/kis_opengl.h +++ b/libs/ui/opengl/kis_opengl.h @@ -1,118 +1,124 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_H_ #define KIS_OPENGL_H_ /** @file */ #include #include +#include +#include "kis_config.h" + #include "kritaui_export.h" class QOpenGLContext; class QString; class QStringList; class QSettings; /** * This class manages a shared OpenGL context and provides utility * functions for checking capabilities and error reporting. */ class KRITAUI_EXPORT KisOpenGL { public: enum FilterMode { NearestFilterMode, // nearest BilinearFilterMode, // linear, no mipmap TrilinearFilterMode, // LINEAR_MIPMAP_LINEAR HighQualityFiltering // Mipmaps + custom shader }; public: #ifdef Q_OS_WIN enum OpenGLRenderer { RendererNone = 0x00, RendererAuto = 0x01, RendererDesktopGL = 0x02, - RendererAngle = 0x04, + RendererOpenGLES = 0x04, }; Q_DECLARE_FLAGS(OpenGLRenderers, OpenGLRenderer); - // Probe the Windows platform abstraction layer for OpenGL detection - static void probeWindowsQpaOpenGL(int argc, char **argv, QString userRendererConfigString); + static QSurfaceFormat selectSurfaceFormat(KisOpenGL::OpenGLRenderer preferredRenderer, + KisConfig::RootSurfaceFormat preferredRootSurfaceFormat, + bool enableDebug); + + static void setDefaultSurfaceFormat(const QSurfaceFormat &format); static OpenGLRenderer getCurrentOpenGLRenderer(); static OpenGLRenderer getQtPreferredOpenGLRenderer(); static OpenGLRenderers getSupportedOpenGLRenderers(); - static OpenGLRenderer getUserOpenGLRendererConfig(); - static OpenGLRenderer getNextUserOpenGLRendererConfig(); - static void setNextUserOpenGLRendererConfig(OpenGLRenderer renderer); + static OpenGLRenderer getUserPreferredOpenGLRendererConfig(); + static void setUserPreferredOpenGLRendererConfig(OpenGLRenderer renderer); static QString convertOpenGLRendererToConfig(OpenGLRenderer renderer); static OpenGLRenderer convertConfigToOpenGLRenderer(QString renderer); #endif /// Request OpenGL version 3.2 static void initialize(); /// Initialize shared OpenGL context static void initializeContext(QOpenGLContext *ctx); static const QString &getDebugText(); static QStringList getOpenGLWarnings(); static bool supportsLoD(); static bool hasOpenGL3(); static bool hasOpenGLES(); /// Check for OpenGL static bool hasOpenGL(); /** * @brief supportsFilter * @return True if OpenGL provides fence sync methods. */ static bool supportsFenceSync(); /** * Returns true if we have a driver that has bugged support to sync objects (a fence) * and false otherwise. */ static bool needsFenceWorkaround(); /** * @see a comment in initializeContext() */ static bool needsPixmapCacheWorkaround(); - static void setDefaultFormat(bool enableDebug = false, bool debugSynchronous = false, QSettings *kritadisplayrc = 0); + static void testingInitializeDefaultSurfaceFormat(); + static void setDebugSynchronous(bool value); private: - + static void fakeInitWindowsOpenGL(KisOpenGL::OpenGLRenderers supportedRenderers, KisOpenGL::OpenGLRenderer preferredByQt); KisOpenGL(); }; #ifdef Q_OS_WIN Q_DECLARE_OPERATORS_FOR_FLAGS(KisOpenGL::OpenGLRenderers); #endif #endif // KIS_OPENGL_H_ diff --git a/libs/ui/opengl/kis_opengl_p.h b/libs/ui/opengl/kis_opengl_p.h index ef74ad6bda..d4b1f5b515 100644 --- a/libs/ui/opengl/kis_opengl_p.h +++ b/libs/ui/opengl/kis_opengl_p.h @@ -1,110 +1,111 @@ /* * Copyright (c) 2017 Alvin Wong * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_P_H_ #define KIS_OPENGL_P_H_ #include #include class QDebug; class QOpenGLContext; class KLocalizedString; namespace KisOpenGLPrivate { class OpenGLCheckResult { int m_glMajorVersion = 0; int m_glMinorVersion = 0; bool m_supportsDeprecatedFunctions = false; bool m_isOpenGLES = false; QString m_rendererString; QString m_driverVersionString; public: OpenGLCheckResult(QOpenGLContext &context); int glMajorVersion() const { return m_glMajorVersion; } int glMinorVersion() const { return m_glMinorVersion; } bool supportsDeprecatedFunctions() const { return m_supportsDeprecatedFunctions; } bool isOpenGLES() const { return m_isOpenGLES; } QString rendererString() const { return m_rendererString; } QString driverVersionString() const { return m_driverVersionString; } bool isSupportedVersion() const { return #ifdef Q_OS_OSX ((m_glMajorVersion * 100 + m_glMinorVersion) >= 302) #else (m_glMajorVersion >= 3 && (m_supportsDeprecatedFunctions || m_isOpenGLES)) || ((m_glMajorVersion * 100 + m_glMinorVersion) == 201) #endif ; } bool supportsLoD() const { return (m_glMajorVersion * 100 + m_glMinorVersion) >= 300; } bool hasOpenGL3() const { return (m_glMajorVersion * 100 + m_glMinorVersion) >= 302; } bool supportsFenceSync() const { return m_glMajorVersion >= 3; } #ifdef Q_OS_WIN // This is only for detecting whether ANGLE is being used. // For detecting generic OpenGL ES please check isOpenGLES bool isUsingAngle() const { return m_rendererString.startsWith("ANGLE", Qt::CaseInsensitive); } #endif }; void appendPlatformOpenGLDebugText(QDebug &debugOut); #ifndef Q_OS_WIN void appendPlatformOpenGLDebugText(QDebug &/*debugOut*/) {} #endif void appendOpenGLWarningString(KLocalizedString warning); +void overrideOpenGLWarningString(QVector warnings); bool isDefaultFormatSet(); } // namespace KisOpenGLPrivate #endif // KIS_OPENGL_P_H_ diff --git a/libs/ui/opengl/kis_opengl_win.cpp b/libs/ui/opengl/kis_opengl_win.cpp deleted file mode 100644 index 7e9eb4a501..0000000000 --- a/libs/ui/opengl/kis_opengl_win.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2017 Alvin Wong - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "opengl/kis_opengl.h" -#include "opengl/kis_opengl_p.h" - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -using namespace KisOpenGLPrivate; - -namespace -{ - -struct WindowsOpenGLStatus { - bool supportsDesktopGL = false; - bool supportsAngleD3D11 = false; - bool isQtPreferAngle = false; - bool overridePreferAngle = false; // override Qt to force ANGLE to be preferred -}; -WindowsOpenGLStatus windowsOpenGLStatus = {}; -KisOpenGL::OpenGLRenderer userRendererConfig; -KisOpenGL::OpenGLRenderer nextUserRendererConfig; -KisOpenGL::OpenGLRenderer currentRenderer; - -QStringList qpaDetectionLog; - -boost::optional checkQpaOpenGLStatus() { - QWindow surface; - surface.setSurfaceType(QSurface::OpenGLSurface); - surface.create(); - QOpenGLContext context; - if (!context.create()) { - qDebug() << "OpenGL context cannot be created"; - return boost::none; - } - if (!context.isValid()) { - qDebug() << "OpenGL context is not valid while checking Qt's OpenGL status"; - return boost::none; - } - if (!context.makeCurrent(&surface)) { - qDebug() << "OpenGL context cannot be made current"; - return boost::none; - } - return OpenGLCheckResult(context); -} - -bool checkIsSupportedDesktopGL(const OpenGLCheckResult &checkResult) { - if (checkResult.isUsingAngle()) { - qWarning() << "ANGLE was being used when desktop OpenGL was wanted, assuming no desktop OpenGL support"; - return false; - } - if (checkResult.isOpenGLES()) { - qWarning() << "Got OpenGL ES instead of desktop OpenGL, this shouldn't happen!"; - return false; - } - return checkResult.isSupportedVersion(); -} - -bool checkIsSupportedAngleD3D11(const OpenGLCheckResult &checkResult) { - if (!checkResult.isOpenGLES()) { - qWarning() << "Got desktop OpenGL instead of OpenGL ES, this shouldn't happen!"; - return false; - } - if (!checkResult.isUsingAngle()) { - // This can happen if someone tries to swap in SwiftShader, don't mind it. - qWarning() << "OpenGL ES context is not ANGLE. Continuing anyway..."; - } - // HACK: Block ANGLE with Direct3D9 - // Direct3D9 does not give OpenGL ES 3.0 - // Some versions of ANGLE returns OpenGL version 3.0 incorrectly - if (checkResult.rendererString().contains("Direct3D9", Qt::CaseInsensitive)) { - qWarning() << "ANGLE tried to use Direct3D9, Krita won't work with it"; - return false; - } - return checkResult.isSupportedVersion(); -} - -void specialOpenGLVendorFilter(WindowsOpenGLStatus &status, const OpenGLCheckResult &checkResult) { - if (!status.supportsAngleD3D11) { - return; - } - - // Special blacklisting of OpenGL/ANGLE is tracked on: - // https://phabricator.kde.org/T7411 - - // HACK: Specifically detect for Intel driver build number - // See https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html - if (checkResult.rendererString().startsWith("Intel")) { - KLocalizedString knownBadIntelWarning = ki18n("The Intel graphics driver in use is known to have issues with OpenGL."); - KLocalizedString grossIntelWarning = ki18n( - "Intel graphics drivers tend to have issues with OpenGL so ANGLE will be used by default. " - "You may manually switch to OpenGL but it is not guaranteed to work properly." - ); - QRegularExpression regex("\\b\\d{2}\\.\\d{2}\\.\\d{2}\\.(\\d{4})\\b"); - QRegularExpressionMatch match = regex.match(checkResult.driverVersionString()); - if (match.hasMatch()) { - int driverBuild = match.captured(1).toInt(); - if (driverBuild > 4636 && driverBuild < 4729) { - // Make ANGLE the preferred renderer for Intel driver versions - // between build 4636 and 4729 (exclusive) due to an UI offset bug. - // See https://communities.intel.com/thread/116003 - // (Build 4636 is known to work from some test results) - qDebug() << "Detected Intel driver build between 4636 and 4729, making ANGLE the preferred renderer"; - status.overridePreferAngle = true; - appendOpenGLWarningString(knownBadIntelWarning); - } else if (driverBuild == 4358) { - // There are several reports on a bug where the canvas is not being - // updated properly which has debug info pointing to this build. - qDebug() << "Detected Intel driver build 4358, making ANGLE the preferred renderer"; - status.overridePreferAngle = true; - appendOpenGLWarningString(knownBadIntelWarning); - } else { - // Intel tends to randomly break OpenGL in some of their new driver - // builds, therefore we just shouldn't use OpenGL by default to - // reduce bug report noises. - qDebug() << "Detected Intel driver, making ANGLE the preferred renderer"; - status.overridePreferAngle = true; - if (status.supportsDesktopGL) { - appendOpenGLWarningString(grossIntelWarning); - } - } - } - } -} - -} // namespace - -void KisOpenGLPrivate::appendPlatformOpenGLDebugText(QDebug &debugOut) { - debugOut << "\n\nQPA OpenGL Detection Info"; - debugOut << "\n supportsDesktopGL:" << windowsOpenGLStatus.supportsDesktopGL; - debugOut << "\n supportsAngleD3D11:" << windowsOpenGLStatus.supportsAngleD3D11; - debugOut << "\n isQtPreferAngle:" << windowsOpenGLStatus.isQtPreferAngle; - debugOut << "\n overridePreferAngle:" << windowsOpenGLStatus.overridePreferAngle; - debugOut << "\n== log ==\n"; - debugOut.noquote(); - debugOut << qpaDetectionLog.join('\n'); - debugOut.resetFormat(); - debugOut << "\n== end log =="; -} - -/** - * This function probes the Qt Platform Abstraction (QPA) for OpenGL diagnostics - * information. The code works under the assumption that the bundled Qt is built - * with `-opengl dynamic` and includes support for ANGLE. - * - * This function is written for Qt 5.9.1. On other versions it might not work - * as well. - */ -void KisOpenGL::probeWindowsQpaOpenGL(int argc, char **argv, QString userRendererConfigString) -{ - KIS_SAFE_ASSERT_RECOVER(isDefaultFormatSet()) { - qWarning() << "Default OpenGL format was not set before calling KisOpenGL::probeWindowsQpaOpenGL. This might be a BUG!"; - setDefaultFormat(); - } - - // Clear env var to prevent affecting tests - qunsetenv("QT_OPENGL"); - - boost::optional qpaDetectionResult; - - qDebug() << "Probing Qt OpenGL detection:"; - { - { - QGuiApplication app(argc, argv); - qpaDetectionResult = checkQpaOpenGLStatus(); - } - } - if (!qpaDetectionResult) { - qWarning() << "Could not initialize OpenGL context!"; - return; - } - qDebug() << "Done probing Qt OpenGL detection"; - - windowsOpenGLStatus.isQtPreferAngle = qpaDetectionResult->isOpenGLES(); - - boost::optional checkResultAngle, checkResultDesktopGL; - if (qpaDetectionResult->isOpenGLES()) { - checkResultAngle = qpaDetectionResult; - // We already checked ANGLE, now check desktop OpenGL - qputenv("QT_OPENGL", "desktop"); - qDebug() << "Checking desktop OpenGL..."; - { - QGuiApplication app(argc, argv); - checkResultDesktopGL = checkQpaOpenGLStatus(); - } - if (!checkResultDesktopGL) { - qWarning() << "Could not initialize OpenGL context!"; - } - qDebug() << "Done checking desktop OpenGL"; - qunsetenv("QT_OPENGL"); - } else { - checkResultDesktopGL = qpaDetectionResult; - // We already checked desktop OpenGL, now check ANGLE - qputenv("QT_OPENGL", "angle"); - qDebug() << "Checking ANGLE..."; - { - QGuiApplication app(argc, argv); - checkResultAngle = checkQpaOpenGLStatus(); - } - if (!checkResultAngle) { - qWarning() << "Could not initialize OpenGL context!"; - } - qDebug() << "Done checking ANGLE"; - qunsetenv("QT_OPENGL"); - } - - windowsOpenGLStatus.supportsDesktopGL = - checkResultDesktopGL && checkIsSupportedDesktopGL(*checkResultDesktopGL); - windowsOpenGLStatus.supportsAngleD3D11 = - checkResultAngle && checkIsSupportedAngleD3D11(*checkResultAngle); - - if (!windowsOpenGLStatus.supportsDesktopGL) { - appendOpenGLWarningString(ki18n("The graphics driver in use does not meet the OpenGL requirements.")); - } else if (windowsOpenGLStatus.isQtPreferAngle) { - appendOpenGLWarningString(ki18n("The graphics driver in use may not work well with OpenGL.")); - } - - // HACK: Filter specific buggy drivers not handled by Qt OpenGL buglist - if (checkResultDesktopGL) { - specialOpenGLVendorFilter(windowsOpenGLStatus, *checkResultDesktopGL); - } - - if (windowsOpenGLStatus.supportsAngleD3D11 - && (checkResultAngle->rendererString().contains("Software Adapter") - || checkResultAngle->rendererString().contains("Microsoft Basic Render Driver"))) { - appendOpenGLWarningString(ki18n( - "ANGLE is using a software Direct3D renderer, which is not hardware-accelerated and may be very slow. " - "This can happen if the graphics drivers are not properly installed, or when using a Remote Desktop session." - )); - } - - userRendererConfig = convertConfigToOpenGLRenderer(userRendererConfigString); - if ((userRendererConfig == RendererDesktopGL && !windowsOpenGLStatus.supportsDesktopGL) || - (userRendererConfig == RendererAngle && !windowsOpenGLStatus.supportsAngleD3D11)) { - // Set it to auto so we won't get stuck - userRendererConfig = RendererAuto; - } - nextUserRendererConfig = userRendererConfig; - switch (userRendererConfig) { - case RendererDesktopGL: - QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true); - currentRenderer = RendererDesktopGL; - break; - case RendererAngle: - QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true); - currentRenderer = RendererAngle; - break; - default: - if (windowsOpenGLStatus.isQtPreferAngle && windowsOpenGLStatus.supportsAngleD3D11) { - currentRenderer = RendererAngle; - } else if (windowsOpenGLStatus.overridePreferAngle && windowsOpenGLStatus.supportsAngleD3D11) { - QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true); - currentRenderer = RendererAngle; - } else if (!windowsOpenGLStatus.isQtPreferAngle && windowsOpenGLStatus.supportsDesktopGL) { - currentRenderer = RendererDesktopGL; - } else { - currentRenderer = RendererNone; - } - break; - } -} - -KisOpenGL::OpenGLRenderer KisOpenGL::getCurrentOpenGLRenderer() -{ - return currentRenderer; -} - -KisOpenGL::OpenGLRenderer KisOpenGL::getQtPreferredOpenGLRenderer() -{ - return (windowsOpenGLStatus.isQtPreferAngle || windowsOpenGLStatus.overridePreferAngle) - ? RendererAngle : RendererDesktopGL; -} - -KisOpenGL::OpenGLRenderers KisOpenGL::getSupportedOpenGLRenderers() -{ - return RendererAuto | - (windowsOpenGLStatus.supportsDesktopGL ? RendererDesktopGL : static_cast(0)) | - (windowsOpenGLStatus.supportsAngleD3D11 ? RendererAngle : static_cast(0)); -} - -KisOpenGL::OpenGLRenderer KisOpenGL::getUserOpenGLRendererConfig() -{ - return userRendererConfig; -} - -KisOpenGL::OpenGLRenderer KisOpenGL::getNextUserOpenGLRendererConfig() -{ - return nextUserRendererConfig; -} - -void KisOpenGL::setNextUserOpenGLRendererConfig(KisOpenGL::OpenGLRenderer renderer) -{ - nextUserRendererConfig = renderer; -} - -QString KisOpenGL::convertOpenGLRendererToConfig(KisOpenGL::OpenGLRenderer renderer) -{ - switch (renderer) { - case RendererDesktopGL: - return QStringLiteral("desktop"); - case RendererAngle: - return QStringLiteral("angle"); - default: - return QStringLiteral("auto"); - } -} - -KisOpenGL::OpenGLRenderer KisOpenGL::convertConfigToOpenGLRenderer(QString renderer) -{ - if (renderer == "desktop") { - return RendererDesktopGL; - } else if (renderer == "angle") { - return RendererAngle; - } else { - return RendererAuto; - } -} diff --git a/libs/ui/tests/kis_derived_resources_test.cpp b/libs/ui/tests/kis_derived_resources_test.cpp index c9451508c0..062197ac91 100644 --- a/libs/ui/tests/kis_derived_resources_test.cpp +++ b/libs/ui/tests/kis_derived_resources_test.cpp @@ -1,159 +1,159 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_derived_resources_test.h" #include #include #include #include #include "kis_canvas_resource_provider.h" #include #include #include #include #include #include #include #include #include #include "testutil.h" #include "opengl/kis_opengl.h" void addResourceTypes() { // All Krita's resource types KoResourcePaths::addResourceType("gmic_definitions", "data", "/gmic/"); KoResourcePaths::addResourceType("icc_profiles", "data", "/color/icc"); KoResourcePaths::addResourceType("icc_profiles", "data", "/profiles/"); KoResourcePaths::addResourceType("kis_actions", "data", "/actions"); KoResourcePaths::addResourceType("kis_brushes", "data", "/brushes/"); KoResourcePaths::addResourceType("kis_defaultpresets", "data", "/defaultpresets/"); KoResourcePaths::addResourceType("kis_images", "data", "/images/"); KoResourcePaths::addResourceType("kis_paintoppresets", "data", "/paintoppresets/"); KoResourcePaths::addResourceType("kis_pics", "data", "/pics/"); KoResourcePaths::addResourceType("kis_resourcebundles", "data", "/bundles/"); KoResourcePaths::addResourceType("kis_shortcuts", "data", "/shortcuts/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("kis_windowlayouts", "data", "/windowlayouts/"); KoResourcePaths::addResourceType("kis_workspaces", "data", "/workspaces/"); KoResourcePaths::addResourceType("ko_effects", "data", "/effects/"); KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/"); KoResourcePaths::addResourceType("ko_palettes", "data", "/palettes/"); KoResourcePaths::addResourceType("ko_patterns", "data", "/patterns/"); KoResourcePaths::addResourceType("metadata_schema", "data", "/metadata/schemas/"); KoResourcePaths::addResourceType("psd_layer_style_collections", "data", "/asl"); KoResourcePaths::addResourceType("tags", "data", "/tags/"); - KisOpenGL::setDefaultFormat(false, false); + KisOpenGL::testingInitializeDefaultSurfaceFormat(); KisConfig cfg(false); cfg.setUseOpenGL(false); } void KisDerivedResourcesTest::test() { addResourceTypes(); KisDocument* doc = createEmptyDocument(); KisMainWindow* mainWindow = KisPart::instance()->createMainWindow(); QPointer view = new KisView(doc, mainWindow->resourceManager(), mainWindow->actionCollection(), mainWindow); KisViewManager *viewManager = new KisViewManager(mainWindow, mainWindow->actionCollection()); KoCanvasResourceProvider *manager = viewManager->resourceProvider()->resourceManager(); QApplication::processEvents(); QString presetFileName = "autobrush_300px.kpp"; QVariant i; KisPaintOpPresetSP preset; if (!presetFileName.isEmpty()) { QString fullFileName = TestUtil::fetchDataFileLazy(presetFileName); preset = new KisPaintOpPreset(fullFileName); bool presetValid = preset->load(); Q_ASSERT(presetValid); Q_UNUSED(presetValid); i.setValue(preset); } QVERIFY(i.isValid()); QSignalSpy spy(manager, SIGNAL(canvasResourceChanged(int,QVariant))); manager->setResource(KisCanvasResourceProvider::CurrentPaintOpPreset, i); QMap expectedSignals; expectedSignals[KisCanvasResourceProvider::CurrentPaintOpPreset] = QVariant::fromValue(preset); expectedSignals[KisCanvasResourceProvider::EraserMode] = false; expectedSignals[KisCanvasResourceProvider::LodSizeThresholdSupported] = true; expectedSignals[KisCanvasResourceProvider::EffectiveLodAvailablility] = true; expectedSignals[KisCanvasResourceProvider::LodSizeThreshold] = 100; expectedSignals[KisCanvasResourceProvider::LodAvailability] = true; expectedSignals[KisCanvasResourceProvider::Opacity] = 1.0; expectedSignals[KisCanvasResourceProvider::Size] = 300.0; expectedSignals[KisCanvasResourceProvider::Flow] = 1.0; expectedSignals[KisCanvasResourceProvider::CurrentEffectiveCompositeOp] = COMPOSITE_OVER; expectedSignals[KisCanvasResourceProvider::CurrentCompositeOp] = COMPOSITE_OVER; auto it = spy.begin(); for (; it != spy.end(); ++it) { const int id = (*it)[0].toInt(); const QVariant value = (*it)[1]; if (!expectedSignals.contains(id)) { qDebug() << ppVar(id) << ppVar(value); QFAIL("Unexpected signal!"); } else { if (expectedSignals[id] != value) { qDebug() << ppVar(id) << ppVar(value) << ppVar(expectedSignals[id]); QFAIL("Unexpected value!"); } } } QCOMPARE(spy.size(), expectedSignals.size()); spy.clear(); preset->settings()->setPaintOpOpacity(0.8); QCOMPARE(spy.size(), 1); QCOMPARE(spy[0][0].toInt(), (int)KisCanvasResourceProvider::Opacity); QCOMPARE(spy[0][1].toDouble(), 0.8); spy.clear(); mainWindow->hide(); QApplication::processEvents(); delete view; delete doc; delete mainWindow; } KISTEST_MAIN(KisDerivedResourcesTest)