Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
14
15QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow) :
16 QQnxWindow(window, context, needRootWindow),
17 m_currentBufferIndex(-1),
18 m_previousBufferIndex(-1)
19{
20 initWindow();
21
22 // Set window usage
23 if (window->type() == Qt::Desktop)
24 return;
25
26 const int val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
27 const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val);
28 if (Q_UNLIKELY(result != 0))
29 qFatal("QQnxRasterWindow: failed to set window alpha usage, errno=%d", errno);
30}
31
33{
34 // How double-buffering works
35 // --------------------------
36 //
37 // The are two buffers, the previous one and the current one.
38 // The previous buffer always contains the complete, full image of the whole window when it
39 // was last posted.
40 // The current buffer starts with the complete, full image of the second to last posting
41 // of the window.
42 //
43 // During painting, Qt paints on the current buffer. Thus, when Qt has finished painting, the
44 // current buffer contains the second to last image plus the newly painted regions.
45 // Since the second to last image is too old, we copy over the image from the previous buffer, but
46 // only for those regions that Qt didn't paint (because that would overwrite what Qt has just
47 // painted). This is the copyPreviousToCurrent() call below.
48 //
49 // After the call to copyPreviousToCurrent(), the current buffer contains the complete, full image of the
50 // whole window in its current state, and we call screen_post_window() to make the new buffer
51 // available to libscreen (called "posting"). There, only the regions that Qt painted on are
52 // posted, as nothing else has changed.
53 //
54 // After that, the previous and the current buffers are swapped, and the whole cycle starts anew.
55
56 // Check if render buffer exists and something was rendered
57 if (m_currentBufferIndex != -1 && !dirty.isEmpty()) {
58 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
59 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
60
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;
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
73 screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0),
74 "Failed to post window");
75
76 // Advance to next nender buffer
77 m_previousBufferIndex = m_currentBufferIndex++;
78 if (m_currentBufferIndex >= MAX_BUFFER_COUNT)
79 m_currentBufferIndex = 0;
80
81 // Save modified region and clear scrolled region
82 m_previousDirty = dirty;
83 m_scrolled = QRegion();
84
86 }
87}
88
89void QQnxRasterWindow::scroll(const QRegion &region, int dx, int dy, bool flush)
90{
91 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
92 blitPreviousToCurrent(region, dx, dy, flush);
93 m_scrolled += region;
94}
95
97{
98 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
99
100 // Check if render buffer is invalid
101 if (m_currentBufferIndex == -1) {
102 auto platformScreen = static_cast<QQnxScreen *>(screen());
103 // Get all buffers available for rendering
104 screen_buffer_t buffers[MAX_BUFFER_COUNT];
105 const int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS,
106 (void **)buffers);
107 Q_SCREEN_CRITICALERROR(result, "Failed to query window buffers");
108
109 // Wrap each buffer and clear
110 for (int i = 0; i < MAX_BUFFER_COUNT; ++i) {
111 m_buffers[i] = QQnxBuffer(buffers[i]);
112
113 // Clear Buffer
114 int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
115 Q_SCREEN_CHECKERROR(screen_fill(platformScreen->nativeContext(), buffers[i], bg),
116 "Failed to clear window buffer");
117 }
118
119 Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), SCREEN_WAIT_IDLE),
120 "Failed to flush blits");
121
122 // Use the first available render buffer
123 m_currentBufferIndex = 0;
124 m_previousBufferIndex = -1;
125 }
126
127 return m_buffers[m_currentBufferIndex];
128}
129
135
137{
138 const QSize windowSize = window()->size();
139
140 if (windowSize != bufferSize())
141 setBufferSize(windowSize);
142}
143
145{
146 return static_cast<QQnxScreen *>(screen())->nativeFormat();
147}
148
150{
151 // Buffers were destroyed; reacquire them
152 m_currentBufferIndex = -1;
153 m_previousDirty = QRegion();
154 m_scrolled = QRegion();
155}
156
157void QQnxRasterWindow::blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush)
158{
159 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window = " << window();
160
161 // Abort if previous buffer is invalid or if nothing to copy
162 if (m_previousBufferIndex == -1 || region.isEmpty())
163 return;
164
165 QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
166 QQnxBuffer &previousBuffer = m_buffers[m_previousBufferIndex];
167
168 // Break down region into non-overlapping rectangles
169 for (auto rit = region.rbegin(), rend = region.rend(); rit != rend; ++rit) {
170 // Clip rectangle to bounds of target
171 const QRect rect = rit->intersected(currentBuffer.rect());
172
173 if (rect.isEmpty())
174 continue;
175
176 // Setup blit operation
177 int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x(),
178 SCREEN_BLIT_SOURCE_Y, rect.y(),
179 SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
180 SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
181 SCREEN_BLIT_DESTINATION_X, rect.x() + dx,
182 SCREEN_BLIT_DESTINATION_Y, rect.y() + dy,
183 SCREEN_BLIT_DESTINATION_WIDTH, rect.width(),
184 SCREEN_BLIT_DESTINATION_HEIGHT, rect.height(),
185 SCREEN_BLIT_END };
186
187 // Queue blit operation
188 Q_SCREEN_CHECKERROR(screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
189 previousBuffer.nativeBuffer(), attribs),
190 "Failed to blit buffers");
191 }
192
193 // Check if flush requested
194 if (flush) {
195 // Wait for all blits to complete
196 Q_SCREEN_CHECKERROR(screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE),
197 "Failed to flush blits");
198
199 // Buffer was modified outside the CPU
200 currentBuffer.invalidateInCache();
201 }
202}
203
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:24
QRect rect() const
Definition qqnxbuffer.h:28
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:31
void windowPosted()
screen_context_t m_screenContext
Definition qqnxwindow.h:84
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:45
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:48
\inmodule QtCore\reentrant
Definition qrect.h:30
QRect intersected(const QRect &other) const noexcept
Definition qrect.h:415
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
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:215
static void * context
#define Q_UNLIKELY(x)
#define Q_FUNC_INFO
#define qFatal
Definition qlogging.h:168
#define qCDebug(category,...)
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 MAX_BUFFER_COUNT
Definition qqnxwindow.h:24
aWidget window() -> setWindowTitle("New Window Title")
[2]