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
qplatformgraphicsbufferhelper.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtGui/qpa/qplatformgraphicsbuffer.h>
5
7#include <QtCore/QDebug>
8#include <QtGui/qopengl.h>
9#include <QtGui/QImage>
10#include <QtGui/QOpenGLContext>
11#include <QtGui/QOpenGLFunctions>
12
13#ifndef GL_UNPACK_ROW_LENGTH
14#define GL_UNPACK_ROW_LENGTH 0x0CF2
15#endif
16
17#ifndef GL_RGB10_A2
18#define GL_RGB10_A2 0x8059
19#endif
20
21#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
22#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
23#endif
24
26
59 bool *swizzle, bool *premultiplied,
60 const QRect &rect)
61{
62 if (graphicsBuffer->lock(QPlatformGraphicsBuffer::TextureAccess)) {
63 if (!graphicsBuffer->bindToTexture(rect)) {
64 qWarning("Failed to bind %sgraphicsbuffer to texture", "");
65 return false;
66 }
67 if (swizzle)
68 *swizzle = false;
69 if (premultiplied)
70 *premultiplied = false;
71 } else if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) {
72 if (!bindSWToTexture(graphicsBuffer, swizzle, premultiplied, rect)) {
73 qWarning("Failed to bind %sgraphicsbuffer to texture", "SW ");
74 return false;
75 }
76 } else {
77 qWarning("Failed to lock");
78 return false;
79 }
80 return true;
81}
82
109 bool *swizzleRandB, bool *premultipliedB,
110 const QRect &subRect)
111{
112#ifndef QT_NO_OPENGL
114 if (!ctx)
115 return false;
116
117 if (!(graphicsBuffer->isLocked() & QPlatformGraphicsBuffer::SWReadAccess))
118 return false;
119
120 QSize size = graphicsBuffer->size();
121
122 Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect));
123
125 GLuint pixelType = GL_UNSIGNED_BYTE;
126
127 bool needsConversion = false;
128 bool swizzle = false;
129 bool premultiplied = false;
130 QImage::Format imageformat = QImage::toImageFormat(graphicsBuffer->format());
131 QImage image(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), imageformat);
132 switch (imageformat) {
134 premultiplied = true;
138 swizzle = true;
139 break;
141 premultiplied = true;
145 break;
148 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
151 premultiplied = true;
152 } else {
153 needsConversion = true;
154 }
155 break;
158 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
161 premultiplied = true;
162 swizzle = true;
163 } else {
164 needsConversion = true;
165 }
166 break;
167 default:
168 needsConversion = true;
169 break;
170 }
171 if (!needsConversion && image.bytesPerLine() != (size.width() * 4) && ctx->isOpenGLES() && ctx->format().majorVersion() < 3)
172 needsConversion = true;
173 if (needsConversion)
175
176 bool needsRowLength = (image.bytesPerLine() != image.width() * 4);
177 QOpenGLFunctions *funcs = ctx->functions();
178
179 QRect rect = subRect;
180 if (rect.isNull() || rect == QRect(QPoint(0,0),size)) {
181 if (needsRowLength)
182 funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(image.bytesPerLine() / 4));
183 funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(), 0, GL_RGBA, pixelType, image.constBits());
184 if (needsRowLength)
185 funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
186 } else {
187 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
188 // OpenGL 2.1+ or OpenGL ES/3+
189 funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(image.bytesPerLine() / 4));
190 funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
191 image.constScanLine(rect.y()) + rect.x() * 4);
192 funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
193 } else
194 {
195 // if the rect is wide enough it's cheaper to just
196 // extend it instead of doing an image copy
197 if (rect.width() >= size.width() / 2) {
198 rect.setX(0);
199 rect.setWidth(size.width());
200 }
201
202 // if the sub-rect is full-width we can pass the image data directly to
203 // OpenGL instead of copying, since there's no gap between scanlines
204
205 if (rect.width() == image.bytesPerLine() / 4) {
206 funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
207 image.constScanLine(rect.y()));
208 } else {
209 funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
210 image.copy(rect).constBits());
211 }
212 }
213 }
214 if (swizzleRandB)
215 *swizzleRandB = swizzle;
216 if (premultipliedB)
217 *premultipliedB = premultiplied;
218
219 return true;
220
221#else
222 Q_UNUSED(graphicsBuffer);
223 Q_UNUSED(swizzleRandB);
224 Q_UNUSED(premultipliedB);
225 Q_UNUSED(subRect);
226 return false;
227#endif // QT_NO_OPENGL
228}
229
\inmodule QtGui
Definition qimage.h:37
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_RGBA8888
Definition qimage.h:59
@ Format_RGB30
Definition qimage.h:63
@ Format_RGB32
Definition qimage.h:46
@ Format_RGBA8888_Premultiplied
Definition qimage.h:60
@ Format_A2BGR30_Premultiplied
Definition qimage.h:62
@ Format_BGR30
Definition qimage.h:61
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
@ Format_A2RGB30_Premultiplied
Definition qimage.h:64
@ Format_ARGB32
Definition qimage.h:47
@ Format_RGBX8888
Definition qimage.h:58
static QImage::Format toImageFormat(QPixelFormat format) noexcept
Converts format into a QImage::Format.
Definition qimage.cpp:6401
\inmodule QtGui
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
virtual bool bindToTexture(const QRect &rect=QRect()) const
Binds the content of this graphics buffer into the currently bound texture.
virtual const uchar * data() const
Accessor for the bytes of the buffer.
virtual int bytesPerLine() const
Accessor for bytes per line in the graphics buffer.
AccessTypes isLocked() const
Function to check if the buffer is locked.
QPixelFormat format() const
Accessor for the pixel format of the buffer.
bool lock(AccessTypes access, const QRect &rect=QRect())
Before the data can be retrieved or before a buffer can be bound to a texture it needs to be locked.
QSize size() const
Accessor for content size.
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
EGLContext ctx
static VulkanServerBufferGlFunctions * funcs
rect
[4]
Q_GUI_EXPORT bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, const QRect &rect=QRect())
Convenience function to both lock and bind the graphicsBuffer to a texture.
bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB=nullptr, bool *premultipliedB=nullptr, const QRect &rect=QRect())
Convenience function that uploads the current raster content to the currently bound texture.
Combined button and popup list for selecting options.
Definition image.cpp:4
#define Q_FALLTHROUGH()
#define qWarning
Definition qlogging.h:166
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
GLenum GLuint GLintptr GLsizeiptr size
[1]
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLsizei GLenum internalFormat
GLuint GLenum swizzle
#define GL_UNSIGNED_INT_2_10_10_10_REV
#define GL_UNPACK_ROW_LENGTH
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define GLuint
#define GL_UNSIGNED_BYTE
#define GL_RGBA
#define Q_UNUSED(x)