/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, 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.0, 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. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #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 #include #include #include #include #include #include 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 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 static void solidFill_template(QScreen *screen, const QColor &color, const QRegion ®ion) { T *dest = reinterpret_cast(screen->base()); const T c = qt_colorConvert(color.rgba(), 0); const int stride = screen->linestep(); const QVector 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(screen->base()); const quint32 c = qt_convertToRgb(color.rgba()); const int stride = screen->linestep(); const QVector 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(screen->base()); const quint16 c = qt_convertToRgb(color.rgba()); const int stride = screen->linestep(); const QVector 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(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(screen->base()); const quint8 c = qGray(color.rgba()) >> 4; const quint8 c8 = (c << 4) | c; const int stride = screen->linestep(); const QVector 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(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(screen->base()); const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff; const int stride = screen->linestep(); const QVector 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; else screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_24 case 24: if (screen->pixelType() == QScreen::NormalPixel) screen->d_ptr->solidFill = solidFill_template; else screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_18 case 18: screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_16 case 16: if (screen->pixelType() == QScreen::NormalPixel) screen->d_ptr->solidFill = solidFill_template; else screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_15 case 15: if (screen->pixelType() == QScreen::NormalPixel) screen->d_ptr->solidFill = solidFill_template; else screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_12 case 12: screen->d_ptr->solidFill = solidFill_template; break; #endif #ifdef QT_QWS_DEPTH_8 case 8: screen->d_ptr->solidFill = solidFill_template; 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 static void blit_template(QScreen *screen, const QImage &image, const QPoint &topLeft, const QRegion ®ion) { DST *dest = reinterpret_cast(screen->base()); const int screenStride = screen->linestep(); const int imageStride = image.bytesPerLine(); if (region.numRects() == 1) { const QRect r = region.boundingRect(); const SRC *src = reinterpret_cast(image.scanLine(r.y())) + r.x(); qt_rectconvert(dest, src, r.x() + topLeft.x(), r.y() + topLeft.y(), r.width(), r.height(), screenStride, imageStride); } else { const QVector rects = region.rects(); for (int i = 0; i < rects.size(); ++i) { const QRect r = rects.at(i); const SRC *src = reinterpret_cast(image.scanLine(r.y())) + r.x(); qt_rectconvert(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(screen, image, topLeft, region); return; #ifdef QT_QWS_DEPTH_16 case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB888: blit_template(screen, image, topLeft, region); return; #ifdef QT_QWS_DEPTH_16 case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB888: blit_template(screen, image, topLeft, region); return; #ifdef QT_QWS_DEPTH_16 case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB666: blit_template(screen, image, topLeft, region); return; #ifdef QT_QWS_DEPTH_16 case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB555: blit_template(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(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(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(screen, image, topLeft, region); return; case QImage::Format_RGB444: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(screen, image, topLeft, region); return; case QImage::Format_ARGB4444_Premultiplied: blit_template(screen, image, topLeft, region); return; case QImage::Format_RGB444: blit_template(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 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 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(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++); ++dest8; } if (count8) { int n = count8; switch (width8 & 0x03) // duff's device { case 0: do { *dest8++ = qt_convertToGray4(src[0]) << 4 | qt_convertToGray4(src[1]); src += 2; case 3: *dest8++ = qt_convertToGray4(src[0]) << 4 | qt_convertToGray4(src[1]); src += 2; case 2: *dest8++ = qt_convertToGray4(src[0]) << 4 | qt_convertToGray4(src[1]); src += 2; case 1: *dest8++ = qt_convertToGray4(src[0]) << 4 | qt_convertToGray4(src[1]); src += 2; } while (--n > 0); } } if (doTail) *dest8 = qt_convertToGray4(*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(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(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(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(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(screen, image, topLeft, region); return; case QImage::Format_RGB444: blit_template(screen, image, topLeft, region); return; case QImage::Format_ARGB4444_Premultiplied: blit_template(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 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(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 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(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++) << i; *dest8++ = d; } for (int i = 0; i < width8; ++i) { *dest8 = (qt_convertToMono(src[0]) << 7) | (qt_convertToMono(src[1]) << 6) | (qt_convertToMono(src[2]) << 5) | (qt_convertToMono(src[3]) << 4) | (qt_convertToMono(src[4]) << 3) | (qt_convertToMono(src[5]) << 2) | (qt_convertToMono(src[6]) << 1) | (qt_convertToMono(src[7])); src += 8; ++dest8; } if (doTail) { quint8 d = *dest8 & tailMask; switch (tailWidth) { case 7: d |= qt_convertToMono(src[6]) << 1; case 6: d |= qt_convertToMono(src[5]) << 2; case 5: d |= qt_convertToMono(src[4]) << 3; case 4: d |= qt_convertToMono(src[3]) << 4; case 3: d |= qt_convertToMono(src[2]) << 5; case 2: d |= qt_convertToMono(src[1]) << 6; case 1: d |= qt_convertToMono(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(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(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(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(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(screen, image, topLeft, region); return; case QImage::Format_RGB444: blit_template(screen, image, topLeft, region); return; case QImage::Format_ARGB4444_Premultiplied: blit_template(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(screen, image, topLeft, region); return; case QImage::Format_RGB16: blit_template(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; 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; 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; 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 numCols() 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::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 coonnect 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(), numCols() */ /*! \fn int QScreen::numCols() 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(), numCols() */ 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 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) { 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.numRects() == 1) { setDirty(r.boundingRect()); } else { const QVector 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_SourceOver); 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 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 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 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 // ### 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); } DIR * dirptr=opendir("/proc/bus/pci"); if(!dirptr) return qt_dodriver("unaccel.so",0,0); DIR * dirptr2; dirent * cards; dirent * busses=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=opendir(buf); if(dirptr2) { cards=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=readdir(dirptr2); } closedir(dirptr2); } } busses=readdir(dirptr); } 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(d_ptr->classId); } QT_END_NAMESPACE