Notes on how to make Krita's canvas embeddable into QML graph
General considerations
- QML can render arbitrary openGL/DirectX/Metal code below or under QML graph. See example here.
- There is also an option to make a full-featured QML object that would render its contents using GPU directly and choose rendering API on the fly. See another example here.
- Both options above are already available in Qt5.
- In Qt6 QML will be using some weird RHI interface that would abstract graphics API somehow. I didn't manage to understand what it is going to be and whether we would be able to use that.
Roadmap for porting Krita to QML
- We have a special class KisAbstractCanvasWidget that abstracts the graphical API. So we would need to make implmentations of it for openGL, DirectX and/or PHI.
- KisAbstractCanvasWidget::widget() will have to be refactored into some higher-level interface. It is used for three purposes actually.
- issue repaint for QOpenGLWidget with canvas->widget()->update(rc)
- setup event filter on it in KisInputManager
- for scrolling in KoCanvasControllerWidget
- KoCanvasControllerWidget will have to be refactored for not using QScrollArea and use the QML version instead. It already inherits from an abstract KoCanvasController, so in theory it should be "not difficult". The problem is that after splitting from Calligra we didn't keep this abstraction clean (there was only one implementation), so the refactoring may become a bit painful. It might happen that the whole zooming infrastructure will have to be refactored (though it would be nice to do that even without porting to QML).
- KisViewManager::statusBar() will have to be refactored into some abstract interface, like KoProgressProxy plus something.
- KisViewManager::paintOpBox() will have to be removed and replaced with some abstract interface (and the whole KisControlFrame will have to be rewritten in QML).
- KisViewManager::mainWindow() will have to go. We use it in rather surprising contexts. E.g. in KisNodeManager::slotTryRestartIsolatedMode() we check if we are the active window and skip restarting for non-active windows.
- All the actions are now loaded by KXmlGuiWindow. We will have to extract this code somehow and create KActionCollection manually.
- Some zoom actions are implemented by accessing "widgets" instead of abstract controllers. Specifically, KisZoomAction uses KoZoomAction widget to switch between predefined zoom levels on wheel events (12.5%,25%,50%,100%). This functionality will have to be moved into a generic class, e.g. KoZoomController (I don't know why it is not there atm).
Questions to be answered/investigated
- Qt6 is going to drop support of ANGLE. Will RHI interface provide us any usable abstractions? Or we will have to implement our canvas code for three native interfaces: openGL, DirectX and Metal? [1]
- Qt6's LTS releases are going to be closed-source only (well, with 1 year delay), so we will have to maintain it somehow ourselves. How are we going to do that?
- Porting Krita to QML will be a huge investment of work. Given that we have plans for GUI redesign anyway, perhaps we could start thinking about some other options we have?
[1] - UPD: as far as I can tell, RHI is going to be an internal API and not available to the users. At least for a few first versions.