src/gui/embedded/qscreenvfb_qws.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QT_NO_QWS_QVFB
       
    43 
       
    44 #define QTOPIA_QVFB_BRIGHTNESS
       
    45 
       
    46 #include <stdlib.h>
       
    47 #include <sys/types.h>
       
    48 #include <sys/ipc.h>
       
    49 #include <sys/shm.h>
       
    50 #include <sys/stat.h>
       
    51 #include <unistd.h>
       
    52 #include <fcntl.h>
       
    53 #include <errno.h>
       
    54 
       
    55 #include <qvfbhdr.h>
       
    56 #include <qscreenvfb_qws.h>
       
    57 #include <qkbdvfb_qws.h>
       
    58 #include <qmousevfb_qws.h>
       
    59 #include <qwindowsystem_qws.h>
       
    60 #include <qsocketnotifier.h>
       
    61 #include <qapplication.h>
       
    62 #include <qscreen_qws.h>
       
    63 #include <qmousedriverfactory_qws.h>
       
    64 #include <qkbddriverfactory_qws.h>
       
    65 #include <qdebug.h>
       
    66 
       
    67 QT_BEGIN_NAMESPACE
       
    68 
       
    69 class QVFbScreenPrivate
       
    70 {
       
    71 public:
       
    72     QVFbScreenPrivate();
       
    73     ~QVFbScreenPrivate();
       
    74 
       
    75     bool success;
       
    76     unsigned char *shmrgn;
       
    77     int brightness;
       
    78     bool blank;
       
    79     QVFbHeader *hdr;
       
    80     QWSMouseHandler *mouse;
       
    81 #ifndef QT_NO_QWS_KEYBOARD
       
    82     QWSKeyboardHandler *keyboard;
       
    83 #endif
       
    84 };
       
    85 
       
    86 QVFbScreenPrivate::QVFbScreenPrivate()
       
    87     : mouse(0)
       
    88 
       
    89 {
       
    90 #ifndef QT_NO_QWS_KEYBOARD
       
    91     keyboard = 0;
       
    92 #endif
       
    93     brightness = 255;
       
    94     blank = false;
       
    95 }
       
    96 
       
    97 QVFbScreenPrivate::~QVFbScreenPrivate()
       
    98 {
       
    99     delete mouse;
       
   100 #ifndef QT_NO_QWS_KEYBOARD
       
   101     delete keyboard;
       
   102 #endif
       
   103 }
       
   104 
       
   105 /*!
       
   106     \internal
       
   107 
       
   108     \class QVFbScreen
       
   109     \ingroup qws
       
   110 
       
   111     \brief The QVFbScreen class implements a screen driver for the
       
   112     virtual framebuffer.
       
   113 
       
   114     Note that this class is only available in \l{Qt for Embedded Linux}.
       
   115     Custom screen drivers can be added by subclassing the
       
   116     QScreenDriverPlugin class, using the QScreenDriverFactory class to
       
   117     dynamically load the driver into the application, but there should
       
   118     only be one screen object per application.
       
   119 
       
   120     The Qt for Embedded Linux platform provides a \l{The Virtual
       
   121     Framebuffer}{virtual framebuffer} for development and debugging;
       
   122     the virtual framebuffer allows Qt for Embedded Linux applications to be
       
   123     developed on a desktop machine, without switching between consoles
       
   124     and X11.
       
   125 
       
   126     \sa QScreen, QScreenDriverPlugin, {Running Applications}
       
   127 */
       
   128 
       
   129 /*!
       
   130     \fn bool QVFbScreen::connect(const QString & displaySpec)
       
   131     \reimp
       
   132 */
       
   133 
       
   134 /*!
       
   135     \fn void QVFbScreen::disconnect()
       
   136     \reimp
       
   137 */
       
   138 
       
   139 /*!
       
   140     \fn bool QVFbScreen::initDevice()
       
   141     \reimp
       
   142 */
       
   143 
       
   144 /*!
       
   145     \fn void QVFbScreen::restore()
       
   146     \reimp
       
   147 */
       
   148 
       
   149 /*!
       
   150     \fn void QVFbScreen::save()
       
   151     \reimp
       
   152 */
       
   153 
       
   154 /*!
       
   155     \fn void QVFbScreen::setDirty(const QRect & r)
       
   156     \reimp
       
   157 */
       
   158 
       
   159 /*!
       
   160     \fn void QVFbScreen::setMode(int nw, int nh, int nd)
       
   161     \reimp
       
   162 */
       
   163 
       
   164 /*!
       
   165     \fn void QVFbScreen::shutdownDevice()
       
   166     \reimp
       
   167 */
       
   168 
       
   169 /*!
       
   170     \fn QVFbScreen::QVFbScreen(int displayId)
       
   171 
       
   172     Constructs a QVNCScreen object. The \a displayId argument
       
   173     identifies the Qt for Embedded Linux server to connect to.
       
   174 */
       
   175 QVFbScreen::QVFbScreen(int display_id)
       
   176     : QScreen(display_id, VFbClass), d_ptr(new QVFbScreenPrivate)
       
   177 {
       
   178     d_ptr->shmrgn = 0;
       
   179     d_ptr->hdr = 0;
       
   180     data = 0;
       
   181 }
       
   182 
       
   183 /*!
       
   184     Destroys this QVFbScreen object.
       
   185 */
       
   186 QVFbScreen::~QVFbScreen()
       
   187 {
       
   188     delete d_ptr;
       
   189 }
       
   190 
       
   191 static QVFbScreen *connected = 0;
       
   192 
       
   193 bool QVFbScreen::connect(const QString &displaySpec)
       
   194 {
       
   195     QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
       
   196     if (displayArgs.contains(QLatin1String("Gray")))
       
   197         grayscale = true;
       
   198 
       
   199     key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLocal8Bit(), 'b');
       
   200 
       
   201     if (key == -1)
       
   202         return false;
       
   203 
       
   204 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
   205 #ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
       
   206     if (displayArgs.contains(QLatin1String("littleendian")))
       
   207 #endif
       
   208         QScreen::setFrameBufferLittleEndian(true);
       
   209 #endif
       
   210 
       
   211     int shmId = shmget(key, 0, 0);
       
   212     if (shmId != -1)
       
   213         d_ptr->shmrgn = (unsigned char *)shmat(shmId, 0, 0);
       
   214     else
       
   215         return false;
       
   216 
       
   217     if ((long)d_ptr->shmrgn == -1 || d_ptr->shmrgn == 0) {
       
   218         qDebug("No shmrgn %ld", (long)d_ptr->shmrgn);
       
   219         return false;
       
   220     }
       
   221 
       
   222     d_ptr->hdr = (QVFbHeader *)d_ptr->shmrgn;
       
   223     data = d_ptr->shmrgn + d_ptr->hdr->dataoffset;
       
   224 
       
   225     dw = w = d_ptr->hdr->width;
       
   226     dh = h = d_ptr->hdr->height;
       
   227     d = d_ptr->hdr->depth;
       
   228 
       
   229     switch (d) {
       
   230     case 1:
       
   231         setPixelFormat(QImage::Format_Mono);
       
   232         break;
       
   233     case 8:
       
   234         setPixelFormat(QImage::Format_Indexed8);
       
   235         break;
       
   236     case 12:
       
   237         setPixelFormat(QImage::Format_RGB444);
       
   238         break;
       
   239     case 15:
       
   240         setPixelFormat(QImage::Format_RGB555);
       
   241         break;
       
   242     case 16:
       
   243         setPixelFormat(QImage::Format_RGB16);
       
   244         break;
       
   245     case 18:
       
   246         setPixelFormat(QImage::Format_RGB666);
       
   247         break;
       
   248     case 24:
       
   249         setPixelFormat(QImage::Format_RGB888);
       
   250         break;
       
   251     case 32:
       
   252         setPixelFormat(QImage::Format_ARGB32_Premultiplied);
       
   253         break;
       
   254     }
       
   255 
       
   256     lstep = d_ptr->hdr->linestep;
       
   257 
       
   258     // Handle display physical size spec.
       
   259     int dimIdxW = -1;
       
   260     int dimIdxH = -1;
       
   261     for (int i = 0; i < displayArgs.size(); ++i) {
       
   262         if (displayArgs.at(i).startsWith(QLatin1String("mmWidth"))) {
       
   263             dimIdxW = i;
       
   264             break;
       
   265         }
       
   266     }
       
   267     for (int i = 0; i < displayArgs.size(); ++i) {
       
   268         if (displayArgs.at(i).startsWith(QLatin1String("mmHeight"))) {
       
   269             dimIdxH = i;
       
   270             break;
       
   271         }
       
   272     }
       
   273     if (dimIdxW >= 0) {
       
   274         bool ok;
       
   275         int pos = 7;
       
   276         if (displayArgs.at(dimIdxW).at(pos) == QLatin1Char('='))
       
   277             ++pos;
       
   278         int pw = displayArgs.at(dimIdxW).mid(pos).toInt(&ok);
       
   279         if (ok) {
       
   280             physWidth = pw;
       
   281             if (dimIdxH < 0)
       
   282                 physHeight = dh*physWidth/dw;
       
   283         }
       
   284     }
       
   285     if (dimIdxH >= 0) {
       
   286         bool ok;
       
   287         int pos = 8;
       
   288         if (displayArgs.at(dimIdxH).at(pos) == QLatin1Char('='))
       
   289             ++pos;
       
   290         int ph = displayArgs.at(dimIdxH).mid(pos).toInt(&ok);
       
   291         if (ok) {
       
   292             physHeight = ph;
       
   293             if (dimIdxW < 0)
       
   294                 physWidth = dw*physHeight/dh;
       
   295         }
       
   296     }
       
   297     if (dimIdxW < 0 && dimIdxH < 0) {
       
   298         const int dpi = 72;
       
   299         physWidth = qRound(dw * 25.4 / dpi);
       
   300         physHeight = qRound(dh * 25.4 / dpi);
       
   301     }
       
   302 
       
   303     qDebug("Connected to VFB server %s: %d x %d x %d %dx%dmm (%dx%ddpi)", displaySpec.toLatin1().data(),
       
   304         w, h, d, physWidth, physHeight, qRound(dw*25.4/physWidth), qRound(dh*25.4/physHeight) );
       
   305 
       
   306     size = lstep * h;
       
   307     mapsize = size;
       
   308     screencols = d_ptr->hdr->numcols;
       
   309     memcpy(screenclut, d_ptr->hdr->clut, sizeof(QRgb) * screencols);
       
   310 
       
   311     connected = this;
       
   312 
       
   313     if (qgetenv("QT_QVFB_BGR").toInt())
       
   314         pixeltype = BGRPixel;
       
   315 
       
   316     return true;
       
   317 }
       
   318 
       
   319 void QVFbScreen::disconnect()
       
   320 {
       
   321     connected = 0;
       
   322     if ((long)d_ptr->shmrgn != -1 && d_ptr->shmrgn) {
       
   323         if (qApp->type() == QApplication::GuiServer && d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
       
   324             d_ptr->hdr->serverVersion = 0;
       
   325         }
       
   326         shmdt((char*)d_ptr->shmrgn);
       
   327     }
       
   328 }
       
   329 
       
   330 bool QVFbScreen::initDevice()
       
   331 {
       
   332 #ifndef QT_NO_QWS_MOUSE_QVFB
       
   333     const QString mouseDev = QT_VFB_MOUSE_PIPE(displayId);
       
   334     d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
       
   335     qwsServer->setDefaultMouse("None");
       
   336     if (d_ptr->mouse)
       
   337         d_ptr->mouse->setScreen(this);
       
   338 #endif
       
   339 
       
   340 #if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
       
   341     const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId);
       
   342     d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
       
   343     qwsServer->setDefaultKeyboard("None");
       
   344 #endif
       
   345 
       
   346     if (d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader))
       
   347         d_ptr->hdr->serverVersion = QT_VERSION;
       
   348 
       
   349     if(d==8) {
       
   350         screencols=256;
       
   351         if (grayscale) {
       
   352             // Build grayscale palette
       
   353             for(int loopc=0;loopc<256;loopc++) {
       
   354                 screenclut[loopc]=qRgb(loopc,loopc,loopc);
       
   355             }
       
   356         } else {
       
   357             // 6x6x6 216 color cube
       
   358             int idx = 0;
       
   359             for(int ir = 0x0; ir <= 0xff; ir+=0x33) {
       
   360                 for(int ig = 0x0; ig <= 0xff; ig+=0x33) {
       
   361                     for(int ib = 0x0; ib <= 0xff; ib+=0x33) {
       
   362                         screenclut[idx]=qRgb(ir, ig, ib);
       
   363                         idx++;
       
   364                     }
       
   365                 }
       
   366             }
       
   367             screencols=idx;
       
   368         }
       
   369         memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
       
   370         d_ptr->hdr->numcols = screencols;
       
   371     } else if (d == 4) {
       
   372         int val = 0;
       
   373         for (int idx = 0; idx < 16; idx++, val += 17) {
       
   374             screenclut[idx] = qRgb(val, val, val);
       
   375         }
       
   376         screencols = 16;
       
   377         memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
       
   378         d_ptr->hdr->numcols = screencols;
       
   379     } else if (d == 1) {
       
   380         screencols = 2;
       
   381         screenclut[1] = qRgb(0xff, 0xff, 0xff);
       
   382         screenclut[0] = qRgb(0, 0, 0);
       
   383         memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
       
   384         d_ptr->hdr->numcols = screencols;
       
   385     }
       
   386 
       
   387 #ifndef QT_NO_QWS_CURSOR
       
   388     QScreenCursor::initSoftwareCursor();
       
   389 #endif
       
   390     return true;
       
   391 }
       
   392 
       
   393 void QVFbScreen::shutdownDevice()
       
   394 {
       
   395 }
       
   396 
       
   397 void QVFbScreen::setMode(int ,int ,int)
       
   398 {
       
   399 }
       
   400 
       
   401 // save the state of the graphics card
       
   402 // This is needed so that e.g. we can restore the palette when switching
       
   403 // between linux virtual consoles.
       
   404 void QVFbScreen::save()
       
   405 {
       
   406     // nothing to do.
       
   407 }
       
   408 
       
   409 // restore the state of the graphics card.
       
   410 void QVFbScreen::restore()
       
   411 {
       
   412 }
       
   413 void QVFbScreen::setDirty(const QRect& rect)
       
   414 {
       
   415     const QRect r = rect.translated(-offset());
       
   416     d_ptr->hdr->dirty = true;
       
   417     d_ptr->hdr->update = d_ptr->hdr->update.united(r);
       
   418 }
       
   419 
       
   420 void QVFbScreen::setBrightness(int b)
       
   421 {
       
   422     if (connected) {
       
   423         connected->d_ptr->brightness = b;
       
   424 
       
   425         QVFbHeader *hdr = connected->d_ptr->hdr;
       
   426         if (hdr->viewerVersion < 0x040400) // brightness not supported
       
   427             return;
       
   428 
       
   429         const int br = connected->d_ptr->blank ? 0 : b;
       
   430         if (hdr->brightness != br) {
       
   431             hdr->brightness = br;
       
   432             connected->setDirty(connected->region().boundingRect());
       
   433         }
       
   434     }
       
   435 }
       
   436 
       
   437 void QVFbScreen::blank(bool on)
       
   438 {
       
   439     d_ptr->blank = on;
       
   440     setBrightness(connected->d_ptr->brightness);
       
   441 }
       
   442 
       
   443 #endif // QT_NO_QWS_QVFB
       
   444 
       
   445 QT_END_NAMESPACE