QPA 插件
类名
描述
QWlrootsOutputWindow
Qt窗口平台抽象实现,实现Qt中QWindow部分功能
QWlrootsIntegration
Qt QPA平台插件实现,对接wlroots输入输出到Qt
QWlrootsCursor
Qt QPA光标平台抽象实现,对接wlr_cursor 前端部分功能到Qcursor(代码待完善)
QWlrootsScreen
Qt QPA屏幕平台抽象实现,对接 wlr_output 前端部分功能到 Qscreen
其中如下图1.1所示是将 wlr_renderer 转为 QWlrootsIntegration 的流程:
wlroots支持Pixman、OpenGLES、Vulkan渲染,其与QQuickWindow更加详细的渲染绑定如下图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 QQuickRenderTarget WRenderHelper::acquireRenderTarget (QQuickRenderControl *rc, QWBuffer *buffer) { W_D (WRenderHelper); Q_ASSERT (buffer); if (d->size.isEmpty ()) return {}; for (int i = 0 ; i < d->buffers.count (); ++i) { auto data = d->buffers[i]; if (data->buffer == buffer) { d->lastBuffer = data; return data->renderTarget; } } std::unique_ptr<BufferData> bufferData (new BufferData) ; bufferData->buffer = buffer; auto texture = QWTexture::fromBuffer (d->renderer, buffer); QQuickRenderTarget rt; if (wlr_renderer_is_pixman (d->renderer->handle ())) { pixman_image_t *image = wlr_pixman_texture_get_image (texture->handle ()); void *data = pixman_image_get_data (image); if (bufferData->paintDevice.constBits () != data) bufferData->paintDevice = WTools::fromPixmanImage (image, data); Q_ASSERT (!bufferData->paintDevice.isNull ()); rt = QQuickRenderTarget::fromPaintDevice (&bufferData->paintDevice); } #ifdef ENABLE_VULKAN_RENDER else if (wlr_renderer_is_vk (d->renderer->handle ())) { wlr_vk_image_attribs attribs; wlr_vk_texture_get_image_attribs (texture->handle (), &attribs); rt = QQuickRenderTarget::fromVulkanImage (attribs.image, attribs.layout, attribs.format, d->size); } #endif else if (wlr_renderer_is_gles2 (d->renderer->handle ())) { wlr_gles2_texture_attribs attribs; wlr_gles2_texture_get_attribs (texture->handle (), &attribs); rt = QQuickRenderTarget::fromOpenGLTexture (attribs.tex, d->size); rt.setMirrorVertically (true ); } delete texture; bufferData->renderTarget = rt; if (QSGRendererInterface::isApiRhiBased (getGraphicsApi (rc))) { if (!rt.isNull ()) { if (!d->ensureRhiRenderTarget (rc, bufferData.get ())) bufferData->renderTarget = {}; } if (bufferData->renderTarget.isNull ()) return {}; } connect (buffer, SIGNAL (beforeDestroy ()), this , SLOT (onBufferDestroy ()), Qt::UniqueConnection); d->buffers.append (bufferData.release ()); d->lastBuffer = d->buffers.last (); return d->buffers.last ()->renderTarget; }
屏幕热插拔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void WBackendPrivate::on_new_output (QWOutput *output) { auto woutput = new WOutput (output, q_func ()); outputList << woutput; QWlrootsIntegration::instance ()->addScreen (woutput); woutput->safeConnect (&QWOutput::beforeDestroy, q_func ()->server (), [this , output] { on_output_destroy (output); }); q_func ()->outputAdded (woutput); } void WBackendPrivate::on_output_destroy (QWOutput *output) { for (int i = 0 ; i < outputList.count (); ++i) { if (outputList.at (i)->handle () == output) { auto device = outputList.takeAt (i); q_func ()->outputRemoved (device); delete device; return ; } } } void WBackend::outputRemoved (WOutput *output) { QWlrootsIntegration::instance ()->removeScreen (output); }
输入设备热插拔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void WSeatPrivate::attachInputDevice (WInputDevice *device) { W_Q (WSeat); device->setSeat (q); auto qtDevice = QWlrootsIntegration::instance ()->addInputDevice (device, name); Q_ASSERT (qtDevice); .... } void WSeatPrivate::detachInputDevice (WInputDevice *device) { if (cursor && device->type () == WInputDevice::Type::Pointer) cursor->detachInputDevice (device); bool ok = QWlrootsIntegration::instance ()->removeInputDevice (device); Q_ASSERT (ok); }