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
qopenglcompositorbackingstore.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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/QOpenGLContext>
5#include <QtGui/QWindow>
6#include <QtGui/QPainter>
7#include <qpa/qplatformbackingstore.h>
8#include <private/qwindow_p.h>
9#include <rhi/qrhi.h>
10
12#include "qopenglcompositor_p.h"
13
14#ifndef GL_UNPACK_ROW_LENGTH
15#define GL_UNPACK_ROW_LENGTH 0x0CF2
16#endif
17
19
44 m_window(window),
45 m_bsTexture(0),
46 m_bsTextureWrapper(nullptr),
47 m_bsTextureContext(0),
48 m_textures(new QPlatformTextureList),
49 m_lockedWidgetTextures(0),
50 m_rhi(nullptr)
51{
52}
53
55{
56 if (m_bsTexture && m_rhi) {
57 delete m_bsTextureWrapper;
58 // Contexts are sharing resources, won't matter which one is
59 // current here, use the rhi's shortcut.
61 glDeleteTextures(1, &m_bsTexture);
62 }
63
64 delete m_textures; // this does not actually own any GL resources
65}
66
71
72void QOpenGLCompositorBackingStore::updateTexture()
73{
74 if (!m_bsTexture) {
75 m_bsTextureContext = QOpenGLContext::currentContext();
76 Q_ASSERT(m_bsTextureContext);
77 glGenTextures(1, &m_bsTexture);
78 glBindTexture(GL_TEXTURE_2D, m_bsTexture);
79 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
80 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
81 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
82 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
83 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
84 } else {
85 glBindTexture(GL_TEXTURE_2D, m_bsTexture);
86 }
87
88 if (!m_dirty.isNull()) {
90 QRect imageRect = m_image.rect();
91
93 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
94 for (const QRect &rect : m_dirty) {
95 QRect r = imageRect & rect;
96 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image.width());
97 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE,
98 m_image.constScanLine(r.y()) + r.x() * 4);
99 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
100 }
101 } else {
102 for (const QRect &rect : m_dirty) {
103 // intersect with image rect to be sure
104 QRect r = imageRect & rect;
105
106 // if the rect is wide enough it's cheaper to just
107 // extend it instead of doing an image copy
108 if (r.width() >= imageRect.width() / 2) {
109 r.setX(0);
110 r.setWidth(imageRect.width());
111 }
112
113 fixed |= r;
114 }
115 for (const QRect &rect : fixed) {
116 // if the sub-rect is full-width we can pass the image data directly to
117 // OpenGL instead of copying, since there's no gap between scanlines
118 if (rect.width() == imageRect.width()) {
119 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
120 m_image.constScanLine(rect.y()));
121 } else {
122 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
123 m_image.copy(rect).constBits());
124 }
125 }
126 }
127
128 m_dirty = QRegion();
129 }
130
131 if (!m_bsTextureWrapper) {
132 m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
133 m_bsTextureWrapper->createFrom({m_bsTexture, 0});
134 }
135}
136
137void QOpenGLCompositorBackingStore::flush(QWindow *flushedWindow, const QRegion &region, const QPoint &offset)
138{
139 // Called for ordinary raster windows.
140
141 Q_UNUSED(region);
143
144 if (!rhi(flushedWindow)) {
147 rhiConfig.setEnabled(true);
148 createRhi(flushedWindow, rhiConfig);
149 }
150
151 static QPlatformTextureList emptyTextureList;
152 bool translucentBackground = m_image.hasAlphaChannel();
153 rhiFlush(flushedWindow, flushedWindow->devicePixelRatio(),
154 region, offset, &emptyTextureList, translucentBackground);
155}
156
158 qreal sourceDevicePixelRatio,
159 const QRegion &region,
160 const QPoint &offset,
162 bool translucentBackground)
163{
164 // QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top.
165
166 Q_UNUSED(region);
168 Q_UNUSED(translucentBackground);
169 Q_UNUSED(sourceDevicePixelRatio);
170
171 m_rhi = rhi(window);
172 Q_ASSERT(m_rhi);
173
175 QOpenGLContext *dstCtx = compositor->context();
176 if (!dstCtx)
177 return FlushFailed;
178
179 QWindow *dstWin = compositor->targetWindow();
180 if (!dstWin)
181 return FlushFailed;
182
183 if (!dstCtx->makeCurrent(dstWin))
184 return FlushFailed;
185
186 QWindowPrivate::get(window)->lastComposeTime.start();
187
188 m_textures->clear();
189 for (int i = 0; i < textures->count(); ++i) {
190 m_textures->appendTexture(textures->source(i), textures->texture(i), textures->geometry(i),
191 textures->clipRect(i), textures->flags(i));
192 }
193
194 updateTexture();
195 m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
196
197 textures->lock(true);
198 m_lockedWidgetTextures = textures;
199
200 compositor->update();
201
202 return FlushSuccess;
203}
204
206{
207 if (m_lockedWidgetTextures) {
208 QPlatformTextureList *textureList = m_lockedWidgetTextures;
209 m_lockedWidgetTextures = 0; // may reenter so null before unlocking
210 textureList->lock(false);
211 }
212}
213
215{
216 m_dirty |= region;
217
218 if (m_image.hasAlphaChannel()) {
219 QPainter p(&m_image);
220 p.setCompositionMode(QPainter::CompositionMode_Source);
221 for (const QRect &r : region)
222 p.fillRect(r, Qt::transparent);
223 }
224}
225
226void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &staticContents)
227{
228 Q_UNUSED(staticContents);
229
231 QOpenGLContext *dstCtx = compositor->context();
232 if (!dstCtx)
233 return;
234 QWindow *dstWin = compositor->targetWindow();
235 if (!dstWin)
236 return;
237
239
240 m_window->create();
241
242 dstCtx->makeCurrent(dstWin);
243 if (m_bsTexture) {
244 delete m_bsTextureWrapper;
245 m_bsTextureWrapper = nullptr;
246 glDeleteTextures(1, &m_bsTexture);
247 m_bsTexture = 0;
248 m_bsTextureContext = nullptr;
249 }
250}
251
253{
254 return m_image;
255}
256
\inmodule QtGui
Definition qimage.h:37
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false.
Definition qimage.cpp:4595
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
QSize size() const
Returns the size of the image, i.e.
int width() const
Returns the width of the image.
int height() const
Returns the height of the image.
@ Format_RGBA8888
Definition qimage.h:59
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
Definition qimage.cpp:1678
QRect rect() const
Returns the enclosing rectangle (0, 0, width(), height()) of the image.
const uchar * constBits() const
Returns a pointer to the first pixel data.
Definition qimage.cpp:1733
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override
Flushes the given region from the specified window.
FlushResult rhiFlush(QWindow *window, qreal sourceDevicePixelRatio, const QRegion &region, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground) override
Flushes the given region from the specified window, and compositing it with the specified textures li...
QPaintDevice * paintDevice() override
Implement this function to return the appropriate paint device.
QImage toImage() const override
Implemented in subclasses to return the content of the backingstore as a QImage.
void resize(const QSize &size, const QRegion &staticContents) override
void beginPaint(const QRegion &region) override
This function is called before painting onto the surface begins, with the region in which the paintin...
const QPlatformTextureList * textures() const
A generic OpenGL-based compositor.
static QOpenGLCompositor * instance()
\inmodule QtGui
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
@ CompositionMode_Source
Definition qpainter.h:101
The QPlatformBackingStore class provides the drawing area for top-level windows.
void createRhi(QWindow *window, QPlatformBackingStoreRhiConfig config)
QWindow * window() const
Returns a pointer to the top-level window associated with this surface.
QRhi * rhi(QWindow *window) const
void appendTexture(void *source, QRhiTexture *texture, const QRect &geometry, const QRect &clipRect=QRect(), Flags flags={ })
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void setX(int x) noexcept
Sets the left edge of the rectangle to the given x coordinate.
Definition qrect.h:215
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool isNull() const
virtual bool createFrom(NativeTexture src)
Similar to create(), except that no new native textures are created.
Definition qrhi.cpp:4490
bool makeThreadLocalNativeContextCurrent()
With OpenGL this makes the OpenGL context current on the current thread.
Definition qrhi.cpp:10166
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10570
\inmodule QtCore
Definition qsize.h:25
static QWindowPrivate * get(QWindow *window)
Definition qwindow_p.h:108
\inmodule QtGui
Definition qwindow.h:63
EGLContext ctx
rect
[4]
Combined button and popup list for selecting options.
@ transparent
Definition qnamespace.h:47
QTextStream & fixed(QTextStream &stream)
Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation) on stream and returns stream.
static QOpenGLCompositor * compositor
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint const GLuint GLuint const GLuint * textures
GLenum GLuint GLintptr offset
GLfloat GLfloat p
[1]
#define GL_CLAMP_TO_EDGE
Definition qopenglext.h:100
#define GL_UNPACK_ROW_LENGTH
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define GL_UNSIGNED_BYTE
#define GL_RGBA
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QObject::connect nullptr
aWidget window() -> setWindowTitle("New Window Title")
[2]