68 int xoff = vinfo.xoffset;
69 int yoff = vinfo.yoffset;
71 if (userGeometry.isValid()) {
72 w = userGeometry.width();
73 h = userGeometry.height();
74 if (q20::cmp_greater(w, vinfo.xres))
76 if (q20::cmp_greater(h, vinfo.yres))
79 int xxoff = userGeometry.x(), yyoff = userGeometry.y();
80 if (xxoff != 0 || yyoff != 0) {
81 if (xxoff < 0 || q20::cmp_greater(xxoff + w, vinfo.xres))
82 xxoff = vinfo.xres - w;
83 if (yyoff < 0 || q20::cmp_greater(yyoff + h, vinfo.yres))
84 yyoff = vinfo.yres - h;
88 xoff += (vinfo.xres - w)/2;
89 yoff += (vinfo.yres - h)/2;
96 if (w == 0 || h == 0) {
97 qWarning(
"Unable to find screen geometry, using 320x240");
102 return QRect(xoff, yoff, w, h);
107 int mmWidth = mmSize.width(), mmHeight = mmSize.height();
109 if (mmWidth <= 0 && mmHeight <= 0) {
110 if (vinfo.width != 0 && vinfo.height != 0
111 && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
112 mmWidth = vinfo.width;
113 mmHeight = vinfo.height;
116 mmWidth = qRound(res.width() * 25.4 / dpi);
117 mmHeight = qRound(res.height() * 25.4 / dpi);
119 }
else if (mmWidth > 0 && mmHeight <= 0) {
120 mmHeight = res.height() * mmWidth/res.width();
121 }
else if (mmHeight > 0 && mmWidth <= 0) {
122 mmWidth = res.width() * mmHeight/res.height();
125 return QSize(mmWidth, mmHeight);
130 const fb_bitfield rgba[4] = { info.red, info.green,
131 info.blue, info.transp };
133 QImage::Format format = QImage::Format_Invalid;
137 const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
138 {0, 8, 0}, {24, 8, 0}};
139 const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
140 {16, 8, 0}, {24, 8, 0}};
141 if (memcmp(rgba, argb8888, 4 *
sizeof(fb_bitfield)) == 0) {
142 format = QImage::Format_ARGB32;
143 }
else if (memcmp(rgba, argb8888, 3 *
sizeof(fb_bitfield)) == 0) {
144 format = QImage::Format_RGB32;
145 }
else if (memcmp(rgba, abgr8888, 3 *
sizeof(fb_bitfield)) == 0) {
146 format = QImage::Format_RGB32;
152 const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
153 {0, 8, 0}, {0, 0, 0}};
154 const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
155 {16, 8, 0}, {0, 0, 0}};
156 if (memcmp(rgba, rgb888, 3 *
sizeof(fb_bitfield)) == 0) {
157 format = QImage::Format_RGB888;
158 }
else if (memcmp(rgba, bgr888, 3 *
sizeof(fb_bitfield)) == 0) {
159 format = QImage::Format_BGR888;
165 const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
166 {0, 6, 0}, {0, 0, 0}};
167 if (memcmp(rgba, rgb666, 3 *
sizeof(fb_bitfield)) == 0)
168 format = QImage::Format_RGB666;
172 const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
173 {0, 5, 0}, {0, 0, 0}};
174 const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
175 {11, 5, 0}, {0, 0, 0}};
176 if (memcmp(rgba, rgb565, 3 *
sizeof(fb_bitfield)) == 0) {
177 format = QImage::Format_RGB16;
178 }
else if (memcmp(rgba, bgr565, 3 *
sizeof(fb_bitfield)) == 0) {
179 format = QImage::Format_RGB16;
185 const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
186 {0, 5, 0}, {15, 1, 0}};
187 const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
188 {10, 5, 0}, {15, 1, 0}};
189 if (memcmp(rgba, rgb1555, 3 *
sizeof(fb_bitfield)) == 0) {
190 format = QImage::Format_RGB555;
191 }
else if (memcmp(rgba, bgr1555, 3 *
sizeof(fb_bitfield)) == 0) {
192 format = QImage::Format_RGB555;
198 const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
199 {0, 4, 0}, {0, 0, 0}};
200 if (memcmp(rgba, rgb444, 3 *
sizeof(fb_bitfield)) == 0)
201 format = QImage::Format_RGB444;
207 format = QImage::Format_Mono;
279 QRegularExpression ttyRx(
"tty=(.*)"_L1);
280 QRegularExpression fbRx(
"fb=(.*)"_L1);
281 QRegularExpression mmSizeRx(
"mmsize=(\\d+)x(\\d+)"_L1);
282 QRegularExpression sizeRx(
"size=(\\d+)x(\\d+)"_L1);
283 QRegularExpression offsetRx(
"offset=(\\d+)x(\\d+)"_L1);
285 QString fbDevice, ttyDevice;
288 bool doSwitchToGraphicsMode =
true;
291 for (
const QString &arg : std::as_const(mArgs)) {
292 QRegularExpressionMatch match;
293 if (arg ==
"nographicsmodeswitch"_L1)
294 doSwitchToGraphicsMode =
false;
295 else if (arg.contains(mmSizeRx, &match))
296 userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
297 else if (arg.contains(sizeRx, &match))
298 userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
299 else if (arg.contains(offsetRx, &match))
300 userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
301 else if (arg.contains(ttyRx, &match))
302 ttyDevice = match.captured(1);
303 else if (arg.contains(fbRx, &match))
304 fbDevice = match.captured(1);
307 if (fbDevice.isEmpty()) {
308 fbDevice =
"/dev/fb0"_L1;
309 if (!QFile::exists(fbDevice))
310 fbDevice =
"/dev/graphics/fb0"_L1;
311 if (!QFile::exists(fbDevice)) {
312 qWarning(
"Unable to figure out framebuffer device. Specify it manually.");
318 mFbFd = openFramebufferDevice(fbDevice);
320 qErrnoWarning(errno,
"Failed to open framebuffer %s", qPrintable(fbDevice));
325 fb_fix_screeninfo finfo;
326 fb_var_screeninfo vinfo;
327 memset(&vinfo, 0,
sizeof(vinfo));
328 memset(&finfo, 0,
sizeof(finfo));
330 if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
331 qErrnoWarning(errno,
"Error reading fixed information");
335 if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
336 qErrnoWarning(errno,
"Error reading variable information");
340 mDepth = determineDepth(vinfo);
341 mBytesPerLine = finfo.line_length;
342 QRect geometry = determineGeometry(vinfo, userGeometry);
343 mGeometry = QRect(QPoint(0, 0), geometry.size());
344 mFormat = determineFormat(vinfo, mDepth);
345 mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
348 mMmap.size = finfo.smem_len;
349 uchar *data = (
unsigned char *)mmap(
nullptr, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
350 if ((
long)data == -1) {
351 qErrnoWarning(errno,
"Failed to mmap framebuffer");
355 mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
356 mMmap.data = data + mMmap.offset;
358 QFbScreen::initializeCompositor();
359 mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
361 mCursor =
new QFbCursor(
this);
363 mTtyFd = openTtyDevice(ttyDevice);
365 qErrnoWarning(errno,
"Failed to open tty");
396 width = mFbScreenImage.width() - x;
398 height = mFbScreenImage.height() - y;
399 return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);
402 QFbWindow *window = windowForId(wid);
404 const QRect geom = window->geometry();
406 width = geom.width() - x;
408 height = geom.height() - y;
409 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
410 rect &= window->geometry();
411 return QPixmap::fromImage(mFbScreenImage).copy(rect);