Skip to content

Commit a00f3fc

Browse files
committed
Add support capturing QtQuick windows backed by Qt Rhi
This is an interesting QtQuick backend to support because of some of the inherent design limitations we have to work around. But we are now able to capture and draw target decorations for these windows backed by Rhi now. The first problem we have to tackle is actually capturing the window contents, but fortunately Qt already has public API to do this. They don't provide a mapping from their bespoke Rhi texture format to QImage unfortunately, but I added a user-visible error message so it's easier for people to submit bugreports for any missing cases. I tried to optimize the readback as best I could, and the performance is about on-par to the OpenGL screen grabber. (I didn't actually benchmark, but it looks good enough to my own eyes.) Another tricky problem to tackle is drawing the remote target decorations, because we previously assumed we always had a QPainter to draw in. (For context, the client's viewport is drawn in QPainter and in the OpenGL there's QOpenGLPaintDevice available.) Not only that, but we can't exactly tell *when* to let Qt readback the swapchain image. The pre-existing screengrabbers grabbed the backbuffer before we drew target decorations so we could draw them client-side. For the drawing part I don't think there's anything we could do save for rewriting it in QtRHI, so we upload it into a texture and draw it onto the backbuffer. Yes it is "slow" but it's more than good enough than it not working at all. For the target decoration part that's not going to be easily possible, so I decided to not do it! Instead, we let ourselves capture the full window contents *including* the decorations we drew. We then skip drawing decorations client-side, and it's practically the same experience save for anything drawn outside the window. That limitation is going to be planned to be addressed in a future patch.
1 parent 5bb3e8d commit a00f3fc

8 files changed

Lines changed: 441 additions & 8 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ if(Qt6Gui_VERSION VERSION_GREATER_EQUAL "6.10.0")
506506
find_package(Qt6WidgetsPrivate REQUIRED NO_MODULE)
507507
find_package(Qt6QmlPrivate NO_MODULE)
508508
find_package(Qt6QuickPrivate NO_MODULE)
509+
find_package(Qt6QuickWidgetsPrivate NO_MODULE)
510+
find_package(Qt6GuiPrivate NO_MODULE)
509511
endif()
510512

511513
# these need to included after the last Qt-related find_package() call

plugins/quickinspector/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,27 @@ if(NOT GAMMARAY_CLIENT_ONLY_BUILD)
7979
)
8080
endif()
8181

82+
qt_add_shaders(
83+
gammaray_quickinspector
84+
"gammaray_quickinspector_shaders"
85+
PRECOMPILE
86+
OPTIMIZED
87+
PREFIX
88+
"/gammaray_quickinspector_shaders/"
89+
FILES
90+
"shaders/rhi_inspector_decorations.vert"
91+
"shaders/rhi_inspector_decorations.frag"
92+
)
93+
8294
target_link_libraries(
8395
gammaray_quickinspector
8496
gammaray_quickinspector_shared
8597
gammaray_core
8698
Qt::Quick
8799
Qt::QuickPrivate
100+
Qt::QuickWidgets
101+
Qt::QuickWidgetsPrivate
102+
Qt::GuiPrivate
88103
gammaray_kitemmodels
89104
)
90105

plugins/quickinspector/quickinspector.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ void RenderModeRequest::apply()
292292
if (connection)
293293
disconnect(connection);
294294

295-
if (window && window->rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL)
295+
if (window && window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
296296
return;
297297

298298
if (window) {
@@ -612,10 +612,10 @@ void QuickInspector::checkFeatures()
612612
return;
613613
}
614614

615-
if (m_window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL)
616-
f = AllCustomRenderModes;
617-
else if (m_window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
615+
if (m_window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
618616
f = AnalyzePainting;
617+
else
618+
f = AllCustomRenderModes;
619619

620620
emit features(f);
621621
}

plugins/quickinspector/quickscenepreviewwidget.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ void QuickScenePreviewWidget::resizeEvent(QResizeEvent *e)
152152

153153
void QuickScenePreviewWidget::renderDecoration(QPainter *p, double zoom) const
154154
{
155+
// TODO: only do this for RHI-based graphics APIs (QSGRenderInterface::isApiRhiBased)
156+
// We want to skip rendering decorations in the client, if we draw it on the target and this rendering backend cannot discern between the two.
157+
if (m_control->serverSideDecorationsEnabled()) {
158+
return;
159+
}
160+
155161
// Scaling and translations on QuickItemGeometry will be done on demand
156162

157163
if (frame().data.userType() == qMetaTypeId<QuickItemGeometry>()) {

0 commit comments

Comments
 (0)