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