Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosplatformbackingstoregl.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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 <qohosplatformbackingstoregl.h>
5
6#include <QtGui/private/qhighdpiscaling_p.h>
7#include <QtOpenGL/private/qopenglpaintdevice_p.h>
8#include <QtGui/qopenglcontext.h>
9#include <QtOpenGL/qopenglframebufferobject.h>
10#include <QtGui/qopenglfunctions.h>
11#include <QtOpenGL/qopengltextureblitter.h>
12#include <memory>
13#include <qohosplatformscreen.h>
14#include <qohosplatformwindow.h>
15#include <render/qohosview.h>
16
18
19namespace
20{
21
22QMatrix3x3 makeSourceTransform(const QRect &targetSubTexture, const QSizeF &srcTextureSize)
23{
24 auto bottomLeftOffset = QPointF(
25 targetSubTexture.x(),
26 srcTextureSize.height() - targetSubTexture.bottomRight().y() - 1.0f);
27 auto normalizedOffset = QPointF(
28 bottomLeftOffset.x() / srcTextureSize.width(),
29 bottomLeftOffset.y() / srcTextureSize.height());
30
31 QMatrix3x3 result;
32 result(0, 2) = static_cast<float>(normalizedOffset.x());
33 result(1, 2) = static_cast<float>(normalizedOffset.y());
34
35 QSizeF textureScaleUv{
36 targetSubTexture.width() / srcTextureSize.width(),
37 targetSubTexture.height() / srcTextureSize.height()};
38
39 result(0, 0) = static_cast<float>(textureScaleUv.width());
40 result(1, 1) = static_cast<float>(textureScaleUv.height());
41
42 return result;
43}
44
45// NOTE - We use std::unique_ptrs of those objects
46// within the class.
47// Those helper functions are explicitly created to avoid
48// problems with calling unique_ptr<O>.release() unique_ptr<O>->release()
49void unbindFrameBufferObject(QOpenGLFramebufferObject &fbo)
50{
51 fbo.release();
52}
53
54void unbindTextureBlitter(QOpenGLTextureBlitter &blitter)
55{
56 blitter.release();
57}
58
59void setViewportAndClearColorBuffer(QOpenGLContext &glCtx, const QSize &viewportSize, const QColor &clearColor)
60{
61 auto *glFuncs = glCtx.functions();
62 glFuncs->glClearColor(
63 static_cast<float>(clearColor.redF()),
64 static_cast<float>(clearColor.greenF()),
65 static_cast<float>(clearColor.blueF()),
66 static_cast<float>(clearColor.alphaF()));
67 glFuncs->glViewport(0, 0, viewportSize.width(), viewportSize.height());
68 glFuncs->glClear(GL_COLOR_BUFFER_BIT);
69}
70
72 QOpenGLTextureBlitter &blitter,
73 QOpenGLFramebufferObject &framebuffer,
74 const QRect &srcRect)
75{
76 static const QMatrix4x4 identityMatrix = {};
77
78 auto dstTransform = identityMatrix;
79 auto srcTransform = makeSourceTransform(srcRect, framebuffer.size());
80
81 blitter.bind();
82 blitter.blit(framebuffer.texture(), dstTransform, srcTransform);
83 unbindTextureBlitter(blitter);
84}
85
96
97QOhosOptional<RenderContextData> RenderContextData::tryCreateForQWindow(QWindow *window)
98{
99 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
100 if (platformWindow == nullptr)
101 return {};
102
103 auto *view = platformWindow->ownedViewOrNull();
104 if (view == nullptr)
105 return {};
106
107 auto optSurfaceResolution = view->surfaceResolution();
108 return optSurfaceResolution.hasValue()
109 ? makeQOhosOptional(
111 .qWindow = window,
112 .platformWindow = platformWindow,
113 .view = view,
114 .unscaledWindowGeometry = platformWindow->windowGeometry(),
115 .surfaceResolution = optSurfaceResolution.value(),
116 })
118}
119
121{
122public:
123 explicit QOhosPlatformBackingStoreGL(QWindow *window);
125
127 void flush(
128 QWindow *targetWindow, const QRegion &relToParentWindowRegion,
129 const QPoint &relToRootWindowOffset) override;
130 void resize(const QSize &size, const QRegion &staticContents) override;
131
132 void beginPaint(const QRegion &) override;
134 QImage toImage() const override;
135
136private:
137 void tryRecreatePaintDeviceIfNeeded();
138
139 std::unique_ptr<QPaintDevice> m_dummyPaintDevice;
140 std::unique_ptr<QOpenGLPaintDevice> m_paintDevice;
141 std::unique_ptr<QOpenGLContext> m_glContext;
142 std::unique_ptr<QOpenGLFramebufferObject> m_framebuffer;
143 std::unique_ptr<QOpenGLTextureBlitter> m_blitter;
144 QOhosOptional<QSize> m_pendingResizeRequest;
145};
146
147
153
155{
156 return m_paintDevice ? m_paintDevice.get() : m_dummyPaintDevice.get();
157}
158
160 QWindow *targetWindow, const QRegion &relToParentWindowRegion,
161 const QPoint &relToRootWindowOffset)
162{
163 Q_UNUSED(relToParentWindowRegion);
164
165 auto optSrcWindowCtxData = RenderContextData::tryCreateForQWindow(window());
166 auto optDstWidnowCtxData = RenderContextData::tryCreateForQWindow(targetWindow);
167
168 if (!optSrcWindowCtxData.hasValue() || !optDstWidnowCtxData.hasValue())
169 return;
170
171 if (!m_glContext)
172 return;
173
174 auto dstWindowCtxData = optDstWidnowCtxData.value();
175
176 unbindFrameBufferObject(*m_framebuffer);
177 m_glContext->makeCurrent(dstWindowCtxData.qWindow);
178
179 if (!m_blitter) {
180 m_blitter = std::make_unique<QOpenGLTextureBlitter>();
181 m_blitter->create();
182 }
183
184 auto dstSize = dstWindowCtxData.unscaledWindowGeometry.size();
185
186 auto srcRect = QRect(
187 relToRootWindowOffset, dstWindowCtxData.platformWindow->windowGeometry().size());
188
189 setViewportAndClearColorBuffer(*m_glContext, dstSize, QColor(Qt::transparent));
190
191 blitFramebufferToWindow(*m_blitter, *m_framebuffer, srcRect);
192
193 m_glContext->swapBuffers(dstWindowCtxData.qWindow);
194}
195
196void QOhosPlatformBackingStoreGL::resize(const QSize &targetSize, const QRegion &)
197{
198 m_pendingResizeRequest = targetSize;
199}
200
201void QOhosPlatformBackingStoreGL::tryRecreatePaintDeviceIfNeeded()
202{
203 auto optRootWindowCtxData = RenderContextData::tryCreateForQWindow(window());
204 if (!optRootWindowCtxData.hasValue())
205 return;
206
207 auto rootWindowCtxData = optRootWindowCtxData.value();
208
209 if (!m_glContext) {
210 m_glContext = std::make_unique<QOpenGLContext>(rootWindowCtxData.qWindow);
211 m_glContext->setFormat(rootWindowCtxData.qWindow->format());
212 m_glContext->create();
213 }
214
215 m_glContext->makeCurrent(rootWindowCtxData.qWindow);
216
217 auto targetFramebufferResolution = m_pendingResizeRequest.valueOr(
218 rootWindowCtxData.platformWindow->windowGeometry().size());
219 if (!m_framebuffer || m_framebuffer->size() != targetFramebufferResolution) {
220 m_framebuffer = std::make_unique<QOpenGLFramebufferObject>(targetFramebufferResolution);
221 m_paintDevice = std::make_unique<QOpenGLPaintDevice>(targetFramebufferResolution);
222 if (QHighDpiScaling::isActive()) {
223 auto pixelDensity = static_cast<QOhosPlatformScreen *>(rootWindowCtxData.platformWindow->screen())->pixelScalingCoefficient();
224 m_paintDevice->setDevicePixelRatio(pixelDensity);
225 }
226
227 m_framebuffer->bind();
228 setViewportAndClearColorBuffer(*m_glContext, targetFramebufferResolution, QColor(Qt::transparent));
229 }
230}
231
233{
234 if (!m_framebuffer || m_pendingResizeRequest.hasValue())
235 tryRecreatePaintDeviceIfNeeded();
236
237 if (!m_framebuffer)
238 return;
239
240 m_pendingResizeRequest = makeEmptyQOhosOptional();
241
242 m_glContext->makeCurrent(window());
243 m_framebuffer->bind();
244}
245
249
250
252{
253 return m_framebuffer
254 ? m_framebuffer->toImage()
255 : QImage();
256}
257
258}
259
261{
262 return std::make_unique<QOhosPlatformBackingStoreGL>(window);
263}
264
265QT_END_NAMESPACE
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
void beginPaint(const QRegion &) override
This function is called before painting onto the surface begins, with the region in which the paintin...
QImage toImage() const override
Implemented in subclasses to return the content of the backingstore as a QImage.
void flush(QWindow *targetWindow, const QRegion &relToParentWindowRegion, const QPoint &relToRootWindowOffset) override
Flushes the given region from the specified window.
void endPaint() override
This function is called after painting onto the surface has ended.
QPaintDevice * paintDevice() override
Implement this function to return the appropriate paint device.
void resize(const QSize &size, const QRegion &staticContents) override
Combined button and popup list for selecting options.
void blitFramebufferToWindow(QOpenGLTextureBlitter &blitter, QOpenGLFramebufferObject &framebuffer, const QRect &srcRect)
void unbindFrameBufferObject(QOpenGLFramebufferObject &fbo)
void unbindTextureBlitter(QOpenGLTextureBlitter &blitter)
void setViewportAndClearColorBuffer(QOpenGLContext &glCtx, const QSize &viewportSize, const QColor &clearColor)
QMatrix3x3 makeSourceTransform(const QRect &targetSubTexture, const QSizeF &srcTextureSize)
std::unique_ptr< QPlatformBackingStore > makeGlOhosPlatformBackingStore(QWindow *window)
QOhosOptional< void > makeEmptyQOhosOptional()
static QOhosOptional< RenderContextData > tryCreateForQWindow(QWindow *window)