source: trunk/src/gui/embedded/qscreenlinuxfb_qws.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 43.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscreenlinuxfb_qws.h"
43
44#ifndef QT_NO_QWS_LINUXFB
45//#include "qmemorymanager_qws.h"
46#include "qwsdisplay_qws.h"
47#include "qpixmap.h"
48#include <private/qwssignalhandler_p.h>
49#include <private/qcore_unix_p.h> // overrides QT_OPEN
50
51#include <unistd.h>
52#include <stdlib.h>
53#include <sys/ioctl.h>
54#include <sys/types.h>
55#include <sys/stat.h>
56#include <sys/mman.h>
57#include <sys/kd.h>
58#include <fcntl.h>
59#include <errno.h>
60#include <stdio.h>
61#include <limits.h>
62#include <signal.h>
63
64#include "qwindowsystem_qws.h"
65
66#if !defined(Q_OS_DARWIN) && !defined(Q_OS_FREEBSD)
67#include <linux/fb.h>
68
69#ifdef __i386__
70#include <asm/mtrr.h>
71#endif
72#endif
73
74QT_BEGIN_NAMESPACE
75
76extern int qws_client_id;
77
78//#define DEBUG_CACHE
79
80class QLinuxFbScreenPrivate : public QObject
81{
82public:
83 QLinuxFbScreenPrivate();
84 ~QLinuxFbScreenPrivate();
85
86 void openTty();
87 void closeTty();
88
89 int fd;
90 int startupw;
91 int startuph;
92 int startupd;
93 bool blank;
94 QLinuxFbScreen::DriverTypes driverType;
95
96 bool doGraphicsMode;
97#ifdef QT_QWS_DEPTH_GENERIC
98 bool doGenericColors;
99#endif
100 int ttyfd;
101 long oldKdMode;
102 QString ttyDevice;
103 QString displaySpec;
104};
105
106QLinuxFbScreenPrivate::QLinuxFbScreenPrivate()
107 : fd(-1), blank(true), doGraphicsMode(true),
108#ifdef QT_QWS_DEPTH_GENERIC
109 doGenericColors(false),
110#endif
111 ttyfd(-1), oldKdMode(KD_TEXT)
112{
113 QWSSignalHandler::instance()->addObject(this);
114}
115
116QLinuxFbScreenPrivate::~QLinuxFbScreenPrivate()
117{
118 closeTty();
119}
120
121void QLinuxFbScreenPrivate::openTty()
122{
123 const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
124
125 if (ttyDevice.isEmpty()) {
126 for (const char * const *dev = devs; *dev; ++dev) {
127 ttyfd = QT_OPEN(*dev, O_RDWR);
128 if (ttyfd != -1)
129 break;
130 }
131 } else {
132 ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR);
133 }
134
135 if (ttyfd == -1)
136 return;
137
138 if (doGraphicsMode) {
139 ioctl(ttyfd, KDGETMODE, &oldKdMode);
140 if (oldKdMode != KD_GRAPHICS) {
141 int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
142 if (ret == -1)
143 doGraphicsMode = false;
144 }
145 }
146
147 // No blankin' screen, no blinkin' cursor!, no cursor!
148 const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
149 QT_WRITE(ttyfd, termctl, sizeof(termctl));
150}
151
152void QLinuxFbScreenPrivate::closeTty()
153{
154 if (ttyfd == -1)
155 return;
156
157 if (doGraphicsMode)
158 ioctl(ttyfd, KDSETMODE, oldKdMode);
159
160 // Blankin' screen, blinkin' cursor!
161 const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
162 QT_WRITE(ttyfd, termctl, sizeof(termctl));
163
164 QT_CLOSE(ttyfd);
165 ttyfd = -1;
166}
167
168/*!
169 \enum QLinuxFbScreen::DriverTypes
170
171 This enum describes the driver type.
172
173 \value GenericDriver Generic Linux framebuffer driver
174 \value EInk8Track e-Ink framebuffer driver using the 8Track chipset
175 */
176
177/*!
178 \fn QLinuxFbScreen::fixupScreenInfo(fb_fix_screeninfo &finfo, fb_var_screeninfo &vinfo)
179
180 Adjust the values returned by the framebuffer driver, to work
181 around driver bugs or nonstandard behavior in certain drivers.
182 \a finfo and \a vinfo specify the fixed and variable screen info
183 returned by the driver.
184 */
185void QLinuxFbScreen::fixupScreenInfo(fb_fix_screeninfo &finfo, fb_var_screeninfo &vinfo)
186{
187 // 8Track e-ink devices (as found in Sony PRS-505) lie
188 // about their bit depth -- they claim they're 1 bit per
189 // pixel while the only supported mode is 8 bit per pixel
190 // grayscale.
191 // Caused by this, they also miscalculate their line length.
192 if(!strcmp(finfo.id, "8TRACKFB") && vinfo.bits_per_pixel == 1) {
193 vinfo.bits_per_pixel = 8;
194 finfo.line_length = vinfo.xres;
195 }
196}
197
198/*!
199 \internal
200
201 \class QLinuxFbScreen
202 \ingroup qws
203
204 \brief The QLinuxFbScreen class implements a screen driver for the
205 Linux framebuffer.
206
207 Note that this class is only available in \l{Qt for Embedded Linux}.
208 Custom screen drivers can be added by subclassing the
209 QScreenDriverPlugin class, using the QScreenDriverFactory class to
210 dynamically load the driver into the application, but there should
211 only be one screen object per application.
212
213 The QLinuxFbScreen class provides the cache() function allocating
214 off-screen graphics memory, and the complementary uncache()
215 function releasing the allocated memory. The latter function will
216 first sync the graphics card to ensure the memory isn't still
217 being used by a command in the graphics card FIFO queue. The
218 deleteEntry() function deletes the given memory block without such
219 synchronization. Given the screen instance and client id, the
220 memory can also be released using the clearCache() function, but
221 this should only be necessary if a client exits abnormally.
222
223 In addition, when in paletted graphics modes, the set() function
224 provides the possibility of setting a specified color index to a
225 given RGB value.
226
227 The QLinuxFbScreen class also acts as a factory for the
228 unaccelerated screen cursor and the unaccelerated raster-based
229 implementation of QPaintEngine (\c QRasterPaintEngine);
230 accelerated drivers for Linux should derive from this class.
231
232 \sa QScreen, QScreenDriverPlugin, {Running Applications}
233*/
234
235/*!
236 \fn bool QLinuxFbScreen::useOffscreen()
237 \internal
238*/
239
240// Unaccelerated screen/driver setup. Can be overridden by accelerated
241// drivers
242
243/*!
244 \fn QLinuxFbScreen::QLinuxFbScreen(int displayId)
245
246 Constructs a QLinuxFbScreen object. The \a displayId argument
247 identifies the Qt for Embedded Linux server to connect to.
248*/
249
250QLinuxFbScreen::QLinuxFbScreen(int display_id)
251 : QScreen(display_id, LinuxFBClass), d_ptr(new QLinuxFbScreenPrivate)
252{
253 canaccel=false;
254 clearCacheFunc = &clearCache;
255#ifdef QT_QWS_CLIENTBLIT
256 setSupportsBlitInClients(true);
257#endif
258}
259
260/*!
261 Destroys this QLinuxFbScreen object.
262*/
263
264QLinuxFbScreen::~QLinuxFbScreen()
265{
266}
267
268/*!
269 \reimp
270
271 This is called by \l{Qt for Embedded Linux} clients to map in the framebuffer.
272 It should be reimplemented by accelerated drivers to map in
273 graphics card registers; those drivers should then call this
274 function in order to set up offscreen memory management. The
275 device is specified in \a displaySpec; e.g. "/dev/fb".
276
277 \sa disconnect()
278*/
279
280bool QLinuxFbScreen::connect(const QString &displaySpec)
281{
282 d_ptr->displaySpec = displaySpec;
283
284 const QStringList args = displaySpec.split(QLatin1Char(':'));
285
286 if (args.contains(QLatin1String("nographicsmodeswitch")))
287 d_ptr->doGraphicsMode = false;
288
289#ifdef QT_QWS_DEPTH_GENERIC
290 if (args.contains(QLatin1String("genericcolors")))
291 d_ptr->doGenericColors = true;
292#endif
293
294 QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
295 if (args.indexOf(ttyRegExp) != -1)
296 d_ptr->ttyDevice = ttyRegExp.cap(1);
297
298#if Q_BYTE_ORDER == Q_BIG_ENDIAN
299#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
300 if (args.contains(QLatin1String("littleendian")))
301#endif
302 QScreen::setFrameBufferLittleEndian(true);
303#endif
304
305 QString dev = QLatin1String("/dev/fb0");
306 foreach(QString d, args) {
307 if (d.startsWith(QLatin1Char('/'))) {
308 dev = d;
309 break;
310 }
311 }
312
313 if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
314 d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
315 if (d_ptr->fd == -1) {
316 if (QApplication::type() == QApplication::GuiServer) {
317 perror("QScreenLinuxFb::connect");
318 qCritical("Error opening framebuffer device %s", qPrintable(dev));
319 return false;
320 }
321 if (access(dev.toLatin1().constData(), R_OK) == 0)
322 d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
323 }
324
325 ::fb_fix_screeninfo finfo;
326 ::fb_var_screeninfo vinfo;
327 //#######################
328 // Shut up Valgrind
329 memset(&vinfo, 0, sizeof(vinfo));
330 memset(&finfo, 0, sizeof(finfo));
331 //#######################
332
333 /* Get fixed screen information */
334 if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
335 perror("QLinuxFbScreen::connect");
336 qWarning("Error reading fixed information");
337 return false;
338 }
339
340 d_ptr->driverType = strcmp(finfo.id, "8TRACKFB") ? GenericDriver : EInk8Track;
341
342 if (finfo.type == FB_TYPE_VGA_PLANES) {
343 qWarning("VGA16 video mode not supported");
344 return false;
345 }
346
347 /* Get variable screen information */
348 if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
349 perror("QLinuxFbScreen::connect");
350 qWarning("Error reading variable information");
351 return false;
352 }
353
354 fixupScreenInfo(finfo, vinfo);
355
356 grayscale = vinfo.grayscale;
357 d = vinfo.bits_per_pixel;
358 if (d == 24) {
359 d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
360 if (d <= 0)
361 d = 24; // reset if color component lengths are not reported
362 } else if (d == 16) {
363 d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
364 if (d <= 0)
365 d = 16;
366 }
367 lstep = finfo.line_length;
368
369 int xoff = vinfo.xoffset;
370 int yoff = vinfo.yoffset;
371 const char* qwssize;
372 if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) {
373 if (d_ptr->fd != -1) {
374 if ((uint)w > vinfo.xres) w = vinfo.xres;
375 if ((uint)h > vinfo.yres) h = vinfo.yres;
376 }
377 dw=w;
378 dh=h;
379 int xxoff, yyoff;
380 if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) {
381 if (xxoff < 0 || xxoff + w > vinfo.xres)
382 xxoff = vinfo.xres - w;
383 if (yyoff < 0 || yyoff + h > vinfo.yres)
384 yyoff = vinfo.yres - h;
385 xoff += xxoff;
386 yoff += yyoff;
387 } else {
388 xoff += (vinfo.xres - w)/2;
389 yoff += (vinfo.yres - h)/2;
390 }
391 } else {
392 dw=w=vinfo.xres;
393 dh=h=vinfo.yres;
394 }
395
396 if (w == 0 || h == 0) {
397 qWarning("QScreenLinuxFb::connect(): Unable to find screen geometry, "
398 "will use 320x240.");
399 dw = w = 320;
400 dh = h = 240;
401 }
402
403 setPixelFormat(vinfo);
404
405 // Handle display physical size spec.
406 QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
407 QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
408 int dimIdxW = displayArgs.indexOf(mmWidthRx);
409 QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
410 int dimIdxH = displayArgs.indexOf(mmHeightRx);
411 if (dimIdxW >= 0) {
412 mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
413 physWidth = mmWidthRx.cap(1).toInt();
414 if (dimIdxH < 0)
415 physHeight = dh*physWidth/dw;
416 }
417 if (dimIdxH >= 0) {
418 mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
419 physHeight = mmHeightRx.cap(1).toInt();
420 if (dimIdxW < 0)
421 physWidth = dw*physHeight/dh;
422 }
423 if (dimIdxW < 0 && dimIdxH < 0) {
424 if (vinfo.width != 0 && vinfo.height != 0
425 && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
426 physWidth = vinfo.width;
427 physHeight = vinfo.height;
428 } else {
429 const int dpi = 72;
430 physWidth = qRound(dw * 25.4 / dpi);
431 physHeight = qRound(dh * 25.4 / dpi);
432 }
433 }
434
435 dataoffset = yoff * lstep + xoff * d / 8;
436 //qDebug("Using %dx%dx%d screen",w,h,d);
437
438 /* Figure out the size of the screen in bytes */
439 size = h * lstep;
440
441 mapsize = finfo.smem_len;
442
443 data = (unsigned char *)-1;
444 if (d_ptr->fd != -1)
445 data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE,
446 MAP_SHARED, d_ptr->fd, 0);
447
448 if ((long)data == -1) {
449 if (QApplication::type() == QApplication::GuiServer) {
450 perror("QLinuxFbScreen::connect");
451 qWarning("Error: failed to map framebuffer device to memory.");
452 return false;
453 }
454 data = 0;
455 } else {
456 data += dataoffset;
457 }
458
459 canaccel = useOffscreen();
460 if(canaccel)
461 setupOffScreen();
462
463 // Now read in palette
464 if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
465 screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
466 int loopc;
467 ::fb_cmap startcmap;
468 startcmap.start=0;
469 startcmap.len=screencols;
470 startcmap.red=(unsigned short int *)
471 malloc(sizeof(unsigned short int)*screencols);
472 startcmap.green=(unsigned short int *)
473 malloc(sizeof(unsigned short int)*screencols);
474 startcmap.blue=(unsigned short int *)
475 malloc(sizeof(unsigned short int)*screencols);
476 startcmap.transp=(unsigned short int *)
477 malloc(sizeof(unsigned short int)*screencols);
478 if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) {
479 perror("QLinuxFbScreen::connect");
480 qWarning("Error reading palette from framebuffer, using default palette");
481 createPalette(startcmap, vinfo, finfo);
482 }
483 int bits_used = 0;
484 for(loopc=0;loopc<screencols;loopc++) {
485 screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8,
486 startcmap.green[loopc] >> 8,
487 startcmap.blue[loopc] >> 8);
488 bits_used |= startcmap.red[loopc]
489 | startcmap.green[loopc]
490 | startcmap.blue[loopc];
491 }
492 // WORKAROUND: Some framebuffer drivers only return 8 bit
493 // color values, so we need to not bit shift them..
494 if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) {
495 for(loopc=0;loopc<screencols;loopc++) {
496 screenclut[loopc] = qRgb(startcmap.red[loopc],
497 startcmap.green[loopc],
498 startcmap.blue[loopc]);
499 }
500 qWarning("8 bits cmap returned due to faulty FB driver, colors corrected");
501 }
502 free(startcmap.red);
503 free(startcmap.green);
504 free(startcmap.blue);
505 free(startcmap.transp);
506 } else {
507 screencols=0;
508 }
509
510 return true;
511}
512
513/*!
514 \reimp
515
516 This unmaps the framebuffer.
517
518 \sa connect()
519*/
520
521void QLinuxFbScreen::disconnect()
522{
523 data -= dataoffset;
524 if (data)
525 munmap((char*)data,mapsize);
526 close(d_ptr->fd);
527}
528
529// #define DEBUG_VINFO
530
531void QLinuxFbScreen::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo)
532{
533 if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
534 screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
535 cmap.start=0;
536 cmap.len=screencols;
537 cmap.red=(unsigned short int *)
538 malloc(sizeof(unsigned short int)*screencols);
539 cmap.green=(unsigned short int *)
540 malloc(sizeof(unsigned short int)*screencols);
541 cmap.blue=(unsigned short int *)
542 malloc(sizeof(unsigned short int)*screencols);
543 cmap.transp=(unsigned short int *)
544 malloc(sizeof(unsigned short int)*screencols);
545
546 if (screencols==16) {
547 if (finfo.type == FB_TYPE_PACKED_PIXELS) {
548 // We'll setup a grayscale cmap for 4bpp linear
549 int val = 0;
550 for (int idx = 0; idx < 16; ++idx, val += 17) {
551 cmap.red[idx] = (val<<8)|val;
552 cmap.green[idx] = (val<<8)|val;
553 cmap.blue[idx] = (val<<8)|val;
554 screenclut[idx]=qRgb(val, val, val);
555 }
556 } else {
557 // Default 16 colour palette
558 // Green is now trolltech green so certain images look nicer
559 // black d_gray l_gray white red green blue cyan magenta yellow
560 unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 };
561 unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F };
562 unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 };
563
564 for (int idx = 0; idx < 16; ++idx) {
565 cmap.red[idx] = ((reds[idx]) << 8)|reds[idx];
566 cmap.green[idx] = ((greens[idx]) << 8)|greens[idx];
567 cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx];
568 cmap.transp[idx] = 0;
569 screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]);
570 }
571 }
572 } else {
573 if (grayscale) {
574 // Build grayscale palette
575 int i;
576 for(i=0;i<screencols;++i) {
577 int bval = screencols == 256 ? i : (i << 4);
578 ushort val = (bval << 8) | bval;
579 cmap.red[i] = val;
580 cmap.green[i] = val;
581 cmap.blue[i] = val;
582 cmap.transp[i] = 0;
583 screenclut[i] = qRgb(bval,bval,bval);
584 }
585 } else {
586 // 6x6x6 216 color cube
587 int idx = 0;
588 for(int ir = 0x0; ir <= 0xff; ir+=0x33) {
589 for(int ig = 0x0; ig <= 0xff; ig+=0x33) {
590 for(int ib = 0x0; ib <= 0xff; ib+=0x33) {
591 cmap.red[idx] = (ir << 8)|ir;
592 cmap.green[idx] = (ig << 8)|ig;
593 cmap.blue[idx] = (ib << 8)|ib;
594 cmap.transp[idx] = 0;
595 screenclut[idx]=qRgb(ir, ig, ib);
596 ++idx;
597 }
598 }
599 }
600 // Fill in rest with 0
601 for (int loopc=0; loopc<40; ++loopc) {
602 screenclut[idx]=0;
603 ++idx;
604 }
605 screencols=idx;
606 }
607 }
608 } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) {
609 cmap.start=0;
610 int rbits=0,gbits=0,bbits=0;
611 switch (vinfo.bits_per_pixel) {
612 case 8:
613 rbits=vinfo.red.length;
614 gbits=vinfo.green.length;
615 bbits=vinfo.blue.length;
616 if(rbits==0 && gbits==0 && bbits==0) {
617 // cyber2000 driver bug hack
618 rbits=3;
619 gbits=3;
620 bbits=2;
621 }
622 break;
623 case 15:
624 rbits=5;
625 gbits=5;
626 bbits=5;
627 break;
628 case 16:
629 rbits=5;
630 gbits=6;
631 bbits=5;
632 break;
633 case 18:
634 case 19:
635 rbits=6;
636 gbits=6;
637 bbits=6;
638 break;
639 case 24: case 32:
640 rbits=gbits=bbits=8;
641 break;
642 }
643 screencols=cmap.len=1<<qMax(rbits,qMax(gbits,bbits));
644 cmap.red=(unsigned short int *)
645 malloc(sizeof(unsigned short int)*256);
646 cmap.green=(unsigned short int *)
647 malloc(sizeof(unsigned short int)*256);
648 cmap.blue=(unsigned short int *)
649 malloc(sizeof(unsigned short int)*256);
650 cmap.transp=(unsigned short int *)
651 malloc(sizeof(unsigned short int)*256);
652 for(unsigned int i = 0x0; i < cmap.len; i++) {
653 cmap.red[i] = i*65535/((1<<rbits)-1);
654 cmap.green[i] = i*65535/((1<<gbits)-1);
655 cmap.blue[i] = i*65535/((1<<bbits)-1);
656 cmap.transp[i] = 0;
657 }
658 }
659}
660
661/*!
662 \reimp
663
664 This is called by the \l{Qt for Embedded Linux} server at startup time.
665 It turns off console blinking, sets up the color palette, enables write
666 combining on the framebuffer and initialises the off-screen memory
667 manager.
668*/
669
670bool QLinuxFbScreen::initDevice()
671{
672 d_ptr->openTty();
673
674 // Grab current mode so we can reset it
675 fb_var_screeninfo vinfo;
676 fb_fix_screeninfo finfo;
677 //#######################
678 // Shut up Valgrind
679 memset(&vinfo, 0, sizeof(vinfo));
680 memset(&finfo, 0, sizeof(finfo));
681 //#######################
682
683 if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
684 perror("QLinuxFbScreen::initDevice");
685 qFatal("Error reading variable information in card init");
686 return false;
687 }
688
689#ifdef DEBUG_VINFO
690 qDebug("Greyscale %d",vinfo.grayscale);
691 qDebug("Nonstd %d",vinfo.nonstd);
692 qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length,
693 vinfo.red.msb_right);
694 qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length,
695 vinfo.green.msb_right);
696 qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length,
697 vinfo.blue.msb_right);
698 qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length,
699 vinfo.transp.msb_right);
700#endif
701
702 if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
703 perror("QLinuxFbScreen::initDevice");
704 qCritical("Error reading fixed information in card init");
705 // It's not an /error/ as such, though definitely a bad sign
706 // so we return true
707 return true;
708 }
709
710 fixupScreenInfo(finfo, vinfo);
711
712 d_ptr->startupw=vinfo.xres;
713 d_ptr->startuph=vinfo.yres;
714 d_ptr->startupd=vinfo.bits_per_pixel;
715 grayscale = vinfo.grayscale;
716
717#ifdef __i386__
718 // Now init mtrr
719 if(!::getenv("QWS_NOMTRR")) {
720 int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0);
721 // MTRR entry goes away when file is closed - i.e.
722 // hopefully when QWS is killed
723 if(mfd != -1) {
724 mtrr_sentry sentry;
725 sentry.base=(unsigned long int)finfo.smem_start;
726 //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start);
727 // Size needs to be in 4k chunks, but that's not always
728 // what we get thanks to graphics card registers. Write combining
729 // these is Not Good, so we write combine what we can
730 // (which is not much - 4 megs on an 8 meg card, it seems)
731 unsigned int size=finfo.smem_len;
732 size=size >> 22;
733 size=size << 22;
734 sentry.size=size;
735 sentry.type=MTRR_TYPE_WRCOMB;
736 if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) {
737 //printf("Couldn't add mtrr entry for %lx %lx, %s\n",
738 //sentry.base,sentry.size,strerror(errno));
739 }
740 }
741
742 // Should we close mfd here?
743 //QT_CLOSE(mfd);
744 }
745#endif
746 if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR))
747 {
748 fb_cmap cmap;
749 createPalette(cmap, vinfo, finfo);
750 if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) {
751 perror("QLinuxFbScreen::initDevice");
752 qWarning("Error writing palette to framebuffer");
753 }
754 free(cmap.red);
755 free(cmap.green);
756 free(cmap.blue);
757 free(cmap.transp);
758 }
759
760 if (canaccel) {
761 *entryp=0;
762 *lowest = mapsize;
763 insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start
764 }
765
766 shared->fifocount = 0;
767 shared->buffer_offset = 0xffffffff; // 0 would be a sensible offset (screen)
768 shared->linestep = 0;
769 shared->cliptop = 0xffffffff;
770 shared->clipleft = 0xffffffff;
771 shared->clipright = 0xffffffff;
772 shared->clipbottom = 0xffffffff;
773 shared->rop = 0xffffffff;
774
775#ifdef QT_QWS_DEPTH_GENERIC
776 if (pixelFormat() == QImage::Format_Invalid && screencols == 0
777 && d_ptr->doGenericColors)
778 {
779 qt_set_generic_blit(this, vinfo.bits_per_pixel,
780 vinfo.red.length, vinfo.green.length,
781 vinfo.blue.length, vinfo.transp.length,
782 vinfo.red.offset, vinfo.green.offset,
783 vinfo.blue.offset, vinfo.transp.offset);
784 }
785#endif
786
787#ifndef QT_NO_QWS_CURSOR
788 QScreenCursor::initSoftwareCursor();
789#endif
790 blank(false);
791
792 return true;
793}
794
795/*
796 The offscreen memory manager's list of entries is stored at the bottom
797 of the offscreen memory area and consistes of a series of QPoolEntry's,
798 each of which keep track of a block of allocated memory. Unallocated memory
799 is implicitly indicated by the gap between blocks indicated by QPoolEntry's.
800 The memory manager looks through any unallocated memory before the end
801 of currently-allocated memory to see if a new block will fit in the gap;
802 if it doesn't it allocated it from the end of currently-allocated memory.
803 Memory is allocated from the top of the framebuffer downwards; if it hits
804 the list of entries then offscreen memory is full and further allocations
805 are made from main RAM (and hence unaccelerated). Allocated memory can
806 be seen as a sort of upside-down stack; lowest keeps track of the
807 bottom of the stack.
808*/
809
810void QLinuxFbScreen::delete_entry(int pos)
811{
812 if (pos > *entryp || pos < 0) {
813 qWarning("Attempt to delete odd pos! %d %d", pos, *entryp);
814 return;
815 }
816
817#ifdef DEBUG_CACHE
818 qDebug("Remove entry: %d", pos);
819#endif
820
821 QPoolEntry *qpe = &entries[pos];
822 if (qpe->start <= *lowest) {
823 // Lowest goes up again
824 *lowest = entries[pos-1].start;
825#ifdef DEBUG_CACHE
826 qDebug(" moved lowest to %d", *lowest);
827#endif
828 }
829
830 (*entryp)--;
831 if (pos == *entryp)
832 return;
833
834 int size = (*entryp)-pos;
835 memmove(&entries[pos], &entries[pos+1], size*sizeof(QPoolEntry));
836}
837
838void QLinuxFbScreen::insert_entry(int pos, int start, int end)
839{
840 if (pos > *entryp) {
841 qWarning("Attempt to insert odd pos! %d %d",pos,*entryp);
842 return;
843 }
844
845#ifdef DEBUG_CACHE
846 qDebug("Insert entry: %d, %d -> %d", pos, start, end);
847#endif
848
849 if (start < (int)*lowest) {
850 *lowest = start;
851#ifdef DEBUG_CACHE
852 qDebug(" moved lowest to %d", *lowest);
853#endif
854 }
855
856 if (pos == *entryp) {
857 entries[pos].start = start;
858 entries[pos].end = end;
859 entries[pos].clientId = qws_client_id;
860 (*entryp)++;
861 return;
862 }
863
864 int size=(*entryp)-pos;
865 memmove(&entries[pos+1],&entries[pos],size*sizeof(QPoolEntry));
866 entries[pos].start=start;
867 entries[pos].end=end;
868 entries[pos].clientId=qws_client_id;
869 (*entryp)++;
870}
871
872/*!
873 \fn uchar * QLinuxFbScreen::cache(int amount)
874
875 Requests the specified \a amount of offscreen graphics card memory
876 from the memory manager, and returns a pointer to the data within
877 the framebuffer (or 0 if there is no free memory).
878
879 Note that the display is locked while memory is allocated in order to
880 preserve the memory pool's integrity.
881
882 Use the QScreen::onCard() function to retrieve an offset (in
883 bytes) from the start of graphics card memory for the returned
884 pointer.
885
886 \sa uncache(), clearCache(), deleteEntry()
887*/
888
889uchar * QLinuxFbScreen::cache(int amount)
890{
891 if (!canaccel || entryp == 0)
892 return 0;
893
894 qt_fbdpy->grab();
895
896 int startp = cacheStart + (*entryp+1) * sizeof(QPoolEntry);
897 if (startp >= (int)*lowest) {
898 // We don't have room for another cache QPoolEntry.
899#ifdef DEBUG_CACHE
900 qDebug("No room for pool entry in VRAM");
901#endif
902 qt_fbdpy->ungrab();
903 return 0;
904 }
905
906 int align = pixmapOffsetAlignment();
907
908 if (*entryp > 1) {
909 // Try to find a gap in the allocated blocks.
910 for (int loopc = 0; loopc < *entryp-1; loopc++) {
911 int freestart = entries[loopc+1].end;
912 int freeend = entries[loopc].start;
913 if (freestart != freeend) {
914 while (freestart % align) {
915 freestart++;
916 }
917 int len=freeend-freestart;
918 if (len >= amount) {
919 insert_entry(loopc+1, freestart, freestart+amount);
920 qt_fbdpy->ungrab();
921 return data+freestart;
922 }
923 }
924 }
925 }
926
927 // No free blocks in already-taken memory; get some more
928 // if we can
929 int newlowest = (*lowest)-amount;
930 if (newlowest % align) {
931 newlowest -= align;
932 while (newlowest % align) {
933 newlowest++;
934 }
935 }
936 if (startp >= newlowest) {
937 qt_fbdpy->ungrab();
938#ifdef DEBUG_CACHE
939 qDebug("No VRAM available for %d bytes", amount);
940#endif
941 return 0;
942 }
943 insert_entry(*entryp, newlowest, *lowest);
944 qt_fbdpy->ungrab();
945
946 return data + newlowest;
947}
948
949/*!
950 \fn void QLinuxFbScreen::uncache(uchar * memoryBlock)
951
952 Deletes the specified \a memoryBlock allocated from the graphics
953 card memory.
954
955 Note that the display is locked while memory is unallocated in
956 order to preserve the memory pool's integrity.
957
958 This function will first sync the graphics card to ensure the
959 memory isn't still being used by a command in the graphics card
960 FIFO queue. It is possible to speed up a driver by overriding this
961 function to avoid syncing. For example, the driver might delay
962 deleting the memory until it detects that all commands dealing
963 with the memory are no longer in the queue. Note that it will then
964 be up to the driver to ensure that the specified \a memoryBlock no
965 longer is being used.
966
967 \sa cache(), deleteEntry(), clearCache()
968 */
969void QLinuxFbScreen::uncache(uchar * c)
970{
971 // need to sync graphics card
972
973 deleteEntry(c);
974}
975
976/*!
977 \fn void QLinuxFbScreen::deleteEntry(uchar * memoryBlock)
978
979 Deletes the specified \a memoryBlock allocated from the graphics
980 card memory.
981
982 \sa uncache(), cache(), clearCache()
983*/
984void QLinuxFbScreen::deleteEntry(uchar * c)
985{
986 qt_fbdpy->grab();
987 unsigned long pos=(unsigned long)c;
988 pos-=((unsigned long)data);
989 unsigned int hold=(*entryp);
990 for(unsigned int loopc=1;loopc<hold;loopc++) {
991 if (entries[loopc].start==pos) {
992 if (entries[loopc].clientId == qws_client_id)
993 delete_entry(loopc);
994 else
995 qWarning("Attempt to delete client id %d cache entry",
996 entries[loopc].clientId);
997 qt_fbdpy->ungrab();
998 return;
999 }
1000 }
1001 qt_fbdpy->ungrab();
1002 qWarning("Attempt to delete unknown offset %ld",pos);
1003}
1004
1005/*!
1006 Removes all entries from the cache for the specified screen \a
1007 instance and client identified by the given \a clientId.
1008
1009 Calling this function should only be necessary if a client exits
1010 abnormally.
1011
1012 \sa cache(), uncache(), deleteEntry()
1013*/
1014void QLinuxFbScreen::clearCache(QScreen *instance, int clientId)
1015{
1016 QLinuxFbScreen *screen = (QLinuxFbScreen *)instance;
1017 if (!screen->canaccel || !screen->entryp)
1018 return;
1019 qt_fbdpy->grab();
1020 for (int loopc = 0; loopc < *(screen->entryp); loopc++) {
1021 if (screen->entries[loopc].clientId == clientId) {
1022 screen->delete_entry(loopc);
1023 loopc--;
1024 }
1025 }
1026 qt_fbdpy->ungrab();
1027}
1028
1029
1030void QLinuxFbScreen::setupOffScreen()
1031{
1032 // Figure out position of offscreen memory
1033 // Set up pool entries pointer table and 64-bit align it
1034 int psize = size;
1035
1036 // hw: this causes the limitation of cursors to 64x64
1037 // the cursor should rather use the normal pixmap mechanism
1038 psize += 4096; // cursor data
1039 psize += 8; // for alignment
1040 psize &= ~0x7; // align
1041
1042 unsigned long pos = (unsigned long)data;
1043 pos += psize;
1044 entryp = ((int *)pos);
1045 lowest = ((unsigned int *)pos)+1;
1046 pos += (sizeof(int))*4;
1047 entries = (QPoolEntry *)pos;
1048
1049 // beginning of offscreen memory available for pixmaps.
1050 cacheStart = psize + 4*sizeof(int) + sizeof(QPoolEntry);
1051}
1052
1053/*!
1054 \reimp
1055
1056 This is called by the \l{Qt for Embedded Linux} server when it shuts
1057 down, and should be inherited if you need to do any card-specific cleanup.
1058 The default version hides the screen cursor and reenables the blinking
1059 cursor and screen blanking.
1060*/
1061
1062void QLinuxFbScreen::shutdownDevice()
1063{
1064 // Causing crashes. Not needed.
1065 //setMode(startupw,startuph,startupd);
1066/*
1067 if (startupd == 8) {
1068 ioctl(fd,FBIOPUTCMAP,startcmap);
1069 free(startcmap->red);
1070 free(startcmap->green);
1071 free(startcmap->blue);
1072 free(startcmap->transp);
1073 delete startcmap;
1074 startcmap = 0;
1075 }
1076*/
1077 d_ptr->closeTty();
1078}
1079
1080/*!
1081 \fn void QLinuxFbScreen::set(unsigned int index,unsigned int red,unsigned int green,unsigned int blue)
1082
1083 Sets the specified color \a index to the specified RGB value, (\a
1084 red, \a green, \a blue), when in paletted graphics modes.
1085*/
1086
1087void QLinuxFbScreen::set(unsigned int i,unsigned int r,unsigned int g,unsigned int b)
1088{
1089 if (d_ptr->fd != -1) {
1090 fb_cmap cmap;
1091 cmap.start=i;
1092 cmap.len=1;
1093 cmap.red=(unsigned short int *)
1094 malloc(sizeof(unsigned short int)*256);
1095 cmap.green=(unsigned short int *)
1096 malloc(sizeof(unsigned short int)*256);
1097 cmap.blue=(unsigned short int *)
1098 malloc(sizeof(unsigned short int)*256);
1099 cmap.transp=(unsigned short int *)
1100 malloc(sizeof(unsigned short int)*256);
1101 cmap.red[0]=r << 8;
1102 cmap.green[0]=g << 8;
1103 cmap.blue[0]=b << 8;
1104 cmap.transp[0]=0;
1105 ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap);
1106 free(cmap.red);
1107 free(cmap.green);
1108 free(cmap.blue);
1109 free(cmap.transp);
1110 }
1111 screenclut[i] = qRgb(r, g, b);
1112}
1113
1114/*!
1115 \reimp
1116
1117 Sets the framebuffer to a new resolution and bit depth. The width is
1118 in \a nw, the height is in \a nh, and the depth is in \a nd. After
1119 doing this any currently-existing paint engines will be invalid and the
1120 screen should be completely redrawn. In a multiple-process
1121 Embedded Qt situation you must signal all other applications to
1122 call setMode() to the same mode and redraw.
1123*/
1124
1125void QLinuxFbScreen::setMode(int nw,int nh,int nd)
1126{
1127 if (d_ptr->fd == -1)
1128 return;
1129
1130 fb_fix_screeninfo finfo;
1131 fb_var_screeninfo vinfo;
1132 //#######################
1133 // Shut up Valgrind
1134 memset(&vinfo, 0, sizeof(vinfo));
1135 memset(&finfo, 0, sizeof(finfo));
1136 //#######################
1137
1138 if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
1139 perror("QLinuxFbScreen::setMode");
1140 qFatal("Error reading variable information in mode change");
1141 }
1142
1143 vinfo.xres=nw;
1144 vinfo.yres=nh;
1145 vinfo.bits_per_pixel=nd;
1146
1147 if (ioctl(d_ptr->fd, FBIOPUT_VSCREENINFO, &vinfo)) {
1148 perror("QLinuxFbScreen::setMode");
1149 qCritical("Error writing variable information in mode change");
1150 }
1151
1152 if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
1153 perror("QLinuxFbScreen::setMode");
1154 qFatal("Error reading changed variable information in mode change");
1155 }
1156
1157 if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
1158 perror("QLinuxFbScreen::setMode");
1159 qFatal("Error reading fixed information");
1160 }
1161
1162 fixupScreenInfo(finfo, vinfo);
1163 disconnect();
1164 connect(d_ptr->displaySpec);
1165 exposeRegion(region(), 0);
1166}
1167
1168// save the state of the graphics card
1169// This is needed so that e.g. we can restore the palette when switching
1170// between linux virtual consoles.
1171
1172/*!
1173 \reimp
1174
1175 This doesn't do anything; accelerated drivers may wish to reimplement
1176 it to save graphics cards registers. It's called by the
1177 \l{Qt for Embedded Linux} server when the virtual console is switched.
1178*/
1179
1180void QLinuxFbScreen::save()
1181{
1182 // nothing to do.
1183}
1184
1185
1186// restore the state of the graphics card.
1187/*!
1188 \reimp
1189
1190 This is called when the virtual console is switched back to
1191 \l{Qt for Embedded Linux} and restores the palette.
1192*/
1193void QLinuxFbScreen::restore()
1194{
1195 if (d_ptr->fd == -1)
1196 return;
1197
1198 if ((d == 8) || (d == 4)) {
1199 fb_cmap cmap;
1200 cmap.start=0;
1201 cmap.len=screencols;
1202 cmap.red=(unsigned short int *)
1203 malloc(sizeof(unsigned short int)*256);
1204 cmap.green=(unsigned short int *)
1205 malloc(sizeof(unsigned short int)*256);
1206 cmap.blue=(unsigned short int *)
1207 malloc(sizeof(unsigned short int)*256);
1208 cmap.transp=(unsigned short int *)
1209 malloc(sizeof(unsigned short int)*256);
1210 for (int loopc = 0; loopc < screencols; loopc++) {
1211 cmap.red[loopc] = qRed(screenclut[loopc]) << 8;
1212 cmap.green[loopc] = qGreen(screenclut[loopc]) << 8;
1213 cmap.blue[loopc] = qBlue(screenclut[loopc]) << 8;
1214 cmap.transp[loopc] = 0;
1215 }
1216 ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap);
1217 free(cmap.red);
1218 free(cmap.green);
1219 free(cmap.blue);
1220 free(cmap.transp);
1221 }
1222}
1223
1224/*!
1225 \fn int QLinuxFbScreen::sharedRamSize(void * end)
1226 \internal
1227*/
1228
1229// This works like the QScreenCursor code. end points to the end
1230// of our shared structure, we return the amount of memory we reserved
1231int QLinuxFbScreen::sharedRamSize(void * end)
1232{
1233 shared=(QLinuxFb_Shared *)end;
1234 shared--;
1235 return sizeof(QLinuxFb_Shared);
1236}
1237
1238/*!
1239 \reimp
1240*/
1241void QLinuxFbScreen::setDirty(const QRect &r)
1242{
1243 if(d_ptr->driverType == EInk8Track) {
1244 // e-Ink displays need a trigger to actually show what is
1245 // in their framebuffer memory. The 8-Track driver does this
1246 // by adding custom IOCTLs - FBIO_EINK_DISP_PIC (0x46a2) takes
1247 // an argument specifying whether or not to flash the screen
1248 // while updating.
1249 // There doesn't seem to be a way to tell it to just update
1250 // a subset of the screen.
1251 if(r.left() == 0 && r.top() == 0 && r.width() == dw && r.height() == dh)
1252 ioctl(d_ptr->fd, 0x46a2, 1);
1253 else
1254 ioctl(d_ptr->fd, 0x46a2, 0);
1255 }
1256}
1257
1258/*!
1259 \reimp
1260*/
1261void QLinuxFbScreen::blank(bool on)
1262{
1263 if (d_ptr->blank == on)
1264 return;
1265
1266#if defined(QT_QWS_IPAQ)
1267 if (on)
1268 system("apm -suspend");
1269#else
1270 if (d_ptr->fd == -1)
1271 return;
1272// Some old kernel versions don't have this. These defines should go
1273// away eventually
1274#if defined(FBIOBLANK)
1275#if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING)
1276 ioctl(d_ptr->fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
1277#else
1278 ioctl(d_ptr->fd, FBIOBLANK, on ? 1 : 0);
1279#endif
1280#endif
1281#endif
1282
1283 d_ptr->blank = on;
1284}
1285
1286void QLinuxFbScreen::setPixelFormat(struct fb_var_screeninfo info)
1287{
1288 const fb_bitfield rgba[4] = { info.red, info.green,
1289 info.blue, info.transp };
1290
1291 QImage::Format format = QImage::Format_Invalid;
1292
1293 switch (d) {
1294 case 32: {
1295 const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
1296 {0, 8, 0}, {24, 8, 0}};
1297 const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
1298 {16, 8, 0}, {24, 8, 0}};
1299 if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {
1300 format = QImage::Format_ARGB32;
1301 } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
1302 format = QImage::Format_RGB32;
1303 } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
1304 format = QImage::Format_RGB32;
1305 pixeltype = QScreen::BGRPixel;
1306 }
1307 break;
1308 }
1309 case 24: {
1310 const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
1311 {0, 8, 0}, {0, 0, 0}};
1312 const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
1313 {16, 8, 0}, {0, 0, 0}};
1314 if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {
1315 format = QImage::Format_RGB888;
1316 } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
1317 format = QImage::Format_RGB888;
1318 pixeltype = QScreen::BGRPixel;
1319 }
1320 break;
1321 }
1322 case 18: {
1323 const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
1324 {0, 6, 0}, {0, 0, 0}};
1325 if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)
1326 format = QImage::Format_RGB666;
1327 break;
1328 }
1329 case 16: {
1330 const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
1331 {0, 5, 0}, {0, 0, 0}};
1332 const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
1333 {11, 5, 0}, {0, 0, 0}};
1334 if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {
1335 format = QImage::Format_RGB16;
1336 } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
1337 format = QImage::Format_RGB16;
1338 pixeltype = QScreen::BGRPixel;
1339 }
1340 break;
1341 }
1342 case 15: {
1343 const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
1344 {0, 5, 0}, {15, 1, 0}};
1345 const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
1346 {10, 5, 0}, {15, 1, 0}};
1347 if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {
1348 format = QImage::Format_RGB555;
1349 } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
1350 format = QImage::Format_RGB555;
1351 pixeltype = QScreen::BGRPixel;
1352 }
1353 break;
1354 }
1355 case 12: {
1356 const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
1357 {0, 4, 0}, {0, 0, 0}};
1358 if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)
1359 format = QImage::Format_RGB444;
1360 break;
1361 }
1362 case 8:
1363 break;
1364 case 1:
1365 format = QImage::Format_Mono; //###: LSB???
1366 break;
1367 default:
1368 break;
1369 }
1370
1371 QScreen::setPixelFormat(format);
1372}
1373
1374bool QLinuxFbScreen::useOffscreen()
1375{
1376 // Not done for 8Track because on e-Ink displays,
1377 // everything is offscreen anyway
1378 if (d_ptr->driverType == EInk8Track || ((mapsize - size) < 16*1024))
1379 return false;
1380
1381 return true;
1382}
1383
1384QT_END_NAMESPACE
1385
1386#endif // QT_NO_QWS_LINUXFB
Note: See TracBrowser for help on using the repository browser.