mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-02-25 03:43:58 +11:00
wayland/screencopy: support dmabufs in vulkan mode
This commit is contained in:
parent
158db16b93
commit
a99519c3ad
8 changed files with 375 additions and 2 deletions
|
|
@ -1,6 +1,8 @@
|
|||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(dmabuf-deps REQUIRED IMPORTED_TARGET libdrm gbm egl)
|
||||
|
||||
find_package(VulkanHeaders REQUIRED)
|
||||
|
||||
qt_add_library(quickshell-wayland-buffer STATIC
|
||||
manager.cpp
|
||||
dmabuf.cpp
|
||||
|
|
@ -10,9 +12,10 @@ qt_add_library(quickshell-wayland-buffer STATIC
|
|||
wl_proto(wlp-linux-dmabuf linux-dmabuf-v1 "${WAYLAND_PROTOCOLS}/stable/linux-dmabuf")
|
||||
|
||||
target_link_libraries(quickshell-wayland-buffer PRIVATE
|
||||
Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
|
||||
Qt::Quick Qt::QuickPrivate Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
|
||||
PkgConfig::dmabuf-deps
|
||||
wlp-linux-dmabuf
|
||||
Vulkan::Headers
|
||||
)
|
||||
|
||||
qs_pch(quickshell-wayland-buffer SET large)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <gbm.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
#include <private/qquickwindow_p.h>
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qdebug.h>
|
||||
#include <qlist.h>
|
||||
|
|
@ -24,12 +25,17 @@
|
|||
#include <qpair.h>
|
||||
#include <qquickwindow.h>
|
||||
#include <qscopedpointer.h>
|
||||
#include <qsgrendererinterface.h>
|
||||
#include <qsgtexture_platform.h>
|
||||
#include <qvulkanfunctions.h>
|
||||
#include <qvulkaninstance.h>
|
||||
#include <qwayland-linux-dmabuf-v1.h>
|
||||
#include <qwaylandclientextension.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <qtypes.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <wayland-linux-dmabuf-v1-client-protocol.h>
|
||||
#include <wayland-util.h>
|
||||
|
|
@ -48,6 +54,25 @@ QS_LOGGING_CATEGORY(logDmabuf, "quickshell.wayland.buffer.dmabuf", QtWarningMsg)
|
|||
|
||||
LinuxDmabufManager* MANAGER = nullptr; // NOLINT
|
||||
|
||||
VkFormat drmFormatToVkFormat(uint32_t drmFormat) {
|
||||
// NOLINTBEGIN(bugprone-branch-clone): XRGB/ARGB intentionally map to the same VK format
|
||||
switch (drmFormat) {
|
||||
case DRM_FORMAT_ARGB8888: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case DRM_FORMAT_XRGB8888: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case DRM_FORMAT_ABGR8888: return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case DRM_FORMAT_XBGR8888: return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case DRM_FORMAT_ARGB2101010: return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
|
||||
case DRM_FORMAT_XRGB2101010: return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
|
||||
case DRM_FORMAT_ABGR2101010: return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
case DRM_FORMAT_XBGR2101010: return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
case DRM_FORMAT_ABGR16161616F: return VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
case DRM_FORMAT_RGB565: return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
case DRM_FORMAT_BGR565: return VK_FORMAT_B5G6R5_UNORM_PACK16;
|
||||
default: return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
// NOLINTEND(bugprone-branch-clone)
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const FourCCStr& fourcc) {
|
||||
|
|
@ -532,6 +557,15 @@ bool WlDmaBuffer::isCompatible(const WlBufferRequest& request) const {
|
|||
}
|
||||
|
||||
WlBufferQSGTexture* WlDmaBuffer::createQsgTexture(QQuickWindow* window) const {
|
||||
auto* ri = window->rendererInterface();
|
||||
if (ri && ri->graphicsApi() == QSGRendererInterface::Vulkan) {
|
||||
return this->createQsgTextureVulkan(window);
|
||||
}
|
||||
|
||||
return this->createQsgTextureGl(window);
|
||||
}
|
||||
|
||||
WlBufferQSGTexture* WlDmaBuffer::createQsgTextureGl(QQuickWindow* window) const {
|
||||
static auto* glEGLImageTargetTexture2DOES = []() {
|
||||
auto* fn = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(
|
||||
eglGetProcAddress("glEGLImageTargetTexture2DOES")
|
||||
|
|
@ -662,6 +696,291 @@ WlBufferQSGTexture* WlDmaBuffer::createQsgTexture(QQuickWindow* window) const {
|
|||
return tex;
|
||||
}
|
||||
|
||||
WlBufferQSGTexture* WlDmaBuffer::createQsgTextureVulkan(QQuickWindow* window) const {
|
||||
auto* ri = window->rendererInterface();
|
||||
auto* vkInst = window->vulkanInstance();
|
||||
|
||||
if (!vkInst) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: no QVulkanInstance.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* vkDevicePtr =
|
||||
static_cast<VkDevice*>(ri->getResource(window, QSGRendererInterface::DeviceResource));
|
||||
auto* vkPhysDevicePtr = static_cast<VkPhysicalDevice*>(
|
||||
ri->getResource(window, QSGRendererInterface::PhysicalDeviceResource)
|
||||
);
|
||||
|
||||
if (!vkDevicePtr || !vkPhysDevicePtr) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: could not get Vulkan device.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VkDevice device = *vkDevicePtr;
|
||||
VkPhysicalDevice physDevice = *vkPhysDevicePtr;
|
||||
|
||||
auto* devFuncs = vkInst->deviceFunctions(device);
|
||||
auto* instFuncs = vkInst->functions();
|
||||
|
||||
if (!devFuncs || !instFuncs) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: "
|
||||
"could not get Vulkan functions.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto getMemoryFdPropertiesKHR = reinterpret_cast<PFN_vkGetMemoryFdPropertiesKHR>(
|
||||
instFuncs->vkGetDeviceProcAddr(device, "vkGetMemoryFdPropertiesKHR")
|
||||
);
|
||||
|
||||
if (!getMemoryFdPropertiesKHR) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: "
|
||||
"vkGetMemoryFdPropertiesKHR not available. "
|
||||
"Missing VK_KHR_external_memory_fd extension.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const VkFormat vkFormat = drmFormatToVkFormat(this->format);
|
||||
if (vkFormat == VK_FORMAT_UNDEFINED) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: unsupported DRM format"
|
||||
<< FourCCStr(this->format);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (this->planeCount > 4) {
|
||||
qCWarning(logDmabuf) << "Failed to create Vulkan QSG texture: too many planes"
|
||||
<< this->planeCount;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::array<VkSubresourceLayout, 4> planeLayouts = {};
|
||||
for (int i = 0; i < this->planeCount; ++i) {
|
||||
planeLayouts[i].offset = this->planes[i].offset; // NOLINT
|
||||
planeLayouts[i].rowPitch = this->planes[i].stride; // NOLINT
|
||||
planeLayouts[i].size = 0;
|
||||
planeLayouts[i].arrayPitch = 0;
|
||||
planeLayouts[i].depthPitch = 0;
|
||||
}
|
||||
|
||||
const bool useModifier = this->modifier != DRM_FORMAT_MOD_INVALID;
|
||||
|
||||
VkExternalMemoryImageCreateInfo externalInfo = {};
|
||||
externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||
externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
|
||||
VkImageDrmFormatModifierExplicitCreateInfoEXT modifierInfo = {};
|
||||
modifierInfo.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
|
||||
modifierInfo.drmFormatModifier = this->modifier;
|
||||
modifierInfo.drmFormatModifierPlaneCount = static_cast<uint32_t>(this->planeCount);
|
||||
modifierInfo.pPlaneLayouts = planeLayouts.data();
|
||||
|
||||
if (useModifier) {
|
||||
externalInfo.pNext = &modifierInfo;
|
||||
}
|
||||
|
||||
VkImageCreateInfo imageInfo = {};
|
||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageInfo.pNext = &externalInfo;
|
||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = vkFormat;
|
||||
imageInfo.extent = {.width = this->width, .height = this->height, .depth = 1};
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.arrayLayers = 1;
|
||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.tiling = useModifier ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : VK_IMAGE_TILING_LINEAR;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkResult result = devFuncs->vkCreateImage(device, &imageInfo, nullptr, &image);
|
||||
if (result != VK_SUCCESS) {
|
||||
qCWarning(logDmabuf) << "Failed to create VkImage for DMA-BUF import, result:" << result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
|
||||
// dup() is required because vkAllocateMemory with VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
|
||||
// takes ownership of the fd on succcess. Without dup, WlDmaBuffer would double-close.
|
||||
const int dupFd = dup(this->planes[0].fd); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (dupFd < 0) {
|
||||
qCWarning(logDmabuf) << "Failed to dup() fd for DMA-BUF import";
|
||||
goto cleanup_fail; // NOLINT
|
||||
}
|
||||
|
||||
{
|
||||
VkMemoryRequirements memReqs = {};
|
||||
devFuncs->vkGetImageMemoryRequirements(device, image, &memReqs);
|
||||
|
||||
VkMemoryFdPropertiesKHR fdProps = {};
|
||||
fdProps.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
|
||||
|
||||
result = getMemoryFdPropertiesKHR(
|
||||
device,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
||||
dupFd,
|
||||
&fdProps
|
||||
);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
close(dupFd);
|
||||
qCWarning(logDmabuf) << "vkGetMemoryFdPropertiesKHR failed, result:" << result;
|
||||
goto cleanup_fail; // NOLINT
|
||||
}
|
||||
|
||||
const uint32_t memTypeBits = memReqs.memoryTypeBits & fdProps.memoryTypeBits;
|
||||
|
||||
VkPhysicalDeviceMemoryProperties memProps = {};
|
||||
instFuncs->vkGetPhysicalDeviceMemoryProperties(physDevice, &memProps);
|
||||
|
||||
uint32_t memTypeIndex = UINT32_MAX;
|
||||
for (uint32_t j = 0; j < memProps.memoryTypeCount; ++j) {
|
||||
if (memTypeBits & (1u << j)) {
|
||||
memTypeIndex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (memTypeIndex == UINT32_MAX) {
|
||||
close(dupFd);
|
||||
qCWarning(logDmabuf) << "No compatible memory type for DMA-BUF import";
|
||||
goto cleanup_fail; // NOLINT
|
||||
}
|
||||
|
||||
VkImportMemoryFdInfoKHR importInfo = {};
|
||||
importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
|
||||
importInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
importInfo.fd = dupFd;
|
||||
|
||||
VkMemoryDedicatedAllocateInfo dedicatedInfo = {};
|
||||
dedicatedInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
||||
dedicatedInfo.image = image;
|
||||
dedicatedInfo.pNext = &importInfo;
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.pNext = &dedicatedInfo;
|
||||
allocInfo.allocationSize = memReqs.size;
|
||||
allocInfo.memoryTypeIndex = memTypeIndex;
|
||||
|
||||
result = devFuncs->vkAllocateMemory(device, &allocInfo, nullptr, &memory);
|
||||
if (result != VK_SUCCESS) {
|
||||
close(dupFd);
|
||||
qCWarning(logDmabuf) << "vkAllocateMemory failed, result:" << result;
|
||||
goto cleanup_fail; // NOLINT
|
||||
}
|
||||
|
||||
result = devFuncs->vkBindImageMemory(device, image, memory, 0);
|
||||
if (result != VK_SUCCESS) {
|
||||
qCWarning(logDmabuf) << "vkBindImageMemory failed, result:" << result;
|
||||
goto cleanup_fail; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// acquire the DMA-BUF from the foreign (compositor) queue and transition
|
||||
// to shader-read layout. oldLayout must be GENERAL (not UNDEFINED) to
|
||||
// preserve the DMA-BUF contents written by the external producer. Hopefully.
|
||||
window->beginExternalCommands();
|
||||
|
||||
auto* cmdBufPtr = static_cast<VkCommandBuffer*>(
|
||||
ri->getResource(window, QSGRendererInterface::CommandListResource)
|
||||
);
|
||||
|
||||
if (cmdBufPtr && *cmdBufPtr) {
|
||||
VkCommandBuffer cmdBuf = *cmdBufPtr;
|
||||
|
||||
// find the graphics queue family index for the ownrship transfer.
|
||||
uint32_t graphicsQueueFamily = 0;
|
||||
uint32_t queueFamilyCount = 0;
|
||||
instFuncs->vkGetPhysicalDeviceQueueFamilyProperties(
|
||||
physDevice, &queueFamilyCount, nullptr
|
||||
);
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
instFuncs->vkGetPhysicalDeviceQueueFamilyProperties(
|
||||
physDevice, &queueFamilyCount, queueFamilies.data()
|
||||
);
|
||||
for (uint32_t i = 0; i < queueFamilyCount; ++i) {
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
graphicsQueueFamily = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier = {};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
|
||||
barrier.dstQueueFamilyIndex = graphicsQueueFamily;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
devFuncs->vkCmdPipelineBarrier(
|
||||
cmdBuf,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
1,
|
||||
&barrier
|
||||
);
|
||||
}
|
||||
|
||||
window->endExternalCommands();
|
||||
|
||||
auto* qsgTexture = QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(
|
||||
reinterpret_cast<quint64>(image),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
static_cast<uint>(vkFormat),
|
||||
QSize(static_cast<int>(this->width), static_cast<int>(this->height)),
|
||||
{}
|
||||
);
|
||||
|
||||
auto* tex = new WlDmaBufferVulkanQSGTexture(
|
||||
devFuncs,
|
||||
device,
|
||||
image,
|
||||
memory,
|
||||
qsgTexture
|
||||
);
|
||||
qCDebug(logDmabuf) << "Created WlDmaBufferVulkanQSGTexture" << tex << "from" << this;
|
||||
return tex;
|
||||
}
|
||||
|
||||
cleanup_fail:
|
||||
if (image != VK_NULL_HANDLE) {
|
||||
devFuncs->vkDestroyImage(device, image, nullptr);
|
||||
}
|
||||
if (memory != VK_NULL_HANDLE) {
|
||||
devFuncs->vkFreeMemory(device, memory, nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WlDmaBufferVulkanQSGTexture::~WlDmaBufferVulkanQSGTexture() {
|
||||
delete this->qsgTexture;
|
||||
|
||||
if (this->image != VK_NULL_HANDLE) {
|
||||
this->devFuncs->vkDestroyImage(this->device, this->image, nullptr);
|
||||
}
|
||||
|
||||
if (this->memory != VK_NULL_HANDLE) {
|
||||
this->devFuncs->vkFreeMemory(this->device, this->memory, nullptr);
|
||||
}
|
||||
|
||||
qCDebug(logDmabuf) << "WlDmaBufferVulkanQSGTexture" << this << "destroyed.";
|
||||
}
|
||||
|
||||
WlDmaBufferQSGTexture::~WlDmaBufferQSGTexture() {
|
||||
auto* context = QOpenGLContext::currentContext();
|
||||
auto* display = context->nativeInterface<QNativeInterface::QEGLContext>()->display();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
|
@ -12,9 +13,11 @@
|
|||
#include <qsize.h>
|
||||
#include <qtclasshelpermacros.h>
|
||||
#include <qtypes.h>
|
||||
#include <qvulkanfunctions.h>
|
||||
#include <qwayland-linux-dmabuf-v1.h>
|
||||
#include <qwaylandclientextension.h>
|
||||
#include <sys/types.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <wayland-linux-dmabuf-v1-client-protocol.h>
|
||||
#include <wayland-util.h>
|
||||
#include <xf86drm.h>
|
||||
|
|
@ -114,6 +117,36 @@ private:
|
|||
friend class WlDmaBuffer;
|
||||
};
|
||||
|
||||
class WlDmaBufferVulkanQSGTexture: public WlBufferQSGTexture {
|
||||
public:
|
||||
~WlDmaBufferVulkanQSGTexture() override;
|
||||
Q_DISABLE_COPY_MOVE(WlDmaBufferVulkanQSGTexture);
|
||||
|
||||
[[nodiscard]] QSGTexture* texture() const override { return this->qsgTexture; }
|
||||
|
||||
private:
|
||||
WlDmaBufferVulkanQSGTexture(
|
||||
QVulkanDeviceFunctions* devFuncs,
|
||||
VkDevice device,
|
||||
VkImage image,
|
||||
VkDeviceMemory memory,
|
||||
QSGTexture* qsgTexture
|
||||
)
|
||||
: devFuncs(devFuncs)
|
||||
, device(device)
|
||||
, image(image)
|
||||
, memory(memory)
|
||||
, qsgTexture(qsgTexture) {}
|
||||
|
||||
QVulkanDeviceFunctions* devFuncs = nullptr;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
QSGTexture* qsgTexture = nullptr;
|
||||
|
||||
friend class WlDmaBuffer;
|
||||
};
|
||||
|
||||
class WlDmaBuffer: public WlBuffer {
|
||||
public:
|
||||
~WlDmaBuffer() override;
|
||||
|
|
@ -151,6 +184,9 @@ private:
|
|||
|
||||
friend class LinuxDmabufManager;
|
||||
friend QDebug& operator<<(QDebug& debug, const WlDmaBuffer* buffer);
|
||||
|
||||
[[nodiscard]] WlBufferQSGTexture* createQsgTextureGl(QQuickWindow* window) const;
|
||||
[[nodiscard]] WlBufferQSGTexture* createQsgTextureVulkan(QQuickWindow* window) const;
|
||||
};
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const WlDmaBuffer* buffer);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <qqmlengine.h>
|
||||
#include <qqmlinfo.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qquickgraphicsconfiguration.h>
|
||||
#include <qquickitem.h>
|
||||
#include <qquickwindow.h>
|
||||
#include <qregion.h>
|
||||
|
|
@ -147,6 +148,15 @@ void ProxyWindowBase::ensureQWindow() {
|
|||
this->window = nullptr; // createQQuickWindow may indirectly reference this->window
|
||||
this->window = this->createQQuickWindow();
|
||||
this->window->setFormat(format);
|
||||
|
||||
// needed for vulkan dmabuf import, qt ignores these if not applicable
|
||||
auto graphicsConfig = this->window->graphicsConfiguration();
|
||||
graphicsConfig.setDeviceExtensions({
|
||||
"VK_KHR_external_memory_fd",
|
||||
"VK_EXT_external_memory_dma_buf",
|
||||
"VK_EXT_image_drm_format_modifier",
|
||||
});
|
||||
this->window->setGraphicsConfiguration(graphicsConfig);
|
||||
}
|
||||
|
||||
void ProxyWindowBase::createWindow() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue