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
qbsdfbscreen.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// Copyright (C) 2015-2016 Oleksandr Tymoshenko <gonzo@bluezbox.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qbsdfbscreen.h"
6#include <QtFbSupport/private/qfbcursor_p.h>
7#include <QtFbSupport/private/qfbwindow_p.h>
8#include <QtCore/QFile>
9#include <QtCore/QRegularExpression>
10#include <QtGui/QPainter>
11
12#include <private/qcore_unix_p.h> // overrides QT_OPEN
13#include <qimage.h>
14#include <qdebug.h>
15
16#include <unistd.h>
17#include <stdlib.h>
18#include <sys/ioctl.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <sys/mman.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <stdio.h>
25#include <limits.h>
26#include <signal.h>
27
28#include <sys/consio.h>
29#include <sys/fbio.h>
30
32
33using namespace Qt::StringLiterals;
34
35enum {
36 DefaultDPI = 100
37};
38
39static int openFramebufferDevice(const QString &dev)
40{
41 const QByteArray devPath = QFile::encodeName(dev);
42
43 int fd = QT_OPEN(devPath.constData(), O_RDWR);
44
45 if (fd == -1)
46 fd = QT_OPEN(devPath.constData(), O_RDONLY);
47
48 return fd;
49}
50
51static QRect determineGeometry(const struct fbtype &fb, const QRect &userGeometry)
52{
53 int xoff = 0;
54 int yoff = 0;
55 int w = 0;
56 int h = 0;
57
58 if (userGeometry.isValid()) {
59 w = qMin(userGeometry.width(), fb.fb_width);
60 h = qMin(userGeometry.height(), fb.fb_height);
61
62 int xxoff = userGeometry.x(), yyoff = userGeometry.y();
63 if (xxoff != 0 || yyoff != 0) {
64 if (xxoff < 0 || xxoff + w > fb.fb_width)
65 xxoff = fb.fb_width - w;
66 if (yyoff < 0 || yyoff + h > fb.fb_height)
67 yyoff = fb.fb_height - h;
68 xoff += xxoff;
69 yoff += yyoff;
70 } else {
71 xoff += (fb.fb_width - w)/2;
72 yoff += (fb.fb_height - h)/2;
73 }
74 } else {
75 w = fb.fb_width;
76 h = fb.fb_height;
77 }
78
79 if (w == 0 || h == 0) {
80 qWarning("Unable to find screen geometry, using 320x240");
81 w = 320;
82 h = 240;
83 }
84
85 return QRect(xoff, yoff, w, h);
86}
87
88static QSizeF determinePhysicalSize(const QSize &mmSize, const QSize &res)
89{
90 int mmWidth = mmSize.width();
91 int mmHeight = mmSize.height();
92
93 if (mmWidth <= 0 && mmHeight <= 0) {
94 const int dpi = DefaultDPI;
95 mmWidth = qRound(res.width() * 25.4 / dpi);
96 mmHeight = qRound(res.height() * 25.4 / dpi);
97 } else if (mmWidth > 0 && mmHeight <= 0) {
98 mmHeight = res.height() * mmWidth/res.width();
99 } else if (mmHeight > 0 && mmWidth <= 0) {
100 mmWidth = res.width() * mmHeight/res.height();
101 }
102
103 return QSize(mmWidth, mmHeight);
104}
105
107 : m_arguments(args)
108{
109}
110
112{
113 if (m_framebufferFd != -1) {
114 munmap(m_mmap.data - m_mmap.offset, m_mmap.size);
115 qt_safe_close(m_framebufferFd);
116 }
117}
118
120{
121 QRegularExpression fbRx("fb=(.*)"_L1);
122 QRegularExpression mmSizeRx("mmsize=(\\d+)x(\\d+)"_L1);
123 QRegularExpression sizeRx("size=(\\d+)x(\\d+)"_L1);
124 QRegularExpression offsetRx("offset=(\\d+)x(\\d+)"_L1);
125
126 QString fbDevice;
127 QSize userMmSize;
128 QRect userGeometry;
129
130 // Parse arguments
131 for (const QString &arg : std::as_const(m_arguments)) {
133 if (arg.contains(mmSizeRx, &match))
134 userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
135 else if (arg.contains(sizeRx, &match))
136 userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
137 else if (arg.contains(offsetRx, &match))
138 userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
139 else if (arg.contains(fbRx, &match))
140 fbDevice = match.captured(1);
141 }
142
143 if (!fbDevice.isEmpty()) {
144 // Open the device
145 m_framebufferFd = openFramebufferDevice(fbDevice);
146 } else {
147 m_framebufferFd = STDIN_FILENO;
148 }
149
150 if (m_framebufferFd == -1) {
151 qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));
152 return false;
153 }
154
155 struct fbtype fb;
156 if (ioctl(m_framebufferFd, FBIOGTYPE, &fb) != 0) {
157 qErrnoWarning(errno, "Error reading framebuffer information");
158 return false;
159 }
160
161 int line_length = 0;
162 if (ioctl(m_framebufferFd, FBIO_GETLINEWIDTH, &line_length) != 0) {
163 qErrnoWarning(errno, "Error reading line length information");
164 return false;
165 }
166
167 mDepth = fb.fb_depth;
168
169 m_bytesPerLine = line_length;
170 const QRect geometry = determineGeometry(fb, userGeometry);
171 mGeometry = QRect(QPoint(0, 0), geometry.size());
172 switch (mDepth) {
173 case 32:
175 break;
176 case 24:
178 break;
179 case 16:
180 // falling back
181 default:
183 break;
184 }
186
187 // mmap the framebuffer
188 const size_t pagemask = getpagesize() - 1;
189 m_mmap.size = (m_bytesPerLine * fb.fb_height + pagemask) & ~pagemask;
190 uchar *data = static_cast<uchar*>(mmap(nullptr, m_mmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebufferFd, 0));
191 if (data == MAP_FAILED) {
192 qErrnoWarning(errno, "Failed to mmap framebuffer");
193 return false;
194 }
195
196 m_mmap.offset = geometry.y() * m_bytesPerLine + geometry.x() * mDepth / 8;
197 m_mmap.data = data + m_mmap.offset;
198
200 m_onscreenImage = QImage(m_mmap.data, geometry.width(), geometry.height(), m_bytesPerLine, mFormat);
201
202 mCursor = new QFbCursor(this);
203
204 return true;
205}
206
208{
209 const QRegion touched = QFbScreen::doRedraw();
210
211 if (touched.isEmpty())
212 return touched;
213
214 if (!m_blitter)
215 m_blitter.reset(new QPainter(&m_onscreenImage));
216
217 for (const QRect &rect : touched)
218 m_blitter->drawImage(rect, mScreenImage, rect);
219 return touched;
220}
221
222// grabWindow() grabs "from the screen" not from the backingstores.
223QPixmap QBsdFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
224{
225 if (!wid) {
226 if (width < 0)
227 width = m_onscreenImage.width() - x;
228 if (height < 0)
229 height = m_onscreenImage.height() - y;
230 return QPixmap::fromImage(m_onscreenImage).copy(x, y, width, height);
231 }
232
233 const QFbWindow *window = windowForId(wid);
234 if (window) {
235 const QRect geom = window->geometry();
236 if (width < 0)
237 width = geom.width() - x;
238 if (height < 0)
239 height = geom.height() - y;
240 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
241 rect &= window->geometry();
242 return QPixmap::fromImage(m_onscreenImage).copy(rect);
243 }
244
245 return QPixmap();
246}
247
bool initialize() override
QBsdFbScreen(const QStringList &args)
~QBsdFbScreen() override
QRegion doRedraw() override
QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override
This function is called when Qt needs to be able to grab the content of a window.
\inmodule QtCore
Definition qbytearray.h:57
QImage mScreenImage
Definition qfbscreen_p.h:89
QFbWindow * windowForId(WId wid) const
QRect geometry() const override
Reimplement in subclass to return the pixel geometry of the screen.
Definition qfbscreen_p.h:45
void initializeCompositor()
Definition qfbscreen.cpp:32
virtual QRegion doRedraw()
QFbCursor * mCursor
Definition qfbscreen_p.h:84
QRect mGeometry
Definition qfbscreen_p.h:85
QImage::Format mFormat
Definition qfbscreen_p.h:87
QSizeF mPhysicalSize
Definition qfbscreen_p.h:88
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
\inmodule QtGui
Definition qimage.h:37
int width() const
Returns the width of the image.
int height() const
Returns the height of the image.
@ Format_RGB888
Definition qimage.h:55
@ Format_RGB32
Definition qimage.h:46
@ Format_RGB16
Definition qimage.h:49
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition qpixmap.cpp:1437
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
rect
[4]
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
static QRect determineGeometry(const struct fbtype &fb, const QRect &userGeometry)
static int openFramebufferDevice(const QString &dev)
static QSizeF determinePhysicalSize(const QSize &mmSize, const QSize &res)
@ DefaultDPI
#define QT_OPEN
static int qt_safe_close(int fd)
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLuint64 GLenum GLint fd
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint res
#define MAP_FAILED
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
unsigned char uchar
Definition qtypes.h:32
aWidget window() -> setWindowTitle("New Window Title")
[2]
QJSValueList args