| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qplatformdefs.h" |
| #include "qscreen_qws.h" |
| |
| #include "qcolormap.h" |
| #include "qscreendriverfactory_qws.h" |
| #include "qwindowsystem_qws.h" |
| #include "qwidget.h" |
| #include "qcolor.h" |
| #include "qpixmap.h" |
| #include "qvarlengtharray.h" |
| #include "qwsdisplay_qws.h" |
| #include "qpainter.h" |
| #include <private/qdrawhelper_p.h> |
| #include <private/qpaintengine_raster_p.h> |
| #include <private/qpixmap_raster_p.h> |
| #include <private/qwindowsurface_qws_p.h> |
| #include <private/qpainter_p.h> |
| #include <private/qwidget_p.h> |
| #include <private/qgraphicssystem_qws_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| // #define QT_USE_MEMCPY_DUFF |
| |
| #ifndef QT_NO_QWS_CURSOR |
| bool qt_sw_cursor=false; |
| Q_GUI_EXPORT QScreenCursor * qt_screencursor = 0; |
| #endif |
| Q_GUI_EXPORT QScreen * qt_screen = 0; |
| |
| ClearCacheFunc QScreen::clearCacheFunc = 0; |
| |
| #ifndef QT_NO_QWS_CURSOR |
| /*! |
| \class QScreenCursor |
| \ingroup qws |
| |
| \brief The QScreenCursor class is a base class for screen cursors |
| in Qt for Embedded Linux. |
| |
| Note that this class is non-portable, and that it is only |
| available in \l{Qt for Embedded Linux}. |
| |
| QScreenCursor implements a software cursor, but can be subclassed |
| to support hardware cursors as well. When deriving from the |
| QScreenCursor class it is important to maintain the cursor's |
| image, position, hot spot (the point within the cursor's image |
| that will be the position of the associated mouse events) and |
| visibility as well as informing whether it is hardware accelerated |
| or not. |
| |
| Note that there may only be one screen cursor at a time. Use the |
| static instance() function to retrieve a pointer to the current |
| screen cursor. Typically, the cursor is constructed by the QScreen |
| class or one of its descendants when it is initializing the |
| device; the QScreenCursor class should never be instantiated |
| explicitly. |
| |
| Use the move() function to change the position of the cursor, and |
| the set() function to alter its image or its hot spot. In |
| addition, you can find out whether the cursor is accelerated or |
| not, using the isAccelerated() function, and the boundingRect() |
| function returns the cursor's bounding rectangle. |
| |
| The cursor's appearance can be controlled using the isVisible(), |
| hide() and show() functions; alternatively the QWSServer class |
| provides some means of controlling the cursor's appearance using |
| the QWSServer::isCursorVisible() and QWSServer::setCursorVisible() |
| functions. |
| |
| \sa QScreen, QWSServer |
| */ |
| |
| /*! |
| \fn static QScreenCursor* QScreenCursor::instance() |
| \since 4.2 |
| |
| Returns a pointer to the application's unique screen cursor. |
| */ |
| |
| extern bool qws_sw_cursor; |
| |
| /*! |
| Constructs a screen cursor |
| */ |
| QScreenCursor::QScreenCursor() |
| { |
| pos = QPoint(qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2); |
| size = QSize(0,0); |
| enable = true; |
| hwaccel = false; |
| supportsAlpha = true; |
| } |
| |
| /*! |
| Destroys the screen cursor. |
| */ |
| QScreenCursor::~QScreenCursor() |
| { |
| } |
| |
| /*! |
| Hides the cursor from the screen. |
| |
| \sa show() |
| */ |
| void QScreenCursor::hide() |
| { |
| if (enable) { |
| enable = false; |
| if (!hwaccel) |
| qt_screen->exposeRegion(boundingRect(), 0); |
| } |
| } |
| |
| /*! |
| Shows the mouse cursor. |
| |
| \sa hide() |
| */ |
| void QScreenCursor::show() |
| { |
| if (!enable) { |
| enable = true; |
| if (!hwaccel) |
| qt_screen->exposeRegion(boundingRect(), 0); |
| } |
| } |
| |
| /*! |
| Sets the cursor's image to be the given \a image. |
| |
| The \a hotx and \a hoty parameters define the cursor's hot spot, |
| i.e., the point within the cursor's image that will be the |
| position of the associated mouse events. |
| |
| \sa move() |
| */ |
| void QScreenCursor::set(const QImage &image, int hotx, int hoty) |
| { |
| const QRect r = boundingRect(); |
| |
| hotspot = QPoint(hotx, hoty); |
| // These are in almost all cases the fastest formats to blend |
| QImage::Format f; |
| switch (qt_screen->depth()) { |
| case 12: |
| f = QImage::Format_ARGB4444_Premultiplied; |
| break; |
| case 15: |
| f = QImage::Format_ARGB8555_Premultiplied; |
| break; |
| case 16: |
| f = QImage::Format_ARGB8565_Premultiplied; |
| break; |
| case 18: |
| f = QImage::Format_ARGB6666_Premultiplied; |
| break; |
| default: |
| f = QImage::Format_ARGB32_Premultiplied; |
| } |
| |
| cursor = image.convertToFormat(f); |
| |
| size = image.size(); |
| |
| if (enable && !hwaccel) |
| qt_screen->exposeRegion(r | boundingRect(), 0); |
| } |
| |
| /*! |
| Moves the mouse cursor to the given position, i.e., (\a x, \a y). |
| |
| Note that the given position defines the top-left corner of the |
| cursor's image, i.e., not the cursor's hot spot (the position of |
| the associated mouse events). |
| |
| \sa set() |
| */ |
| void QScreenCursor::move(int x, int y) |
| { |
| QRegion r = boundingRect(); |
| pos = QPoint(x,y); |
| if (enable && !hwaccel) { |
| r |= boundingRect(); |
| qt_screen->exposeRegion(r, 0); |
| } |
| } |
| |
| |
| /*! |
| \fn void QScreenCursor::initSoftwareCursor () |
| |
| Initializes the screen cursor. |
| |
| This function is typically called from the screen driver when |
| initializing the device. Alternatively, the cursor can be set |
| directly using the pointer returned by the static instance() |
| function. |
| |
| \sa QScreen::initDevice() |
| */ |
| void QScreenCursor::initSoftwareCursor() |
| { |
| qt_screencursor = new QScreenCursor; |
| } |
| |
| |
| #endif // QT_NO_QWS_CURSOR |
| |
| |
| /*! |
| \fn QRect QScreenCursor::boundingRect () const |
| |
| Returns the cursor's bounding rectangle. |
| */ |
| |
| /*! |
| \internal |
| \fn bool QScreenCursor::enabled () |
| */ |
| |
| /*! |
| \fn QImage QScreenCursor::image () const |
| |
| Returns the cursor's image. |
| */ |
| |
| |
| /*! |
| \fn bool QScreenCursor::isAccelerated () const |
| |
| Returns true if the cursor is accelerated; otherwise false. |
| */ |
| |
| /*! |
| \fn bool QScreenCursor::isVisible () const |
| |
| Returns true if the cursor is visible; otherwise false. |
| */ |
| |
| /*! |
| \internal |
| \fn bool QScreenCursor::supportsAlphaCursor () const |
| */ |
| |
| /* |
| \variable QScreenCursor::cursor |
| |
| \brief the cursor's image. |
| |
| \sa image() |
| */ |
| |
| /* |
| \variable QScreenCursor::size |
| |
| \brief the cursor's size |
| */ |
| |
| /* |
| \variable QScreenCursor::pos |
| |
| \brief the cursor's position, i.e., the position of the top-left |
| corner of the crsor's image |
| |
| \sa set(), move() |
| */ |
| |
| /* |
| \variable QScreenCursor::hotspot |
| |
| \brief the cursor's hotspot, i.e., the point within the cursor's |
| image that will be the position of the associated mouse events. |
| |
| \sa set(), move() |
| */ |
| |
| /* |
| \variable QScreenCursor::enable |
| |
| \brief whether the cursor is visible or not |
| |
| \sa isVisible() |
| */ |
| |
| /* |
| \variable QScreenCursor::hwaccel |
| |
| \brief holds whether the cursor is accelerated or not |
| |
| If the cursor is not accelerated, its image will be included by |
| the screen when it composites the window surfaces. |
| |
| \sa isAccelerated() |
| |
| */ |
| |
| /* |
| \variable QScreenCursor::supportsAlpha |
| */ |
| |
| /*! |
| \internal |
| \macro qt_screencursor |
| \relates QScreenCursor |
| |
| A global pointer referring to the unique screen cursor. It is |
| equivalent to the pointer returned by the |
| QScreenCursor::instance() function. |
| */ |
| |
| |
| |
| class QScreenPrivate |
| { |
| public: |
| QScreenPrivate(QScreen *parent, QScreen::ClassId id = QScreen::CustomClass); |
| ~QScreenPrivate(); |
| |
| inline QImage::Format preferredImageFormat() const; |
| |
| typedef void (*SolidFillFunc)(QScreen*, const QColor&, const QRegion&); |
| typedef void (*BlitFunc)(QScreen*, const QImage&, const QPoint&, const QRegion&); |
| |
| SolidFillFunc solidFill; |
| BlitFunc blit; |
| |
| QPoint offset; |
| QList<QScreen*> subScreens; |
| QPixmapDataFactory* pixmapFactory; |
| QGraphicsSystem* graphicsSystem; |
| QWSGraphicsSystem defaultGraphicsSystem; //### |
| QImage::Format pixelFormat; |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| bool fb_is_littleEndian; |
| #endif |
| #ifdef QT_QWS_CLIENTBLIT |
| bool supportsBlitInClients; |
| #endif |
| int classId; |
| QScreen *q_ptr; |
| }; |
| |
| template <typename T> |
| static void solidFill_template(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| T *dest = reinterpret_cast<T*>(screen->base()); |
| const T c = qt_colorConvert<T, quint32>(color.rgba(), 0); |
| const int stride = screen->linestep(); |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride); |
| } |
| } |
| |
| #ifdef QT_QWS_DEPTH_GENERIC |
| static void solidFill_rgb_32bpp(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| quint32 *dest = reinterpret_cast<quint32*>(screen->base()); |
| const quint32 c = qt_convertToRgb<quint32>(color.rgba()); |
| |
| const int stride = screen->linestep(); |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride); |
| } |
| } |
| |
| static void solidFill_rgb_16bpp(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| quint16 *dest = reinterpret_cast<quint16*>(screen->base()); |
| const quint16 c = qt_convertToRgb<quint32>(color.rgba()); |
| |
| const int stride = screen->linestep(); |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride); |
| } |
| } |
| #endif // QT_QWS_DEPTH_GENERIC |
| |
| #ifdef QT_QWS_DEPTH_4 |
| static inline void qt_rectfill_gray4(quint8 *dest, quint8 value, |
| int x, int y, int width, int height, |
| int stride) |
| { |
| const int pixelsPerByte = 2; |
| dest += y * stride + x / pixelsPerByte; |
| const int doAlign = x & 1; |
| const int doTail = (width - doAlign) & 1; |
| const int width8 = (width - doAlign) / pixelsPerByte; |
| |
| for (int j = 0; j < height; ++j) { |
| if (doAlign) |
| *dest = (*dest & 0xf0) | (value & 0x0f); |
| if (width8) |
| qt_memfill<quint8>(dest + doAlign, value, width8); |
| if (doTail) { |
| quint8 *d = dest + doAlign + width8; |
| *d = (*d & 0x0f) | (value & 0xf0); |
| } |
| dest += stride; |
| } |
| } |
| |
| static void solidFill_gray4(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| quint8 *dest = reinterpret_cast<quint8*>(screen->base()); |
| const quint8 c = qGray(color.rgba()) >> 4; |
| const quint8 c8 = (c << 4) | c; |
| |
| const int stride = screen->linestep(); |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| qt_rectfill_gray4(dest, c8, r.x(), r.y(), r.width(), r.height(), |
| stride); |
| } |
| } |
| #endif // QT_QWS_DEPTH_4 |
| |
| #ifdef QT_QWS_DEPTH_1 |
| static inline void qt_rectfill_mono(quint8 *dest, quint8 value, |
| int x, int y, int width, int height, |
| int stride) |
| { |
| const int pixelsPerByte = 8; |
| const int alignWidth = qMin(width, (8 - (x & 7)) & 7); |
| const int doAlign = (alignWidth > 0 ? 1 : 0); |
| const int alignStart = pixelsPerByte - 1 - (x & 7); |
| const int alignStop = alignStart - (alignWidth - 1); |
| const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop; |
| const int tailWidth = (width - alignWidth) & 7; |
| const int doTail = (tailWidth > 0 ? 1 : 0); |
| const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1; |
| const int width8 = (width - alignWidth) / pixelsPerByte; |
| |
| dest += y * stride + x / pixelsPerByte; |
| stride -= (doAlign + width8); |
| |
| for (int j = 0; j < height; ++j) { |
| if (doAlign) { |
| *dest = (*dest & ~alignMask) | (value & alignMask); |
| ++dest; |
| } |
| if (width8) { |
| qt_memfill<quint8>(dest, value, width8); |
| dest += width8; |
| } |
| if (doTail) |
| *dest = (*dest & tailMask) | (value & ~tailMask); |
| dest += stride; |
| } |
| } |
| |
| static void solidFill_mono(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| quint8 *dest = reinterpret_cast<quint8*>(screen->base()); |
| const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff; |
| |
| const int stride = screen->linestep(); |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| qt_rectfill_mono(dest, c8, r.x(), r.y(), r.width(), r.height(), |
| stride); |
| } |
| } |
| #endif // QT_QWS_DEPTH_1 |
| |
| void qt_solidFill_setup(QScreen *screen, const QColor &color, |
| const QRegion ®ion) |
| { |
| switch (screen->depth()) { |
| #ifdef QT_QWS_DEPTH_32 |
| case 32: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->solidFill = solidFill_template<quint32>; |
| else |
| screen->d_ptr->solidFill = solidFill_template<qabgr8888>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_24 |
| case 24: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->solidFill = solidFill_template<qrgb888>; |
| else |
| screen->d_ptr->solidFill = solidFill_template<quint24>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_18 |
| case 18: |
| screen->d_ptr->solidFill = solidFill_template<quint18>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_16 |
| case 16: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->solidFill = solidFill_template<quint16>; |
| else |
| screen->d_ptr->solidFill = solidFill_template<qbgr565>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_15 |
| case 15: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->solidFill = solidFill_template<qrgb555>; |
| else |
| screen->d_ptr->solidFill = solidFill_template<qbgr555>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_12 |
| case 12: |
| screen->d_ptr->solidFill = solidFill_template<qrgb444>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_8 |
| case 8: |
| screen->d_ptr->solidFill = solidFill_template<quint8>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_4 |
| case 4: |
| screen->d_ptr->solidFill = solidFill_gray4; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_1 |
| case 1: |
| screen->d_ptr->solidFill = solidFill_mono; |
| break; |
| #endif |
| default: |
| qFatal("solidFill_setup(): Screen depth %d not supported!", |
| screen->depth()); |
| screen->d_ptr->solidFill = 0; |
| break; |
| } |
| screen->d_ptr->solidFill(screen, color, region); |
| } |
| |
| template <typename DST, typename SRC> |
| static void blit_template(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| DST *dest = reinterpret_cast<DST*>(screen->base()); |
| const int screenStride = screen->linestep(); |
| const int imageStride = image.bytesPerLine(); |
| |
| if (region.rectCount() == 1) { |
| const QRect r = region.boundingRect(); |
| const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y())) |
| + r.x(); |
| qt_rectconvert<DST, SRC>(dest, src, |
| r.x() + topLeft.x(), r.y() + topLeft.y(), |
| r.width(), r.height(), |
| screenStride, imageStride); |
| } else { |
| const QVector<QRect> rects = region.rects(); |
| |
| for (int i = 0; i < rects.size(); ++i) { |
| const QRect r = rects.at(i); |
| const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y())) |
| + r.x(); |
| qt_rectconvert<DST, SRC>(dest, src, |
| r.x() + topLeft.x(), r.y() + topLeft.y(), |
| r.width(), r.height(), |
| screenStride, imageStride); |
| } |
| } |
| } |
| |
| #ifdef QT_QWS_DEPTH_32 |
| static void blit_32(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<quint32, quint32>(screen, image, topLeft, region); |
| return; |
| #ifdef QT_QWS_DEPTH_16 |
| case QImage::Format_RGB16: |
| blit_template<quint32, quint16>(screen, image, topLeft, region); |
| return; |
| #endif |
| default: |
| qCritical("blit_32(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_32 |
| |
| #ifdef QT_QWS_DEPTH_24 |
| static void blit_24(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<quint24, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB888: |
| blit_template<quint24, qrgb888>(screen, image, topLeft, region); |
| return; |
| #ifdef QT_QWS_DEPTH_16 |
| case QImage::Format_RGB16: |
| blit_template<quint24, quint16>(screen, image, topLeft, region); |
| return; |
| #endif |
| default: |
| qCritical("blit_24(): Image format %d not supported!", image.format()); |
| } |
| } |
| |
| static void blit_qrgb888(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qrgb888, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB888: |
| blit_template<qrgb888, qrgb888>(screen, image, topLeft, region); |
| return; |
| #ifdef QT_QWS_DEPTH_16 |
| case QImage::Format_RGB16: |
| blit_template<qrgb888, quint16>(screen, image, topLeft, region); |
| return; |
| #endif |
| default: |
| qCritical("blit_24(): Image format %d not supported!", image.format()); |
| break; |
| } |
| } |
| #endif // QT_QWS_DEPTH_24 |
| |
| #ifdef QT_QWS_DEPTH_18 |
| static void blit_18(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qrgb666, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB666: |
| blit_template<qrgb666, qrgb666>(screen, image, topLeft, region); |
| return; |
| #ifdef QT_QWS_DEPTH_16 |
| case QImage::Format_RGB16: |
| blit_template<qrgb666, quint16>(screen, image, topLeft, region); |
| return; |
| #endif |
| default: |
| qCritical("blit_18(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_18 |
| |
| #if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && (defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15)) |
| class quint16LE |
| { |
| public: |
| inline quint16LE(quint32 v) { |
| data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8); |
| } |
| |
| inline quint16LE(int v) { |
| data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8); |
| } |
| |
| inline quint16LE(quint16 v) { |
| data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8); |
| } |
| |
| inline quint16LE(qrgb555 v) { |
| data = (( (quint16)v & 0xff00) >> 8) | |
| (( (quint16)v & 0x00ff) << 8); |
| } |
| |
| inline bool operator==(const quint16LE &v) const |
| { |
| return data == v.data; |
| } |
| |
| private: |
| quint16 data; |
| }; |
| #endif |
| |
| #ifdef QT_QWS_DEPTH_16 |
| static void blit_16(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| // ### This probably doesn't work but it's a case which should never happen |
| blit_template<quint16, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<quint16, quint16>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_16(): Image format %d not supported!", image.format()); |
| } |
| } |
| |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| static void blit_16_bigToLittleEndian(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, |
| const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<quint16LE, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<quint16LE, quint16>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_16_bigToLittleEndian(): Image format %d not supported!", image.format()); |
| } |
| } |
| |
| #endif // Q_BIG_ENDIAN |
| #endif // QT_QWS_DEPTH_16 |
| |
| #ifdef QT_QWS_DEPTH_15 |
| static void blit_15(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qrgb555, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB555: |
| blit_template<qrgb555, qrgb555>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<qrgb555, quint16>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_15(): Image format %d not supported!", image.format()); |
| } |
| } |
| |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| static void blit_15_bigToLittleEndian(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, |
| const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB555: |
| blit_template<quint16LE, qrgb555>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_15_bigToLittleEndian(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // Q_BIG_ENDIAN |
| #endif // QT_QWS_DEPTH_15 |
| |
| |
| #ifdef QT_QWS_DEPTH_12 |
| static void blit_12(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_ARGB4444_Premultiplied: |
| blit_template<qrgb444, qargb4444>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB444: |
| blit_template<qrgb444, qrgb444>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_12(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_12 |
| |
| #ifdef QT_QWS_DEPTH_8 |
| static void blit_8(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<quint8, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<quint8, quint16>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_ARGB4444_Premultiplied: |
| blit_template<quint8, qargb4444>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB444: |
| blit_template<quint8, qrgb444>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_8(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_8 |
| |
| #ifdef QT_QWS_DEPTH_4 |
| |
| struct qgray4 { quint8 dummy; } Q_PACKED; |
| |
| template <typename SRC> |
| Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToGray4(SRC color); |
| |
| template <> |
| inline quint8 qt_convertToGray4(quint32 color) |
| { |
| return qGray(color) >> 4; |
| } |
| |
| template <> |
| inline quint8 qt_convertToGray4(quint16 color) |
| { |
| const int r = (color & 0xf800) >> 11; |
| const int g = (color & 0x07e0) >> 6; // only keep 5 bit |
| const int b = (color & 0x001f); |
| return (r * 11 + g * 16 + b * 5) >> 6; |
| } |
| |
| template <> |
| inline quint8 qt_convertToGray4(qrgb444 color) |
| { |
| return qt_convertToGray4(quint32(color)); |
| } |
| |
| template <> |
| inline quint8 qt_convertToGray4(qargb4444 color) |
| { |
| return qt_convertToGray4(quint32(color)); |
| } |
| |
| template <typename SRC> |
| Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_gray4(qgray4 *dest4, const SRC *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| const int pixelsPerByte = 2; |
| quint8 *dest8 = reinterpret_cast<quint8*>(dest4) |
| + y * dstStride + x / pixelsPerByte; |
| const int doAlign = x & 1; |
| const int doTail = (width - doAlign) & 1; |
| const int width8 = (width - doAlign) / pixelsPerByte; |
| const int count8 = (width8 + 3) / 4; |
| |
| srcStride = srcStride / sizeof(SRC) - width; |
| dstStride -= (width8 + doAlign); |
| |
| for (int i = 0; i < height; ++i) { |
| if (doAlign) { |
| *dest8 = (*dest8 & 0xf0) | qt_convertToGray4<SRC>(*src++); |
| ++dest8; |
| } |
| if (count8) { |
| int n = count8; |
| switch (width8 & 0x03) // duff's device |
| { |
| case 0: do { *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4 |
| | qt_convertToGray4<SRC>(src[1]); |
| src += 2; |
| case 3: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4 |
| | qt_convertToGray4<SRC>(src[1]); |
| src += 2; |
| case 2: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4 |
| | qt_convertToGray4<SRC>(src[1]); |
| src += 2; |
| case 1: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4 |
| | qt_convertToGray4<SRC>(src[1]); |
| src += 2; |
| } while (--n > 0); |
| } |
| } |
| |
| if (doTail) |
| *dest8 = qt_convertToGray4<SRC>(*src++) << 4 | (*dest8 & 0x0f); |
| |
| dest8 += dstStride; |
| src += srcStride; |
| } |
| } |
| |
| template <> |
| void qt_rectconvert(qgray4 *dest, const quint32 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_gray4<quint32>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qgray4 *dest, const quint16 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_gray4<quint16>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qgray4 *dest, const qrgb444 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_gray4<qrgb444>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qgray4 *dest, const qargb4444 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_gray4<qargb4444>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| static void blit_4(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qgray4, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<qgray4, quint16>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB444: |
| blit_template<qgray4, qrgb444>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_ARGB4444_Premultiplied: |
| blit_template<qgray4, qargb4444>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_4(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_4 |
| |
| #ifdef QT_QWS_DEPTH_1 |
| |
| struct qmono { quint8 dummy; } Q_PACKED; |
| |
| template <typename SRC> |
| Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToMono(SRC color); |
| |
| template <> |
| inline quint8 qt_convertToMono(quint32 color) |
| { |
| return qGray(color) >> 7; |
| } |
| |
| template <> |
| inline quint8 qt_convertToMono(quint16 color) |
| { |
| return (qGray(qt_colorConvert<quint32, quint16>(color, 0)) >> 7); |
| } |
| |
| template <> |
| inline quint8 qt_convertToMono(qargb4444 color) |
| { |
| return (qGray(quint32(color)) >> 7); |
| } |
| |
| template <> |
| inline quint8 qt_convertToMono(qrgb444 color) |
| { |
| return (qGray(quint32(color)) >> 7); |
| } |
| |
| template <typename SRC> |
| inline void qt_rectconvert_mono(qmono *dest, const SRC *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| const int pixelsPerByte = 8; |
| quint8 *dest8 = reinterpret_cast<quint8*>(dest) |
| + y * dstStride + x / pixelsPerByte; |
| const int alignWidth = qMin(width, (8 - (x & 7)) & 7); |
| const int doAlign = (alignWidth > 0 ? 1 : 0); |
| const int alignStart = pixelsPerByte - 1 - (x & 7); |
| const int alignStop = alignStart - (alignWidth - 1); |
| const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop; |
| const int tailWidth = (width - alignWidth) & 7; |
| const int doTail = (tailWidth > 0 ? 1 : 0); |
| const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1; |
| const int width8 = (width - alignWidth) / pixelsPerByte; |
| |
| srcStride = srcStride / sizeof(SRC) - (width8 * 8 + alignWidth); |
| dstStride -= (width8 + doAlign); |
| |
| for (int j = 0; j < height; ++j) { |
| if (doAlign) { |
| quint8 d = *dest8 & ~alignMask; |
| for (int i = alignStart; i >= alignStop; --i) |
| d |= qt_convertToMono<SRC>(*src++) << i; |
| *dest8++ = d; |
| } |
| for (int i = 0; i < width8; ++i) { |
| *dest8 = (qt_convertToMono<SRC>(src[0]) << 7) |
| | (qt_convertToMono<SRC>(src[1]) << 6) |
| | (qt_convertToMono<SRC>(src[2]) << 5) |
| | (qt_convertToMono<SRC>(src[3]) << 4) |
| | (qt_convertToMono<SRC>(src[4]) << 3) |
| | (qt_convertToMono<SRC>(src[5]) << 2) |
| | (qt_convertToMono<SRC>(src[6]) << 1) |
| | (qt_convertToMono<SRC>(src[7])); |
| src += 8; |
| ++dest8; |
| } |
| if (doTail) { |
| quint8 d = *dest8 & tailMask; |
| switch (tailWidth) { |
| case 7: d |= qt_convertToMono<SRC>(src[6]) << 1; |
| case 6: d |= qt_convertToMono<SRC>(src[5]) << 2; |
| case 5: d |= qt_convertToMono<SRC>(src[4]) << 3; |
| case 4: d |= qt_convertToMono<SRC>(src[3]) << 4; |
| case 3: d |= qt_convertToMono<SRC>(src[2]) << 5; |
| case 2: d |= qt_convertToMono<SRC>(src[1]) << 6; |
| case 1: d |= qt_convertToMono<SRC>(src[0]) << 7; |
| } |
| *dest8 = d; |
| } |
| |
| dest8 += dstStride; |
| src += srcStride; |
| } |
| } |
| |
| template <> |
| void qt_rectconvert(qmono *dest, const quint32 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_mono<quint32>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qmono *dest, const quint16 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_mono<quint16>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qmono *dest, const qrgb444 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_mono<qrgb444>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| template <> |
| void qt_rectconvert(qmono *dest, const qargb4444 *src, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| { |
| qt_rectconvert_mono<qargb4444>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| } |
| |
| static void blit_1(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qmono, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<qmono, quint16>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB444: |
| blit_template<qmono, qrgb444>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_ARGB4444_Premultiplied: |
| blit_template<qmono, qargb4444>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_1(): Image format %d not supported!", image.format()); |
| } |
| } |
| #endif // QT_QWS_DEPTH_1 |
| |
| #ifdef QT_QWS_DEPTH_GENERIC |
| |
| static void blit_rgb(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (image.format()) { |
| case QImage::Format_ARGB32_Premultiplied: |
| blit_template<qrgb, quint32>(screen, image, topLeft, region); |
| return; |
| case QImage::Format_RGB16: |
| blit_template<qrgb, quint16>(screen, image, topLeft, region); |
| return; |
| default: |
| qCritical("blit_rgb(): Image format %d not supported!", image.format()); |
| } |
| } |
| |
| void qt_set_generic_blit(QScreen *screen, int bpp, |
| int len_red, int len_green, int len_blue, int len_alpha, |
| int off_red, int off_green, int off_blue, int off_alpha) |
| { |
| qrgb::bpp = bpp / 8; |
| qrgb::len_red = len_red; |
| qrgb::len_green = len_green; |
| qrgb::len_blue = len_blue; |
| qrgb::len_alpha = len_alpha; |
| qrgb::off_red = off_red; |
| qrgb::off_green = off_green; |
| qrgb::off_blue = off_blue; |
| qrgb::off_alpha = off_alpha; |
| screen->d_ptr->blit = blit_rgb; |
| if (bpp == 16) |
| screen->d_ptr->solidFill = solidFill_rgb_16bpp; |
| else if (bpp == 32) |
| screen->d_ptr->solidFill = solidFill_rgb_32bpp; |
| } |
| |
| #endif // QT_QWS_DEPTH_GENERIC |
| |
| void qt_blit_setup(QScreen *screen, const QImage &image, |
| const QPoint &topLeft, const QRegion ®ion) |
| { |
| switch (screen->depth()) { |
| #ifdef QT_QWS_DEPTH_32 |
| case 32: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->blit = blit_32; |
| else |
| screen->d_ptr->blit = blit_template<qabgr8888, quint32>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_24 |
| case 24: |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->blit = blit_qrgb888; |
| else |
| screen->d_ptr->blit = blit_24; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_18 |
| case 18: |
| screen->d_ptr->blit = blit_18; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_16 |
| case 16: |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| if (screen->d_ptr->fb_is_littleEndian) |
| screen->d_ptr->blit = blit_16_bigToLittleEndian; |
| else |
| #endif |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->blit = blit_16; |
| else |
| screen->d_ptr->blit = blit_template<qbgr565, quint16>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_15 |
| case 15: |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| if (screen->d_ptr->fb_is_littleEndian) |
| screen->d_ptr->blit = blit_15_bigToLittleEndian; |
| else |
| #endif // Q_BIG_ENDIAN |
| if (screen->pixelType() == QScreen::NormalPixel) |
| screen->d_ptr->blit = blit_15; |
| else |
| screen->d_ptr->blit = blit_template<qbgr555, qrgb555>; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_12 |
| case 12: |
| screen->d_ptr->blit = blit_12; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_8 |
| case 8: |
| screen->d_ptr->blit = blit_8; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_4 |
| case 4: |
| screen->d_ptr->blit = blit_4; |
| break; |
| #endif |
| #ifdef QT_QWS_DEPTH_1 |
| case 1: |
| screen->d_ptr->blit = blit_1; |
| break; |
| #endif |
| default: |
| qFatal("blit_setup(): Screen depth %d not supported!", |
| screen->depth()); |
| screen->d_ptr->blit = 0; |
| break; |
| } |
| screen->d_ptr->blit(screen, image, topLeft, region); |
| } |
| |
| QScreenPrivate::QScreenPrivate(QScreen *parent, QScreen::ClassId id) |
| : defaultGraphicsSystem(QWSGraphicsSystem(parent)), |
| pixelFormat(QImage::Format_Invalid), |
| #ifdef QT_QWS_CLIENTBLIT |
| supportsBlitInClients(false), |
| #endif |
| classId(id), q_ptr(parent) |
| { |
| solidFill = qt_solidFill_setup; |
| blit = qt_blit_setup; |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| fb_is_littleEndian = false; |
| #endif |
| pixmapFactory = 0; |
| graphicsSystem = &defaultGraphicsSystem; |
| } |
| |
| QScreenPrivate::~QScreenPrivate() |
| { |
| } |
| |
| QImage::Format QScreenPrivate::preferredImageFormat() const |
| { |
| if (pixelFormat > QImage::Format_Indexed8) |
| return pixelFormat; |
| |
| if (q_ptr->depth() <= 16) |
| return QImage::Format_RGB16; |
| else |
| return QImage::Format_ARGB32_Premultiplied; |
| } |
| |
| /*! |
| \class QScreen |
| \ingroup qws |
| |
| \brief The QScreen class is a base class for screen drivers in |
| Qt for Embedded Linux. |
| |
| Note that this class is only available in \l{Qt for Embedded Linux}. |
| |
| \l{Qt for Embedded Linux} provides ready-made drivers for several screen |
| protocols, see the \l{Qt for Embedded Linux Display Management}{display |
| management} documentation for details. Custom screen drivers can |
| be implemented by subclassing the QScreen class and creating a |
| screen driver plugin (derived from QScreenDriverPlugin). The |
| default implementation of the QScreenDriverFactory class |
| will automatically detect the plugin, and load the driver into the |
| server application at run-time using Qt's \l {How to Create Qt |
| Plugins}{plugin system}. |
| |
| When rendering, the default behavior is for each |
| client to render its widgets as well as its decorations into |
| memory, while the server copies the memory content to the device's |
| framebuffer using the screen driver. See the \l{Qt for Embedded Linux |
| Architecture} overview for details (note that it is possible for |
| the clients to manipulate and control the underlying hardware |
| directly as well). |
| |
| Starting with Qt 4.2, it is also possible to add an |
| accelerated graphics driver to take advantage of available |
| hardware resources. See the \l{Adding an Accelerated Graphics |
| Driver to Qt for Embedded Linux} documentation for details. |
| |
| \tableofcontents |
| |
| \section1 Framebuffer Management |
| |
| When a \l{Qt for Embedded Linux} application starts running, it |
| calls the screen driver's connect() function to map the |
| framebuffer and the accelerated drivers that the graphics card |
| control registers. The connect() function should then read out the |
| parameters of the framebuffer and use them as required to set this |
| class's protected variables. |
| |
| The initDevice() function can be reimplemented to initialize the |
| graphics card. Note, however, that connect() is called \e before |
| the initDevice() function, so, for some hardware configurations, |
| some of the initialization that would normally be done in the |
| initDevice() function might have to be done in the connect() |
| function. |
| |
| Likewise, just before a \l{Qt for Embedded Linux} application |
| exits, it calls the screen driver's disconnect() function. The |
| server application will in addition call the shutdownDevice() |
| function before it calls disconnect(). Note that the default |
| implementation of the shutdownDevice() function only hides the |
| mouse cursor. |
| |
| QScreen also provides the save() and restore() functions, making |
| it possible to save and restore the state of the graphics |
| card. Note that the default implementations do nothing. Hardware |
| screen drivers should reimplement these functions to save (and |
| restore) its registers, enabling switching between virtual |
| consoles. |
| |
| In addition, you can use the base() function to retrieve a pointer |
| to the beginning of the framebuffer, and the region() function to |
| retrieve the framebuffer's region. Use the onCard() function to |
| determine whether the framebuffer is within the graphics card's |
| memory, and the totalSize() function to determine the size of the |
| available graphics card memory (including the screen). Finally, |
| you can use the offset() function to retrieve the offset between |
| the framebuffer's coordinates and the application's coordinate |
| system. |
| |
| \section1 Palette Management |
| |
| QScreen provides several functions to retrieve information about |
| the color palette: The clut() function returns a pointer to the |
| color lookup table (i.e. its color palette). Use the colorCount() |
| function to determine the number of entries in this table, and the |
| alloc() function to retrieve the palette index of the color that |
| is the closest match to a given RGB value. |
| |
| To determine if the screen driver supports a given color depth, |
| use the supportsDepth() function that returns true of the |
| specified depth is supported. |
| |
| \section1 Drawing on Screen |
| |
| When a screen update is required, the \l{Qt for Embedded Linux} server runs |
| through all the top-level windows that intersect with the region |
| that is about to be updated, and ensures that the associated |
| clients have updated their memory buffer. Then the server calls |
| the exposeRegion() function that composes the window surfaces and |
| copies the content of memory to screen by calling the blit() and |
| solidFill() functions. |
| |
| The blit() function copies a given region in a given image to a |
| specified point using device coordinates, while the solidFill() |
| function fills the given region of the screen with the specified |
| color. Note that normally there is no need to call either of these |
| functions explicitly. |
| |
| In addition, QScreen provides the blank() function that can be |
| reimplemented to prevent any contents from being displayed on the |
| screen, and the setDirty() function that can be reimplemented to |
| indicate that a given rectangle of the screen has been |
| altered. Note that the default implementations of these functions |
| do nothing. |
| |
| Reimplement the mapFromDevice() and mapToDevice() functions to |
| map objects from the framebuffer coordinate system to the |
| coordinate space used by the application, and vice versa. Be aware |
| that the default implementations simply return the given objects |
| as they are. |
| |
| \section1 Properties |
| |
| \table |
| \header \o Property \o Functions |
| \row |
| \o Size |
| \o |
| |
| The size of the screen can be retrieved using the screenSize() |
| function. The size is returned in bytes. |
| |
| The framebuffer's logical width and height can be retrieved using |
| width() and height(), respectively. These functions return values |
| are given in pixels. Alternatively, the physicalWidth() and |
| physicalHeight() function returns the same metrics in |
| millimeters. QScreen also provides the deviceWidth() and |
| deviceHeight() functions returning the physical width and height |
| of the device in pixels. Note that the latter metrics can differ |
| from the ones used if the display is centered within the |
| framebuffer. |
| |
| \row |
| \o Resolution |
| \o |
| |
| Reimplement the setMode() function to be able to set the |
| framebuffer to a new resolution (width and height) and bit depth. |
| |
| The current depth of the framebuffer can be always be retrieved |
| using the depth() function. Use the pixmapDepth() function to |
| obtain the preferred depth for pixmaps. |
| |
| \row |
| \o Pixmap Alignment |
| \o |
| |
| Use the pixmapOffsetAlignment() function to retrieve the value to |
| which the start address of pixmaps held in the graphics card's |
| memory, should be aligned. |
| |
| Use the pixmapLinestepAlignment() to retrieve the value to which |
| the \e {individual scanlines} of pixmaps should be aligned. |
| |
| \row |
| \o Image Display |
| \o |
| |
| The isInterlaced() function tells whether the screen is displaying |
| images progressively, and the isTransformed() function whether it |
| is rotated. The transformOrientation() function can be |
| reimplemented to return the current rotation. |
| |
| \row |
| \o Scanlines |
| \o |
| |
| Use the linestep() function to retrieve the length of each |
| scanline of the framebuffer. |
| |
| \row |
| \o Pixel Type |
| \o |
| |
| The pixelType() function returns the screen's pixel storage format as |
| described by the PixelType enum. |
| |
| \endtable |
| |
| \section1 Subclassing and Initial Values |
| |
| You need to set the following members when implementing a subclass of QScreen: |
| |
| \table |
| \header \o Member \o Initial Value |
| \row \o \l{QScreen::}{data} \o A pointer to the framebuffer if possible; |
| 0 otherwise. |
| \row \o \l{QScreen::}{lstep} \o The number of bytes between each scanline |
| in the framebuffer. |
| \row \o \l{QScreen::}{w} \o The logical screen width in pixels. |
| \row \o \l{QScreen::}{h} \o The logical screen height in pixels. |
| \row \o \l{QScreen::}{dw} \o The real screen width in pixels. |
| \row \o \l{QScreen::}{dh} \o The real screen height in pixels. |
| \row \o \l{QScreen::}{d} \o The number of bits per pixel. |
| \row \o \l{QScreen::}{physWidth} \o The screen width in millimeters. |
| \row \o \l{QScreen::}{physHeight} \o The screen height in millimeters. |
| \endtable |
| |
| The logical screen values are the same as the real screen values unless the |
| screen is transformed in some way; e.g., rotated. |
| |
| See also the \l{Accelerated Graphics Driver Example} for an example that |
| shows how to initialize these values. |
| |
| \sa QScreenDriverPlugin, QScreenDriverFactory, {Qt for Embedded Linux Display |
| Management} |
| */ |
| |
| /*! |
| \enum QScreen::PixelType |
| |
| This enum describes the pixel storage format of the screen, |
| i.e. the order of the red (R), green (G) and blue (B) components |
| of a pixel. |
| |
| \value NormalPixel Red-green-blue (RGB) |
| \value BGRPixel Blue-green-red (BGR) |
| |
| \sa pixelType() |
| */ |
| |
| /*! |
| \enum QScreen::ClassId |
| |
| This enum defines the class identifiers for the known screen subclasses. |
| |
| \value LinuxFBClass QLinuxFBScreen |
| \value TransformedClass QTransformedScreen |
| \value VNCClass QVNCScreen |
| \value MultiClass QMultiScreen |
| \value VFbClass QVFbScreen |
| \value DirectFBClass QDirectFBScreen |
| \value SvgalibClass QSvgalibScreen |
| \value ProxyClass QProxyScreen |
| \value GLClass QGLScreen |
| \value CustomClass Unknown QScreen subclass |
| |
| \sa classId() |
| */ |
| |
| /*! |
| \variable QScreen::screenclut |
| \brief the color table |
| |
| Initialize this variable in a subclass using a paletted screen mode, |
| and initialize its partner, QScreen::screencols. |
| |
| \sa screencols |
| */ |
| |
| /*! |
| \variable QScreen::screencols |
| \brief the number of entries in the color table |
| |
| Initialize this variable in a subclass using a paletted screen mode, |
| and initialize its partner, QScreen::screenclut. |
| |
| \sa screenclut |
| */ |
| |
| /*! |
| \variable QScreen::data |
| \brief points to the first visible pixel in the frame buffer. |
| |
| You must initialize this variable if you are using the default |
| implementation of non-buffered painting Qt::WA_PaintOnScreen, |
| QPixmap::grabWindow() or QDirectPainter::frameBuffer(). If you |
| initialize this variable, you must also initialize QScreen::size and |
| QScreen::mapsize. |
| |
| \sa QScreen::size, QScreen::mapsize |
| */ |
| |
| /*! |
| \variable QScreen::w |
| \brief the logical width of the screen. |
| |
| This variable \e{must} be initialized by a subclass. |
| */ |
| |
| /*! |
| \variable QScreen::lstep |
| \brief the number of bytes representing a line in the frame buffer. |
| |
| i.e., \e{line step}. \c {data[lstep * 2]} is the address of the |
| first visible pixel in the third line of the frame buffer. |
| |
| \sa data |
| */ |
| |
| /*! |
| \variable QScreen::h |
| \brief the logical height of the screen. |
| |
| This variable \e{must} be initialized by a subclass. |
| */ |
| |
| /*! |
| \variable QScreen::d |
| \brief the pixel depth |
| |
| This is the number of significant bits used to set a pixel |
| color. This variable \e{must} be initialized by a subclass. |
| */ |
| |
| /*! |
| \variable QScreen::pixeltype |
| \brief set to BGRPixel |
| |
| Set this variable to BGRPixel in a subclass, if the screen pixel |
| format is a BGR type and you have used setPixelFormat() to set the |
| pixel format to the corresponding RGB format. e.g., you have set the |
| pixel format to QImage::Format_RGB555, but your screen really uses |
| BGR, not RGB. |
| */ |
| |
| /*! |
| \variable QScreen::grayscale |
| \brief the gray scale screen mode flag |
| |
| Set this variable to true in a subclass, if you are using a |
| grayscale screen mode. e.g., in an 8-bit mode where you don't want |
| to use the palette, but you want to use the grayscales. |
| */ |
| |
| /*! |
| \variable QScreen::dw |
| \brief the device width |
| |
| This is the number of pixels in a row of the physical screen. It |
| \e{must} be initialized by a subclass. Normally, it should be set to |
| the logical width QScreen::w, but it might be different, e.g., if |
| you are doing rotations in software. |
| |
| \sa QScreen::w |
| */ |
| |
| /*! |
| \variable QScreen::dh |
| \brief the device height |
| |
| This is the number of pixels in a column of the physical screen. It |
| \e{must} be initialized by a subclass. Normally, it should be set to |
| the logical height QScreen::h, but it might be different, e.g., if |
| you are doing rotations in software. |
| |
| \sa QScreen::h |
| */ |
| |
| /*! |
| \variable QScreen::size |
| \brief the number of bytes in the visible region of the frame buffer |
| |
| This is the number of bytes in the visible part of the block pointed |
| to by the QScreen::data pointer. You must initialize this variable |
| if you initialize the QScreen::data pointer. |
| |
| \sa QScreen::data, QScreen::mapsize |
| */ |
| |
| /*! |
| \variable QScreen::mapsize |
| \brief the total number of bytes in the frame buffer |
| |
| This is the total number of bytes in the block pointed to by the |
| QScreen::data pointer. You must initialize this variable if you |
| initialize the QScreen::data pointer. |
| |
| \sa QScreen::data, QScreen::size |
| */ |
| |
| /*! |
| \variable QScreen::physWidth |
| \brief the physical width of the screen in millimeters. |
| |
| Currently, this variable is used when calculating the screen DPI, |
| which in turn is used when deciding the actual font size Qt is |
| using. |
| */ |
| |
| /*! |
| \variable QScreen::physHeight |
| \brief the physical height of the screen in millimeters. |
| |
| Currently, this variable is used when calculating the screen DPI, |
| which in turn is used when deciding the actual font size Qt is |
| using. |
| */ |
| |
| /*! |
| \fn static QScreen* QScreen::instance() |
| |
| Returns a pointer to the application's QScreen instance. |
| |
| If this screen consists of several subscreens, operations to the |
| returned instance will affect all its subscreens. Use the |
| subscreens() function to retrieve access to a particular |
| subscreen. |
| |
| \sa subScreens(), subScreenIndexAt() |
| */ |
| |
| /*! |
| \fn QList<QScreen*> QScreen::subScreens() const |
| \since 4.2 |
| |
| Returns a list of this screen's subscreens. Use the |
| subScreenIndexAt() function to retrieve the index of a screen at a |
| given position. |
| |
| Note that if \e this screen consists of several subscreens, |
| operations to \e this instance will affect all subscreens by |
| default. |
| |
| \sa instance(), subScreenIndexAt() |
| */ |
| |
| /*! |
| \fn int QScreen::physicalWidth() const |
| \since 4.2 |
| |
| Returns the physical width of the screen in millimeters. |
| |
| \sa width(), deviceWidth(), physicalHeight() |
| */ |
| |
| /*! |
| \fn int QScreen::physicalHeight() const |
| \since 4.2 |
| |
| Returns the physical height of the screen in millimeters. |
| |
| \sa height(), deviceHeight(), physicalWidth() |
| */ |
| |
| /*! |
| \fn virtual bool QScreen::initDevice() = 0 |
| |
| This function is called by the \l{Qt for Embedded Linux} server to |
| initialize the framebuffer. Note that a server application will call the |
| connect() function prior to this function. |
| |
| Implement this function to make accelerated drivers set up the |
| graphics card. Return true to indicate success and false to indicate |
| failure. |
| |
| \sa shutdownDevice(), connect() |
| */ |
| |
| /*! |
| \fn virtual bool QScreen::connect(const QString &displaySpec) = 0 |
| |
| This function is called by every \l{Qt for Embedded Linux} |
| application on startup, and must be implemented to map in the |
| framebuffer and the accelerated drivers that the graphics card |
| control registers. Note that connect must be called \e before |
| the initDevice() function. |
| |
| Ensure that true is returned if a connection to the screen device |
| is made. Otherwise, return false. Upon making the connection, the |
| function should read out the parameters of the framebuffer and use |
| them as required to set this class's protected variables. |
| |
| The \a displaySpec argument is passed by the QWS_DISPLAY |
| environment variable or the -display command line parameter, and |
| has the following syntax: |
| |
| \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 0 |
| |
| For example, to use the mach64 driver on fb1 as display 2: |
| |
| \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 1 |
| |
| See \l{Qt for Embedded Linux Display Management} for more details. |
| |
| \sa disconnect(), initDevice(), {Running Qt for Embedded Linux Applications} |
| */ |
| |
| /*! |
| \fn QScreen::disconnect() |
| |
| This function is called by every \l{Qt for Embedded Linux} application |
| before exiting, and must be implemented to unmap the |
| framebuffer. Note that a server application will call the |
| shutdownDevice() function prior to this function. |
| |
| \sa connect(), shutdownDevice(), {Running Qt for Embedded Linux |
| Applications} |
| */ |
| |
| /*! |
| \fn QScreen::setMode(int width, int height, int depth) |
| |
| Implement this function to reset the framebuffer's resolution (\a |
| width and \a height) and bit \a depth. |
| |
| After the resolution has been set, existing paint engines will be |
| invalid and the framebuffer should be completely redrawn. In a |
| multiple-process situation, all other applications must be |
| notified to reset their mode and update themselves accordingly. |
| */ |
| |
| /*! |
| \fn QScreen::blank(bool on) |
| |
| Prevents the screen driver form displaying any content on the |
| screen. |
| |
| Note that the default implementation does nothing. |
| |
| Reimplement this function to prevent the screen driver from |
| displaying any contents on the screen if \a on is true; otherwise |
| the contents is expected to be shown. |
| |
| \sa blit() |
| */ |
| |
| /*! |
| \fn int QScreen::pixmapOffsetAlignment() |
| |
| Returns the value (in bits) to which the start address of pixmaps |
| held in the graphics card's memory, should be aligned. |
| |
| Note that the default implementation returns 64; reimplement this |
| function to override the return value, e.g., when implementing an |
| accelerated driver (see the \l {Adding an Accelerated Graphics |
| Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver} |
| documentation for details). |
| |
| \sa pixmapLinestepAlignment() |
| */ |
| |
| /*! |
| \fn int QScreen::pixmapLinestepAlignment() |
| |
| Returns the value (in bits) to which individual scanlines of |
| pixmaps held in the graphics card's memory, should be |
| aligned. |
| |
| Note that the default implementation returns 64; reimplement this |
| function to override the return value, e.g., when implementing an |
| accelerated driver (see the \l {Adding an Accelerated Graphics |
| Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver} |
| documentation for details). |
| |
| \sa pixmapOffsetAlignment() |
| */ |
| |
| /*! |
| \fn QScreen::width() const |
| |
| Returns the logical width of the framebuffer in pixels. |
| |
| \sa deviceWidth(), physicalWidth(), height() |
| */ |
| |
| /*! |
| \fn int QScreen::height() const |
| |
| Returns the logical height of the framebuffer in pixels. |
| |
| \sa deviceHeight(), physicalHeight(), width() |
| */ |
| |
| /*! |
| \fn QScreen::depth() const |
| |
| Returns the depth of the framebuffer, in bits per pixel. |
| |
| Note that the returned depth is the number of bits each pixel |
| fills rather than the number of significant bits, so 24bpp and |
| 32bpp express the same range of colors (8 bits of red, green and |
| blue). |
| |
| \sa clut(), pixmapDepth() |
| */ |
| |
| /*! |
| \fn int QScreen::pixmapDepth() const |
| |
| Returns the preferred depth for pixmaps, in bits per pixel. |
| |
| \sa depth() |
| */ |
| |
| /*! |
| \fn QScreen::linestep() const |
| |
| Returns the length of each scanline of the framebuffer in bytes. |
| |
| \sa isInterlaced() |
| */ |
| |
| /*! |
| \fn QScreen::deviceWidth() const |
| |
| Returns the physical width of the framebuffer device in pixels. |
| |
| Note that the returned width can differ from the width which |
| \l{Qt for Embedded Linux} will actually use, that is if the display is |
| centered within the framebuffer. |
| |
| \sa width(), physicalWidth(), deviceHeight() |
| */ |
| |
| /*! |
| \fn QScreen::deviceHeight() const |
| |
| Returns the full height of the framebuffer device in pixels. |
| |
| Note that the returned height can differ from the height which |
| \l{Qt for Embedded Linux} will actually use, that is if the display is |
| centered within the framebuffer. |
| |
| \sa height(), physicalHeight(), deviceWidth() |
| */ |
| |
| /*! |
| \fn uchar *QScreen::base() const |
| |
| Returns a pointer to the beginning of the framebuffer. |
| |
| \sa onCard(), region(), totalSize() |
| */ |
| |
| /*! |
| \fn uchar *QScreen::cache(int) |
| |
| \internal |
| |
| This function is used to store pixmaps in graphics memory for the |
| use of the accelerated drivers. See QLinuxFbScreen (where the |
| caching is implemented) for more information. |
| */ |
| |
| /*! |
| \fn QScreen::uncache(uchar *) |
| |
| \internal |
| |
| This function is called on pixmap destruction to remove them from |
| graphics card memory. |
| */ |
| |
| /*! |
| \fn QScreen::screenSize() const |
| |
| Returns the size of the screen in bytes. |
| |
| The screen size is always located at the beginning of framebuffer |
| memory, i.e. it can also be retrieved using the base() function. |
| |
| \sa base(), region() |
| */ |
| |
| /*! |
| \fn QScreen::totalSize() const |
| |
| Returns the size of the available graphics card memory (including |
| the screen) in bytes. |
| |
| \sa onCard() |
| */ |
| |
| // Unaccelerated screen/driver setup. Can be overridden by accelerated |
| // drivers |
| |
| /*! |
| \fn QScreen::QScreen(int displayId) |
| |
| Constructs a new screen driver. |
| |
| The \a displayId identifies the \l{Qt for Embedded Linux} server to connect |
| to. |
| */ |
| |
| /*! |
| \fn QScreen::clut() |
| |
| Returns a pointer to the screen's color lookup table (i.e. its |
| color palette). |
| |
| Note that this function only apply in paletted modes like 8-bit, |
| i.e. in modes where only the palette indexes (and not the actual |
| color values) are stored in memory. |
| |
| \sa alloc(), depth(), colorCount() |
| */ |
| |
| /*! |
| \obsolete |
| \fn int QScreen::numCols() |
| |
| \sa colorCount() |
| */ |
| |
| /*! |
| \since 4.6 |
| \fn int QScreen::colorCount() |
| |
| Returns the number of entries in the screen's color lookup table |
| (i.e. its color palette). A pointer to the color table can be |
| retrieved using the clut() function. |
| |
| \sa clut(), alloc() |
| */ |
| |
| /*! |
| \since 4.4 |
| |
| Constructs a new screen driver. |
| |
| The \a display_id identifies the \l{Qt for Embedded Linux} |
| server to connect to. The \a classId specifies the class |
| identifier. |
| */ |
| QScreen::QScreen(int display_id, ClassId classId) |
| : screencols(0), data(0), entries(0), entryp(0), lowest(0), |
| w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false), |
| dw(0), dh(0), size(0), mapsize(0), displayId(display_id), |
| physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this, classId)) |
| { |
| clearCacheFunc = 0; |
| } |
| |
| QScreen::QScreen(int display_id) |
| : screencols(0), data(0), entries(0), entryp(0), lowest(0), |
| w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false), |
| dw(0), dh(0), size(0), mapsize(0), displayId(display_id), |
| physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this)) |
| { |
| clearCacheFunc = 0; |
| } |
| |
| /*! |
| Destroys this screen driver. |
| */ |
| |
| QScreen::~QScreen() |
| { |
| delete d_ptr; |
| } |
| |
| /*! |
| This function is called by the \l{Qt for Embedded Linux} server before it |
| calls the disconnect() function when exiting. |
| |
| Note that the default implementation only hides the mouse cursor; |
| reimplement this function to do the necessary graphics card |
| specific cleanup. |
| |
| \sa initDevice(), disconnect() |
| */ |
| |
| void QScreen::shutdownDevice() |
| { |
| #ifndef QT_NO_QWS_CURSOR |
| if (qt_screencursor) |
| qt_screencursor->hide(); |
| #endif |
| } |
| |
| extern bool qws_accel; //in qapplication_qws.cpp |
| |
| /*! |
| \fn PixelType QScreen::pixelType() const |
| |
| Returns the pixel storage format of the screen. |
| */ |
| |
| /*! |
| Returns the pixel format of the screen, or \c QImage::Format_Invalid |
| if the pixel format is not a supported image format. |
| |
| */ |
| QImage::Format QScreen::pixelFormat() const |
| { |
| return d_ptr->pixelFormat; |
| } |
| |
| /*! |
| Sets the screen's pixel format to \a format. |
| */ |
| void QScreen::setPixelFormat(QImage::Format format) |
| { |
| d_ptr->pixelFormat = format; |
| } |
| |
| |
| /*! |
| \fn int QScreen::alloc(unsigned int red, unsigned int green, unsigned int blue) |
| |
| Returns the index in the screen's palette which is the closest |
| match to the given RGB value (\a red, \a green, \a blue). |
| |
| Note that this function only apply in paletted modes like 8-bit, |
| i.e. in modes where only the palette indexes (and not the actual |
| color values) are stored in memory. |
| |
| \sa clut(), colorCount() |
| */ |
| |
| int QScreen::alloc(unsigned int r,unsigned int g,unsigned int b) |
| { |
| int ret = 0; |
| if (d == 8) { |
| if (grayscale) |
| return qGray(r, g, b); |
| |
| // First we look to see if we match a default color |
| const int pos = (r + 25) / 51 * 36 + (g + 25) / 51 * 6 + (b + 25) / 51; |
| if (pos < screencols && screenclut[pos] == qRgb(r, g, b)) { |
| return pos; |
| } |
| |
| // search for nearest color |
| unsigned int mindiff = 0xffffffff; |
| unsigned int diff; |
| int dr,dg,db; |
| |
| for (int loopc = 0; loopc < screencols; ++loopc) { |
| dr = qRed(screenclut[loopc]) - r; |
| dg = qGreen(screenclut[loopc]) - g; |
| db = qBlue(screenclut[loopc]) - b; |
| diff = dr*dr + dg*dg + db*db; |
| |
| if (diff < mindiff) { |
| ret = loopc; |
| if (!diff) |
| break; |
| mindiff = diff; |
| } |
| } |
| } else if (d == 4) { |
| ret = qGray(r, g, b) >> 4; |
| } else if (d == 1) { |
| ret = qGray(r, g, b) >= 128; |
| } else { |
| qFatal("cannot alloc %dbpp color", d); |
| } |
| |
| return ret; |
| } |
| |
| /*! |
| Saves the current state of the graphics card. |
| |
| For example, hardware screen drivers should reimplement the save() |
| and restore() functions to save and restore its registers, |
| enabling swintching between virtual consoles. |
| |
| Note that the default implementation does nothing. |
| |
| \sa restore() |
| */ |
| |
| void QScreen::save() |
| { |
| } |
| |
| /*! |
| Restores the previously saved state of the graphics card. |
| |
| For example, hardware screen drivers should reimplement the save() |
| and restore() functions to save and restore its registers, |
| enabling swintching between virtual consoles. |
| |
| Note that the default implementation does nothing. |
| |
| \sa save() |
| */ |
| |
| void QScreen::restore() |
| { |
| } |
| |
| void QScreen::blank(bool) |
| { |
| } |
| |
| /*! |
| \internal |
| */ |
| |
| void QScreen::set(unsigned int, unsigned int, unsigned int, unsigned int) |
| { |
| } |
| |
| /*! |
| \fn bool QScreen::supportsDepth(int depth) const |
| |
| Returns true if the screen supports the specified color \a depth; |
| otherwise returns false. |
| |
| \sa clut() |
| */ |
| |
| bool QScreen::supportsDepth(int d) const |
| { |
| if (false) { |
| //Just to simplify the ifdeffery |
| #ifdef QT_QWS_DEPTH_1 |
| } else if(d==1) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_4 |
| } else if(d==4) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_8 |
| } else if(d==8) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_16 |
| } else if(d==16) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_15 |
| } else if (d == 15) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_18 |
| } else if(d==18 || d==19) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_24 |
| } else if(d==24) { |
| return true; |
| #endif |
| #ifdef QT_QWS_DEPTH_32 |
| } else if(d==32) { |
| return true; |
| #endif |
| } |
| return false; |
| } |
| |
| /*! |
| \fn bool QScreen::onCard(const unsigned char *buffer) const |
| |
| Returns true if the specified \a buffer is within the graphics |
| card's memory; otherwise returns false (i.e. if it's in main RAM). |
| |
| \sa base(), totalSize() |
| */ |
| |
| bool QScreen::onCard(const unsigned char * p) const |
| { |
| long t=(unsigned long)p; |
| long bmin=(unsigned long)data; |
| if (t < bmin) |
| return false; |
| if(t >= bmin+mapsize) |
| return false; |
| return true; |
| } |
| |
| /*! |
| \fn bool QScreen::onCard(const unsigned char * buffer, ulong& offset) const |
| \overload |
| |
| If the specified \a buffer is within the graphics card's memory, |
| this function stores the offset from the start of graphics card |
| memory (in bytes), in the location specified by the \a offset |
| parameter. |
| */ |
| |
| bool QScreen::onCard(const unsigned char * p, ulong& offset) const |
| { |
| long t=(unsigned long)p; |
| long bmin=(unsigned long)data; |
| if (t < bmin) |
| return false; |
| long o = t - bmin; |
| if (o >= mapsize) |
| return false; |
| offset = o; |
| return true; |
| } |
| |
| /* |
| #if !defined(QT_NO_QWS_REPEATER) |
| { "Repeater", qt_get_screen_repeater, 0 }, |
| #endif |
| #if defined(QT_QWS_EE) |
| { "EE", qt_get_screen_ee, 0 }, |
| #endif |
| |
| */ |
| |
| /* |
| Given a display_id (number of the \l{Qt for Embedded Linux} server to connect to) |
| and a spec (e.g. Mach64:/dev/fb0) return a QScreen-descendant. |
| The QScreenDriverFactory is queried for a suitable driver and, if found, |
| asked to create a driver. |
| People writing new graphics drivers should either hook their own |
| QScreen-descendant into QScreenDriverFactory or use the QScreenDriverPlugin |
| to make a dynamically loadable driver. |
| */ |
| |
| Q_GUI_EXPORT QScreen* qt_get_screen(int display_id, const char *spec) |
| { |
| QString displaySpec = QString::fromAscii(spec); |
| QString driver = displaySpec; |
| int colon = displaySpec.indexOf(QLatin1Char(':')); |
| if (colon >= 0) |
| driver.truncate(colon); |
| driver = driver.trimmed(); |
| |
| bool foundDriver = false; |
| QString driverName = driver; |
| |
| QStringList driverList; |
| if (!driver.isEmpty()) |
| driverList << driver; |
| else |
| driverList = QScreenDriverFactory::keys(); |
| |
| for (int i = 0; i < driverList.size(); ++i) { |
| const QString driverName = driverList.at(i); |
| qt_screen = QScreenDriverFactory::create(driverName, display_id); |
| if (qt_screen) { |
| foundDriver = true; |
| if (qt_screen->connect(displaySpec)) { |
| return qt_screen; |
| } else { |
| delete qt_screen; |
| qt_screen = 0; |
| } |
| } |
| } |
| |
| if (driver.isNull()) |
| qFatal("No suitable driver found"); |
| else if (foundDriver) |
| qFatal("%s: driver cannot connect", driver.toLatin1().constData()); |
| else |
| qFatal("%s: driver not found", driver.toLatin1().constData()); |
| |
| return 0; |
| } |
| |
| #ifndef QT_NO_QWS_CURSOR |
| static void blendCursor(QImage *dest, const QImage &cursor, const QPoint &offset) |
| { |
| QRasterBuffer rb; |
| rb.prepare(dest); |
| |
| QSpanData spanData; |
| spanData.init(&rb, 0); |
| spanData.type = QSpanData::Texture; |
| spanData.initTexture(&cursor, 256); |
| spanData.dx = -offset.x(); |
| spanData.dy = -offset.y(); |
| if (!spanData.blend) |
| return; |
| |
| const QRect rect = QRect(offset, cursor.size()) |
| & QRect(QPoint(0, 0), dest->size()); |
| const int w = rect.width(); |
| const int h = rect.height(); |
| |
| QVarLengthArray<QT_FT_Span, 32> spans(h); |
| for (int i = 0; i < h; ++i) { |
| spans[i].x = rect.x(); |
| spans[i].len = w; |
| spans[i].y = rect.y() + i; |
| spans[i].coverage = 255; |
| } |
| spanData.blend(h, spans.constData(), &spanData); |
| } |
| #endif // QT_NO_QWS_CURSOR |
| |
| /*! |
| \fn void QScreen::exposeRegion(QRegion region, int windowIndex) |
| |
| This function is called by the \l{Qt for Embedded Linux} server whenever a |
| screen update is required. \a region is the area on the screen |
| that must be updated, and \a windowIndex is the index into |
| QWSServer::clientWindows() of the window that required the |
| update. QWSWindow::state() gives more information about the cause. |
| |
| The default implementation composes the |
| affected windows and paints the given \a region on screen by |
| calling the blit() and solidFill() functions |
| |
| This function can be reimplemented to perform composition in |
| hardware, or to perform transition effects. |
| For simpler hardware acceleration, or to interface with |
| this is typically done by reimplementing the blit() and |
| solidFill() functions instead. |
| |
| Note that there is no need to call this function explicitly. |
| |
| \sa blit(), solidFill(), blank() |
| */ |
| void QScreen::exposeRegion(QRegion r, int windowIndex) |
| { |
| r &= region(); |
| if (r.isEmpty()) |
| return; |
| |
| int changing = windowIndex; |
| // when we have just lowered a window, we have to expose all the windows below where the |
| // window used to be. |
| if (changing && qwsServer->clientWindows().at(changing)->state() == QWSWindow::Lowering) |
| changing = 0; |
| #ifdef QTOPIA_PERFTEST |
| static enum { PerfTestUnknown, PerfTestOn, PerfTestOff } perfTestState = PerfTestUnknown; |
| if(PerfTestUnknown == perfTestState) { |
| if(::getenv("QTOPIA_PERFTEST")) |
| perfTestState = PerfTestOn; |
| else |
| perfTestState = PerfTestOff; |
| } |
| if(PerfTestOn == perfTestState) { |
| QWSWindow *changed = qwsServer->clientWindows().at(changing); |
| if(!changed->client()->identity().isEmpty()) |
| qDebug() << "Performance : expose_region :" |
| << changed->client()->identity() |
| << r.boundingRect() << ": " |
| << qPrintable( QTime::currentTime().toString( "h:mm:ss.zzz" ) ); |
| } |
| #endif |
| |
| const QRect bounds = r.boundingRect(); |
| QRegion blendRegion; |
| QImage *blendBuffer = 0; |
| |
| #ifndef QT_NO_QWS_CURSOR |
| if (qt_screencursor && !qt_screencursor->isAccelerated()) { |
| blendRegion = r & qt_screencursor->boundingRect(); |
| } |
| #endif |
| compose(0, r, blendRegion, &blendBuffer, changing); |
| |
| if (blendBuffer && !blendBuffer->isNull()) { |
| const QPoint offset = blendRegion.boundingRect().topLeft(); |
| #ifndef QT_NO_QWS_CURSOR |
| if (qt_screencursor && !qt_screencursor->isAccelerated()) { |
| const QRect cursorRect = qt_screencursor->boundingRect(); |
| if (blendRegion.intersects(cursorRect)) { |
| blendCursor(blendBuffer, qt_screencursor->image(), |
| cursorRect.topLeft() - offset); |
| } |
| } |
| #endif // QT_NO_QWS_CURSOR |
| blit(*blendBuffer, offset, blendRegion); |
| delete blendBuffer; |
| } |
| |
| if (r.rectCount() == 1) { |
| setDirty(r.boundingRect()); |
| } else { |
| const QVector<QRect> rects = r.rects(); |
| for (int i = 0; i < rects.size(); ++i) |
| setDirty(rects.at(i)); |
| } |
| } |
| |
| /*! |
| \fn void QScreen::blit(const QImage &image, const QPoint &topLeft, const QRegion ®ion) |
| |
| Copies the given \a region in the given \a image to the point |
| specified by \a topLeft using device coordinates. |
| |
| This function is called from the exposeRegion() function; it is |
| not intended to be called explicitly. |
| |
| Reimplement this function to make use of \l{Adding an Accelerated |
| Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that |
| this function must be reimplemented if the framebuffer format is |
| not supported by \l{Qt for Embedded Linux} (See the |
| \l{Qt for Embedded Linux Display Management}{Display Management} |
| documentation for more details). |
| |
| \sa exposeRegion(), solidFill(), blank() |
| */ |
| void QScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®) |
| { |
| const QRect bound = (region() & QRect(topLeft, img.size())).boundingRect(); |
| QWSDisplay::grab(); |
| d_ptr->blit(this, img, topLeft - offset(), |
| (reg & bound).translated(-topLeft)); |
| QWSDisplay::ungrab(); |
| } |
| |
| #ifdef QT_QWS_CLIENTBLIT |
| /*! |
| Returns true if this screen driver supports calling QScreen::blit() and |
| QScreen::setDirty() directly from non-server applications, otherwise returns |
| false. |
| |
| If available, this is used to optimize the performance of non-occluded, opaque |
| client windows by removing the server round trip when they are updated. |
| |
| \sa setSupportsBlitInClients() |
| */ |
| bool QScreen::supportsBlitInClients() const |
| { |
| return d_ptr->supportsBlitInClients; |
| } |
| |
| /*! |
| If \a supported, the screen driver is marked as supporting blitting directly |
| from non-server applications. |
| |
| \sa supportsBlitInClients() |
| */ |
| void QScreen::setSupportsBlitInClients(bool supported) |
| { |
| d_ptr->supportsBlitInClients = supported; |
| } |
| #endif |
| |
| /*! |
| \internal |
| */ |
| |
| void QScreen::blit(QWSWindow *win, const QRegion &clip) |
| { |
| QWSWindowSurface *surface = win->windowSurface(); |
| if (!surface) |
| return; |
| |
| const QImage &img = surface->image(); |
| if (img.isNull()) |
| return; |
| |
| const QRegion rgn = clip & win->paintedRegion(); |
| if (rgn.isEmpty()) |
| return; |
| |
| surface->lock(); |
| blit(img, win->requestedRegion().boundingRect().topLeft(), rgn); |
| surface->unlock(); |
| } |
| |
| struct fill_data { |
| quint32 color; |
| uchar *data; |
| int lineStep; |
| int x; |
| int y; |
| int w; |
| int h; |
| }; |
| |
| /*! |
| Fills the given \a region of the screen with the specified \a |
| color. |
| |
| This function is called from the exposeRegion() function; it is |
| not intended to be called explicitly. |
| |
| Reimplement this function to make use of \l{Adding an Accelerated |
| Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that |
| this function must be reimplemented if the framebuffer format is |
| not supported by \l{Qt for Embedded Linux} (See the |
| \l{Qt for Embedded Linux Display Management}{Display Management} |
| documentation for more details). |
| |
| \sa exposeRegion(), blit(), blank() |
| */ |
| // the base class implementation works in device coordinates, so that transformed drivers can use it |
| void QScreen::solidFill(const QColor &color, const QRegion ®ion) |
| { |
| QWSDisplay::grab(); |
| d_ptr->solidFill(this, color, |
| region.translated(-offset()) & QRect(0, 0, dw, dh)); |
| QWSDisplay::ungrab(); |
| } |
| |
| /*! |
| \since 4.2 |
| |
| Creates and returns a new window surface matching the given \a |
| key. |
| |
| The server application will call this function whenever it needs |
| to create a server side representation of a window, e.g. when |
| copying the content of memory to the screen using the screen |
| driver. |
| |
| Note that this function must be reimplemented when adding an |
| accelerated graphics driver. See the |
| \l{Adding an Accelerated Graphics Driver to Qt for Embedded Linux} |
| {Adding an Accelerated Graphics Driver} documentation for details. |
| |
| \sa {Qt for Embedded Linux Architecture} |
| */ |
| QWSWindowSurface* QScreen::createSurface(const QString &key) const |
| { |
| #ifndef QT_NO_PAINTONSCREEN |
| if (key == QLatin1String("OnScreen")) |
| return new QWSOnScreenSurface; |
| else |
| #endif |
| if (key == QLatin1String("mem")) |
| return new QWSLocalMemSurface; |
| #ifndef QT_NO_QWS_MULTIPROCESS |
| else if (key == QLatin1String("shm")) |
| return new QWSSharedMemSurface; |
| #endif |
| #ifndef QT_NO_PAINT_DEBUG |
| else if (key == QLatin1String("Yellow")) |
| return new QWSYellowSurface; |
| #endif |
| #ifndef QT_NO_DIRECTPAINTER |
| else if (key == QLatin1String("DirectPainter")) |
| return new QWSDirectPainterSurface; |
| #endif |
| |
| return 0; |
| } |
| |
| #ifndef QT_NO_PAINTONSCREEN |
| bool QScreen::isWidgetPaintOnScreen(const QWidget *w) |
| { |
| static int doOnScreen = -1; |
| if (doOnScreen == -1) { |
| const QByteArray env = qgetenv("QT_ONSCREEN_PAINT"); |
| if (env == "force") |
| doOnScreen = 2; |
| else |
| doOnScreen = (env.toInt() > 0 ? 1 : 0); |
| } |
| |
| if (doOnScreen == 2) // force |
| return true; |
| |
| if (doOnScreen == 0 && !w->testAttribute(Qt::WA_PaintOnScreen)) |
| return false; |
| |
| return w->d_func()->isOpaque; |
| } |
| #endif |
| |
| /*! |
| \overload |
| |
| Creates and returns a new window surface for the given \a widget. |
| */ |
| QWSWindowSurface* QScreen::createSurface(QWidget *widget) const |
| { |
| #ifndef QT_NO_PAINTONSCREEN |
| if (isWidgetPaintOnScreen(widget) && base()) |
| return new QWSOnScreenSurface(widget); |
| else |
| #endif |
| if (QApplication::type() == QApplication::GuiServer) |
| return new QWSLocalMemSurface(widget); |
| #ifndef QT_NO_QWS_MULTIPROCESS |
| else |
| return new QWSSharedMemSurface(widget); |
| #endif |
| |
| return 0; |
| } |
| |
| void QScreen::compose(int level, const QRegion &exposed, QRegion &blend, |
| QImage **blendbuffer, int changing_level) |
| { |
| QRect exposed_bounds = exposed.boundingRect(); |
| QWSWindow *win = 0; |
| do { |
| win = qwsServer->clientWindows().value(level); // null is background |
| ++level; |
| } while (win && !win->paintedRegion().boundingRect().intersects(exposed_bounds)); |
| |
| QWSWindowSurface *surface = (win ? win->windowSurface() : 0); |
| bool above_changing = level <= changing_level; // 0 is topmost |
| |
| QRegion exposedBelow = exposed; |
| bool opaque = true; |
| |
| if (win) { |
| opaque = win->isOpaque() || !surface->isBuffered(); |
| if (opaque) { |
| exposedBelow -= win->paintedRegion(); |
| if (above_changing || !surface->isBuffered()) |
| blend -= exposed & win->paintedRegion(); |
| } else { |
| blend += exposed & win->paintedRegion(); |
| } |
| } |
| if (win && !exposedBelow.isEmpty()) { |
| compose(level, exposedBelow, blend, blendbuffer, changing_level); |
| } else { |
| QSize blendSize = blend.boundingRect().size(); |
| if (!blendSize.isNull()) { |
| *blendbuffer = new QImage(blendSize, d_ptr->preferredImageFormat()); |
| } |
| } |
| |
| const QRegion blitRegion = exposed - blend; |
| if (!win) |
| paintBackground(blitRegion); |
| else if (!above_changing && surface->isBuffered()) |
| blit(win, blitRegion); |
| |
| QRegion blendRegion = exposed & blend; |
| |
| if (win) |
| blendRegion &= win->paintedRegion(); |
| if (!blendRegion.isEmpty()) { |
| |
| QPoint off = blend.boundingRect().topLeft(); |
| |
| QRasterBuffer rb; |
| rb.prepare(*blendbuffer); |
| QSpanData spanData; |
| spanData.init(&rb, 0); |
| if (!win) { |
| const QImage::Format format = (*blendbuffer)->format(); |
| switch (format) { |
| case QImage::Format_ARGB32_Premultiplied: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB8565_Premultiplied: |
| case QImage::Format_ARGB8555_Premultiplied: |
| case QImage::Format_ARGB6666_Premultiplied: |
| case QImage::Format_ARGB4444_Premultiplied: |
| spanData.rasterBuffer->compositionMode = QPainter::CompositionMode_Source; |
| break; |
| default: |
| break; |
| } |
| spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_Source); |
| spanData.dx = off.x(); |
| spanData.dy = off.y(); |
| } else if (!surface->isBuffered()) { |
| return; |
| } else { |
| const QImage &img = surface->image(); |
| QPoint winoff = off - win->requestedRegion().boundingRect().topLeft(); |
| // convert win->opacity() from scale [0..255] to [0..256] |
| int const_alpha = win->opacity(); |
| const_alpha += (const_alpha >> 7); |
| spanData.type = QSpanData::Texture; |
| spanData.initTexture(&img, const_alpha); |
| spanData.dx = winoff.x(); |
| spanData.dy = winoff.y(); |
| } |
| if (!spanData.blend) |
| return; |
| |
| if (surface) |
| surface->lock(); |
| const QVector<QRect> rects = blendRegion.rects(); |
| const int nspans = 256; |
| QT_FT_Span spans[nspans]; |
| for (int i = 0; i < rects.size(); ++i) { |
| int y = rects.at(i).y() - off.y(); |
| int ye = y + rects.at(i).height(); |
| int x = rects.at(i).x() - off.x(); |
| int len = rects.at(i).width(); |
| while (y < ye) { |
| int n = qMin(nspans, ye - y); |
| int i = 0; |
| while (i < n) { |
| spans[i].x = x; |
| spans[i].len = len; |
| spans[i].y = y + i; |
| spans[i].coverage = 255; |
| ++i; |
| } |
| spanData.blend(n, spans, &spanData); |
| y += n; |
| } |
| } |
| if (surface) |
| surface->unlock(); |
| } |
| } |
| |
| void QScreen::paintBackground(const QRegion &r) |
| { |
| const QBrush &bg = qwsServer->backgroundBrush(); |
| Qt::BrushStyle bs = bg.style(); |
| if (bs == Qt::NoBrush || r.isEmpty()) |
| return; |
| |
| if (bs == Qt::SolidPattern) { |
| solidFill(bg.color(), r); |
| } else { |
| const QRect br = r.boundingRect(); |
| QImage img(br.size(), d_ptr->preferredImageFormat()); |
| QPoint off = br.topLeft(); |
| QRasterBuffer rb; |
| rb.prepare(&img); |
| QSpanData spanData; |
| spanData.init(&rb, 0); |
| spanData.setup(bg, 256, QPainter::CompositionMode_Source); |
| spanData.dx = off.x(); |
| spanData.dy = off.y(); |
| Q_ASSERT(spanData.blend); |
| |
| const QVector<QRect> rects = r.rects(); |
| const int nspans = 256; |
| QT_FT_Span spans[nspans]; |
| for (int i = 0; i < rects.size(); ++i) { |
| int y = rects.at(i).y() - off.y(); |
| int ye = y + rects.at(i).height(); |
| int x = rects.at(i).x() - off.x(); |
| int len = rects.at(i).width(); |
| while (y < ye) { |
| int n = qMin(nspans, ye - y); |
| int i = 0; |
| while (i < n) { |
| spans[i].x = x; |
| spans[i].len = len; |
| spans[i].y = y + i; |
| spans[i].coverage = 255; |
| ++i; |
| } |
| spanData.blend(n, spans, &spanData); |
| y += n; |
| } |
| } |
| blit(img, br.topLeft(), r); |
| } |
| } |
| |
| /*! |
| \fn virtual int QScreen::sharedRamSize(void *) |
| |
| \internal |
| */ |
| |
| /*! |
| \fn QScreen::setDirty(const QRect& rectangle) |
| |
| Marks the given \a rectangle as dirty. |
| |
| Note that the default implementation does nothing; reimplement |
| this function to indicate that the given \a rectangle has been |
| altered. |
| */ |
| |
| void QScreen::setDirty(const QRect&) |
| { |
| } |
| |
| /*! |
| \fn QScreen::isTransformed() const |
| |
| Returns true if the screen is transformed (for instance, rotated |
| 90 degrees); otherwise returns false. |
| |
| \sa transformOrientation(), isInterlaced() |
| */ |
| |
| bool QScreen::isTransformed() const |
| { |
| return false; |
| } |
| |
| /*! |
| \fn QScreen::isInterlaced() const |
| |
| Returns true if the display is interlaced (i.e. is displaying |
| images progressively like a television screen); otherwise returns |
| false. |
| |
| If the display is interlaced, the drawing is altered to look |
| better. |
| |
| \sa isTransformed(), linestep() |
| */ |
| |
| bool QScreen::isInterlaced() const |
| { |
| return false;//qws_screen_is_interlaced;; |
| } |
| |
| /*! |
| \fn QScreen::mapToDevice(const QSize &size) const |
| |
| Maps the given \a size from the coordinate space used by the |
| application to the framebuffer coordinate system. Note that the |
| default implementation simply returns the given \a size as it is. |
| |
| Reimplement this function to use the given device's coordinate |
| system when mapping. |
| |
| \sa mapFromDevice() |
| */ |
| |
| QSize QScreen::mapToDevice(const QSize &s) const |
| { |
| return s; |
| } |
| |
| /*! |
| \fn QScreen::mapFromDevice(const QSize &size) const |
| |
| Maps the given \a size from the framebuffer coordinate system to |
| the coordinate space used by the application. Note that the |
| default implementation simply returns the given \a size as it is. |
| |
| Reimplement this function to use the given device's coordinate |
| system when mapping. |
| |
| \sa mapToDevice() |
| */ |
| |
| QSize QScreen::mapFromDevice(const QSize &s) const |
| { |
| return s; |
| } |
| |
| /*! |
| \fn QScreen::mapToDevice(const QPoint &point, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a point from the coordinate space used by the |
| application to the framebuffer coordinate system, passing the |
| device's \a screenSize as argument. Note that the default |
| implementation returns the given \a point as it is. |
| */ |
| |
| QPoint QScreen::mapToDevice(const QPoint &p, const QSize &) const |
| { |
| return p; |
| } |
| |
| /*! |
| \fn QScreen::mapFromDevice(const QPoint &point, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a point from the framebuffer coordinate system to |
| the coordinate space used by the application, passing the device's |
| \a screenSize as argument. Note that the default implementation |
| simply returns the given \a point as it is. |
| */ |
| |
| QPoint QScreen::mapFromDevice(const QPoint &p, const QSize &) const |
| { |
| return p; |
| } |
| |
| /*! |
| \fn QScreen::mapToDevice(const QRect &rectangle, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a rectangle from the coordinate space used by the |
| application to the framebuffer coordinate system, passing the |
| device's \a screenSize as argument. Note that the default |
| implementation returns the given \a rectangle as it is. |
| */ |
| |
| QRect QScreen::mapToDevice(const QRect &r, const QSize &) const |
| { |
| return r; |
| } |
| |
| /*! |
| \fn QScreen::mapFromDevice(const QRect &rectangle, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a rectangle from the framebuffer coordinate system to |
| the coordinate space used by the application, passing the device's |
| \a screenSize as argument. Note that the default implementation |
| simply returns the given \a rectangle as it is. |
| */ |
| |
| QRect QScreen::mapFromDevice(const QRect &r, const QSize &) const |
| { |
| return r; |
| } |
| |
| /*! |
| \fn QScreen::mapToDevice(const QImage &image) const |
| \overload |
| |
| Maps the given \a image from the coordinate space used by the |
| application to the framebuffer coordinate system. Note that the |
| default implementation returns the given \a image as it is. |
| */ |
| |
| QImage QScreen::mapToDevice(const QImage &i) const |
| { |
| return i; |
| } |
| |
| /*! |
| \fn QScreen::mapFromDevice(const QImage &image) const |
| \overload |
| |
| Maps the given \a image from the framebuffer coordinate system to |
| the coordinate space used by the application. Note that the |
| default implementation simply returns the given \a image as it is. |
| */ |
| |
| QImage QScreen::mapFromDevice(const QImage &i) const |
| { |
| return i; |
| } |
| |
| /*! |
| \fn QScreen::mapToDevice(const QRegion ®ion, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a region from the coordinate space used by the |
| application to the framebuffer coordinate system, passing the |
| device's \a screenSize as argument. Note that the default |
| implementation returns the given \a region as it is. |
| */ |
| |
| QRegion QScreen::mapToDevice(const QRegion &r, const QSize &) const |
| { |
| return r; |
| } |
| |
| /*! |
| \fn QScreen::mapFromDevice(const QRegion ®ion, const QSize &screenSize) const |
| \overload |
| |
| Maps the given \a region from the framebuffer coordinate system to |
| the coordinate space used by the application, passing the device's |
| \a screenSize as argument. Note that the default implementation |
| simply returns the given \a region as it is. |
| */ |
| |
| QRegion QScreen::mapFromDevice(const QRegion &r, const QSize &) const |
| { |
| return r; |
| } |
| |
| /*! |
| \fn QScreen::transformOrientation() const |
| |
| Returns the current rotation as an integer value. |
| |
| Note that the default implementation returns 0; reimplement this |
| function to override this value. |
| |
| \sa isTransformed() |
| */ |
| |
| int QScreen::transformOrientation() const |
| { |
| return 0; |
| } |
| |
| int QScreen::pixmapDepth() const |
| { |
| return depth(); |
| } |
| |
| /*! |
| \internal |
| */ |
| int QScreen::memoryNeeded(const QString&) |
| { |
| return 0; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QScreen::haltUpdates() |
| { |
| } |
| |
| /*! |
| \internal |
| */ |
| void QScreen::resumeUpdates() |
| { |
| } |
| |
| /*! |
| \fn QRegion QScreen::region() const |
| \since 4.2 |
| |
| Returns the region covered by this screen driver. |
| |
| \sa base(), screenSize() |
| */ |
| |
| /*! |
| \internal |
| */ |
| void QScreen::setOffset(const QPoint &p) |
| { |
| d_ptr->offset = p; |
| } |
| |
| /*! |
| \since 4.2 |
| |
| Returns the logical offset of the screen, i.e., the offset between |
| (0,0) in screen coordinates and the application coordinate system. |
| */ |
| QPoint QScreen::offset() const |
| { |
| return d_ptr->offset; |
| } |
| |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| void QScreen::setFrameBufferLittleEndian(bool littleEndian) |
| { |
| d_ptr->fb_is_littleEndian = littleEndian; |
| } |
| |
| bool QScreen::frameBufferLittleEndian() const |
| { |
| return d_ptr->fb_is_littleEndian; |
| } |
| #endif |
| |
| /*! |
| \fn int QScreen::subScreenIndexAt(const QPoint &position) const |
| \since 4.2 |
| |
| Returns the index of the subscreen at the given \a position; |
| returns -1 if no screen is found. |
| |
| The index identifies the subscreen in the list of pointers |
| returned by the subScreens() function. |
| |
| \sa instance(), subScreens() |
| */ |
| int QScreen::subScreenIndexAt(const QPoint &p) const |
| { |
| const QList<QScreen*> screens = subScreens(); |
| const int n = screens.count(); |
| for (int i = 0; i < n; ++i) { |
| if (screens.at(i)->region().contains(p)) |
| return i; |
| } |
| |
| return -1; |
| } |
| |
| #if 0 |
| #ifdef QT_LOADABLE_MODULES |
| #include <dlfcn.h> |
| |
| // ### needs update after driver init changes |
| |
| static QScreen * qt_dodriver(char * driver,char * a,unsigned char * b) |
| |
| { |
| char buf[200]; |
| strcpy(buf,"/etc/qws/drivers/"); |
| qstrcpy(buf+17,driver); |
| qDebug("Attempting driver %s",driver); |
| |
| void * handle; |
| handle=dlopen(buf,RTLD_LAZY); |
| if(handle==0) { |
| qFatal("Module load error"); |
| } |
| QScreen *(*qt_get_screen_func)(char *,unsigned char *); |
| qt_get_screen_func=dlsym(handle,"qt_get_screen"); |
| if(qt_get_screen_func==0) { |
| qFatal("Couldn't get symbol"); |
| } |
| QScreen * ret=qt_get_screen_func(a,b); |
| return ret; |
| } |
| |
| static QScreen * qt_do_entry(char * entry) |
| { |
| unsigned char config[256]; |
| |
| FILE * f=fopen(entry,"r"); |
| if(!f) { |
| return 0; |
| } |
| |
| int r=fread(config,256,1,f); |
| if(r<1) |
| return 0; |
| |
| fclose(f); |
| |
| unsigned short vendorid=*((unsigned short int *)config); |
| unsigned short deviceid=*(((unsigned short int *)config)+1); |
| if(config[0xb]!=3) |
| return 0; |
| |
| if(vendorid==0x1002) { |
| if(deviceid==0x4c4d) { |
| qDebug("Compaq Armada/IBM Thinkpad's Mach64 card"); |
| return qt_dodriver("mach64.so",entry,config); |
| } else if(deviceid==0x4742) { |
| qDebug("Desktop Rage Pro Mach64 card"); |
| return qt_dodriver("mach64.so",entry,config); |
| } else { |
| qDebug("Unrecognised ATI card id %x",deviceid); |
| return 0; |
| } |
| } else { |
| qDebug("Unrecognised vendor"); |
| } |
| return 0; |
| } |
| |
| extern bool qws_accel; |
| |
| /// ** NOT SUPPPORTED ** |
| |
| QScreen * qt_probe_bus() |
| { |
| if(!qws_accel) { |
| return qt_dodriver("unaccel.so",0,0); |
| } |
| |
| QT_DIR *dirptr = QT_OPENDIR("/proc/bus/pci"); |
| if(!dirptr) |
| return qt_dodriver("unaccel.so",0,0); |
| QT_DIR * dirptr2; |
| QT_DIRENT *cards; |
| |
| QT_DIRENT *busses = QT_READDIR(dirptr); |
| |
| while(busses) { |
| if(busses->d_name[0]!='.') { |
| char buf[100]; |
| strcpy(buf,"/proc/bus/pci/"); |
| qstrcpy(buf+14,busses->d_name); |
| int p=strlen(buf); |
| dirptr2 = QT_OPENDIR(buf); |
| if(dirptr2) { |
| cards = QT_READDIR(dirptr2); |
| while(cards) { |
| if(cards->d_name[0]!='.') { |
| buf[p]='/'; |
| qstrcpy(buf+p+1,cards->d_name); |
| QScreen * ret=qt_do_entry(buf); |
| if(ret) |
| return ret; |
| } |
| cards = QT_READDIR(dirptr2); |
| } |
| QT_CLOSEDIR(dirptr2); |
| } |
| } |
| busses = QT_READDIR(dirptr); |
| } |
| QT_CLOSEDIR(dirptr); |
| |
| return qt_dodriver("unaccel.so",0,0); |
| } |
| |
| #else |
| |
| char *qt_qws_hardcoded_slot = "/proc/bus/pci/01/00.0"; |
| |
| const unsigned char* qt_probe_bus() |
| { |
| const char * slot; |
| slot=::getenv("QWS_CARD_SLOT"); |
| if(!slot) |
| slot=qt_qws_hardcoded_slot; |
| if (slot) { |
| static unsigned char config[256]; |
| FILE * f=fopen(slot,"r"); |
| if(!f) { |
| qDebug("Open failure for %s",slot); |
| slot=0; |
| } else { |
| int r=fread((char*)config,256,1,f); |
| fclose(f); |
| if(r<1) { |
| qDebug("Read failure"); |
| return 0; |
| } else { |
| return config; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| #endif |
| |
| #endif // 0 |
| |
| /*! |
| \internal |
| \since 4.4 |
| */ |
| void QScreen::setPixmapDataFactory(QPixmapDataFactory *factory) |
| { |
| static bool shownWarning = false; |
| if (!shownWarning) { |
| qWarning("QScreen::setPixmapDataFactory() is deprecated - use setGraphicsSystem() instead"); |
| shownWarning = true; |
| } |
| |
| d_ptr->pixmapFactory = factory; |
| } |
| |
| /*! |
| \internal |
| \since 4.4 |
| */ |
| QPixmapDataFactory* QScreen::pixmapDataFactory() const |
| { |
| return d_ptr->pixmapFactory; |
| } |
| |
| /*! |
| \internal |
| \since 4.5 |
| */ |
| void QScreen::setGraphicsSystem(QGraphicsSystem* system) |
| { |
| d_ptr->graphicsSystem = system; |
| } |
| |
| /*! |
| \internal |
| \since 4.5 |
| */ |
| QGraphicsSystem* QScreen::graphicsSystem() const |
| { |
| return d_ptr->graphicsSystem; |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Returns the class identifier for the screen object. |
| */ |
| QScreen::ClassId QScreen::classId() const |
| { |
| return static_cast<ClassId>(d_ptr->classId); |
| } |
| |
| QT_END_NAMESPACE |