4#include <QtGui/QOpenGLContext>
5#include <QtGui/QWindow>
6#include <QtGui/QPainter>
7#include <qpa/qplatformbackingstore.h>
8#include <private/qwindow_p.h>
14#ifndef GL_UNPACK_ROW_LENGTH
15#define GL_UNPACK_ROW_LENGTH 0x0CF2
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
42QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)
43 : QPlatformBackingStore(window),
46 m_bsTextureWrapper(
nullptr),
47 m_bsTextureContext(0),
48 m_textures(
new QPlatformTextureList),
49 m_lockedWidgetTextures(0),
54QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()
56 if (m_bsTexture && m_rhi) {
57 delete m_bsTextureWrapper;
60 m_rhi->makeThreadLocalNativeContextCurrent();
61 glDeleteTextures(1, &m_bsTexture);
67QPaintDevice *QOpenGLCompositorBackingStore::paintDevice()
72void QOpenGLCompositorBackingStore::updateTexture()
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);
85 glBindTexture(GL_TEXTURE_2D, m_bsTexture);
88 if (!m_dirty.isNull()) {
90 QRect imageRect = m_image.rect();
92 QOpenGLContext *ctx = QOpenGLContext::currentContext();
93 if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
94 for (
const QRect &rect : m_dirty) {
95 QRect r = imageRect & rect;
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);
102 for (
const QRect &rect : m_dirty) {
104 QRect r = imageRect & rect;
108 if (r.width() >= imageRect.width() / 2) {
110 r.setWidth(imageRect.width());
115 for (
const QRect &rect : fixed) {
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()));
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());
131 if (!m_bsTextureWrapper) {
132 m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
133 m_bsTextureWrapper->createFrom({m_bsTexture, 0});
137void QOpenGLCompositorBackingStore::flush(QWindow *flushedWindow,
const QRegion ®ion,
const QPoint &offset)
144 QOpenGLCompositorWindow *handle =
dynamic_cast<QOpenGLCompositorWindow *>(flushedWindow->handle());
145 if (handle && !handle->backingStore())
146 handle->setBackingStore(
this);
148 if (!rhi(flushedWindow)) {
149 QPlatformBackingStoreRhiConfig rhiConfig;
150 rhiConfig.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
151 rhiConfig.setEnabled(
true);
152 createRhi(flushedWindow, rhiConfig);
155 static QPlatformTextureList emptyTextureList;
156 bool translucentBackground = m_image.hasAlphaChannel();
157 rhiFlush(flushedWindow, flushedWindow->devicePixelRatio(),
158 region, offset, &emptyTextureList, translucentBackground);
161QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWindow *window,
162 qreal sourceDevicePixelRatio,
163 const QRegion ®ion,
164 const QPoint &offset,
165 QPlatformTextureList *textures,
166 bool translucentBackground,
167 qreal sourceTransformFactor)
173 Q_UNUSED(translucentBackground);
174 Q_UNUSED(sourceDevicePixelRatio);
175 Q_UNUSED(sourceTransformFactor);
180 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
181 QOpenGLContext *dstCtx = compositor->context();
185 QWindow *dstWin = compositor->targetWindow();
189 if (!dstCtx->makeCurrent(dstWin))
192 QWindowPrivate::get(window)->lastComposeTime.start();
195 for (
int i = 0; i < textures->count(); ++i) {
196 m_textures->appendTexture(textures->source(i), textures->texture(i), textures->geometry(i),
197 textures->clipRect(i), textures->flags(i));
201 m_textures->appendTexture(
nullptr, m_bsTextureWrapper, window->geometry());
203 textures->lock(
true);
204 m_lockedWidgetTextures = textures;
206 compositor->update();
211void QOpenGLCompositorBackingStore::notifyComposited()
213 if (m_lockedWidgetTextures) {
214 QPlatformTextureList *textureList = m_lockedWidgetTextures;
215 m_lockedWidgetTextures = 0;
216 textureList->lock(
false);
220void QOpenGLCompositorBackingStore::beginPaint(
const QRegion ®ion)
224 if (m_image.hasAlphaChannel()) {
225 QPainter p(&m_image);
226 p.setCompositionMode(QPainter::CompositionMode_Source);
227 for (
const QRect &r : region)
228 p.fillRect(r, Qt::transparent);
232void QOpenGLCompositorBackingStore::resize(
const QSize &size,
const QRegion &staticContents)
234 Q_UNUSED(staticContents);
236 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
237 QOpenGLContext *dstCtx = compositor->context();
240 QWindow *dstWin = compositor->targetWindow();
244 m_image = QImage(size, QImage::Format_RGBA8888);
248 dstCtx->makeCurrent(dstWin);
250 delete m_bsTextureWrapper;
251 m_bsTextureWrapper =
nullptr;
252 glDeleteTextures(1, &m_bsTexture);
254 m_bsTextureContext =
nullptr;
258QImage QOpenGLCompositorBackingStore::toImage()
const