Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
vulkanserverbufferintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5
6#include "vulkanwrapper.h"
7
8#include <QtOpenGL/QOpenGLTexture>
9#include <QtGui/QOpenGLContext>
10#include <QtGui/QOffscreenSurface>
11#include <QtGui/qopengl.h>
12
13#include <unistd.h>
14#include <fcntl.h>
15
16#include <QtCore/QDebug>
17
19static constexpr bool vsbiExtraDebug = false;
20
21#define DECL_GL_FUNCTION(name, type) \
22 type name
23
24#define FIND_GL_FUNCTION(name, type) \
25 do { \
26 name = reinterpret_cast<type>(glContext->getProcAddress(#name)); \
27 if (!name) { \
28 qWarning() << "ERROR in GL proc lookup. Could not find " #name; \
29 return false; \
30 } \
31 } while (0)
32
34{
35 DECL_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
36 DECL_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
37 //DECL_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
38 DECL_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
39 DECL_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);
40
41 bool init(QOpenGLContext *glContext)
42 {
43 FIND_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
44 FIND_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
45 //FIND_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
46 FIND_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
47 FIND_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);
48
49 return true;
50 }
51 static bool create(QOpenGLContext *glContext);
52};
53
55
56//RAII
58{
59public:
61 {
64 if (!localContext) {
65 localContext = new QOpenGLContext;
66 localContext->setShareContext(QOpenGLContext::globalShareContext());
67 localContext->create();
68 }
69 if (!offscreenSurface) {
70 offscreenSurface = new QOffscreenSurface;
71 offscreenSurface->setFormat(localContext->format());
72 offscreenSurface->create();
73 }
74 localContext->makeCurrent(offscreenSurface);
75 localContextInUse = true;
76 } else {
77 qCritical("VulkanServerBufferIntegration: no globalShareContext");
78 }
79 }
80 }
82 {
83 if (localContextInUse)
84 localContext->doneCurrent();
85 }
86 QOpenGLContext *context() { return localContextInUse ? localContext : QOpenGLContext::currentContext(); }
87private:
88 static QOpenGLContext *localContext;
89 static QOffscreenSurface *offscreenSurface;
90 bool localContextInUse = false;
91};
92
93QOpenGLContext *CurrentContext::localContext = nullptr;
94QOffscreenSurface *CurrentContext::offscreenSurface = nullptr;
95
97{
98 if (funcs)
99 return true;
101 if (!funcs->init(glContext)) {
102 delete funcs;
103 funcs = nullptr;
104 return false;
105 }
106 return true;
107}
108
110 : QtWayland::ServerBuffer(qimage.size(),format)
111 , m_integration(integration)
112 , m_width(qimage.width())
113 , m_height(qimage.height())
114{
116 switch (m_format) {
117 case RGBA32:
118 m_glInternalFormat = GL_RGBA8;
119 break;
120 // case A8:
121 // m_glInternalFormat = GL_R8;
122 // break;
123 default:
124 qWarning("VulkanServerBuffer: unsupported format");
125 m_glInternalFormat = GL_RGBA8;
126 break;
127 }
128
129 auto vulkanWrapper = m_integration->vulkanWrapper();
130 m_vImage = vulkanWrapper->createTextureImage(qimage);
131 if (m_vImage)
132 m_fd = vulkanWrapper->getImageInfo(m_vImage, &m_memorySize);
133}
134
136 : QtWayland::ServerBuffer(size, QtWayland::ServerBuffer::Custom)
137 , m_integration(integration)
138 , m_width(size.width())
139 , m_height(size.height())
140 , m_vImage(vImage)
141 , m_glInternalFormat(glInternalFormat)
142{
143 auto vulkanWrapper = m_integration->vulkanWrapper();
144 m_fd = vulkanWrapper->getImageInfo(m_vImage, &m_memorySize);
145}
146
148{
149 delete m_texture; //this is always nullptr for now
150 auto vulkanWrapper = m_integration->vulkanWrapper();
151 vulkanWrapper->freeTextureImage(m_vImage);
152}
153
154struct ::wl_resource *VulkanServerBuffer::resourceForClient(struct ::wl_client *client)
155{
156 auto *bufferResource = resourceMap().value(client);
157 if (!bufferResource) {
158 auto integrationResource = m_integration->resourceMap().value(client);
159 if (!integrationResource) {
160 qWarning("VulkanServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the vulkan interface");
161 return nullptr;
162 }
163 struct ::wl_resource *shm_integration_resource = integrationResource->handle;
164 Resource *resource = add(client, 1);
165 m_integration->send_server_buffer_created(shm_integration_resource, resource->handle, m_fd, m_width, m_height, m_memorySize, m_glInternalFormat);
166 return resource->handle;
167 }
168 return bufferResource->handle;
169}
170
172{
173 if (m_texture && m_texture->isCreated())
174 return m_texture;
175
176 CurrentContext current;
177
179 return nullptr;
180
181 funcs->glCreateMemoryObjectsEXT(1, &m_memoryObject);
182 if (vsbiExtraDebug) qDebug() << "glCreateMemoryObjectsEXT" << Qt::hex << glGetError();
183
184
185 int dupfd = fcntl(m_fd, F_DUPFD_CLOEXEC, 0);
186 if (dupfd < 0) {
187 perror("VulkanServerBuffer::toOpenGlTexture() Could not dup fd:");
188 return nullptr;
189 }
190
191 funcs->glImportMemoryFdEXT(m_memoryObject, m_memorySize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, dupfd);
192 if (vsbiExtraDebug) qDebug() << "glImportMemoryFdEXT" << Qt::hex << glGetError();
193
194
195 if (!m_texture)
197 m_texture->create();
198
199 GLuint texId = m_texture->textureId();
200 if (vsbiExtraDebug) qDebug() << "created texture" << texId << Qt::hex << glGetError();
201
202 m_texture->bind();
203 if (vsbiExtraDebug) qDebug() << "bound texture" << texId << Qt::hex << glGetError();
204 funcs->glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_glInternalFormat, m_size.width(), m_size.height(), m_memoryObject, 0 );
205 if (vsbiExtraDebug) qDebug() << "glTexStorageMem2DEXT" << Qt::hex << glGetError();
206 if (vsbiExtraDebug) qDebug() << "format" << Qt::hex << m_glInternalFormat << GL_RGBA8;
207
208
209 return m_texture;
210}
211
213{
214 if (!m_texture || !m_texture->isCreated())
215 return;
216
217 CurrentContext current;
218 m_texture->destroy();
219 funcs->glDeleteMemoryObjectsEXT(1, &m_memoryObject);
220}
221
222
224{
225 return (m_texture && m_texture->isCreated()) || resourceMap().size() > 0;
226}
227
229{
230 qCDebug(qLcWaylandCompositorHardwareIntegration) << "server_buffer RELEASE resource" << resource->handle << wl_resource_get_id(resource->handle) << "for client" << resource->client();
231 wl_resource_destroy(resource->handle);
232}
233
237
241
243{
245
246 QtWaylandServer::zqt_vulkan_server_buffer_v1::init(compositor->display(), 1);
247 return true;
248}
249
251{
252 switch (format) {
254 return true;
256 return false;
257 default:
258 return false;
259 }
260}
261
263{
264 if (!m_vulkanWrapper) {
265 CurrentContext current;
266 m_vulkanWrapper = new VulkanWrapper(current.context());
267 }
268 return new VulkanServerBuffer(this, qimage, format);
269}
270
273 uint glInternalFormat)
274{
275 if (!m_vulkanWrapper) {
276 CurrentContext current;
277 m_vulkanWrapper = new VulkanWrapper(current.context());
278 }
279
280 auto *vImage = m_vulkanWrapper->createTextureImageFromData(
281 reinterpret_cast<const uchar *>(view.constData()), view.size(), size, glInternalFormat);
282
283 if (vImage)
284 return new VulkanServerBuffer(this, vImage, glInternalFormat, size);
285
286 qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not load compressed texture";
287 return nullptr;
288}
289
static QPlatformNativeInterface * platformNativeInterface()
\inmodule QtGui
Definition qimage.h:37
\inmodule QtGui
\inmodule QtGui
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
static QOpenGLContext * globalShareContext()
\inmodule QtGui
bool isCreated() const
Returns true if the underlying OpenGL texture object has been created.
void destroy()
Destroys the underlying OpenGL texture object.
bool create()
Creates the underlying OpenGL texture object.
void bind()
Binds this texture to the currently active texture unit ready for rendering.
GLuint textureId() const
Returns the name of the underlying OpenGL texture object or 0 if it has not yet been created.
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
bool supportsFormat(QtWayland::ServerBuffer::Format format) const override
bool initializeHardware(QWaylandCompositor *) override
QtWayland::ServerBuffer * createServerBufferFromData(QByteArrayView view, const QSize &size, uint glInternalFormat) override
QtWayland::ServerBuffer * createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format) override
VulkanServerBuffer(VulkanServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
void server_buffer_release(Resource *resource) override
QOpenGLTexture * toOpenGlTexture() override
struct::wl_resource * resourceForClient(struct ::wl_client *) override
VulkanImageWrapper * createTextureImageFromData(const uchar *pixels, uint bufferSize, const QSize &size, uint glInternalFormat)
void freeTextureImage(VulkanImageWrapper *imageWrapper)
static QT_BEGIN_NAMESPACE constexpr bool vsbiExtraDebug
static VulkanServerBufferGlFunctions * funcs
#define FIND_GL_FUNCTION(name, type)
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
#define qCritical
Definition qlogging.h:167
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qCWarning(category,...)
#define qCDebug(category,...)
static QOpenGLCompositor * compositor
#define GL_HANDLE_TYPE_OPAQUE_FD_EXT
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei width
GLint GLsizei GLsizei GLenum format
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define GL_RGBA8
#define GLuint
unsigned char uchar
Definition qtypes.h:32
unsigned int uint
Definition qtypes.h:34
QQuickView * view
[0]
view create()
DECL_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC)
DECL_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC)
DECL_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC)
DECL_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC)
static bool create(QOpenGLContext *glContext)