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
qqnxrasterwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 - 2014 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qqnxglobal.h"
6
8#include "qqnxscreen.h"
9
10#include <QDebug>
11
12#include <private/qhighdpiscaling_p.h>
13
14#include <errno.h>
15
16QT_BEGIN_NAMESPACE
17
18QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow) :
19 QQnxWindow(window, context, needRootWindow),
20 m_currentBufferIndex(-1),
21 m_previousBufferIndex(-1)
22{
23 initWindow();
24
25 const int val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
26 const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val);
27 if (Q_UNLIKELY(result != 0))
28 qFatal("QQnxRasterWindow: failed to set window alpha usage, errno=%d", errno);
29}
30
31void QQnxRasterWindow::post(const QRegion &dirty)
32{
33 // How double-buffering works
34 // --------------------------
35 //
36 // The are two buffers, the previous one and the current one.
37 // The previous buffer always contains the complete, full image of the whole window when it
38 // was last posted.
39 // The current buffer starts with the complete, full image of the second to last posting
40 // of the window.
41 //
42 // During painting, Qt paints on the current buffer. Thus, when Qt has finished painting, the
43 // current buffer contains the second to last image plus the newly painted regions.
44 // Since the second to last image is too old, we copy over the image from the previous buffer, but
45 // only for those regions that Qt didn't paint (because that would overwrite what Qt has just
46 // painted). This is the copyPreviousToCurrent() call below.
47 //
48 // After the call to copyPreviousToCurrent(), the current buffer contains the complete, full image of the
49 // whole window in its current state, and we call screen_post_window() to make the new buffer
50 // available to libscreen (called "posting"). There, only the regions that Qt painted on are
51 // posted, as nothing else has changed.
52 //
53 // After that, the previous and the current buffers are swapped, and the whole cycle starts anew.
54
55 // Check if render buffer exists and something was rendered
56 if (m_currentBufferIndex != -1 && !dirty.isEmpty()) {
57 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
58 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
59
60#if defined(QQNX_INCREMENTAL_RASTER_UPDATE)
61 // Copy unmodified region from old render buffer to new render buffer;
62 // required to allow partial updates
63 QRegion preserve = m_previousDirty - dirty - m_scrolled;
64 blitPreviousToCurrent(preserve, 0, 0);
65
66 // Calculate region that changed
67 QRegion modified = preserve + dirty + m_scrolled;
68 QRect rect = modified.boundingRect();
69 int dirtyRect[4] = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() };
70
71 // Update the display with contents of render buffer
72 Q_SCREEN_CHECKERROR(
73 screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0),
74 "Failed to post window");
75#else
76 // Update the display with contents of render buffer
78 screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 0, NULL, 0),
79 "Failed to post window");
80#endif
81
82 // Advance to next nender buffer
83 m_previousBufferIndex = m_currentBufferIndex++;
84 if (m_currentBufferIndex >= MAX_BUFFER_COUNT)
85 m_currentBufferIndex = 0;
86
87 // Save modified region and clear scrolled region
88 m_previousDirty = QRect(QPoint(0, 0), QHighDpi::toNativePixels(window()->size(), window()));
89 m_scrolled = QRegion();
90
92 }
93}
94
95void QQnxRasterWindow::scroll(const QRegion &region, int dx, int dy, bool flush)
96{
97 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
98 blitPreviousToCurrent(region, dx, dy, flush);
99 m_scrolled += region;
100}
101
103{
104 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
105
106 // Check if render buffer is invalid
107 if (m_currentBufferIndex == -1) {
108 auto platformScreen = static_cast<QQnxScreen *>(screen());
109 // Get all buffers available for rendering
110 screen_buffer_t buffers[MAX_BUFFER_COUNT];
111 const int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS,
112 (void **)buffers);
113 Q_SCREEN_CRITICALERROR(result, "Failed to query window buffers");
114
115 // Wrap each buffer and clear
116 for (int i = 0; i < MAX_BUFFER_COUNT; ++i) {
117 m_buffers[i] = QQnxBuffer(buffers[i]);
118
119 // Clear Buffer
120 int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
121 Q_SCREEN_CHECKERROR(screen_fill(platformScreen->nativeContext(), buffers[i], bg),
122 "Failed to clear window buffer");
123 }
124
125 Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), SCREEN_WAIT_IDLE),
126 "Failed to flush blits");
127
128 // Use the first available render buffer
129 m_currentBufferIndex = 0;
130 m_previousBufferIndex = -1;
131 }
132
133 return m_buffers[m_currentBufferIndex];
134}
135
136void QQnxRasterWindow::setParent(const QPlatformWindow *wnd)
137{
138 QQnxWindow::setParent(wnd);
140}
141
143{
144 adjustBufferSize(QHighDpi::toNativePixels(window()->size(), window()));
145}
146
147void QQnxRasterWindow::adjustBufferSize(const QSize &size)
148{
149 if (size != bufferSize())
150 setBufferSize(size);
151}
152
154{
155 return static_cast<QQnxScreen *>(screen())->nativeFormat();
156}
157
159{
160 // Buffers were destroyed; reacquire them
161 m_previousBufferIndex = -1;
162 m_currentBufferIndex = -1;
163 m_previousDirty = QRegion();
164 m_scrolled = QRegion();
165}
166
167void QQnxRasterWindow::blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush)
168{
169 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
170
171 // Abort if previous buffer is invalid or if nothing to copy
172 if (m_previousBufferIndex == -1 || region.isEmpty())
173 return;
174
175 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
176 QQnxBuffer &previousBuffer = m_buffers[m_previousBufferIndex];
177
178 // Break down region into non-overlapping rectangles
179 for (auto rit = region.rbegin(), rend = region.rend(); rit != rend; ++rit) {
180 // Clip rectangle to bounds of target
181 const QRect rect = rit->intersected(currentBuffer.rect());
182
183 if (rect.isEmpty())
184 continue;
185
186 // Setup blit operation
187 int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x(),
188 SCREEN_BLIT_SOURCE_Y, rect.y(),
189 SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
190 SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
191 SCREEN_BLIT_DESTINATION_X, rect.x() + dx,
192 SCREEN_BLIT_DESTINATION_Y, rect.y() + dy,
193 SCREEN_BLIT_DESTINATION_WIDTH, rect.width(),
194 SCREEN_BLIT_DESTINATION_HEIGHT, rect.height(),
195 SCREEN_BLIT_END };
196
197 // Queue blit operation
198 Q_SCREEN_CHECKERROR(screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
199 previousBuffer.nativeBuffer(), attribs),
200 "Failed to blit buffers");
201 }
202
203 // Check if flush requested
204 if (flush) {
205 // Wait for all blits to complete
206 Q_SCREEN_CHECKERROR(screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE),
207 "Failed to flush blits");
208
209 // Buffer was modified outside the CPU
210 currentBuffer.invalidateInCache();
211 }
212}
213
214QT_END_NAMESPACE
void invalidateInCache()
void blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush=false)
QQnxBuffer & renderBuffer()
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
int pixelFormat() const override
void adjustBufferSize(const QSize &size)
void scroll(const QRegion &region, int dx, int dy, bool flush=false)
void resetBuffers() override
void post(const QRegion &dirty)
void windowPosted()
#define Q_SCREEN_CRITICALERROR(x, message)
Definition qqnxglobal.h:20
#define Q_SCREEN_CHECKERROR(x, message)
Definition qqnxglobal.h:17
#define MAX_BUFFER_COUNT
Definition qqnxwindow.h:25