| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2011 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 | 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 |
|
|---|
| 106 | QLinuxFbScreenPrivate::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 |
|
|---|
| 116 | QLinuxFbScreenPrivate::~QLinuxFbScreenPrivate()
|
|---|
| 117 | {
|
|---|
| 118 | closeTty();
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|
| 121 | void 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 |
|
|---|
| 152 | void 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 | */
|
|---|
| 185 | void 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 |
|
|---|
| 250 | QLinuxFbScreen::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 |
|
|---|
| 264 | QLinuxFbScreen::~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 |
|
|---|
| 280 | bool 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 |
|
|---|
| 521 | void 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 |
|
|---|
| 531 | void 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 |
|
|---|
| 670 | bool 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 |
|
|---|
| 810 | void 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 |
|
|---|
| 838 | void 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 |
|
|---|
| 889 | uchar * 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 | */
|
|---|
| 969 | void 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 | */
|
|---|
| 984 | void 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 | */
|
|---|
| 1014 | void 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 |
|
|---|
| 1030 | void 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 |
|
|---|
| 1062 | void 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 |
|
|---|
| 1087 | void 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 |
|
|---|
| 1125 | void 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 |
|
|---|
| 1180 | void 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 | */
|
|---|
| 1193 | void 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
|
|---|
| 1231 | int QLinuxFbScreen::sharedRamSize(void * end)
|
|---|
| 1232 | {
|
|---|
| 1233 | shared=(QLinuxFb_Shared *)end;
|
|---|
| 1234 | shared--;
|
|---|
| 1235 | return sizeof(QLinuxFb_Shared);
|
|---|
| 1236 | }
|
|---|
| 1237 |
|
|---|
| 1238 | /*!
|
|---|
| 1239 | \reimp
|
|---|
| 1240 | */
|
|---|
| 1241 | void 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 | */
|
|---|
| 1261 | void 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 |
|
|---|
| 1286 | void 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 |
|
|---|
| 1374 | bool 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 |
|
|---|
| 1384 | QT_END_NAMESPACE
|
|---|
| 1385 |
|
|---|
| 1386 | #endif // QT_NO_QWS_LINUXFB
|
|---|