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 <optional>
14#include <qohosplatformscreen.h>
15#include <qohosplatformwindow.h>
16#include <render/qohosview.h>
17
19
20namespace
21{
22
23QMatrix3x3 makeSourceTransform(const QRect &targetSubTexture, const QSizeF &srcTextureSize)
24{
25 auto bottomLeftOffset = QPointF(
26 targetSubTexture.x(),
27 srcTextureSize.height() - targetSubTexture.bottomRight().y() - 1.0f);
28 auto normalizedOffset = QPointF(
29 bottomLeftOffset.x() / srcTextureSize.width(),
30 bottomLeftOffset.y() / srcTextureSize.height());
31
32 QMatrix3x3 result;
33 result(0, 2) = static_cast<float>(normalizedOffset.x());
34 result(1, 2) = static_cast<float>(normalizedOffset.y());
35
36 QSizeF textureScaleUv{
37 targetSubTexture.width() / srcTextureSize.width(),
38 targetSubTexture.height() / srcTextureSize.height()};
39
40 result(0, 0) = static_cast<float>(textureScaleUv.width());
41 result(1, 1) = static_cast<float>(textureScaleUv.height());
42
43 return result;
44}
45
46// NOTE - We use std::unique_ptrs of those objects
47// within the class.
48// Those helper functions are explicitly created to avoid
49// problems with calling unique_ptr<O>.release() unique_ptr<O>->release()
50void unbindFrameBufferObject(QOpenGLFramebufferObject &fbo)
51{
52 fbo.release();
53}
54
55void unbindTextureBlitter(QOpenGLTextureBlitter &blitter)
56{
57 blitter.release();
58}
59
60void setViewportAndClearColorBuffer(QOpenGLContext &glCtx, const QSize &viewportSize, const QColor &clearColor)
61{
62 auto *glFuncs = glCtx.functions();
63 glFuncs->glClearColor(
64 static_cast<float>(clearColor.redF()),
65 static_cast<float>(clearColor.greenF()),
66 static_cast<float>(clearColor.blueF()),
67 static_cast<float>(clearColor.alphaF()));
68 glFuncs->glViewport(0, 0, viewportSize.width(), viewportSize.height());
69 glFuncs->glClear(GL_COLOR_BUFFER_BIT);
70}
71
73 QOpenGLTextureBlitter &blitter,
74 QOpenGLFramebufferObject &framebuffer,
75 const QRect &srcRect)
76{
77 static const QMatrix4x4 identityMatrix = {};
78
79 auto dstTransform = identityMatrix;
80 auto srcTransform = makeSourceTransform(srcRect, framebuffer.size());
81
82 blitter.bind();
83 blitter.blit(framebuffer.texture(), dstTransform, srcTransform);
84 unbindTextureBlitter(blitter);
85}
86
97
98std::optional<RenderContextData> RenderContextData::tryCreateForQWindow(QWindow *window)
99{
100 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
101 if (platformWindow == nullptr)
102 return {};
103
104 auto *view = platformWindow->ownedViewOrNull();
105 if (view == nullptr)
106 return {};
107
108 auto optSurfaceResolution = view->surfaceResolution();
109 return optSurfaceResolution.has_value()
110 ? std::optional(
112 .qWindow = window,
113 .platformWindow = platformWindow,
114 .view = view,
115 .unscaledWindowGeometry = platformWindow->windowGeometry(),
116 .surfaceResolution = optSurfaceResolution.value(),
117 })
118 : std::nullopt;
119}
120
122{
123public:
124 explicit QOhosPlatformBackingStoreGL(QWindow *window);
126
128 void flush(
129 QWindow *targetWindow, const QRegion &relToParentWindowRegion,
130 const QPoint &relToRootWindowOffset) override;
131 void resize(const QSize &size, const QRegion &staticContents) override;
132
133 void beginPaint(const QRegion &) override;
135 QImage toImage() const override;
136
137private:
138 void tryRecreatePaintDeviceIfNeeded();
139
140 std::unique_ptr<QPaintDevice> m_dummyPaintDevice;
141 std::unique_ptr<QOpenGLPaintDevice> m_paintDevice;
142 std::unique_ptr<QOpenGLContext> m_glContext;
143 std::unique_ptr<QOpenGLFramebufferObject> m_framebuffer;
144 std::unique_ptr<QOpenGLTextureBlitter> m_blitter;
145 std::optional<QSize> m_pendingResizeRequest;
146};
147
148
154
156{
157 return m_paintDevice ? m_paintDevice.get() : m_dummyPaintDevice.get();
158}
159
161 QWindow *targetWindow, const QRegion &relToParentWindowRegion,
162 const QPoint &relToRootWindowOffset)
163{
164 Q_UNUSED(relToParentWindowRegion);
165
166 auto optSrcWindowCtxData = RenderContextData::tryCreateForQWindow(window());
167 auto optDstWidnowCtxData = RenderContextData::tryCreateForQWindow(targetWindow);
168
169 if (!optSrcWindowCtxData.has_value() || !optDstWidnowCtxData.has_value())
170 return;
171
172 if (!m_glContext)
173 return;
174
175 auto dstWindowCtxData = optDstWidnowCtxData.value();
176
177 unbindFrameBufferObject(*m_framebuffer);
178 m_glContext->makeCurrent(dstWindowCtxData.qWindow);
179
180 if (!m_blitter) {
181 m_blitter = std::make_unique<QOpenGLTextureBlitter>();
182 m_blitter->create();
183 }
184
185 auto dstSize = dstWindowCtxData.unscaledWindowGeometry.size();
186
187 auto srcRect = QRect(
188 relToRootWindowOffset, dstWindowCtxData.platformWindow->windowGeometry().size());
189
190 setViewportAndClearColorBuffer(*m_glContext, dstSize, QColor(Qt::transparent));
191
192 blitFramebufferToWindow(*m_blitter, *m_framebuffer, srcRect);
193
194 m_glContext->swapBuffers(dstWindowCtxData.qWindow);
195}
196
197void QOhosPlatformBackingStoreGL::resize(const QSize &targetSize, const QRegion &)
198{
199 m_pendingResizeRequest = targetSize;
200}
201
202void QOhosPlatformBackingStoreGL::tryRecreatePaintDeviceIfNeeded()
203{
204 auto optRootWindowCtxData = RenderContextData::tryCreateForQWindow(window());
205 if (!optRootWindowCtxData.has_value())
206 return;
207
208 auto rootWindowCtxData = optRootWindowCtxData.value();
209
210 if (!m_glContext) {
211 m_glContext = std::make_unique<QOpenGLContext>(rootWindowCtxData.qWindow);
212 m_glContext->setFormat(rootWindowCtxData.qWindow->format());
213 m_glContext->create();
214 }
215
216 m_glContext->makeCurrent(rootWindowCtxData.qWindow);
217
218 auto targetFramebufferResolution = m_pendingResizeRequest.value_or(
219 rootWindowCtxData.platformWindow->windowGeometry().size());
220 if (!m_framebuffer || m_framebuffer->size() != targetFramebufferResolution) {
221 m_framebuffer = std::make_unique<QOpenGLFramebufferObject>(targetFramebufferResolution);
222 m_paintDevice = std::make_unique<QOpenGLPaintDevice>(targetFramebufferResolution);
223 if (QHighDpiScaling::isActive()) {
224 auto pixelDensity = static_cast<QOhosPlatformScreen *>(rootWindowCtxData.platformWindow->screen())->pixelScalingCoefficient();
225 m_paintDevice->setDevicePixelRatio(pixelDensity);
226 }
227
228 m_framebuffer->bind();
229 setViewportAndClearColorBuffer(*m_glContext, targetFramebufferResolution, QColor(Qt::transparent));
230 }
231}
232
234{
235 if (!m_framebuffer || m_pendingResizeRequest.has_value())
236 tryRecreatePaintDeviceIfNeeded();
237
238 if (!m_framebuffer)
239 return;
240
241 m_pendingResizeRequest = {};
242
243 m_glContext->makeCurrent(window());
244 m_framebuffer->bind();
245}
246
250
251
253{
254 return m_framebuffer
255 ? m_framebuffer->toImage()
256 : QImage();
257}
258
259}
260
262{
263 return std::make_unique<QOhosPlatformBackingStoreGL>(window);
264}
265
266QT_END_NAMESPACE
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)
static std::optional< RenderContextData > tryCreateForQWindow(QWindow *window)