Qt 4.8
qlinuxfbintegration.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qlinuxfbintegration.h"
43 #include "../fb_base/fb_base.h"
45 #include <QtGui/private/qpixmap_raster_p.h>
46 #include <private/qcore_unix_p.h> // overrides QT_OPEN
47 #include <qimage.h>
48 #include <qdebug.h>
49 
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <sys/ioctl.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <sys/mman.h>
56 #include <sys/kd.h>
57 #include <fcntl.h>
58 #include <errno.h>
59 #include <stdio.h>
60 #include <limits.h>
61 #include <signal.h>
62 
63 #if !defined(Q_OS_DARWIN) && !defined(Q_OS_FREEBSD)
64 #include <linux/fb.h>
65 
66 #ifdef __i386__
67 #include <asm/mtrr.h>
68 #endif
69 #endif
70 
72 
74 {
75 public:
78 
79  void openTty();
80  void closeTty();
81 
82  int fd;
83  int startupw;
84  int startuph;
85  int startupd;
86  bool blank;
87 
89 #ifdef QT_QWS_DEPTH_GENERIC
90  bool doGenericColors;
91 #endif
92  int ttyfd;
93  long oldKdMode;
96 };
97 
99  : fd(-1), blank(true), doGraphicsMode(true),
100 #ifdef QT_QWS_DEPTH_GENERIC
101  doGenericColors(false),
102 #endif
103  ttyfd(-1), oldKdMode(KD_TEXT)
104 {
105 }
106 
108 {
109  closeTty();
110 }
111 
113 {
114  const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
115 
116  if (ttyDevice.isEmpty()) {
117  for (const char * const *dev = devs; *dev; ++dev) {
118  ttyfd = QT_OPEN(*dev, O_RDWR);
119  if (ttyfd != -1)
120  break;
121  }
122  } else {
124  }
125 
126  if (ttyfd == -1)
127  return;
128 
129  if (doGraphicsMode) {
130  ioctl(ttyfd, KDGETMODE, &oldKdMode);
131  if (oldKdMode != KD_GRAPHICS) {
132  int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
133  if (ret == -1)
134  doGraphicsMode = false;
135  }
136  }
137 
138  // No blankin' screen, no blinkin' cursor!, no cursor!
139  const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
140  QT_WRITE(ttyfd, termctl, sizeof(termctl));
141 }
142 
144 {
145  if (ttyfd == -1)
146  return;
147 
148  if (doGraphicsMode)
149  ioctl(ttyfd, KDSETMODE, oldKdMode);
150 
151  // Blankin' screen, blinkin' cursor!
152  const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
153  QT_WRITE(ttyfd, termctl, sizeof(termctl));
154 
155  QT_CLOSE(ttyfd);
156  ttyfd = -1;
157 }
158 
160  :fontDb(new QGenericUnixFontDatabase())
161 {
163 
164  // XXX
165  QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY"));
166 
167  if (!connect(displaySpec))
168  qFatal("QLinuxFbIntegration: could not initialize screen");
169  initDevice();
170 
171  // Create a QImage directly on the screen's framebuffer.
172  // This is the blit target for copying windows to the screen.
174  screenFormat);
177 }
178 
180 {
181  delete mPrimaryScreen;
182  delete d_ptr;
183 }
184 
185 bool QLinuxFbIntegration::connect(const QString &displaySpec)
186 {
187  const QStringList args = displaySpec.split(QLatin1Char(':'));
188 
189  if (args.contains(QLatin1String("nographicsmodeswitch")))
190  d_ptr->doGraphicsMode = false;
191 
192 #ifdef QT_QWS_DEPTH_GENERIC
193  if (args.contains(QLatin1String("genericcolors")))
194  d_ptr->doGenericColors = true;
195 #endif
196 
197  QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
198  if (args.indexOf(ttyRegExp) != -1)
199  d_ptr->ttyDevice = ttyRegExp.cap(1);
200 
201 #if 0
202 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
203 #ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
204  if (args.contains(QLatin1String("littleendian")))
205 #endif
207 #endif
208 #endif
209 
210  // Check for explicitly specified device
211  const int len = 8; // "/dev/fbx"
212  int m = displaySpec.indexOf(QLatin1String("/dev/fb"));
213 
214  QString dev;
215  if (m > 0)
216  dev = displaySpec.mid(m, len);
217  else
218  dev = QLatin1String("/dev/fb0");
219 
220  if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
221  d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
222  if (d_ptr->fd == -1) {
223  if (access(dev.toLatin1().constData(), R_OK) == 0)
224  d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
225  if (d_ptr->fd == 1) {
226  qWarning("Error opening framebuffer device %s", qPrintable(dev));
227  return false;
228  }
229  }
230 
231  fb_fix_screeninfo finfo;
232  fb_var_screeninfo vinfo;
233  //#######################
234  // Shut up Valgrind
235  memset(&vinfo, 0, sizeof(vinfo));
236  memset(&finfo, 0, sizeof(finfo));
237  //#######################
238 
239  /* Get fixed screen information */
240  if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
241  perror("QLinuxFbIntegration::connect");
242  qWarning("Error reading fixed information");
243  return false;
244  }
245 
246  if (finfo.type == FB_TYPE_VGA_PLANES) {
247  qWarning("VGA16 video mode not supported");
248  return false;
249  }
250 
251  /* Get variable screen information */
252  if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
253  perror("QLinuxFbIntegration::connect");
254  qWarning("Error reading variable information");
255  return false;
256  }
257 
258  grayscale = vinfo.grayscale;
259  d = vinfo.bits_per_pixel;
260  if (d == 24) {
261  d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
262  if (d <= 0)
263  d = 24; // reset if color component lengths are not reported
264  } else if (d == 16) {
265  d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
266  if (d <= 0)
267  d = 16;
268  }
269  lstep = finfo.line_length;
270 
271  int xoff = vinfo.xoffset;
272  int yoff = vinfo.yoffset;
273  const char* qwssize;
274  if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) {
275  if (d_ptr->fd != -1) {
276  if ((uint)w > vinfo.xres) w = vinfo.xres;
277  if ((uint)h > vinfo.yres) h = vinfo.yres;
278  }
279  dw=w;
280  dh=h;
281  int xxoff, yyoff;
282  if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) {
283  if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))
284  xxoff = vinfo.xres - w;
285  if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))
286  yyoff = vinfo.yres - h;
287  xoff += xxoff;
288  yoff += yyoff;
289  } else {
290  xoff += (vinfo.xres - w)/2;
291  yoff += (vinfo.yres - h)/2;
292  }
293  } else {
294  dw=w=vinfo.xres;
295  dh=h=vinfo.yres;
296  }
297 
298  if (w == 0 || h == 0) {
299  qWarning("QLinuxFbIntegration::connect(): Unable to find screen geometry, "
300  "will use 320x240.");
301  dw = w = 320;
302  dh = h = 240;
303  }
304 
305  setPixelFormat(vinfo);
306 
307  // Handle display physical size spec.
308  QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
309  QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
310  int dimIdxW = displayArgs.indexOf(mmWidthRx);
311  QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
312  int dimIdxH = displayArgs.indexOf(mmHeightRx);
313  if (dimIdxW >= 0) {
314  mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
315  physWidth = mmWidthRx.cap(1).toInt();
316  if (dimIdxH < 0)
318  }
319  if (dimIdxH >= 0) {
320  mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
321  physHeight = mmHeightRx.cap(1).toInt();
322  if (dimIdxW < 0)
324  }
325  if (dimIdxW < 0 && dimIdxH < 0) {
326  if (vinfo.width != 0 && vinfo.height != 0
327  && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
328  physWidth = vinfo.width;
329  physHeight = vinfo.height;
330  } else {
331  const int dpi = 72;
332  physWidth = qRound(dw * 25.4 / dpi);
333  physHeight = qRound(dh * 25.4 / dpi);
334  }
335  }
336 
337  dataoffset = yoff * lstep + xoff * d / 8;
338  //qDebug("Using %dx%dx%d screen",w,h,d);
339 
340  /* Figure out the size of the screen in bytes */
341  size = h * lstep;
342 
343  mapsize = finfo.smem_len;
344 
345  data = (unsigned char *)-1;
346  if (d_ptr->fd != -1)
347  data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE,
348  MAP_SHARED, d_ptr->fd, 0);
349 
350  if ((long)data == -1) {
351  perror("QLinuxFbIntegration::connect");
352  qWarning("Error: failed to map framebuffer device to memory.");
353  return false;
354  } else {
355  data += dataoffset;
356  }
357 
358 #if 0
359  canaccel = useOffscreen();
360  if(canaccel)
361  setupOffScreen();
362 #endif
363  canaccel = false;
364 
365  // Now read in palette
366  if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
367  screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
368  int loopc;
369  fb_cmap startcmap;
370  startcmap.start=0;
371  startcmap.len=screencols;
372  startcmap.red=(unsigned short int *)
373  malloc(sizeof(unsigned short int)*screencols);
374  startcmap.green=(unsigned short int *)
375  malloc(sizeof(unsigned short int)*screencols);
376  startcmap.blue=(unsigned short int *)
377  malloc(sizeof(unsigned short int)*screencols);
378  startcmap.transp=(unsigned short int *)
379  malloc(sizeof(unsigned short int)*screencols);
380  if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) {
381  perror("QLinuxFbIntegration::connect");
382  qWarning("Error reading palette from framebuffer, using default palette");
383  createPalette(startcmap, vinfo, finfo);
384  }
385  int bits_used = 0;
386  for(loopc=0;loopc<screencols;loopc++) {
387  screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8,
388  startcmap.green[loopc] >> 8,
389  startcmap.blue[loopc] >> 8);
390  bits_used |= startcmap.red[loopc]
391  | startcmap.green[loopc]
392  | startcmap.blue[loopc];
393  }
394  // WORKAROUND: Some framebuffer drivers only return 8 bit
395  // color values, so we need to not bit shift them..
396  if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) {
397  for(loopc=0;loopc<screencols;loopc++) {
398  screenclut[loopc] = qRgb(startcmap.red[loopc],
399  startcmap.green[loopc],
400  startcmap.blue[loopc]);
401  }
402  qWarning("8 bits cmap returned due to faulty FB driver, colors corrected");
403  }
404  free(startcmap.red);
405  free(startcmap.green);
406  free(startcmap.blue);
407  free(startcmap.transp);
408  } else {
409  screencols=0;
410  }
411 
412  return true;
413 }
414 
416 {
417  d_ptr->openTty();
418 
419  // Grab current mode so we can reset it
420  fb_var_screeninfo vinfo;
421  fb_fix_screeninfo finfo;
422  //#######################
423  // Shut up Valgrind
424  memset(&vinfo, 0, sizeof(vinfo));
425  memset(&finfo, 0, sizeof(finfo));
426  //#######################
427 
428  if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
429  perror("QLinuxFbScreen::initDevice");
430  qFatal("Error reading variable information in card init");
431  return false;
432  }
433 
434 #ifdef DEBUG_VINFO
435  qDebug("Greyscale %d",vinfo.grayscale);
436  qDebug("Nonstd %d",vinfo.nonstd);
437  qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length,
438  vinfo.red.msb_right);
439  qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length,
440  vinfo.green.msb_right);
441  qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length,
442  vinfo.blue.msb_right);
443  qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length,
444  vinfo.transp.msb_right);
445 #endif
446 
447  d_ptr->startupw=vinfo.xres;
448  d_ptr->startuph=vinfo.yres;
449  d_ptr->startupd=vinfo.bits_per_pixel;
450  grayscale = vinfo.grayscale;
451 
452  if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
453  perror("QLinuxFbScreen::initDevice");
454  qCritical("Error reading fixed information in card init");
455  // It's not an /error/ as such, though definitely a bad sign
456  // so we return true
457  return true;
458  }
459 
460 #ifdef __i386__
461  // Now init mtrr
462  if(!::getenv("QWS_NOMTRR")) {
463  int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0);
464  // MTRR entry goes away when file is closed - i.e.
465  // hopefully when QWS is killed
466  if(mfd != -1) {
467  mtrr_sentry sentry;
468  sentry.base=(unsigned long int)finfo.smem_start;
469  //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start);
470  // Size needs to be in 4k chunks, but that's not always
471  // what we get thanks to graphics card registers. Write combining
472  // these is Not Good, so we write combine what we can
473  // (which is not much - 4 megs on an 8 meg card, it seems)
474  unsigned int size=finfo.smem_len;
475  size=size >> 22;
476  size=size << 22;
477  sentry.size=size;
478  sentry.type=MTRR_TYPE_WRCOMB;
479  if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) {
480  //printf("Couldn't add mtrr entry for %lx %lx, %s\n",
481  //sentry.base,sentry.size,strerror(errno));
482  }
483  }
484 
485  // Should we close mfd here?
486  //QT_CLOSE(mfd);
487  }
488 #endif
489  if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR))
490  {
491  fb_cmap cmap;
492  createPalette(cmap, vinfo, finfo);
493  if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) {
494  perror("QLinuxFbScreen::initDevice");
495  qWarning("Error writing palette to framebuffer");
496  }
497  free(cmap.red);
498  free(cmap.green);
499  free(cmap.blue);
500  free(cmap.transp);
501  }
502 
503 #if 0
504  if (canaccel) {
505  *entryp=0;
506  *lowest = mapsize;
507  insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start
508  }
509 
510  shared->fifocount = 0;
511  shared->buffer_offset = 0xffffffff; // 0 would be a sensible offset (screen)
512  shared->linestep = 0;
513  shared->cliptop = 0xffffffff;
514  shared->clipleft = 0xffffffff;
515  shared->clipright = 0xffffffff;
516  shared->clipbottom = 0xffffffff;
517  shared->rop = 0xffffffff;
518 #endif
519 
520 #ifdef QT_QWS_DEPTH_GENERIC
521  if (pixelFormat() == QImage::Format_Invalid && screencols == 0
522  && d_ptr->doGenericColors)
523  {
524  qt_set_generic_blit(this, vinfo.bits_per_pixel,
525  vinfo.red.length, vinfo.green.length,
526  vinfo.blue.length, vinfo.transp.length,
527  vinfo.red.offset, vinfo.green.offset,
528  vinfo.blue.offset, vinfo.transp.offset);
529  }
530 #endif
531 
532 #if 0
533 #ifndef QT_NO_QWS_CURSOR
535 #endif
536 #endif
537  blank(false);
538 
539  return true;
540 }
541 
542 void QLinuxFbIntegration::setPixelFormat(struct fb_var_screeninfo info)
543 {
544  const fb_bitfield rgba[4] = { info.red, info.green,
545  info.blue, info.transp };
546 
548 
549  switch (d) {
550  case 32: {
551  const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
552  {0, 8, 0}, {24, 8, 0}};
553  const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
554  {16, 8, 0}, {24, 8, 0}};
555  if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {
556  format = QImage::Format_ARGB32;
557  } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
558  format = QImage::Format_RGB32;
559  } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
560  format = QImage::Format_RGB32;
562  }
563  break;
564  }
565  case 24: {
566  const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
567  {0, 8, 0}, {0, 0, 0}};
568  const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
569  {16, 8, 0}, {0, 0, 0}};
570  if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {
571  format = QImage::Format_RGB888;
572  } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
573  format = QImage::Format_RGB888;
575  }
576  break;
577  }
578  case 18: {
579  const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
580  {0, 6, 0}, {0, 0, 0}};
581  if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)
582  format = QImage::Format_RGB666;
583  break;
584  }
585  case 16: {
586  const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
587  {0, 5, 0}, {0, 0, 0}};
588  const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
589  {11, 5, 0}, {0, 0, 0}};
590  if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {
591  format = QImage::Format_RGB16;
592  } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
593  format = QImage::Format_RGB16;
595  }
596  break;
597  }
598  case 15: {
599  const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
600  {0, 5, 0}, {15, 1, 0}};
601  const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
602  {10, 5, 0}, {15, 1, 0}};
603  if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {
604  format = QImage::Format_RGB555;
605  } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
606  format = QImage::Format_RGB555;
608  }
609  break;
610  }
611  case 12: {
612  const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
613  {0, 4, 0}, {0, 0, 0}};
614  if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)
615  format = QImage::Format_RGB444;
616  break;
617  }
618  case 8:
619  break;
620  case 1:
621  format = QImage::Format_Mono; //###: LSB???
622  break;
623  default:
624  break;
625  }
626 
628 }
629 
630 void QLinuxFbIntegration::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo)
631 {
632  if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
633  screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
634  cmap.start=0;
635  cmap.len=screencols;
636  cmap.red=(unsigned short int *)
637  malloc(sizeof(unsigned short int)*screencols);
638  cmap.green=(unsigned short int *)
639  malloc(sizeof(unsigned short int)*screencols);
640  cmap.blue=(unsigned short int *)
641  malloc(sizeof(unsigned short int)*screencols);
642  cmap.transp=(unsigned short int *)
643  malloc(sizeof(unsigned short int)*screencols);
644 
645  if (screencols==16) {
646  if (finfo.type == FB_TYPE_PACKED_PIXELS) {
647  // We'll setup a grayscale cmap for 4bpp linear
648  int val = 0;
649  for (int idx = 0; idx < 16; ++idx, val += 17) {
650  cmap.red[idx] = (val<<8)|val;
651  cmap.green[idx] = (val<<8)|val;
652  cmap.blue[idx] = (val<<8)|val;
653  screenclut[idx]=qRgb(val, val, val);
654  }
655  } else {
656  // Default 16 colour palette
657  // Green is now trolltech green so certain images look nicer
658  // black d_gray l_gray white red green blue cyan magenta yellow
659  unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 };
660  unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F };
661  unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 };
662 
663  for (int idx = 0; idx < 16; ++idx) {
664  cmap.red[idx] = ((reds[idx]) << 8)|reds[idx];
665  cmap.green[idx] = ((greens[idx]) << 8)|greens[idx];
666  cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx];
667  cmap.transp[idx] = 0;
668  screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]);
669  }
670  }
671  } else {
672  if (grayscale) {
673  // Build grayscale palette
674  int i;
675  for(i=0;i<screencols;++i) {
676  int bval = screencols == 256 ? i : (i << 4);
677  ushort val = (bval << 8) | bval;
678  cmap.red[i] = val;
679  cmap.green[i] = val;
680  cmap.blue[i] = val;
681  cmap.transp[i] = 0;
682  screenclut[i] = qRgb(bval,bval,bval);
683  }
684  } else {
685  // 6x6x6 216 color cube
686  int idx = 0;
687  for(int ir = 0x0; ir <= 0xff; ir+=0x33) {
688  for(int ig = 0x0; ig <= 0xff; ig+=0x33) {
689  for(int ib = 0x0; ib <= 0xff; ib+=0x33) {
690  cmap.red[idx] = (ir << 8)|ir;
691  cmap.green[idx] = (ig << 8)|ig;
692  cmap.blue[idx] = (ib << 8)|ib;
693  cmap.transp[idx] = 0;
694  screenclut[idx]=qRgb(ir, ig, ib);
695  ++idx;
696  }
697  }
698  }
699  // Fill in rest with 0
700  for (int loopc=0; loopc<40; ++loopc) {
701  screenclut[idx]=0;
702  ++idx;
703  }
704  screencols=idx;
705  }
706  }
707  } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) {
708  cmap.start=0;
709  int rbits=0,gbits=0,bbits=0;
710  switch (vinfo.bits_per_pixel) {
711  case 8:
712  rbits=vinfo.red.length;
713  gbits=vinfo.green.length;
714  bbits=vinfo.blue.length;
715  if(rbits==0 && gbits==0 && bbits==0) {
716  // cyber2000 driver bug hack
717  rbits=3;
718  gbits=3;
719  bbits=2;
720  }
721  break;
722  case 15:
723  rbits=5;
724  gbits=5;
725  bbits=5;
726  break;
727  case 16:
728  rbits=5;
729  gbits=6;
730  bbits=5;
731  break;
732  case 18:
733  case 19:
734  rbits=6;
735  gbits=6;
736  bbits=6;
737  break;
738  case 24: case 32:
739  rbits=gbits=bbits=8;
740  break;
741  }
742  screencols=cmap.len=1<<qMax(rbits,qMax(gbits,bbits));
743  cmap.red=(unsigned short int *)
744  malloc(sizeof(unsigned short int)*256);
745  cmap.green=(unsigned short int *)
746  malloc(sizeof(unsigned short int)*256);
747  cmap.blue=(unsigned short int *)
748  malloc(sizeof(unsigned short int)*256);
749  cmap.transp=(unsigned short int *)
750  malloc(sizeof(unsigned short int)*256);
751  for(unsigned int i = 0x0; i < cmap.len; i++) {
752  cmap.red[i] = i*65535/((1<<rbits)-1);
753  cmap.green[i] = i*65535/((1<<gbits)-1);
754  cmap.blue[i] = i*65535/((1<<bbits)-1);
755  cmap.transp[i] = 0;
756  }
757  }
758 }
759 
761 {
762  if (d_ptr->blank == on)
763  return;
764 
765 #if defined(QT_QWS_IPAQ)
766  if (on)
767  system("apm -suspend");
768 #else
769  if (d_ptr->fd == -1)
770  return;
771 // Some old kernel versions don't have this. These defines should go
772 // away eventually
773 #if defined(FBIOBLANK)
774 #if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING)
775  ioctl(d_ptr->fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
776 #else
777  ioctl(d_ptr->fd, FBIOBLANK, on ? 1 : 0);
778 #endif
779 #endif
780 #endif
781 
782  d_ptr->blank = on;
783 }
784 
786 {
787  switch (cap) {
788  case ThreadedPixmaps: return true;
789  default: return QPlatformIntegration::hasCapability(cap);
790  }
791 }
792 
793 
795 {
796  return new QRasterPixmapData(type);
797 }
798 
800 {
801  QFbWindowSurface * surface =
802  new QFbWindowSurface(mPrimaryScreen, widget);
803  return surface;
804 }
805 
807 {
808  QFbWindow *w = new QFbWindow(widget);
810  return w;
811 }
812 
814 {
815  return fontDb;
816 }
817 
819  int h, int lstep, QImage::Format screenFormat) : compositePainter(0)
820 {
821  data = d;
822  mGeometry = QRect(0,0,w,h);
824  mFormat = screenFormat;
825  mDepth = 16;
827  mFormat);
830 #ifndef QT_NO_CURSOR
831  cursor = new QPlatformSoftwareCursor(this);
832 #endif
833 }
834 
836 {
837  mGeometry = rect;
838  delete mFbScreenImage;
841  delete compositePainter;
842  compositePainter = 0;
843 
844  delete mScreenImage;
846  mFormat);
847 }
848 
850 {
851  mFormat = format;
852  delete mFbScreenImage;
855  delete compositePainter;
856  compositePainter = 0;
857 
858  delete mScreenImage;
860  mFormat);
861 }
862 
864 {
865  QRegion touched;
866  touched = QFbScreen::doRedraw();
867 
868  if (!compositePainter) {
870  }
871 
872  QVector<QRect> rects = touched.rects();
873  for (int i = 0; i < rects.size(); i++)
874  compositePainter->drawImage(rects[i], *mScreenImage, rects[i]);
875  return touched;
876 }
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
QImage * mScreenImage
Definition: fb_base.h:197
Format
The following image formats are available in Qt.
Definition: qimage.h:91
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
unsigned long WId
Definition: qwindowdefs.h:119
QLinuxFbIntegrationPrivate * d_ptr
int type
Definition: qmetatype.cpp:239
static mach_timebase_info_data_t info
QString cap(int nth=0) const
Returns the text captured by the nth subexpression.
Definition: qregexp.cpp:4310
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual QRegion doRedraw()
Definition: fb_base.cpp:229
QPointer< QWidget > widget
int d
the pixel depth
Definition: qscreen_qws.h:327
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
bool hasCapability(QPlatformIntegration::Capability cap) const
QList< QPlatformScreen * > mScreens
QPlatformWindow * createPlatformWindow(QWidget *widget, WId WinId) const
Factory function for QPlatformWindow.
QImage::Format mFormat
Definition: fb_base.h:195
virtual bool hasCapability(Capability cap) const
#define O_RDONLY
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
static QColor cmap[256]
Definition: qgl_mac.mm:760
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
bool connect(const QString &displaySpec)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QPlatformWindow class provides an abstraction for top-level windows.
QImage::Format screenFormat
static void initSoftwareCursor()
Initializes the screen cursor.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
Q_CORE_EXPORT void qDebug(const char *,...)
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QPlatformFontDatabase * fontDb
virtual void addWindow(QFbWindow *surface)
Definition: fb_base.cpp:305
QPlatformFontDatabase * fontDatabase() const
Accessor for the platform integrations fontdatabase.
int access(const char *, int)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void setPixelFormat(struct fb_var_screeninfo)
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned int uint
Definition: qglobal.h:996
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QWindowSurface * createWindowSurface(QWidget *widget, WId WinId) const
Factory function for QWindowSurface.
QRect mGeometry
Definition: fb_base.h:193
int mDepth
Definition: fb_base.h:194
The QWindowSurface class provides the drawing area for top-level windows.
QPlatformSoftwareCursor * cursor
Definition: fb_base.h:186
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
Q_CORE_EXPORT void qFatal(const char *,...)
#define QT_OPEN
Definition: qcore_unix_p.h:186
void setFormat(QImage::Format format)
QLinuxFbScreen(int display_id)
Constructs a QLinuxFbScreen object.
unsigned short ushort
Definition: qglobal.h:995
QPainter * compositePainter
void setFrameBufferLittleEndian(bool littleEndian)
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
virtual QImage::Format format() const
Reimplement in subclass to return the image format which corresponds to the screen format...
Definition: fb_base.h:164
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
virtual void setPhysicalSize(QSize size)
Definition: fb_base.cpp:167
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Definition: qpainter.cpp:5936
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
bool exactMatch(const QString &str) const
Returns true if str is matched exactly by this regular expression; otherwise returns false...
Definition: qregexp.cpp:4094
int lstep
the number of bytes representing a line in the frame buffer.
Definition: qscreen_qws.h:325
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
QPixmapData * createPixmapData(QPixmapData::PixelType type) const
Factory function for QPixmapData.
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
QLinuxFbScreen * mPrimaryScreen
void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo)
#define QT_WRITE
Definition: qcore_unix_p.h:289
The QLinuxFbScreen class implements a screen driver for the Linux framebuffer.
#define qPrintable(string)
Definition: qglobal.h:1750
#define O_RDWR
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
void setGeometry(QRect rect)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
#define O_WRONLY
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
Q_CORE_EXPORT void qCritical(const char *,...)
#define QT_CLOSE
Definition: qcore_unix_p.h:304