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
138{
139 // Called for ordinary raster windows.
140 auto *handle = dynamic_cast<QOpenGLCompositorWindow *>(window->handle());
141 if (handle && !handle->backingStore())
142 handle->setBackingStore(this);
143
144 Q_UNUSED(region);
146
147 m_rhi = rhi();
148 if (!m_rhi) {
150 m_rhi = rhi();
151 }
152 Q_ASSERT(m_rhi);
153
155 QOpenGLContext *dstCtx = compositor->context();
156 if (!dstCtx)
157 return;
158
159 QWindow *dstWin = compositor->targetWindow();
160 if (!dstWin)
161 return;
162
163 if (!dstCtx->makeCurrent(dstWin))
164 return;
165
166 updateTexture();
167 m_textures->clear();
168 m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
169
170 compositor->update();
171}
172
174 qreal sourceDevicePixelRatio,
175 const QRegion &region,
176 const QPoint &offset,
178 bool translucentBackground)
179{
180 // QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top.
181
182 Q_UNUSED(region);
184 Q_UNUSED(translucentBackground);
185 Q_UNUSED(sourceDevicePixelRatio);
186
187 m_rhi = rhi();
188 if (!m_rhi) {
190 m_rhi = rhi();
191 }
192 Q_ASSERT(m_rhi);
193
195 QOpenGLContext *dstCtx = compositor->context();
196 if (!dstCtx)
197 return FlushFailed;
198
199 QWindow *dstWin = compositor->targetWindow();
200 if (!dstWin)
201 return FlushFailed;
202
203 if (!dstCtx->makeCurrent(dstWin))
204 return FlushFailed;
205
206 QWindowPrivate::get(window)->lastComposeTime.start();
207
208 m_textures->clear();
209 for (int i = 0; i < textures->count(); ++i) {
210 m_textures->appendTexture(textures->source(i), textures->texture(i), textures->geometry(i),
211 textures->clipRect(i), textures->flags(i));
212 }
213
214 updateTexture();
215 m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
216
217 textures->lock(true);
218 m_lockedWidgetTextures = textures;
219
220 compositor->update();
221
222 return FlushSuccess;
223}
224
226{
227 if (m_lockedWidgetTextures) {
228 QPlatformTextureList *textureList = m_lockedWidgetTextures;
229 m_lockedWidgetTextures = 0; // may reenter so null before unlocking
230 textureList->lock(false);
231 }
232}
233
235{
236 m_dirty |= region;
237
238 if (m_image.hasAlphaChannel()) {
239 QPainter p(&m_image);
240 p.setCompositionMode(QPainter::CompositionMode_Source);
241 for (const QRect &r : region)
242 p.fillRect(r, Qt::transparent);
243 }
244}
245
246void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &staticContents)
247{
248 Q_UNUSED(staticContents);
249
251 QOpenGLContext *dstCtx = compositor->context();
252 if (!dstCtx)
253 return;
254 QWindow *dstWin = compositor->targetWindow();
255 if (!dstWin)
256 return;
257
259
260 m_window->create();
261
262 dstCtx->makeCurrent(dstWin);
263 if (m_bsTexture) {
264 delete m_bsTextureWrapper;
265 m_bsTextureWrapper = nullptr;
266 glDeleteTextures(1, &m_bsTexture);
267 m_bsTexture = 0;
268 m_bsTextureContext = nullptr;
269 }
270}
271
273{
274 return m_image;
275}
276
\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:4589
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
virtual void setBackingStore(QOpenGLCompositorBackingStore *backingStore)=0
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 setRhiConfig(const QPlatformBackingStoreRhiConfig &config)
QWindow * window() const
Returns a pointer to the top-level window associated with this surface.
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:4487
bool makeThreadLocalNativeContextCurrent()
With OpenGL this makes the OpenGL context current on the current thread.
Definition qrhi.cpp:10158
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10562
\inmodule QtCore
Definition qsize.h:25
static QWindowPrivate * get(QWindow *window)
Definition qwindow_p.h:106
\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
GLuint64 GLenum void * handle
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]