Qt 6.x
The Qt SDK
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
4#include "qqnxglobal.h"
5
6#include "qqnxrasterwindow.h"
7#include "qqnxscreen.h"
8
9#include <QDebug>
10
11#include <errno.h>
12
13#if defined(QQNXRASTERWINDOW_DEBUG)
14#define qRasterWindowDebug qDebug
15#else
16#define qRasterWindowDebug QT_NO_QDEBUG_MACRO
17#endif
18
20
21QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow) :
22 QQnxWindow(window, context, needRootWindow),
23 m_currentBufferIndex(-1),
24 m_previousBufferIndex(-1)
25{
26 initWindow();
27
28 // Set window usage
29 if (window->type() == Qt::Desktop)
30 return;
31
32 const int val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
33 const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val);
34 if (Q_UNLIKELY(result != 0))
35 qFatal("QQnxRasterWindow: failed to set window alpha usage, errno=%d", errno);
36}
37
39{
40 // How double-buffering works
41 // --------------------------
42 //
43 // The are two buffers, the previous one and the current one.
44 // The previous buffer always contains the complete, full image of the whole window when it
45 // was last posted.
46 // The current buffer starts with the complete, full image of the second to last posting
47 // of the window.
48 //
49 // During painting, Qt paints on the current buffer. Thus, when Qt has finished painting, the
50 // current buffer contains the second to last image plus the newly painted regions.
51 // Since the second to last image is too old, we copy over the image from the previous buffer, but
52 // only for those regions that Qt didn't paint (because that would overwrite what Qt has just
53 // painted). This is the copyPreviousToCurrent() call below.
54 //
55 // After the call to copyPreviousToCurrent(), the current buffer contains the complete, full image of the
56 // whole window in its current state, and we call screen_post_window() to make the new buffer
57 // available to libscreen (called "posting"). There, only the regions that Qt painted on are
58 // posted, as nothing else has changed.
59 //
60 // After that, the previous and the current buffers are swapped, and the whole cycle starts anew.
61
62 // Check if render buffer exists and something was rendered
63 if (m_currentBufferIndex != -1 && !dirty.isEmpty()) {
64 qRasterWindowDebug() << "window =" << window();
65 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
66
67 // Copy unmodified region from old render buffer to new render buffer;
68 // required to allow partial updates
69 QRegion preserve = m_previousDirty - dirty - m_scrolled;
71
72 // Calculate region that changed
73 QRegion modified = preserve + dirty + m_scrolled;
74 QRect rect = modified.boundingRect();
75 int dirtyRect[4] = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() };
76
77 // Update the display with contents of render buffer
79 screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0),
80 "Failed to post window");
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 = dirty;
89 m_scrolled = QRegion();
90
92 }
93}
94
95void QQnxRasterWindow::scroll(const QRegion &region, int dx, int dy, bool flush)
96{
97 qRasterWindowDebug() << "window =" << window();
98 blitPreviousToCurrent(region, dx, dy, flush);
99 m_scrolled += region;
100}
101
103{
104 qRasterWindowDebug() << "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
137{
140}
141
143{
144 const QSize windowSize = window()->size();
145
146 if (windowSize != bufferSize())
147 setBufferSize(windowSize);
148}
149
151{
152 return static_cast<QQnxScreen *>(screen())->nativeFormat();
153}
154
156{
157 // Buffers were destroyed; reacquire them
158 m_currentBufferIndex = -1;
159 m_previousDirty = QRegion();
160 m_scrolled = QRegion();
161}
162
163void QQnxRasterWindow::blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush)
164{
165 qRasterWindowDebug() << "window =" << window();
166
167 // Abort if previous buffer is invalid or if nothing to copy
168 if (m_previousBufferIndex == -1 || region.isEmpty())
169 return;
170
171 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
172 QQnxBuffer &previousBuffer = m_buffers[m_previousBufferIndex];
173
174 // Break down region into non-overlapping rectangles
175 for (auto rit = region.rbegin(), rend = region.rend(); rit != rend; ++rit) {
176 // Clip rectangle to bounds of target
177 const QRect rect = rit->intersected(currentBuffer.rect());
178
179 if (rect.isEmpty())
180 continue;
181
182 // Setup blit operation
183 int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x(),
184 SCREEN_BLIT_SOURCE_Y, rect.y(),
185 SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
186 SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
187 SCREEN_BLIT_DESTINATION_X, rect.x() + dx,
188 SCREEN_BLIT_DESTINATION_Y, rect.y() + dy,
189 SCREEN_BLIT_DESTINATION_WIDTH, rect.width(),
190 SCREEN_BLIT_DESTINATION_HEIGHT, rect.height(),
191 SCREEN_BLIT_END };
192
193 // Queue blit operation
194 Q_SCREEN_CHECKERROR(screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
195 previousBuffer.nativeBuffer(), attribs),
196 "Failed to blit buffers");
197 }
198
199 // Check if flush requested
200 if (flush) {
201 // Wait for all blits to complete
202 Q_SCREEN_CHECKERROR(screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE),
203 "Failed to flush blits");
204
205 // Buffer was modified outside the CPU
206 currentBuffer.invalidateInCache();
207 }
208}
209
The QPlatformWindow class provides an abstraction for top-level windows.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
void invalidateInCache()
screen_buffer_t nativeBuffer() const
Definition qqnxbuffer.h:21
QRect rect() const
Definition qqnxbuffer.h:25
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 scroll(const QRegion &region, int dx, int dy, bool flush=false)
QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow)
void resetBuffers() override
void post(const QRegion &dirty)
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
Definition qqnxwindow.h:28
void windowPosted()
screen_context_t m_screenContext
Definition qqnxwindow.h:81
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
void initWindow()
screen_window_t nativeHandle() const
Definition qqnxwindow.h:42
void setBufferSize(const QSize &size)
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
QSize bufferSize() const
Definition qqnxwindow.h:45
\inmodule QtCore\reentrant
Definition qrect.h:30
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QRect boundingRect() const noexcept
Returns the bounding rectangle of this region.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
const_reverse_iterator rbegin() const noexcept
Definition qregion.h:53
const_reverse_iterator rend() const noexcept
Definition qregion.h:55
\inmodule QtCore
Definition qsize.h:25
\inmodule QtGui
Definition qwindow.h:63
QSize size() const override
Returns the size of the window excluding any window frame.
Definition qwindow.h:210
rect
[4]
Combined button and popup list for selecting options.
@ Desktop
Definition qnamespace.h:214
static void * context
#define Q_UNLIKELY(x)
#define qFatal
Definition qlogging.h:164
GLuint const GLuint * buffers
GLuint GLsizei const void GLenum preserve
GLuint GLfloat * val
GLuint64EXT * result
[6]
const GLint * attribs
#define Q_SCREEN_CRITICALERROR(x, message)
Definition qqnxglobal.h:16
#define Q_SCREEN_CHECKERROR(x, message)
Definition qqnxglobal.h:13
#define qRasterWindowDebug
#define MAX_BUFFER_COUNT
Definition qqnxwindow.h:21
aWidget window() -> setWindowTitle("New Window Title")
[2]