67 int xoff = vinfo.xoffset;
68 int yoff = vinfo.yoffset;
70 if (userGeometry.isValid()) {
71 w = userGeometry.width();
72 h = userGeometry.height();
73 if (q20::cmp_greater(w, vinfo.xres))
75 if (q20::cmp_greater(h, vinfo.yres))
78 int xxoff = userGeometry.x(), yyoff = userGeometry.y();
79 if (xxoff != 0 || yyoff != 0) {
80 if (xxoff < 0 || q20::cmp_greater(xxoff + w, vinfo.xres))
81 xxoff = vinfo.xres - w;
82 if (yyoff < 0 || q20::cmp_greater(yyoff + h, vinfo.yres))
83 yyoff = vinfo.yres - h;
87 xoff += (vinfo.xres - w)/2;
88 yoff += (vinfo.yres - h)/2;
95 if (w == 0 || h == 0) {
96 qWarning(
"Unable to find screen geometry, using 320x240");
101 return QRect(xoff, yoff, w, h);
106 int mmWidth = mmSize.width(), mmHeight = mmSize.height();
108 if (mmWidth <= 0 && mmHeight <= 0) {
109 if (vinfo.width != 0 && vinfo.height != 0
110 && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
111 mmWidth = vinfo.width;
112 mmHeight = vinfo.height;
115 mmWidth = qRound(res.width() * 25.4 / dpi);
116 mmHeight = qRound(res.height() * 25.4 / dpi);
118 }
else if (mmWidth > 0 && mmHeight <= 0) {
119 mmHeight = res.height() * mmWidth/res.width();
120 }
else if (mmHeight > 0 && mmWidth <= 0) {
121 mmWidth = res.width() * mmHeight/res.height();
124 return QSize(mmWidth, mmHeight);
129 const fb_bitfield rgba[4] = { info.red, info.green,
130 info.blue, info.transp };
132 QImage::Format format = QImage::Format_Invalid;
136 const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
137 {0, 8, 0}, {24, 8, 0}};
138 const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
139 {16, 8, 0}, {24, 8, 0}};
140 if (memcmp(rgba, argb8888, 4 *
sizeof(fb_bitfield)) == 0) {
141 format = QImage::Format_ARGB32;
142 }
else if (memcmp(rgba, argb8888, 3 *
sizeof(fb_bitfield)) == 0) {
143 format = QImage::Format_RGB32;
144 }
else if (memcmp(rgba, abgr8888, 3 *
sizeof(fb_bitfield)) == 0) {
145 format = QImage::Format_RGB32;
151 const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
152 {0, 8, 0}, {0, 0, 0}};
153 const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
154 {16, 8, 0}, {0, 0, 0}};
155 if (memcmp(rgba, rgb888, 3 *
sizeof(fb_bitfield)) == 0) {
156 format = QImage::Format_RGB888;
157 }
else if (memcmp(rgba, bgr888, 3 *
sizeof(fb_bitfield)) == 0) {
158 format = QImage::Format_BGR888;
164 const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
165 {0, 6, 0}, {0, 0, 0}};
166 if (memcmp(rgba, rgb666, 3 *
sizeof(fb_bitfield)) == 0)
167 format = QImage::Format_RGB666;
171 const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
172 {0, 5, 0}, {0, 0, 0}};
173 const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
174 {11, 5, 0}, {0, 0, 0}};
175 if (memcmp(rgba, rgb565, 3 *
sizeof(fb_bitfield)) == 0) {
176 format = QImage::Format_RGB16;
177 }
else if (memcmp(rgba, bgr565, 3 *
sizeof(fb_bitfield)) == 0) {
178 format = QImage::Format_RGB16;
184 const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
185 {0, 5, 0}, {15, 1, 0}};
186 const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
187 {10, 5, 0}, {15, 1, 0}};
188 if (memcmp(rgba, rgb1555, 3 *
sizeof(fb_bitfield)) == 0) {
189 format = QImage::Format_RGB555;
190 }
else if (memcmp(rgba, bgr1555, 3 *
sizeof(fb_bitfield)) == 0) {
191 format = QImage::Format_RGB555;
197 const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
198 {0, 4, 0}, {0, 0, 0}};
199 if (memcmp(rgba, rgb444, 3 *
sizeof(fb_bitfield)) == 0)
200 format = QImage::Format_RGB444;
206 format = QImage::Format_Mono;
278 QRegularExpression ttyRx(
"tty=(.*)"_L1);
279 QRegularExpression fbRx(
"fb=(.*)"_L1);
280 QRegularExpression mmSizeRx(
"mmsize=(\\d+)x(\\d+)"_L1);
281 QRegularExpression sizeRx(
"size=(\\d+)x(\\d+)"_L1);
282 QRegularExpression offsetRx(
"offset=(\\d+)x(\\d+)"_L1);
284 QString fbDevice, ttyDevice;
287 bool doSwitchToGraphicsMode =
true;
290 for (
const QString &arg : std::as_const(mArgs)) {
291 QRegularExpressionMatch match;
292 if (arg ==
"nographicsmodeswitch"_L1)
293 doSwitchToGraphicsMode =
false;
294 else if (arg.contains(mmSizeRx, &match))
295 userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
296 else if (arg.contains(sizeRx, &match))
297 userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
298 else if (arg.contains(offsetRx, &match))
299 userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
300 else if (arg.contains(ttyRx, &match))
301 ttyDevice = match.captured(1);
302 else if (arg.contains(fbRx, &match))
303 fbDevice = match.captured(1);
306 if (fbDevice.isEmpty()) {
307 fbDevice =
"/dev/fb0"_L1;
308 if (!QFile::exists(fbDevice))
309 fbDevice =
"/dev/graphics/fb0"_L1;
310 if (!QFile::exists(fbDevice)) {
311 qWarning(
"Unable to figure out framebuffer device. Specify it manually.");
317 mFbFd = openFramebufferDevice(fbDevice);
319 qErrnoWarning(errno,
"Failed to open framebuffer %s", qPrintable(fbDevice));
324 fb_fix_screeninfo finfo;
325 fb_var_screeninfo vinfo;
326 memset(&vinfo, 0,
sizeof(vinfo));
327 memset(&finfo, 0,
sizeof(finfo));
329 if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
330 qErrnoWarning(errno,
"Error reading fixed information");
334 if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
335 qErrnoWarning(errno,
"Error reading variable information");
339 mDepth = determineDepth(vinfo);
340 mBytesPerLine = finfo.line_length;
341 QRect geometry = determineGeometry(vinfo, userGeometry);
342 mGeometry = QRect(QPoint(0, 0), geometry.size());
343 mFormat = determineFormat(vinfo, mDepth);
344 mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
347 mMmap.size = finfo.smem_len;
348 uchar *data = (
unsigned char *)mmap(
nullptr, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
349 if ((
long)data == -1) {
350 qErrnoWarning(errno,
"Failed to mmap framebuffer");
354 mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
355 mMmap.data = data + mMmap.offset;
357 QFbScreen::initializeCompositor();
358 mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
360 mCursor =
new QFbCursor(
this);
362 mTtyFd = openTtyDevice(ttyDevice);
364 qErrnoWarning(errno,
"Failed to open tty");
395 width = mFbScreenImage.width() - x;
397 height = mFbScreenImage.height() - y;
398 return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);
401 QFbWindow *window = windowForId(wid);
403 const QRect geom = window->geometry();
405 width = geom.width() - x;
407 height = geom.height() - y;
408 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
409 rect &= window->geometry();
410 return QPixmap::fromImage(mFbScreenImage).copy(rect);