5#include <QtGui/QOpenGLContext>
6#include <QtGui/QWindow>
7#include <QtGui/QPainter>
8#include <qpa/qplatformbackingstore.h>
9#include <private/qwindow_p.h>
15#ifndef GL_UNPACK_ROW_LENGTH
16#define GL_UNPACK_ROW_LENGTH 0x0CF2
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
43QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)
44 : QPlatformBackingStore(window),
47 m_bsTextureWrapper(
nullptr),
48 m_bsTextureContext(0),
49 m_textures(
new QPlatformTextureList),
50 m_lockedWidgetTextures(0),
55QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()
57 if (m_bsTexture && m_rhi) {
58 delete m_bsTextureWrapper;
61 m_rhi->makeThreadLocalNativeContextCurrent();
62 glDeleteTextures(1, &m_bsTexture);
68QPaintDevice *QOpenGLCompositorBackingStore::paintDevice()
73void QOpenGLCompositorBackingStore::updateTexture()
76 m_bsTextureContext = QOpenGLContext::currentContext();
77 Q_ASSERT(m_bsTextureContext);
78 glGenTextures(1, &m_bsTexture);
79 glBindTexture(GL_TEXTURE_2D, m_bsTexture);
80 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
81 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
82 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
83 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
84 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
86 glBindTexture(GL_TEXTURE_2D, m_bsTexture);
89 if (!m_dirty.isNull()) {
91 QRect imageRect = m_image.rect();
93 QOpenGLContext *ctx = QOpenGLContext::currentContext();
94 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
95 for (
const QRect &rect : m_dirty) {
96 QRect r = imageRect & rect;
98 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE,
99 m_image.constScanLine(r.y()) + r.x() * 4);
103 for (
const QRect &rect : m_dirty) {
105 QRect r = imageRect & rect;
109 if (r.width() >= imageRect.width() / 2) {
111 r.setWidth(imageRect.width());
116 for (
const QRect &rect : fixed) {
119 if (rect.width() == imageRect.width()) {
120 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
121 m_image.constScanLine(rect.y()));
123 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
124 m_image.copy(rect).constBits());
132 if (!m_bsTextureWrapper) {
133 m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
134 m_bsTextureWrapper->createFrom({m_bsTexture, 0});
138void QOpenGLCompositorBackingStore::flush(QWindow *flushedWindow,
const QRegion ®ion,
const QPoint &offset)
145 QOpenGLCompositorWindow *handle =
dynamic_cast<QOpenGLCompositorWindow *>(flushedWindow->handle());
146 if (handle && !handle->backingStore())
147 handle->setBackingStore(
this);
149 if (!rhi(flushedWindow)) {
150 QPlatformBackingStoreRhiConfig rhiConfig;
151 rhiConfig.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
152 rhiConfig.setEnabled(
true);
153 createRhi(flushedWindow, rhiConfig);
156 static QPlatformTextureList emptyTextureList;
157 bool translucentBackground = m_image.hasAlphaChannel();
158 rhiFlush(flushedWindow, flushedWindow->devicePixelRatio(),
159 region, offset, &emptyTextureList, translucentBackground);
162QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWindow *window,
163 qreal sourceDevicePixelRatio,
164 const QRegion ®ion,
165 const QPoint &offset,
166 QPlatformTextureList *textures,
167 bool translucentBackground,
168 qreal sourceTransformFactor)
174 Q_UNUSED(translucentBackground);
175 Q_UNUSED(sourceDevicePixelRatio);
176 Q_UNUSED(sourceTransformFactor);
181 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
182 QOpenGLContext *dstCtx = compositor->context();
186 QWindow *dstWin = compositor->targetWindow();
190 if (!dstCtx->makeCurrent(dstWin))
193 QWindowPrivate::get(window)->lastComposeTime.start();
196 for (
int i = 0; i < textures->count(); ++i) {
197 m_textures->appendTexture(textures->source(i), textures->texture(i), textures->geometry(i),
198 textures->clipRect(i), textures->flags(i));
202 m_textures->appendTexture(
nullptr, m_bsTextureWrapper, window->geometry());
204 textures->lock(
true);
205 m_lockedWidgetTextures = textures;
207 compositor->update();
212void QOpenGLCompositorBackingStore::notifyComposited()
214 if (m_lockedWidgetTextures) {
215 QPlatformTextureList *textureList = m_lockedWidgetTextures;
216 m_lockedWidgetTextures = 0;
217 textureList->lock(
false);
221void QOpenGLCompositorBackingStore::beginPaint(
const QRegion ®ion)
225 if (m_image.hasAlphaChannel()) {
226 QPainter p(&m_image);
227 p.setCompositionMode(QPainter::CompositionMode_Source);
228 for (
const QRect &r : region)
229 p.fillRect(r, Qt::transparent);
233void QOpenGLCompositorBackingStore::resize(
const QSize &size,
const QRegion &staticContents)
235 Q_UNUSED(staticContents);
237 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
238 QOpenGLContext *dstCtx = compositor->context();
241 QWindow *dstWin = compositor->targetWindow();
245 m_image = QImage(size, QImage::Format_RGBA8888);
249 dstCtx->makeCurrent(dstWin);
251 delete m_bsTextureWrapper;
252 m_bsTextureWrapper =
nullptr;
253 glDeleteTextures(1, &m_bsTexture);
255 m_bsTextureContext =
nullptr;
259QImage QOpenGLCompositorBackingStore::toImage()
const
Combined button and popup list for selecting options.