1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qplatformdefs.h"
43 #include "qscreen_qws.h"
44 
45 #include "qcolormap.h"
46 #include "qscreendriverfactory_qws.h"
47 #include "qwindowsystem_qws.h"
48 #include "qwidget.h"
49 #include "qcolor.h"
50 #include "qpixmap.h"
51 #include "qvarlengtharray.h"
52 #include "qwsdisplay_qws.h"
53 #include "qpainter.h"
54 #include <private/qdrawhelper_p.h>
55 #include <private/qpaintengine_raster_p.h>
56 #include <private/qpixmap_raster_p.h>
57 #include <private/qwindowsurface_qws_p.h>
58 #include <private/qpainter_p.h>
59 #include <private/qwidget_p.h>
60 #include <private/qgraphicssystem_qws_p.h>
61 
62 QT_BEGIN_NAMESPACE
63 
64 // #define QT_USE_MEMCPY_DUFF
65 
66 #ifndef QT_NO_QWS_CURSOR
67 Q_GUI_EXPORT QScreenCursor * qt_screencursor = 0;
68 #endif
69 Q_GUI_EXPORT QScreen * qt_screen = 0;
70 
71 ClearCacheFunc QScreen::clearCacheFunc = 0;
72 
73 #ifndef QT_NO_QWS_CURSOR
74 /*!
75     \class QScreenCursor
76     \ingroup qws
77 
78     \brief The QScreenCursor class is a base class for screen cursors
79     in Qt for Embedded Linux.
80 
81     Note that this class is non-portable, and that it is only
82     available in \l{Qt for Embedded Linux}.
83 
84     QScreenCursor implements a software cursor, but can be subclassed
85     to support hardware cursors as well. When deriving from the
86     QScreenCursor class it is important to maintain the cursor's
87     image, position, hot spot (the point within the cursor's image
88     that will be the position of the associated mouse events) and
89     visibility as well as informing whether it is hardware accelerated
90     or not.
91 
92     Note that there may only be one screen cursor at a time. Use the
93     static instance() function to retrieve a pointer to the current
94     screen cursor. Typically, the cursor is constructed by the QScreen
95     class or one of its descendants when it is initializing the
96     device; the QScreenCursor class should never be instantiated
97     explicitly.
98 
99     Use the move() function to change the position of the cursor, and
100     the set() function to alter its image or its hot spot. In
101     addition, you can find out whether the cursor is accelerated or
102     not, using the isAccelerated() function, and the boundingRect()
103     function returns the cursor's bounding rectangle.
104 
105     The cursor's appearance can be controlled using the isVisible(),
106     hide() and show() functions; alternatively the QWSServer class
107     provides some means of controlling the cursor's appearance using
108     the QWSServer::isCursorVisible() and QWSServer::setCursorVisible()
109     functions.
110 
111     \sa QScreen, QWSServer
112 */
113 
114 /*!
115     \fn static QScreenCursor* QScreenCursor::instance()
116     \since 4.2
117 
118     Returns a pointer to the application's unique screen cursor.
119 */
120 
121 /*!
122     Constructs a screen cursor
123 */
QScreenCursor()124 QScreenCursor::QScreenCursor()
125 {
126     pos = QPoint(qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2);
127     size = QSize(0,0);
128     enable = true;
129     hwaccel = false;
130     supportsAlpha = true;
131 }
132 
133 /*!
134     Destroys the screen cursor.
135 */
~QScreenCursor()136 QScreenCursor::~QScreenCursor()
137 {
138 }
139 
140 /*!
141     Hides the cursor from the screen.
142 
143     \sa show()
144 */
hide()145 void QScreenCursor::hide()
146 {
147     if (enable) {
148         enable = false;
149         if (!hwaccel)
150             qt_screen->exposeRegion(boundingRect(), 0);
151     }
152 }
153 
154 /*!
155     Shows the mouse cursor.
156 
157     \sa hide()
158 */
show()159 void QScreenCursor::show()
160 {
161     if (!enable) {
162         enable = true;
163         if (!hwaccel)
164             qt_screen->exposeRegion(boundingRect(), 0);
165     }
166 }
167 
168 /*!
169     Sets the cursor's image to be the given \a image.
170 
171     The \a hotx and \a hoty parameters define the cursor's hot spot,
172     i.e., the point within the cursor's image that will be the
173     position of the associated mouse events.
174 
175     \sa move()
176 */
set(const QImage & image,int hotx,int hoty)177 void QScreenCursor::set(const QImage &image, int hotx, int hoty)
178 {
179     const QRect r = boundingRect();
180 
181     hotspot = QPoint(hotx, hoty);
182     // These are in almost all cases the fastest formats to blend
183     QImage::Format f;
184     switch (qt_screen->depth()) {
185     case 12:
186         f = QImage::Format_ARGB4444_Premultiplied;
187         break;
188     case 15:
189         f =  QImage::Format_ARGB8555_Premultiplied;
190         break;
191     case 16:
192         f = QImage::Format_ARGB8565_Premultiplied;
193         break;
194     case 18:
195         f = QImage::Format_ARGB6666_Premultiplied;
196         break;
197     default:
198         f =  QImage::Format_ARGB32_Premultiplied;
199     }
200 
201     cursor = image.convertToFormat(f);
202 
203     size = image.size();
204 
205     if (enable && !hwaccel)
206         qt_screen->exposeRegion(r | boundingRect(), 0);
207 }
208 
209 /*!
210     Moves the mouse cursor to the given position, i.e., (\a x, \a y).
211 
212     Note that the given position defines the top-left corner of the
213     cursor's image, i.e., not the cursor's hot spot (the position of
214     the associated mouse events).
215 
216     \sa set()
217 */
move(int x,int y)218 void QScreenCursor::move(int x, int y)
219 {
220     QRegion r = boundingRect();
221     pos = QPoint(x,y);
222     if (enable && !hwaccel) {
223         r |= boundingRect();
224         qt_screen->exposeRegion(r, 0);
225     }
226 }
227 
228 
229 /*!
230     \fn void QScreenCursor::initSoftwareCursor ()
231 
232     Initializes the screen cursor.
233 
234     This function is typically called from the screen driver when
235     initializing the device. Alternatively, the cursor can be set
236     directly using the pointer returned by the static instance()
237     function.
238 
239     \sa QScreen::initDevice()
240 */
initSoftwareCursor()241 void QScreenCursor::initSoftwareCursor()
242 {
243     qt_screencursor = new QScreenCursor;
244 }
245 
246 
247 #endif // QT_NO_QWS_CURSOR
248 
249 
250 /*!
251     \fn QRect QScreenCursor::boundingRect () const
252 
253     Returns the cursor's bounding rectangle.
254 */
255 
256 /*!
257     \internal
258     \fn bool QScreenCursor::enabled ()
259 */
260 
261 /*!
262     \fn QImage QScreenCursor::image () const
263 
264     Returns the cursor's image.
265 */
266 
267 
268 /*!
269     \fn bool QScreenCursor::isAccelerated () const
270 
271     Returns true if the cursor is accelerated; otherwise false.
272 */
273 
274 /*!
275     \fn bool QScreenCursor::isVisible () const
276 
277     Returns true if the cursor is visible; otherwise false.
278 */
279 
280 /*!
281     \internal
282     \fn bool QScreenCursor::supportsAlphaCursor () const
283 */
284 
285 /*
286     \variable QScreenCursor::cursor
287 
288     \brief the cursor's image.
289 
290     \sa image()
291 */
292 
293 /*
294     \variable QScreenCursor::size
295 
296     \brief the cursor's size
297 */
298 
299 /*
300     \variable QScreenCursor::pos
301 
302     \brief the cursor's position, i.e., the position of the top-left
303     corner of the crsor's image
304 
305     \sa set(), move()
306 */
307 
308 /*
309     \variable QScreenCursor::hotspot
310 
311     \brief the cursor's hotspot, i.e., the point within the cursor's
312     image that will be the position of the associated mouse events.
313 
314     \sa set(), move()
315 */
316 
317 /*
318     \variable QScreenCursor::enable
319 
320     \brief whether the cursor is visible or not
321 
322     \sa isVisible()
323 */
324 
325 /*
326     \variable QScreenCursor::hwaccel
327 
328     \brief holds whether the cursor is accelerated or not
329 
330     If the cursor is not accelerated, its image will be included by
331     the screen when it composites the window surfaces.
332 
333     \sa isAccelerated()
334 
335 */
336 
337 /*
338     \variable QScreenCursor::supportsAlpha
339 */
340 
341 /*!
342     \internal
343     \macro qt_screencursor
344     \relates QScreenCursor
345 
346     A global pointer referring to the unique screen cursor. It is
347     equivalent to the pointer returned by the
348     QScreenCursor::instance() function.
349 */
350 
351 
352 
353 class QScreenPrivate
354 {
355 public:
356     QScreenPrivate(QScreen *parent, QScreen::ClassId id = QScreen::CustomClass);
357     ~QScreenPrivate();
358 
359     inline QImage::Format preferredImageFormat() const;
360 
361     typedef void (*SolidFillFunc)(QScreen*, const QColor&, const QRegion&);
362     typedef void (*BlitFunc)(QScreen*, const QImage&, const QPoint&, const QRegion&);
363 
364     SolidFillFunc solidFill;
365     BlitFunc blit;
366 
367     QPoint offset;
368     QList<QScreen*> subScreens;
369     QPixmapDataFactory* pixmapFactory;
370     QGraphicsSystem* graphicsSystem;
371     QWSGraphicsSystem defaultGraphicsSystem; //###
372     QImage::Format pixelFormat;
373 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
374     bool fb_is_littleEndian;
375 #endif
376 #ifdef QT_QWS_CLIENTBLIT
377     bool supportsBlitInClients;
378 #endif
379     int classId;
380     QScreen *q_ptr;
381 };
382 
383 template <typename T>
solidFill_template(QScreen * screen,const QColor & color,const QRegion & region)384 static void solidFill_template(QScreen *screen, const QColor &color,
385                                const QRegion &region)
386 {
387     T *dest = reinterpret_cast<T*>(screen->base());
388     const T c = qt_colorConvert<T, quint32>(color.rgba(), 0);
389     const int stride = screen->linestep();
390     const QVector<QRect> rects = region.rects();
391 
392     for (int i = 0; i < rects.size(); ++i) {
393         const QRect r = rects.at(i);
394         qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
395     }
396 }
397 
398 #ifdef QT_QWS_DEPTH_GENERIC
solidFill_rgb_32bpp(QScreen * screen,const QColor & color,const QRegion & region)399 static void solidFill_rgb_32bpp(QScreen *screen, const QColor &color,
400                                 const QRegion &region)
401 {
402     quint32 *dest = reinterpret_cast<quint32*>(screen->base());
403     const quint32 c = qt_convertToRgb<quint32>(color.rgba());
404 
405     const int stride = screen->linestep();
406     const QVector<QRect> rects = region.rects();
407 
408     for (int i = 0; i < rects.size(); ++i) {
409         const QRect r = rects.at(i);
410         qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
411     }
412 }
413 
solidFill_rgb_16bpp(QScreen * screen,const QColor & color,const QRegion & region)414 static void solidFill_rgb_16bpp(QScreen *screen, const QColor &color,
415                                 const QRegion &region)
416 {
417     quint16 *dest = reinterpret_cast<quint16*>(screen->base());
418     const quint16 c = qt_convertToRgb<quint32>(color.rgba());
419 
420     const int stride = screen->linestep();
421     const QVector<QRect> rects = region.rects();
422 
423     for (int i = 0; i < rects.size(); ++i) {
424         const QRect r = rects.at(i);
425         qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
426     }
427 }
428 #endif // QT_QWS_DEPTH_GENERIC
429 
430 #ifdef QT_QWS_DEPTH_4
qt_rectfill_gray4(quint8 * dest,quint8 value,int x,int y,int width,int height,int stride)431 static inline void qt_rectfill_gray4(quint8 *dest, quint8 value,
432                                      int x, int y, int width, int height,
433                                      int stride)
434 {
435     const int pixelsPerByte = 2;
436     dest += y * stride + x / pixelsPerByte;
437     const int doAlign = x & 1;
438     const int doTail = (width - doAlign) & 1;
439     const int width8 = (width - doAlign) / pixelsPerByte;
440 
441     for (int j = 0; j < height; ++j) {
442         if (doAlign)
443             *dest = (*dest & 0xf0) | (value & 0x0f);
444         if (width8)
445             qt_memfill<quint8>(dest + doAlign, value, width8);
446         if (doTail) {
447             quint8 *d = dest + doAlign + width8;
448             *d = (*d & 0x0f) | (value & 0xf0);
449         }
450         dest += stride;
451     }
452 }
453 
solidFill_gray4(QScreen * screen,const QColor & color,const QRegion & region)454 static void solidFill_gray4(QScreen *screen, const QColor &color,
455                             const QRegion &region)
456 {
457     quint8 *dest = reinterpret_cast<quint8*>(screen->base());
458     const quint8 c = qGray(color.rgba()) >> 4;
459     const quint8 c8 = (c << 4) | c;
460 
461     const int stride = screen->linestep();
462     const QVector<QRect> rects = region.rects();
463 
464     for (int i = 0; i < rects.size(); ++i) {
465         const QRect r = rects.at(i);
466         qt_rectfill_gray4(dest, c8, r.x(), r.y(), r.width(), r.height(),
467                           stride);
468     }
469 }
470 #endif // QT_QWS_DEPTH_4
471 
472 #ifdef QT_QWS_DEPTH_1
qt_rectfill_mono(quint8 * dest,quint8 value,int x,int y,int width,int height,int stride)473 static inline void qt_rectfill_mono(quint8 *dest, quint8 value,
474                                     int x, int y, int width, int height,
475                                     int stride)
476 {
477     const int pixelsPerByte = 8;
478     const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
479     const int doAlign = (alignWidth > 0 ? 1 : 0);
480     const int alignStart = pixelsPerByte - 1 - (x & 7);
481     const int alignStop = alignStart - (alignWidth - 1);
482     const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
483     const int tailWidth = (width - alignWidth) & 7;
484     const int doTail = (tailWidth > 0 ? 1 : 0);
485     const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
486     const int width8 = (width - alignWidth) / pixelsPerByte;
487 
488     dest += y * stride + x / pixelsPerByte;
489     stride -= (doAlign + width8);
490 
491     for (int j = 0; j < height; ++j) {
492         if (doAlign) {
493             *dest = (*dest & ~alignMask) | (value & alignMask);
494             ++dest;
495         }
496         if (width8) {
497             qt_memfill<quint8>(dest, value, width8);
498             dest += width8;
499         }
500         if (doTail)
501             *dest = (*dest & tailMask) | (value & ~tailMask);
502         dest += stride;
503     }
504 }
505 
solidFill_mono(QScreen * screen,const QColor & color,const QRegion & region)506 static void solidFill_mono(QScreen *screen, const QColor &color,
507                            const QRegion &region)
508 {
509     quint8 *dest = reinterpret_cast<quint8*>(screen->base());
510     const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff;
511 
512     const int stride = screen->linestep();
513     const QVector<QRect> rects = region.rects();
514 
515     for (int i = 0; i < rects.size(); ++i) {
516         const QRect r = rects.at(i);
517         qt_rectfill_mono(dest, c8, r.x(), r.y(), r.width(), r.height(),
518                          stride);
519     }
520 }
521 #endif // QT_QWS_DEPTH_1
522 
qt_solidFill_setup(QScreen * screen,const QColor & color,const QRegion & region)523 void qt_solidFill_setup(QScreen *screen, const QColor &color,
524                         const QRegion &region)
525 {
526     switch (screen->depth()) {
527 #ifdef QT_QWS_DEPTH_32
528     case 32:
529         if (screen->pixelType() == QScreen::NormalPixel)
530             screen->d_ptr->solidFill = solidFill_template<quint32>;
531         else
532             screen->d_ptr->solidFill = solidFill_template<qabgr8888>;
533         break;
534 #endif
535 #ifdef QT_QWS_DEPTH_24
536     case 24:
537         if (screen->pixelType() == QScreen::NormalPixel)
538             screen->d_ptr->solidFill = solidFill_template<qrgb888>;
539         else
540             screen->d_ptr->solidFill = solidFill_template<quint24>;
541         break;
542 #endif
543 #ifdef QT_QWS_DEPTH_18
544     case 18:
545         screen->d_ptr->solidFill = solidFill_template<quint18>;
546         break;
547 #endif
548 #ifdef QT_QWS_DEPTH_16
549     case 16:
550         if (screen->pixelType() == QScreen::NormalPixel)
551             screen->d_ptr->solidFill = solidFill_template<quint16>;
552         else
553             screen->d_ptr->solidFill = solidFill_template<qbgr565>;
554         break;
555 #endif
556 #ifdef QT_QWS_DEPTH_15
557     case 15:
558         if (screen->pixelType() == QScreen::NormalPixel)
559             screen->d_ptr->solidFill = solidFill_template<qrgb555>;
560         else
561             screen->d_ptr->solidFill = solidFill_template<qbgr555>;
562         break;
563 #endif
564 #ifdef QT_QWS_DEPTH_12
565     case 12:
566         screen->d_ptr->solidFill = solidFill_template<qrgb444>;
567         break;
568 #endif
569 #ifdef QT_QWS_DEPTH_8
570     case 8:
571         screen->d_ptr->solidFill = solidFill_template<quint8>;
572         break;
573 #endif
574 #ifdef QT_QWS_DEPTH_4
575     case 4:
576         screen->d_ptr->solidFill = solidFill_gray4;
577         break;
578 #endif
579 #ifdef QT_QWS_DEPTH_1
580     case 1:
581         screen->d_ptr->solidFill = solidFill_mono;
582         break;
583 #endif
584      default:
585         qFatal("solidFill_setup(): Screen depth %d not supported!",
586                screen->depth());
587         screen->d_ptr->solidFill = 0;
588         break;
589     }
590     screen->d_ptr->solidFill(screen, color, region);
591 }
592 
593 template <typename DST, typename SRC>
blit_template(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)594 static void blit_template(QScreen *screen, const QImage &image,
595                           const QPoint &topLeft, const QRegion &region)
596 {
597     DST *dest = reinterpret_cast<DST*>(screen->base());
598     const int screenStride = screen->linestep();
599     const int imageStride = image.bytesPerLine();
600 
601     if (region.rectCount() == 1) {
602         const QRect r = region.boundingRect();
603         const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
604                          + r.x();
605         qt_rectconvert<DST, SRC>(dest, src,
606                                  r.x() + topLeft.x(), r.y() + topLeft.y(),
607                                  r.width(), r.height(),
608                                  screenStride, imageStride);
609     } else {
610         const QVector<QRect> rects = region.rects();
611 
612         for (int i = 0; i < rects.size(); ++i) {
613             const QRect r = rects.at(i);
614             const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
615                              + r.x();
616             qt_rectconvert<DST, SRC>(dest, src,
617                                      r.x() + topLeft.x(), r.y() + topLeft.y(),
618                                      r.width(), r.height(),
619                                      screenStride, imageStride);
620         }
621     }
622 }
623 
624 #ifdef QT_QWS_DEPTH_32
blit_32(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)625 static void blit_32(QScreen *screen, const QImage &image,
626                     const QPoint &topLeft, const QRegion &region)
627 {
628     switch (image.format()) {
629     case QImage::Format_RGB32:
630     case QImage::Format_ARGB32:
631     case QImage::Format_ARGB32_Premultiplied:
632         blit_template<quint32, quint32>(screen, image, topLeft, region);
633         return;
634 #ifdef QT_QWS_DEPTH_16
635     case QImage::Format_RGB16:
636         blit_template<quint32, quint16>(screen, image, topLeft, region);
637         return;
638 #endif
639     default:
640         qCritical("blit_32(): Image format %d not supported!", image.format());
641     }
642 }
643 #endif // QT_QWS_DEPTH_32
644 
645 #ifdef QT_QWS_DEPTH_24
blit_24(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)646 static void blit_24(QScreen *screen, const QImage &image,
647                     const QPoint &topLeft, const QRegion &region)
648 {
649     switch (image.format()) {
650     case QImage::Format_RGB32:
651     case QImage::Format_ARGB32:
652     case QImage::Format_ARGB32_Premultiplied:
653         blit_template<quint24, quint32>(screen, image, topLeft, region);
654         return;
655     case QImage::Format_RGB888:
656         blit_template<quint24, qrgb888>(screen, image, topLeft, region);
657         return;
658 #ifdef QT_QWS_DEPTH_16
659     case QImage::Format_RGB16:
660         blit_template<quint24, quint16>(screen, image, topLeft, region);
661         return;
662 #endif
663     default:
664         qCritical("blit_24(): Image format %d not supported!", image.format());
665     }
666 }
667 
blit_qrgb888(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)668 static void blit_qrgb888(QScreen *screen, const QImage &image,
669                          const QPoint &topLeft, const QRegion &region)
670 {
671     switch (image.format()) {
672     case QImage::Format_RGB32:
673     case QImage::Format_ARGB32:
674     case QImage::Format_ARGB32_Premultiplied:
675         blit_template<qrgb888, quint32>(screen, image, topLeft, region);
676         return;
677     case QImage::Format_RGB888:
678         blit_template<qrgb888, qrgb888>(screen, image, topLeft, region);
679         return;
680 #ifdef QT_QWS_DEPTH_16
681     case QImage::Format_RGB16:
682         blit_template<qrgb888, quint16>(screen, image, topLeft, region);
683         return;
684 #endif
685     default:
686         qCritical("blit_24(): Image format %d not supported!", image.format());
687         break;
688     }
689 }
690 #endif // QT_QWS_DEPTH_24
691 
692 #ifdef QT_QWS_DEPTH_18
blit_18(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)693 static void blit_18(QScreen *screen, const QImage &image,
694                     const QPoint &topLeft, const QRegion &region)
695 {
696     switch (image.format()) {
697     case QImage::Format_RGB32:
698     case QImage::Format_ARGB32:
699     case QImage::Format_ARGB32_Premultiplied:
700         blit_template<qrgb666, quint32>(screen, image, topLeft, region);
701         return;
702     case QImage::Format_RGB666:
703         blit_template<qrgb666, qrgb666>(screen, image, topLeft, region);
704         return;
705 #ifdef QT_QWS_DEPTH_16
706     case QImage::Format_RGB16:
707         blit_template<qrgb666, quint16>(screen, image, topLeft, region);
708         return;
709 #endif
710     default:
711         qCritical("blit_18(): Image format %d not supported!", image.format());
712     }
713 }
714 #endif // QT_QWS_DEPTH_18
715 
716 #if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && (defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15))
717 class quint16LE
718 {
719 public:
quint16LE(quint32 v)720     inline quint16LE(quint32 v) {
721         data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
722     }
723 
quint16LE(int v)724     inline quint16LE(int v) {
725         data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
726     }
727 
quint16LE(quint16 v)728     inline quint16LE(quint16 v) {
729         data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
730     }
731 
quint16LE(qrgb555 v)732     inline quint16LE(qrgb555 v) {
733         data = (( (quint16)v & 0xff00) >> 8) |
734                (( (quint16)v & 0x00ff) << 8);
735     }
736 
operator ==(const quint16LE & v) const737     inline bool operator==(const quint16LE &v) const
738     {
739         return data == v.data;
740     }
741 
742 private:
743     quint16 data;
744 };
745 #endif
746 
747 #ifdef QT_QWS_DEPTH_16
blit_16(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)748 static void blit_16(QScreen *screen, const QImage &image,
749                     const QPoint &topLeft, const QRegion &region)
750 {
751     switch (image.format()) {
752     case QImage::Format_RGB32:
753     case QImage::Format_ARGB32:
754     case QImage::Format_ARGB32_Premultiplied:
755         // ### This probably doesn't work but it's a case which should never happen
756         blit_template<quint16, quint32>(screen, image, topLeft, region);
757         return;
758     case QImage::Format_RGB16:
759         blit_template<quint16, quint16>(screen, image, topLeft, region);
760         return;
761     default:
762         qCritical("blit_16(): Image format %d not supported!", image.format());
763     }
764 }
765 
766 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
blit_16_bigToLittleEndian(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)767 static void blit_16_bigToLittleEndian(QScreen *screen, const QImage &image,
768                                       const QPoint &topLeft,
769                                       const QRegion &region)
770 {
771     switch (image.format()) {
772     case QImage::Format_RGB32:
773     case QImage::Format_ARGB32:
774     case QImage::Format_ARGB32_Premultiplied:
775         blit_template<quint16LE, quint32>(screen, image, topLeft, region);
776         return;
777     case QImage::Format_RGB16:
778         blit_template<quint16LE, quint16>(screen, image, topLeft, region);
779         return;
780     default:
781         qCritical("blit_16_bigToLittleEndian(): Image format %d not supported!", image.format());
782     }
783 }
784 
785 #endif // Q_BIG_ENDIAN
786 #endif // QT_QWS_DEPTH_16
787 
788 #ifdef QT_QWS_DEPTH_15
blit_15(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)789 static void blit_15(QScreen *screen, const QImage &image,
790                     const QPoint &topLeft, const QRegion &region)
791 {
792     switch (image.format()) {
793     case QImage::Format_RGB32:
794     case QImage::Format_ARGB32:
795     case QImage::Format_ARGB32_Premultiplied:
796         blit_template<qrgb555, quint32>(screen, image, topLeft, region);
797         return;
798     case QImage::Format_RGB555:
799         blit_template<qrgb555, qrgb555>(screen, image, topLeft, region);
800         return;
801     case QImage::Format_RGB16:
802         blit_template<qrgb555, quint16>(screen, image, topLeft, region);
803         return;
804     default:
805         qCritical("blit_15(): Image format %d not supported!", image.format());
806     }
807 }
808 
809 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
blit_15_bigToLittleEndian(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)810 static void blit_15_bigToLittleEndian(QScreen *screen, const QImage &image,
811                                       const QPoint &topLeft,
812                                       const QRegion &region)
813 {
814     switch (image.format()) {
815     case QImage::Format_RGB555:
816         blit_template<quint16LE, qrgb555>(screen, image, topLeft, region);
817         return;
818     default:
819         qCritical("blit_15_bigToLittleEndian(): Image format %d not supported!", image.format());
820     }
821 }
822 #endif // Q_BIG_ENDIAN
823 #endif // QT_QWS_DEPTH_15
824 
825 
826 #ifdef QT_QWS_DEPTH_12
blit_12(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)827 static void blit_12(QScreen *screen, const QImage &image,
828                     const QPoint &topLeft, const QRegion &region)
829 {
830     switch (image.format()) {
831     case QImage::Format_ARGB4444_Premultiplied:
832         blit_template<qrgb444, qargb4444>(screen, image, topLeft, region);
833         return;
834     case QImage::Format_RGB444:
835         blit_template<qrgb444, qrgb444>(screen, image, topLeft, region);
836         return;
837     default:
838         qCritical("blit_12(): Image format %d not supported!", image.format());
839     }
840 }
841 #endif // QT_QWS_DEPTH_12
842 
843 #ifdef QT_QWS_DEPTH_8
blit_8(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)844 static void blit_8(QScreen *screen, const QImage &image,
845                    const QPoint &topLeft, const QRegion &region)
846 {
847     switch (image.format()) {
848     case QImage::Format_RGB32:
849     case QImage::Format_ARGB32:
850     case QImage::Format_ARGB32_Premultiplied:
851         blit_template<quint8, quint32>(screen, image, topLeft, region);
852         return;
853     case QImage::Format_RGB16:
854         blit_template<quint8, quint16>(screen, image, topLeft, region);
855         return;
856     case QImage::Format_ARGB4444_Premultiplied:
857         blit_template<quint8, qargb4444>(screen, image, topLeft, region);
858         return;
859     case QImage::Format_RGB444:
860         blit_template<quint8, qrgb444>(screen, image, topLeft, region);
861         return;
862     default:
863         qCritical("blit_8(): Image format %d not supported!", image.format());
864     }
865 }
866 #endif // QT_QWS_DEPTH_8
867 
868 #ifdef QT_QWS_DEPTH_4
869 
870 struct qgray4 { quint8 dummy; } Q_PACKED;
871 
872 template <typename SRC>
873 Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToGray4(SRC color);
874 
875 template <>
qt_convertToGray4(quint32 color)876 inline quint8 qt_convertToGray4(quint32 color)
877 {
878     return qGray(color) >> 4;
879 }
880 
881 template <>
qt_convertToGray4(quint16 color)882 inline quint8 qt_convertToGray4(quint16 color)
883 {
884     const int r = (color & 0xf800) >> 11;
885     const int g = (color & 0x07e0) >> 6; // only keep 5 bit
886     const int b = (color & 0x001f);
887     return (r * 11 + g * 16 + b * 5) >> 6;
888 }
889 
890 template <>
qt_convertToGray4(qrgb444 color)891 inline quint8 qt_convertToGray4(qrgb444 color)
892 {
893     return qt_convertToGray4(quint32(color));
894 }
895 
896 template <>
qt_convertToGray4(qargb4444 color)897 inline quint8 qt_convertToGray4(qargb4444 color)
898 {
899     return qt_convertToGray4(quint32(color));
900 }
901 
902 template <typename SRC>
qt_rectconvert_gray4(qgray4 * dest4,const SRC * src,int x,int y,int width,int height,int dstStride,int srcStride)903 Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_gray4(qgray4 *dest4, const SRC *src,
904                                         int x, int y, int width, int height,
905                                         int dstStride, int srcStride)
906 {
907     const int pixelsPerByte = 2;
908     quint8 *dest8 = reinterpret_cast<quint8*>(dest4)
909                     + y * dstStride + x / pixelsPerByte;
910     const int doAlign = x & 1;
911     const int doTail = (width - doAlign) & 1;
912     const int width8 = (width - doAlign) / pixelsPerByte;
913     const int count8 = (width8 + 3) / 4;
914 
915     srcStride = srcStride / sizeof(SRC) - width;
916     dstStride -= (width8 + doAlign);
917 
918     for (int i = 0; i < height; ++i) {
919         if (doAlign) {
920             *dest8 = (*dest8 & 0xf0) | qt_convertToGray4<SRC>(*src++);
921             ++dest8;
922         }
923         if (count8) {
924             int n = count8;
925             switch (width8 & 0x03) // duff's device
926             {
927             case 0: do { *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
928                                     | qt_convertToGray4<SRC>(src[1]);
929                          src += 2;
930             case 3:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
931                                     | qt_convertToGray4<SRC>(src[1]);
932                          src += 2;
933             case 2:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
934                                     | qt_convertToGray4<SRC>(src[1]);
935                          src += 2;
936             case 1:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
937                                     | qt_convertToGray4<SRC>(src[1]);
938                          src += 2;
939             } while (--n > 0);
940             }
941         }
942 
943         if (doTail)
944             *dest8 = qt_convertToGray4<SRC>(*src++) << 4 | (*dest8 & 0x0f);
945 
946         dest8 += dstStride;
947         src += srcStride;
948     }
949 }
950 
951 template <>
qt_rectconvert(qgray4 * dest,const quint32 * src,int x,int y,int width,int height,int dstStride,int srcStride)952 void qt_rectconvert(qgray4 *dest, const quint32 *src,
953                     int x, int y, int width, int height,
954                     int dstStride, int srcStride)
955 {
956     qt_rectconvert_gray4<quint32>(dest, src, x, y, width, height,
957                                   dstStride, srcStride);
958 }
959 
960 template <>
qt_rectconvert(qgray4 * dest,const quint16 * src,int x,int y,int width,int height,int dstStride,int srcStride)961 void qt_rectconvert(qgray4 *dest, const quint16 *src,
962                     int x, int y, int width, int height,
963                     int dstStride, int srcStride)
964 {
965     qt_rectconvert_gray4<quint16>(dest, src, x, y, width, height,
966                                   dstStride, srcStride);
967 }
968 
969 template <>
qt_rectconvert(qgray4 * dest,const qrgb444 * src,int x,int y,int width,int height,int dstStride,int srcStride)970 void qt_rectconvert(qgray4 *dest, const qrgb444 *src,
971                     int x, int y, int width, int height,
972                     int dstStride, int srcStride)
973 {
974     qt_rectconvert_gray4<qrgb444>(dest, src, x, y, width, height,
975                                   dstStride, srcStride);
976 }
977 
978 template <>
qt_rectconvert(qgray4 * dest,const qargb4444 * src,int x,int y,int width,int height,int dstStride,int srcStride)979 void qt_rectconvert(qgray4 *dest, const qargb4444 *src,
980                     int x, int y, int width, int height,
981                     int dstStride, int srcStride)
982 {
983     qt_rectconvert_gray4<qargb4444>(dest, src, x, y, width, height,
984                                     dstStride, srcStride);
985 }
986 
blit_4(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)987 static void blit_4(QScreen *screen, const QImage &image,
988                    const QPoint &topLeft, const QRegion &region)
989 {
990     switch (image.format()) {
991     case QImage::Format_ARGB32_Premultiplied:
992         blit_template<qgray4, quint32>(screen, image, topLeft, region);
993         return;
994     case QImage::Format_RGB16:
995         blit_template<qgray4, quint16>(screen, image, topLeft, region);
996         return;
997     case QImage::Format_RGB444:
998         blit_template<qgray4, qrgb444>(screen, image, topLeft, region);
999         return;
1000     case QImage::Format_ARGB4444_Premultiplied:
1001         blit_template<qgray4, qargb4444>(screen, image, topLeft, region);
1002         return;
1003     default:
1004         qCritical("blit_4(): Image format %d not supported!", image.format());
1005     }
1006 }
1007 #endif // QT_QWS_DEPTH_4
1008 
1009 #ifdef QT_QWS_DEPTH_1
1010 
1011 struct qmono { quint8 dummy; } Q_PACKED;
1012 
1013 template <typename SRC>
1014 Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToMono(SRC color);
1015 
1016 template <>
qt_convertToMono(quint32 color)1017 inline quint8 qt_convertToMono(quint32 color)
1018 {
1019     return qGray(color) >> 7;
1020 }
1021 
1022 template <>
qt_convertToMono(quint16 color)1023 inline quint8 qt_convertToMono(quint16 color)
1024 {
1025     return (qGray(qt_colorConvert<quint32, quint16>(color, 0)) >> 7);
1026 }
1027 
1028 template <>
qt_convertToMono(qargb4444 color)1029 inline quint8 qt_convertToMono(qargb4444 color)
1030 {
1031     return (qGray(quint32(color)) >> 7);
1032 }
1033 
1034 template <>
qt_convertToMono(qrgb444 color)1035 inline quint8 qt_convertToMono(qrgb444 color)
1036 {
1037     return (qGray(quint32(color)) >> 7);
1038 }
1039 
1040 template <typename SRC>
qt_rectconvert_mono(qmono * dest,const SRC * src,int x,int y,int width,int height,int dstStride,int srcStride)1041 inline void qt_rectconvert_mono(qmono *dest, const SRC *src,
1042                                        int x, int y, int width, int height,
1043                                        int dstStride, int srcStride)
1044 {
1045     const int pixelsPerByte = 8;
1046     quint8 *dest8 = reinterpret_cast<quint8*>(dest)
1047                     + y * dstStride + x / pixelsPerByte;
1048     const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
1049     const int doAlign = (alignWidth > 0 ? 1 : 0);
1050     const int alignStart = pixelsPerByte - 1 - (x & 7);
1051     const int alignStop = alignStart - (alignWidth - 1);
1052     const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
1053     const int tailWidth = (width - alignWidth) & 7;
1054     const int doTail = (tailWidth > 0 ? 1 : 0);
1055     const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
1056     const int width8 = (width - alignWidth) / pixelsPerByte;
1057 
1058     srcStride = srcStride / sizeof(SRC) - (width8 * 8 + alignWidth);
1059     dstStride -= (width8 + doAlign);
1060 
1061     for (int j = 0;  j < height; ++j) {
1062         if (doAlign) {
1063             quint8 d = *dest8 & ~alignMask;
1064             for (int i = alignStart; i >= alignStop; --i)
1065                 d |= qt_convertToMono<SRC>(*src++) << i;
1066             *dest8++ = d;
1067         }
1068         for (int i = 0; i < width8; ++i) {
1069             *dest8 = (qt_convertToMono<SRC>(src[0]) << 7)
1070                      | (qt_convertToMono<SRC>(src[1]) << 6)
1071                      | (qt_convertToMono<SRC>(src[2]) << 5)
1072                      | (qt_convertToMono<SRC>(src[3]) << 4)
1073                      | (qt_convertToMono<SRC>(src[4]) << 3)
1074                      | (qt_convertToMono<SRC>(src[5]) << 2)
1075                      | (qt_convertToMono<SRC>(src[6]) << 1)
1076                      | (qt_convertToMono<SRC>(src[7]));
1077             src += 8;
1078             ++dest8;
1079         }
1080         if (doTail) {
1081             quint8 d = *dest8 & tailMask;
1082             switch (tailWidth) {
1083             case 7: d |= qt_convertToMono<SRC>(src[6]) << 1;
1084             case 6: d |= qt_convertToMono<SRC>(src[5]) << 2;
1085             case 5: d |= qt_convertToMono<SRC>(src[4]) << 3;
1086             case 4: d |= qt_convertToMono<SRC>(src[3]) << 4;
1087             case 3: d |= qt_convertToMono<SRC>(src[2]) << 5;
1088             case 2: d |= qt_convertToMono<SRC>(src[1]) << 6;
1089             case 1: d |= qt_convertToMono<SRC>(src[0]) << 7;
1090             }
1091             *dest8 = d;
1092         }
1093 
1094         dest8 += dstStride;
1095         src += srcStride;
1096     }
1097 }
1098 
1099 template <>
qt_rectconvert(qmono * dest,const quint32 * src,int x,int y,int width,int height,int dstStride,int srcStride)1100 void qt_rectconvert(qmono *dest, const quint32 *src,
1101                     int x, int y, int width, int height,
1102                     int dstStride, int srcStride)
1103 {
1104     qt_rectconvert_mono<quint32>(dest, src, x, y, width, height,
1105                                  dstStride, srcStride);
1106 }
1107 
1108 template <>
qt_rectconvert(qmono * dest,const quint16 * src,int x,int y,int width,int height,int dstStride,int srcStride)1109 void qt_rectconvert(qmono *dest, const quint16 *src,
1110                     int x, int y, int width, int height,
1111                     int dstStride, int srcStride)
1112 {
1113     qt_rectconvert_mono<quint16>(dest, src, x, y, width, height,
1114                                  dstStride, srcStride);
1115 }
1116 
1117 template <>
qt_rectconvert(qmono * dest,const qrgb444 * src,int x,int y,int width,int height,int dstStride,int srcStride)1118 void qt_rectconvert(qmono *dest, const qrgb444 *src,
1119                     int x, int y, int width, int height,
1120                     int dstStride, int srcStride)
1121 {
1122     qt_rectconvert_mono<qrgb444>(dest, src, x, y, width, height,
1123                                  dstStride, srcStride);
1124 }
1125 
1126 template <>
qt_rectconvert(qmono * dest,const qargb4444 * src,int x,int y,int width,int height,int dstStride,int srcStride)1127 void qt_rectconvert(qmono *dest, const qargb4444 *src,
1128                     int x, int y, int width, int height,
1129                     int dstStride, int srcStride)
1130 {
1131     qt_rectconvert_mono<qargb4444>(dest, src, x, y, width, height,
1132                                    dstStride, srcStride);
1133 }
1134 
blit_1(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)1135 static void blit_1(QScreen *screen, const QImage &image,
1136                    const QPoint &topLeft, const QRegion &region)
1137 {
1138     switch (image.format()) {
1139     case QImage::Format_ARGB32_Premultiplied:
1140         blit_template<qmono, quint32>(screen, image, topLeft, region);
1141         return;
1142     case QImage::Format_RGB16:
1143         blit_template<qmono, quint16>(screen, image, topLeft, region);
1144         return;
1145     case QImage::Format_RGB444:
1146         blit_template<qmono, qrgb444>(screen, image, topLeft, region);
1147         return;
1148     case QImage::Format_ARGB4444_Premultiplied:
1149         blit_template<qmono, qargb4444>(screen, image, topLeft, region);
1150         return;
1151     default:
1152         qCritical("blit_1(): Image format %d not supported!", image.format());
1153     }
1154 }
1155 #endif // QT_QWS_DEPTH_1
1156 
1157 #ifdef QT_QWS_DEPTH_GENERIC
1158 
blit_rgb(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)1159 static void blit_rgb(QScreen *screen, const QImage &image,
1160                      const QPoint &topLeft, const QRegion &region)
1161 {
1162     switch (image.format()) {
1163     case QImage::Format_ARGB32_Premultiplied:
1164         blit_template<qrgb, quint32>(screen, image, topLeft, region);
1165         return;
1166     case QImage::Format_RGB16:
1167         blit_template<qrgb, quint16>(screen, image, topLeft, region);
1168         return;
1169     default:
1170         qCritical("blit_rgb(): Image format %d not supported!", image.format());
1171     }
1172 }
1173 
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)1174 void qt_set_generic_blit(QScreen *screen, int bpp,
1175                          int len_red, int len_green, int len_blue, int len_alpha,
1176                          int off_red, int off_green, int off_blue, int off_alpha)
1177 {
1178     qrgb::bpp = bpp / 8;
1179     qrgb::len_red = len_red;
1180     qrgb::len_green = len_green;
1181     qrgb::len_blue = len_blue;
1182     qrgb::len_alpha = len_alpha;
1183     qrgb::off_red = off_red;
1184     qrgb::off_green = off_green;
1185     qrgb::off_blue = off_blue;
1186     qrgb::off_alpha = off_alpha;
1187     screen->d_ptr->blit = blit_rgb;
1188     if (bpp == 16)
1189         screen->d_ptr->solidFill = solidFill_rgb_16bpp;
1190     else if (bpp == 32)
1191         screen->d_ptr->solidFill = solidFill_rgb_32bpp;
1192 }
1193 
1194 #endif // QT_QWS_DEPTH_GENERIC
1195 
qt_blit_setup(QScreen * screen,const QImage & image,const QPoint & topLeft,const QRegion & region)1196 void qt_blit_setup(QScreen *screen, const QImage &image,
1197                    const QPoint &topLeft, const QRegion &region)
1198 {
1199     switch (screen->depth()) {
1200 #ifdef QT_QWS_DEPTH_32
1201     case 32:
1202         if (screen->pixelType() == QScreen::NormalPixel)
1203             screen->d_ptr->blit = blit_32;
1204         else
1205             screen->d_ptr->blit = blit_template<qabgr8888, quint32>;
1206         break;
1207 #endif
1208 #ifdef QT_QWS_DEPTH_24
1209     case 24:
1210         if (screen->pixelType() == QScreen::NormalPixel)
1211             screen->d_ptr->blit = blit_qrgb888;
1212         else
1213             screen->d_ptr->blit = blit_24;
1214         break;
1215 #endif
1216 #ifdef QT_QWS_DEPTH_18
1217     case 18:
1218         screen->d_ptr->blit = blit_18;
1219         break;
1220 #endif
1221 #ifdef QT_QWS_DEPTH_16
1222     case 16:
1223 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1224         if (screen->d_ptr->fb_is_littleEndian)
1225             screen->d_ptr->blit = blit_16_bigToLittleEndian;
1226         else
1227 #endif
1228         if (screen->pixelType() == QScreen::NormalPixel)
1229             screen->d_ptr->blit = blit_16;
1230         else
1231             screen->d_ptr->blit = blit_template<qbgr565, quint16>;
1232         break;
1233 #endif
1234 #ifdef QT_QWS_DEPTH_15
1235     case 15:
1236 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1237         if (screen->d_ptr->fb_is_littleEndian)
1238             screen->d_ptr->blit = blit_15_bigToLittleEndian;
1239         else
1240 #endif // Q_BIG_ENDIAN
1241         if (screen->pixelType() == QScreen::NormalPixel)
1242             screen->d_ptr->blit = blit_15;
1243         else
1244             screen->d_ptr->blit = blit_template<qbgr555, qrgb555>;
1245         break;
1246 #endif
1247 #ifdef QT_QWS_DEPTH_12
1248     case 12:
1249         screen->d_ptr->blit = blit_12;
1250         break;
1251 #endif
1252 #ifdef QT_QWS_DEPTH_8
1253     case 8:
1254         screen->d_ptr->blit = blit_8;
1255         break;
1256 #endif
1257 #ifdef QT_QWS_DEPTH_4
1258     case 4:
1259         screen->d_ptr->blit = blit_4;
1260         break;
1261 #endif
1262 #ifdef QT_QWS_DEPTH_1
1263     case 1:
1264         screen->d_ptr->blit = blit_1;
1265         break;
1266 #endif
1267     default:
1268         qFatal("blit_setup(): Screen depth %d not supported!",
1269                screen->depth());
1270         screen->d_ptr->blit = 0;
1271         break;
1272     }
1273     screen->d_ptr->blit(screen, image, topLeft, region);
1274 }
1275 
QScreenPrivate(QScreen * parent,QScreen::ClassId id)1276 QScreenPrivate::QScreenPrivate(QScreen *parent, QScreen::ClassId id)
1277     : defaultGraphicsSystem(QWSGraphicsSystem(parent)),
1278       pixelFormat(QImage::Format_Invalid),
1279 #ifdef QT_QWS_CLIENTBLIT
1280       supportsBlitInClients(false),
1281 #endif
1282       classId(id), q_ptr(parent)
1283 {
1284     solidFill = qt_solidFill_setup;
1285     blit = qt_blit_setup;
1286 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1287     fb_is_littleEndian = false;
1288 #endif
1289     pixmapFactory = 0;
1290     graphicsSystem = &defaultGraphicsSystem;
1291 }
1292 
~QScreenPrivate()1293 QScreenPrivate::~QScreenPrivate()
1294 {
1295 }
1296 
preferredImageFormat() const1297 QImage::Format QScreenPrivate::preferredImageFormat() const
1298 {
1299     if (pixelFormat > QImage::Format_Indexed8)
1300         return pixelFormat;
1301 
1302     if (q_ptr->depth() <= 16)
1303         return QImage::Format_RGB16;
1304     else
1305         return QImage::Format_ARGB32_Premultiplied;
1306 }
1307 
1308 /*!
1309     \class QScreen
1310     \ingroup qws
1311 
1312     \brief The QScreen class is a base class for screen drivers in
1313     Qt for Embedded Linux.
1314 
1315     Note that this class is only available in \l{Qt for Embedded Linux}.
1316 
1317     \l{Qt for Embedded Linux} provides ready-made drivers for several screen
1318     protocols, see the \l{Qt for Embedded Linux Display Management}{display
1319     management} documentation for details. Custom screen drivers can
1320     be implemented by subclassing the QScreen class and creating a
1321     screen driver plugin (derived from QScreenDriverPlugin). The
1322     default implementation of the QScreenDriverFactory class
1323     will automatically detect the plugin, and load the driver into the
1324     server application at run-time using Qt's \l {How to Create Qt
1325     Plugins}{plugin system}.
1326 
1327     When rendering, the default behavior is for each
1328     client to render its widgets as well as its decorations into
1329     memory, while the server copies the memory content to the device's
1330     framebuffer using the screen driver. See the \l{Qt for Embedded Linux
1331     Architecture} overview for details (note that it is possible for
1332     the clients to manipulate and control the underlying hardware
1333     directly as well).
1334 
1335     Starting with Qt 4.2, it is also possible to add an
1336     accelerated graphics driver to take advantage of available
1337     hardware resources. See the \l{Adding an Accelerated Graphics
1338     Driver to Qt for Embedded Linux} documentation for details.
1339 
1340     \tableofcontents
1341 
1342     \section1 Framebuffer Management
1343 
1344     When a \l{Qt for Embedded Linux} application starts running, it
1345     calls the screen driver's connect() function to map the
1346     framebuffer and the accelerated drivers that the graphics card
1347     control registers. The connect() function should then read out the
1348     parameters of the framebuffer and use them as required to set this
1349     class's protected variables.
1350 
1351     The initDevice() function can be reimplemented to initialize the
1352     graphics card. Note, however, that connect() is called \e before
1353     the initDevice() function, so, for some hardware configurations,
1354     some of the initialization that would normally be done in the
1355     initDevice() function might have to be done in the connect()
1356     function.
1357 
1358     Likewise, just before a \l{Qt for Embedded Linux} application
1359     exits, it calls the screen driver's disconnect() function. The
1360     server application will in addition call the shutdownDevice()
1361     function before it calls disconnect(). Note that the default
1362     implementation of the shutdownDevice() function only hides the
1363     mouse cursor.
1364 
1365     QScreen also provides the save() and restore() functions, making
1366     it possible to save and restore the state of the graphics
1367     card. Note that the default implementations do nothing. Hardware
1368     screen drivers should reimplement these functions to save (and
1369     restore) its registers, enabling switching between virtual
1370     consoles.
1371 
1372     In addition, you can use the base() function to retrieve a pointer
1373     to the beginning of the framebuffer, and the region() function to
1374     retrieve the framebuffer's region. Use the onCard() function to
1375     determine whether the framebuffer is within the graphics card's
1376     memory, and the totalSize() function to determine the size of the
1377     available graphics card memory (including the screen). Finally,
1378     you can use the offset() function to retrieve the offset between
1379     the framebuffer's coordinates and the application's coordinate
1380     system.
1381 
1382     \section1 Palette Management
1383 
1384     QScreen provides several functions to retrieve information about
1385     the color palette: The clut() function returns a pointer to the
1386     color lookup table (i.e. its color palette). Use the colorCount()
1387     function to determine the number of entries in this table, and the
1388     alloc() function to retrieve the palette index of the color that
1389     is the closest match to a given RGB value.
1390 
1391     To determine if the screen driver supports a given color depth,
1392     use the supportsDepth() function that returns true of the
1393     specified depth is supported.
1394 
1395     \section1 Drawing on Screen
1396 
1397     When a screen update is required, the \l{Qt for Embedded Linux} server runs
1398     through all the top-level windows that intersect with the region
1399     that is about to be updated, and ensures that the associated
1400     clients have updated their memory buffer. Then the server calls
1401     the exposeRegion() function that composes the window surfaces and
1402     copies the content of memory to screen by calling the blit() and
1403     solidFill() functions.
1404 
1405     The blit() function copies a given region in a given image to a
1406     specified point using device coordinates, while the solidFill()
1407     function fills the given region of the screen with the specified
1408     color. Note that normally there is no need to call either of these
1409     functions explicitly.
1410 
1411     In addition, QScreen provides the blank() function that can be
1412     reimplemented to prevent any contents from being displayed on the
1413     screen, and the setDirty() function that can be reimplemented to
1414     indicate that a given rectangle of the screen has been
1415     altered. Note that the default implementations of these functions
1416     do nothing.
1417 
1418     Reimplement the mapFromDevice() and mapToDevice() functions to
1419     map objects from the framebuffer coordinate system to the
1420     coordinate space used by the application, and vice versa. Be aware
1421     that the default implementations simply return the given objects
1422     as they are.
1423 
1424     \section1 Properties
1425 
1426     \table
1427     \header \o Property \o Functions
1428     \row
1429     \o Size
1430     \o
1431 
1432     The size of the screen can be retrieved using the screenSize()
1433     function. The size is returned in bytes.
1434 
1435     The framebuffer's logical width and height can be retrieved using
1436     width() and height(), respectively. These functions return values
1437     are given in pixels. Alternatively, the physicalWidth() and
1438     physicalHeight() function returns the same metrics in
1439     millimeters. QScreen also provides the deviceWidth() and
1440     deviceHeight() functions returning the physical width and height
1441     of the device in pixels. Note that the latter metrics can differ
1442     from the ones used if the display is centered within the
1443     framebuffer.
1444 
1445     \row
1446     \o Resolution
1447     \o
1448 
1449     Reimplement the setMode() function to be able to set the
1450     framebuffer to a new resolution (width and height) and bit depth.
1451 
1452     The current depth of the framebuffer can be always be retrieved
1453     using the depth() function. Use the pixmapDepth() function to
1454     obtain the preferred depth for pixmaps.
1455 
1456     \row
1457     \o Pixmap Alignment
1458     \o
1459 
1460     Use the pixmapOffsetAlignment() function to retrieve the value to
1461     which the start address of pixmaps held in the graphics card's
1462     memory, should be aligned.
1463 
1464     Use the pixmapLinestepAlignment() to retrieve the value to which
1465     the \e {individual scanlines} of pixmaps should be aligned.
1466 
1467     \row
1468     \o Image Display
1469     \o
1470 
1471     The isInterlaced() function tells whether the screen is displaying
1472     images progressively, and the isTransformed() function whether it
1473     is rotated. The transformOrientation() function can be
1474     reimplemented to return the current rotation.
1475 
1476     \row
1477     \o Scanlines
1478     \o
1479 
1480     Use the linestep() function to retrieve the length of each
1481     scanline of the framebuffer.
1482 
1483     \row
1484     \o Pixel Type
1485     \o
1486 
1487     The pixelType() function returns the screen's pixel storage format as
1488     described by the PixelType enum.
1489 
1490     \endtable
1491 
1492     \section1 Subclassing and Initial Values
1493 
1494     You need to set the following members when implementing a subclass of QScreen:
1495 
1496     \table
1497     \header \o Member \o Initial Value
1498     \row \o \l{QScreen::}{data} \o A pointer to the framebuffer if possible;
1499     0 otherwise.
1500     \row \o \l{QScreen::}{lstep} \o The number of bytes between each scanline
1501     in the framebuffer.
1502     \row \o \l{QScreen::}{w} \o The logical screen width in pixels.
1503     \row \o \l{QScreen::}{h} \o The logical screen height in pixels.
1504     \row \o \l{QScreen::}{dw} \o The real screen width in pixels.
1505     \row \o \l{QScreen::}{dh} \o The real screen height in pixels.
1506     \row \o \l{QScreen::}{d} \o The number of bits per pixel.
1507     \row \o \l{QScreen::}{physWidth} \o The screen width in millimeters.
1508     \row \o \l{QScreen::}{physHeight} \o The screen height in millimeters.
1509     \endtable
1510 
1511     The logical screen values are the same as the real screen values unless the
1512     screen is transformed in some way; e.g., rotated.
1513 
1514     See also the \l{Accelerated Graphics Driver Example} for an example that
1515     shows how to initialize these values.
1516 
1517     \sa QScreenDriverPlugin, QScreenDriverFactory, {Qt for Embedded Linux Display
1518     Management}
1519 */
1520 
1521 /*!
1522     \enum QScreen::PixelType
1523 
1524     This enum describes the pixel storage format of the screen,
1525     i.e. the order of the red (R), green (G) and blue (B) components
1526     of a pixel.
1527 
1528     \value NormalPixel Red-green-blue (RGB)
1529     \value BGRPixel Blue-green-red (BGR)
1530 
1531     \sa pixelType()
1532 */
1533 
1534 /*!
1535     \enum QScreen::ClassId
1536 
1537     This enum defines the class identifiers for the known screen subclasses.
1538 
1539     \value LinuxFBClass QLinuxFBScreen
1540     \value TransformedClass QTransformedScreen
1541     \value VNCClass QVNCScreen
1542     \value MultiClass QMultiScreen
1543     \value VFbClass QVFbScreen
1544     \value DirectFBClass QDirectFBScreen
1545     \value SvgalibClass QSvgalibScreen
1546     \value ProxyClass QProxyScreen
1547     \value GLClass QGLScreen
1548     \value IntfbClass QIntfbScreen
1549     \value CustomClass Unknown QScreen subclass
1550 
1551     \sa classId()
1552 */
1553 
1554 /*!
1555   \variable QScreen::screenclut
1556   \brief the color table
1557 
1558   Initialize this variable in a subclass using a paletted screen mode,
1559   and initialize its partner, QScreen::screencols.
1560 
1561   \sa screencols
1562 */
1563 
1564 /*!
1565   \variable QScreen::screencols
1566   \brief the number of entries in the color table
1567 
1568   Initialize this variable in a subclass using a paletted screen mode,
1569   and initialize its partner, QScreen::screenclut.
1570 
1571   \sa screenclut
1572 */
1573 
1574 /*!
1575   \variable QScreen::data
1576   \brief points to the first visible pixel in the frame buffer.
1577 
1578   You must initialize this variable if you are using the default
1579   implementation of non-buffered painting Qt::WA_PaintOnScreen,
1580   QPixmap::grabWindow() or QDirectPainter::frameBuffer(). If you
1581   initialize this variable, you must also initialize QScreen::size and
1582   QScreen::mapsize.
1583 
1584   \sa QScreen::size, QScreen::mapsize
1585 */
1586 
1587 /*!
1588   \variable QScreen::w
1589   \brief the logical width of the screen.
1590 
1591   This variable \e{must} be initialized by a subclass.
1592 */
1593 
1594 /*!
1595   \variable QScreen::lstep
1596   \brief the number of bytes representing a line in the frame buffer.
1597 
1598   i.e., \e{line step}. \c {data[lstep * 2]} is the address of the
1599   first visible pixel in the third line of the frame buffer.
1600 
1601   \sa data
1602 */
1603 
1604 /*!
1605   \variable QScreen::h
1606   \brief the logical height of the screen.
1607 
1608   This variable \e{must} be initialized by a subclass.
1609 */
1610 
1611 /*!
1612   \variable QScreen::d
1613   \brief the pixel depth
1614 
1615   This is the number of significant bits used to set a pixel
1616   color. This variable \e{must} be initialized by a subclass.
1617 */
1618 
1619 /*!
1620   \variable QScreen::pixeltype
1621   \brief set to BGRPixel
1622 
1623   Set this variable to BGRPixel in a subclass, if the screen pixel
1624   format is a BGR type and you have used setPixelFormat() to set the
1625   pixel format to the corresponding RGB format. e.g., you have set the
1626   pixel format to QImage::Format_RGB555, but your screen really uses
1627   BGR, not RGB.
1628 */
1629 
1630 /*!
1631   \variable QScreen::grayscale
1632   \brief the gray scale screen mode flag
1633 
1634   Set this variable to true in a subclass, if you are using a
1635   grayscale screen mode. e.g., in an 8-bit mode where you don't want
1636   to use the palette, but you want to use the grayscales.
1637 */
1638 
1639 /*!
1640   \variable QScreen::dw
1641   \brief the device width
1642 
1643   This is the number of pixels in a row of the physical screen.  It
1644   \e{must} be initialized by a subclass. Normally, it should be set to
1645   the logical width QScreen::w, but it might be different, e.g., if
1646   you are doing rotations in software.
1647 
1648   \sa QScreen::w
1649 */
1650 
1651 /*!
1652   \variable QScreen::dh
1653   \brief the device height
1654 
1655   This is the number of pixels in a column of the physical screen.  It
1656   \e{must} be initialized by a subclass. Normally, it should be set to
1657   the logical height QScreen::h, but it might be different, e.g., if
1658   you are doing rotations in software.
1659 
1660   \sa QScreen::h
1661 */
1662 
1663 /*!
1664   \variable QScreen::size
1665   \brief the number of bytes in the visible region of the frame buffer
1666 
1667   This is the number of bytes in the visible part of the block pointed
1668   to by the QScreen::data pointer. You must initialize this variable
1669   if you initialize the QScreen::data pointer.
1670 
1671   \sa QScreen::data, QScreen::mapsize
1672 */
1673 
1674 /*!
1675   \variable QScreen::mapsize
1676   \brief the total number of bytes in the frame buffer
1677 
1678   This is the total number of bytes in the block pointed to by the
1679   QScreen::data pointer. You must initialize this variable if you
1680   initialize the QScreen::data pointer.
1681 
1682   \sa QScreen::data, QScreen::size
1683 */
1684 
1685 /*!
1686   \variable QScreen::physWidth
1687   \brief the physical width of the screen in millimeters.
1688 
1689   Currently, this variable is used when calculating the screen DPI,
1690   which in turn is used when deciding the actual font size Qt is
1691   using.
1692 */
1693 
1694 /*!
1695   \variable QScreen::physHeight
1696   \brief the physical height of the screen in millimeters.
1697 
1698   Currently, this variable is used when calculating the screen DPI,
1699   which in turn is used when deciding the actual font size Qt is
1700   using.
1701 */
1702 
1703 /*!
1704     \fn static QScreen* QScreen::instance()
1705 
1706     Returns a pointer to the application's QScreen instance.
1707 
1708     If this screen consists of several subscreens, operations to the
1709     returned instance will affect all its subscreens. Use the
1710     subscreens() function to retrieve access to a particular
1711     subscreen.
1712 
1713     \sa subScreens(), subScreenIndexAt()
1714 */
1715 
1716 /*!
1717     \fn QList<QScreen*> QScreen::subScreens() const
1718     \since 4.2
1719 
1720     Returns a list of this screen's subscreens. Use the
1721     subScreenIndexAt() function to retrieve the index of a screen at a
1722     given position.
1723 
1724     Note that if \e this screen consists of several subscreens,
1725     operations to \e this instance will affect all subscreens by
1726     default.
1727 
1728     \sa instance(), subScreenIndexAt()
1729 */
1730 
1731 /*!
1732     \fn int QScreen::physicalWidth() const
1733     \since 4.2
1734 
1735     Returns the physical width of the screen in millimeters.
1736 
1737     \sa width(), deviceWidth(), physicalHeight()
1738 */
1739 
1740 /*!
1741     \fn int QScreen::physicalHeight() const
1742     \since 4.2
1743 
1744     Returns the physical height of the screen in millimeters.
1745 
1746     \sa height(), deviceHeight(), physicalWidth()
1747 */
1748 
1749 /*!
1750     \fn virtual bool QScreen::initDevice() = 0
1751 
1752     This function is called by the \l{Qt for Embedded Linux} server to
1753     initialize the framebuffer. Note that a server application will call the
1754     connect() function prior to this function.
1755 
1756     Implement this function to make accelerated drivers set up the
1757     graphics card. Return true to indicate success and false to indicate
1758     failure.
1759 
1760     \sa shutdownDevice(), connect()
1761 */
1762 
1763 /*!
1764     \fn virtual bool QScreen::connect(const QString &displaySpec) = 0
1765 
1766     This function is called by every \l{Qt for Embedded Linux}
1767     application on startup, and must be implemented to map in the
1768     framebuffer and the accelerated drivers that the graphics card
1769     control registers.  Note that connect must be called \e before
1770     the initDevice() function.
1771 
1772     Ensure that true is returned if a connection to the screen device
1773     is made. Otherwise, return false. Upon making the connection, the
1774     function should read out the parameters of the framebuffer and use
1775     them as required to set this class's protected variables.
1776 
1777     The \a displaySpec argument is passed by the QWS_DISPLAY
1778     environment variable or the -display command line parameter, and
1779     has the following syntax:
1780 
1781     \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 0
1782 
1783     For example, to use the mach64 driver on fb1 as display 2:
1784 
1785     \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 1
1786 
1787     See \l{Qt for Embedded Linux Display Management} for more details.
1788 
1789     \sa disconnect(), initDevice(), {Running Qt for Embedded Linux Applications}
1790 */
1791 
1792 /*!
1793     \fn QScreen::disconnect()
1794 
1795     This function is called by every \l{Qt for Embedded Linux} application
1796     before exiting, and must be implemented to unmap the
1797     framebuffer. Note that a server application will call the
1798     shutdownDevice() function prior to this function.
1799 
1800     \sa connect(), shutdownDevice(), {Running Qt for Embedded Linux
1801     Applications}
1802 */
1803 
1804 /*!
1805     \fn QScreen::setMode(int width, int height, int depth)
1806 
1807     Implement this function to reset the framebuffer's resolution (\a
1808     width and \a height) and bit \a depth.
1809 
1810     After the resolution has been set, existing paint engines will be
1811     invalid and the framebuffer should be completely redrawn. In a
1812     multiple-process situation, all other applications must be
1813     notified to reset their mode and update themselves accordingly.
1814 */
1815 
1816 /*!
1817     \fn QScreen::blank(bool on)
1818 
1819     Prevents the screen driver form displaying any content on the
1820     screen.
1821 
1822     Note that the default implementation does nothing.
1823 
1824     Reimplement this function to prevent the screen driver from
1825     displaying any contents on the screen if \a on is true; otherwise
1826     the contents is expected to be shown.
1827 
1828     \sa blit()
1829 */
1830 
1831 /*!
1832     \fn int QScreen::pixmapOffsetAlignment()
1833 
1834     Returns the value (in bits) to which the start address of pixmaps
1835     held in the graphics card's memory, should be aligned.
1836 
1837     Note that the default implementation returns 64; reimplement this
1838     function to override the return value, e.g., when implementing an
1839     accelerated driver (see the \l {Adding an Accelerated Graphics
1840     Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
1841     documentation for details).
1842 
1843     \sa pixmapLinestepAlignment()
1844 */
1845 
1846 /*!
1847     \fn int QScreen::pixmapLinestepAlignment()
1848 
1849     Returns the value (in bits) to which individual scanlines of
1850     pixmaps held in the graphics card's memory, should be
1851     aligned.
1852 
1853     Note that the default implementation returns 64; reimplement this
1854     function to override the return value, e.g., when implementing an
1855     accelerated driver (see the \l {Adding an Accelerated Graphics
1856     Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
1857     documentation for details).
1858 
1859     \sa pixmapOffsetAlignment()
1860 */
1861 
1862 /*!
1863     \fn QScreen::width() const
1864 
1865     Returns the logical width of the framebuffer in pixels.
1866 
1867     \sa deviceWidth(), physicalWidth(), height()
1868 */
1869 
1870 /*!
1871     \fn int QScreen::height() const
1872 
1873     Returns the logical height of the framebuffer in pixels.
1874 
1875     \sa deviceHeight(), physicalHeight(), width()
1876 */
1877 
1878 /*!
1879     \fn QScreen::depth() const
1880 
1881     Returns the depth of the framebuffer, in bits per pixel.
1882 
1883     Note that the returned depth is the number of bits each pixel
1884     fills rather than the number of significant bits, so 24bpp and
1885     32bpp express the same range of colors (8 bits of red, green and
1886     blue).
1887 
1888     \sa clut(), pixmapDepth()
1889 */
1890 
1891 /*!
1892     \fn int QScreen::pixmapDepth() const
1893 
1894     Returns the preferred depth for pixmaps, in bits per pixel.
1895 
1896     \sa depth()
1897 */
1898 
1899 /*!
1900     \fn QScreen::linestep() const
1901 
1902     Returns the length of each scanline of the framebuffer in bytes.
1903 
1904     \sa isInterlaced()
1905 */
1906 
1907 /*!
1908     \fn QScreen::deviceWidth() const
1909 
1910     Returns the physical width of the framebuffer device in pixels.
1911 
1912     Note that the returned width can differ from the width which
1913     \l{Qt for Embedded Linux} will actually use, that is if the display is
1914     centered within the framebuffer.
1915 
1916     \sa width(), physicalWidth(), deviceHeight()
1917 */
1918 
1919 /*!
1920     \fn QScreen::deviceHeight() const
1921 
1922     Returns the full height of the framebuffer device in pixels.
1923 
1924     Note that the returned height can differ from the height which
1925     \l{Qt for Embedded Linux} will actually use, that is if the display is
1926     centered within the framebuffer.
1927 
1928     \sa height(), physicalHeight(), deviceWidth()
1929 */
1930 
1931 /*!
1932     \fn uchar *QScreen::base() const
1933 
1934     Returns a pointer to the beginning of the framebuffer.
1935 
1936     \sa onCard(), region(), totalSize()
1937 */
1938 
1939 /*!
1940     \fn uchar *QScreen::cache(int)
1941 
1942     \internal
1943 
1944     This function is used to store pixmaps in graphics memory for the
1945     use of the accelerated drivers. See QLinuxFbScreen (where the
1946     caching is implemented) for more information.
1947 */
1948 
1949 /*!
1950     \fn QScreen::uncache(uchar *)
1951 
1952     \internal
1953 
1954     This function is called on pixmap destruction to remove them from
1955     graphics card memory.
1956 */
1957 
1958 /*!
1959     \fn QScreen::screenSize() const
1960 
1961     Returns the size of the screen in bytes.
1962 
1963     The screen size is always located at the beginning of framebuffer
1964     memory, i.e. it can also be retrieved using the base() function.
1965 
1966     \sa base(), region()
1967 */
1968 
1969 /*!
1970     \fn QScreen::totalSize() const
1971 
1972     Returns the size of the available graphics card memory (including
1973     the screen) in bytes.
1974 
1975     \sa onCard()
1976 */
1977 
1978 // Unaccelerated screen/driver setup. Can be overridden by accelerated
1979 // drivers
1980 
1981 /*!
1982     \fn QScreen::QScreen(int displayId)
1983 
1984     Constructs a new screen driver.
1985 
1986     The \a displayId identifies the \l{Qt for Embedded Linux} server to connect
1987     to.
1988 */
1989 
1990 /*!
1991     \fn QScreen::clut()
1992 
1993     Returns a pointer to the screen's color lookup table (i.e. its
1994     color palette).
1995 
1996     Note that this function only apply in paletted modes like 8-bit,
1997     i.e. in modes where only the palette indexes (and not the actual
1998     color values) are stored in memory.
1999 
2000     \sa alloc(), depth(), colorCount()
2001 */
2002 
2003 /*!
2004     \obsolete
2005     \fn int QScreen::numCols()
2006 
2007     \sa colorCount()
2008 */
2009 
2010 /*!
2011     \since 4.6
2012     \fn int QScreen::colorCount()
2013 
2014     Returns the number of entries in the screen's color lookup table
2015     (i.e. its color palette). A pointer to the color table can be
2016     retrieved using the clut() function.
2017 
2018     \sa clut(), alloc()
2019 */
2020 
2021 /*!
2022     \since 4.4
2023 
2024     Constructs a new screen driver.
2025 
2026     The \a display_id identifies the \l{Qt for Embedded Linux}
2027     server to connect to. The \a classId specifies the class
2028     identifier.
2029 */
QScreen(int display_id,ClassId classId)2030 QScreen::QScreen(int display_id, ClassId classId)
2031     : screencols(0), data(0), entries(0), entryp(0), lowest(0),
2032       w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
2033       dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
2034       physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this, classId))
2035 {
2036     clearCacheFunc = 0;
2037 }
2038 
QScreen(int display_id)2039 QScreen::QScreen(int display_id)
2040     : screencols(0), data(0), entries(0), entryp(0), lowest(0),
2041       w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
2042       dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
2043       physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this))
2044 {
2045     clearCacheFunc = 0;
2046 }
2047 
2048 /*!
2049     Destroys this screen driver.
2050 */
2051 
~QScreen()2052 QScreen::~QScreen()
2053 {
2054     delete d_ptr;
2055 }
2056 
2057 /*!
2058     This function is called by the \l{Qt for Embedded Linux} server before it
2059     calls the disconnect() function when exiting.
2060 
2061     Note that the default implementation only hides the mouse cursor;
2062     reimplement this function to do the necessary graphics card
2063     specific cleanup.
2064 
2065     \sa initDevice(), disconnect()
2066 */
2067 
shutdownDevice()2068 void QScreen::shutdownDevice()
2069 {
2070 #ifndef QT_NO_QWS_CURSOR
2071     if (qt_screencursor)
2072         qt_screencursor->hide();
2073 #endif
2074 }
2075 
2076 extern bool qws_accel; //in qapplication_qws.cpp
2077 
2078 /*!
2079     \fn PixelType QScreen::pixelType() const
2080 
2081     Returns the pixel storage format of the screen.
2082 */
2083 
2084 /*!
2085   Returns the pixel format of the screen, or \c QImage::Format_Invalid
2086   if the pixel format is not a supported image format.
2087 
2088 */
pixelFormat() const2089 QImage::Format QScreen::pixelFormat() const
2090 {
2091     return d_ptr->pixelFormat;
2092 }
2093 
2094 /*!
2095   Sets the screen's pixel format to \a format.
2096  */
setPixelFormat(QImage::Format format)2097 void QScreen::setPixelFormat(QImage::Format format)
2098 {
2099     d_ptr->pixelFormat = format;
2100 }
2101 
2102 
2103 /*!
2104     \fn int QScreen::alloc(unsigned int red, unsigned int green, unsigned int blue)
2105 
2106     Returns the index in the screen's palette which is the closest
2107     match to the given RGB value (\a red, \a green, \a blue).
2108 
2109     Note that this function only apply in paletted modes like 8-bit,
2110     i.e. in modes where only the palette indexes (and not the actual
2111     color values) are stored in memory.
2112 
2113     \sa clut(), colorCount()
2114 */
2115 
alloc(unsigned int r,unsigned int g,unsigned int b)2116 int QScreen::alloc(unsigned int r,unsigned int g,unsigned int b)
2117 {
2118     int ret = 0;
2119     if (d == 8) {
2120         if (grayscale)
2121             return qGray(r, g, b);
2122 
2123         // First we look to see if we match a default color
2124         const int pos = (r + 25) / 51 * 36 + (g + 25) / 51 * 6 + (b + 25) / 51;
2125         if (pos < screencols && screenclut[pos] == qRgb(r, g, b)) {
2126             return pos;
2127         }
2128 
2129         // search for nearest color
2130         unsigned int mindiff = 0xffffffff;
2131         unsigned int diff;
2132         int dr,dg,db;
2133 
2134         for (int loopc = 0; loopc < screencols; ++loopc) {
2135             dr = qRed(screenclut[loopc]) - r;
2136             dg = qGreen(screenclut[loopc]) - g;
2137             db = qBlue(screenclut[loopc]) - b;
2138             diff = dr*dr + dg*dg + db*db;
2139 
2140             if (diff < mindiff) {
2141                 ret = loopc;
2142                 if (!diff)
2143                     break;
2144                 mindiff = diff;
2145             }
2146         }
2147     } else if (d == 4) {
2148         ret = qGray(r, g, b) >> 4;
2149     } else if (d == 1) {
2150         ret = qGray(r, g, b) >= 128;
2151     } else {
2152         qFatal("cannot alloc %dbpp color", d);
2153     }
2154 
2155     return ret;
2156 }
2157 
2158 /*!
2159     Saves the current state of the graphics card.
2160 
2161     For example, hardware screen drivers should reimplement the save()
2162     and restore() functions to save and restore its registers,
2163     enabling swintching between virtual consoles.
2164 
2165     Note that the default implementation does nothing.
2166 
2167     \sa restore()
2168 */
2169 
save()2170 void QScreen::save()
2171 {
2172 }
2173 
2174 /*!
2175     Restores the previously saved state of the graphics card.
2176 
2177     For example, hardware screen drivers should reimplement the save()
2178     and restore() functions to save and restore its registers,
2179     enabling swintching between virtual consoles.
2180 
2181     Note that the default implementation does nothing.
2182 
2183     \sa save()
2184 */
2185 
restore()2186 void QScreen::restore()
2187 {
2188 }
2189 
blank(bool)2190 void QScreen::blank(bool)
2191 {
2192 }
2193 
2194 /*!
2195     \internal
2196 */
2197 
set(unsigned int,unsigned int,unsigned int,unsigned int)2198 void QScreen::set(unsigned int, unsigned int, unsigned int, unsigned int)
2199 {
2200 }
2201 
2202 /*!
2203     \fn bool QScreen::supportsDepth(int depth) const
2204 
2205     Returns true if the screen supports the specified color \a depth;
2206     otherwise returns false.
2207 
2208     \sa clut()
2209 */
2210 
supportsDepth(int d) const2211 bool QScreen::supportsDepth(int d) const
2212 {
2213     if (false) {
2214         //Just to simplify the ifdeffery
2215 #ifdef QT_QWS_DEPTH_1
2216     } else if(d==1) {
2217         return true;
2218 #endif
2219 #ifdef QT_QWS_DEPTH_4
2220     } else if(d==4) {
2221         return true;
2222 #endif
2223 #ifdef QT_QWS_DEPTH_8
2224     } else if(d==8) {
2225         return true;
2226 #endif
2227 #ifdef QT_QWS_DEPTH_16
2228     } else if(d==16) {
2229         return true;
2230 #endif
2231 #ifdef QT_QWS_DEPTH_15
2232     } else if (d == 15) {
2233         return true;
2234 #endif
2235 #ifdef QT_QWS_DEPTH_18
2236     } else if(d==18 || d==19) {
2237         return true;
2238 #endif
2239 #ifdef QT_QWS_DEPTH_24
2240     } else if(d==24) {
2241         return true;
2242 #endif
2243 #ifdef QT_QWS_DEPTH_32
2244     } else if(d==32) {
2245         return true;
2246 #endif
2247     }
2248     return false;
2249 }
2250 
2251 /*!
2252     \fn bool QScreen::onCard(const unsigned char *buffer) const
2253 
2254     Returns true if the specified \a buffer is within the graphics
2255     card's memory; otherwise returns false (i.e. if it's in main RAM).
2256 
2257     \sa base(), totalSize()
2258 */
2259 
onCard(const unsigned char * p) const2260 bool QScreen::onCard(const unsigned char * p) const
2261 {
2262     long t=(unsigned long)p;
2263     long bmin=(unsigned long)data;
2264     if (t < bmin)
2265         return false;
2266     if(t >= bmin+mapsize)
2267         return false;
2268     return true;
2269 }
2270 
2271 /*!
2272     \fn bool QScreen::onCard(const unsigned char * buffer, ulong& offset) const
2273     \overload
2274 
2275     If the specified \a buffer is within the graphics card's memory,
2276     this function stores the offset from the start of graphics card
2277     memory (in bytes), in the location specified by the \a offset
2278     parameter.
2279 */
2280 
onCard(const unsigned char * p,ulong & offset) const2281 bool QScreen::onCard(const unsigned char * p, ulong& offset) const
2282 {
2283     long t=(unsigned long)p;
2284     long bmin=(unsigned long)data;
2285     if (t < bmin)
2286         return false;
2287     long o = t - bmin;
2288     if (o >= mapsize)
2289         return false;
2290     offset = o;
2291     return true;
2292 }
2293 
2294 /*
2295 #if !defined(QT_NO_QWS_REPEATER)
2296     { "Repeater", qt_get_screen_repeater, 0 },
2297 #endif
2298 #if defined(QT_QWS_EE)
2299     { "EE", qt_get_screen_ee, 0 },
2300 #endif
2301 
2302 */
2303 
2304 /*
2305 Given a display_id (number of the \l{Qt for Embedded Linux} server to connect to)
2306 and a spec (e.g. Mach64:/dev/fb0) return a QScreen-descendant.
2307 The QScreenDriverFactory is queried for a suitable driver and, if found,
2308 asked to create a driver.
2309 People writing new graphics drivers should either hook their own
2310 QScreen-descendant into QScreenDriverFactory or use the QScreenDriverPlugin
2311 to make a dynamically loadable driver.
2312 */
2313 
qt_get_screen(int display_id,const char * spec)2314 Q_GUI_EXPORT QScreen* qt_get_screen(int display_id, const char *spec)
2315 {
2316     QString displaySpec = QString::fromAscii(spec);
2317     QString driver = displaySpec;
2318     int colon = displaySpec.indexOf(QLatin1Char(':'));
2319     if (colon >= 0)
2320         driver.truncate(colon);
2321     driver = driver.trimmed();
2322 
2323     bool foundDriver = false;
2324     QString driverName = driver;
2325 
2326     QStringList driverList;
2327     if (!driver.isEmpty())
2328         driverList << driver;
2329     else
2330         driverList = QScreenDriverFactory::keys();
2331 
2332     for (int i = 0; i < driverList.size(); ++i) {
2333         const QString driverName = driverList.at(i);
2334         qt_screen = QScreenDriverFactory::create(driverName, display_id);
2335         if (qt_screen) {
2336             foundDriver = true;
2337             if (qt_screen->connect(displaySpec)) {
2338                 return qt_screen;
2339             } else {
2340                 delete qt_screen;
2341                 qt_screen = 0;
2342             }
2343         }
2344     }
2345 
2346     if (driver.isNull())
2347         qFatal("No suitable driver found");
2348     else if (foundDriver)
2349         qFatal("%s: driver cannot connect", driver.toLatin1().constData());
2350     else
2351         qFatal("%s: driver not found", driver.toLatin1().constData());
2352 
2353     return 0;
2354 }
2355 
2356 #ifndef QT_NO_QWS_CURSOR
blendCursor(QImage * dest,const QImage & cursor,const QPoint & offset)2357 static void blendCursor(QImage *dest, const QImage &cursor, const QPoint &offset)
2358 {
2359     QRasterBuffer rb;
2360     rb.prepare(dest);
2361 
2362     QSpanData spanData;
2363     spanData.init(&rb, 0);
2364     spanData.type = QSpanData::Texture;
2365     spanData.initTexture(&cursor, 256);
2366     spanData.dx = -offset.x();
2367     spanData.dy = -offset.y();
2368     if (!spanData.blend)
2369         return;
2370 
2371     const QRect rect = QRect(offset, cursor.size())
2372                        & QRect(QPoint(0, 0), dest->size());
2373     const int w = rect.width();
2374     const int h = rect.height();
2375 
2376     QVarLengthArray<QT_FT_Span, 32> spans(h);
2377     for (int i = 0; i < h; ++i) {
2378         spans[i].x = rect.x();
2379         spans[i].len = w;
2380         spans[i].y = rect.y() + i;
2381         spans[i].coverage = 255;
2382     }
2383     spanData.blend(h, spans.constData(), &spanData);
2384 }
2385 #endif // QT_NO_QWS_CURSOR
2386 
2387 /*!
2388     \fn void QScreen::exposeRegion(QRegion region, int windowIndex)
2389 
2390     This function is called by the \l{Qt for Embedded Linux} server whenever a
2391     screen update is required. \a region is the area on the screen
2392     that must be updated, and \a windowIndex is the index into
2393     QWSServer::clientWindows() of the window that required the
2394     update. QWSWindow::state() gives more information about the cause.
2395 
2396     The default implementation composes the
2397     affected windows and paints the given \a region on screen by
2398     calling the blit() and solidFill() functions
2399 
2400     This function can be reimplemented to perform composition in
2401     hardware, or to perform transition effects.
2402     For simpler hardware acceleration, or to interface with
2403     this is typically done by reimplementing the blit() and
2404     solidFill() functions instead.
2405 
2406     Note that there is no need to call this function explicitly.
2407 
2408     \sa blit(), solidFill(), blank()
2409 */
exposeRegion(QRegion r,int windowIndex)2410 void QScreen::exposeRegion(QRegion r, int windowIndex)
2411 {
2412     r &= region();
2413     if (r.isEmpty())
2414         return;
2415 
2416     int changing = windowIndex;
2417     // when we have just lowered a window, we have to expose all the windows below where the
2418     // window used to be.
2419     if (changing && qwsServer->clientWindows().at(changing)->state() == QWSWindow::Lowering)
2420         changing = 0;
2421 #ifdef QTOPIA_PERFTEST
2422     static enum { PerfTestUnknown, PerfTestOn, PerfTestOff } perfTestState = PerfTestUnknown;
2423     if(PerfTestUnknown == perfTestState) {
2424         if(::getenv("QTOPIA_PERFTEST"))
2425             perfTestState = PerfTestOn;
2426         else
2427             perfTestState = PerfTestOff;
2428     }
2429     if(PerfTestOn == perfTestState) {
2430         QWSWindow *changed = qwsServer->clientWindows().at(changing);
2431         if(!changed->client()->identity().isEmpty())
2432             qDebug() << "Performance  :  expose_region  :"
2433                      << changed->client()->identity()
2434                      << r.boundingRect() << ": "
2435                      << qPrintable( QTime::currentTime().toString( "h:mm:ss.zzz" ) );
2436     }
2437 #endif
2438 
2439     const QRect bounds = r.boundingRect();
2440     QRegion blendRegion;
2441     QImage *blendBuffer = 0;
2442 
2443 #ifndef QT_NO_QWS_CURSOR
2444     if (qt_screencursor && !qt_screencursor->isAccelerated()) {
2445         blendRegion = r & qt_screencursor->boundingRect();
2446     }
2447 #endif
2448     compose(0, r, blendRegion, &blendBuffer, changing);
2449 
2450     if (blendBuffer && !blendBuffer->isNull()) {
2451         const QPoint offset = blendRegion.boundingRect().topLeft();
2452 #ifndef QT_NO_QWS_CURSOR
2453         if (qt_screencursor && !qt_screencursor->isAccelerated()) {
2454             const QRect cursorRect = qt_screencursor->boundingRect();
2455             if (blendRegion.intersects(cursorRect)) {
2456                 blendCursor(blendBuffer, qt_screencursor->image(),
2457                             cursorRect.topLeft() - offset);
2458             }
2459         }
2460 #endif // QT_NO_QWS_CURSOR
2461         blit(*blendBuffer, offset, blendRegion);
2462         delete blendBuffer;
2463     }
2464 
2465     if (r.rectCount() == 1) {
2466         setDirty(r.boundingRect());
2467     } else {
2468         const QVector<QRect> rects = r.rects();
2469         for (int i = 0; i < rects.size(); ++i)
2470             setDirty(rects.at(i));
2471     }
2472 }
2473 
2474 /*!
2475     \fn void QScreen::blit(const QImage &image, const QPoint &topLeft, const QRegion &region)
2476 
2477     Copies the given \a region in the given \a image to the point
2478     specified by \a topLeft using device coordinates.
2479 
2480     This function is called from the exposeRegion() function; it is
2481     not intended to be called explicitly.
2482 
2483     Reimplement this function to make use of \l{Adding an Accelerated
2484     Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
2485     this function must be reimplemented if the framebuffer format is
2486     not supported by \l{Qt for Embedded Linux} (See the
2487     \l{Qt for Embedded Linux Display Management}{Display Management}
2488     documentation for more details).
2489 
2490     \sa exposeRegion(), solidFill(), blank()
2491 */
blit(const QImage & img,const QPoint & topLeft,const QRegion & reg)2492 void QScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &reg)
2493 {
2494     const QRect bound = (region() & QRect(topLeft, img.size())).boundingRect();
2495     QWSDisplay::grab();
2496     d_ptr->blit(this, img, topLeft - offset(),
2497             (reg & bound).translated(-topLeft));
2498     QWSDisplay::ungrab();
2499 }
2500 
2501 #ifdef QT_QWS_CLIENTBLIT
2502 /*!
2503   Returns true if this screen driver supports calling QScreen::blit() and
2504   QScreen::setDirty() directly from non-server applications, otherwise returns
2505   false.
2506 
2507   If available, this is used to optimize the performance of non-occluded, opaque
2508   client windows by removing the server round trip when they are updated.
2509 
2510   \sa setSupportsBlitInClients()
2511  */
supportsBlitInClients() const2512 bool QScreen::supportsBlitInClients() const
2513 {
2514     return d_ptr->supportsBlitInClients;
2515 }
2516 
2517 /*!
2518   If \a supported, the screen driver is marked as supporting blitting directly
2519   from non-server applications.
2520 
2521   \sa supportsBlitInClients()
2522  */
setSupportsBlitInClients(bool supported)2523 void QScreen::setSupportsBlitInClients(bool supported)
2524 {
2525     d_ptr->supportsBlitInClients = supported;
2526 }
2527 #endif
2528 
2529 /*!
2530     \internal
2531 */
2532 
blit(QWSWindow * win,const QRegion & clip)2533 void QScreen::blit(QWSWindow *win, const QRegion &clip)
2534 {
2535     QWSWindowSurface *surface = win->windowSurface();
2536     if (!surface)
2537         return;
2538 
2539     const QImage &img = surface->image();
2540     if (img.isNull())
2541         return;
2542 
2543     const QRegion rgn = clip & win->paintedRegion();
2544     if (rgn.isEmpty())
2545         return;
2546 
2547     surface->lock();
2548     blit(img, win->requestedRegion().boundingRect().topLeft(), rgn);
2549     surface->unlock();
2550 }
2551 
2552 struct fill_data {
2553     quint32 color;
2554     uchar *data;
2555     int lineStep;
2556     int x;
2557     int y;
2558     int w;
2559     int h;
2560 };
2561 
2562 /*!
2563     Fills the given \a region of the screen with the specified \a
2564     color.
2565 
2566     This function is called from the exposeRegion() function; it is
2567     not intended to be called explicitly.
2568 
2569     Reimplement this function to make use of \l{Adding an Accelerated
2570     Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
2571     this function must be reimplemented if the framebuffer format is
2572     not supported by \l{Qt for Embedded Linux} (See the
2573     \l{Qt for Embedded Linux Display Management}{Display Management}
2574     documentation for more details).
2575 
2576     \sa exposeRegion(), blit(), blank()
2577 */
2578 // the base class implementation works in device coordinates, so that transformed drivers can use it
solidFill(const QColor & color,const QRegion & region)2579 void QScreen::solidFill(const QColor &color, const QRegion &region)
2580 {
2581     QWSDisplay::grab();
2582     d_ptr->solidFill(this, color,
2583                      region.translated(-offset()) & QRect(0, 0, dw, dh));
2584     QWSDisplay::ungrab();
2585 }
2586 
2587 /*!
2588     \since 4.2
2589 
2590     Creates and returns a new window surface matching the given \a
2591     key.
2592 
2593     The server application will call this function whenever it needs
2594     to create a server side representation of a window, e.g. when
2595     copying the content of memory to the screen using the screen
2596     driver.
2597 
2598     Note that this function must be reimplemented when adding an
2599     accelerated graphics driver. See the
2600     \l{Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
2601     {Adding an Accelerated Graphics Driver} documentation for details.
2602 
2603     \sa {Qt for Embedded Linux Architecture}
2604 */
createSurface(const QString & key) const2605 QWSWindowSurface* QScreen::createSurface(const QString &key) const
2606 {
2607 #ifndef QT_NO_PAINTONSCREEN
2608     if (key == QLatin1String("OnScreen"))
2609         return new QWSOnScreenSurface;
2610     else
2611 #endif
2612     if (key == QLatin1String("mem"))
2613         return new QWSLocalMemSurface;
2614 #ifndef QT_NO_QWS_MULTIPROCESS
2615     else if (key == QLatin1String("shm"))
2616         return new QWSSharedMemSurface;
2617 #endif
2618 #ifndef QT_NO_PAINT_DEBUG
2619     else if (key == QLatin1String("Yellow"))
2620         return new QWSYellowSurface;
2621 #endif
2622 #ifndef QT_NO_DIRECTPAINTER
2623     else if (key == QLatin1String("DirectPainter"))
2624         return new QWSDirectPainterSurface;
2625 #endif
2626 
2627     return 0;
2628 }
2629 
2630 #ifndef QT_NO_PAINTONSCREEN
isWidgetPaintOnScreen(const QWidget * w)2631 bool QScreen::isWidgetPaintOnScreen(const QWidget *w)
2632 {
2633     static int doOnScreen = -1;
2634     if (doOnScreen == -1) {
2635         const QByteArray env = qgetenv("QT_ONSCREEN_PAINT");
2636         if (env == "force")
2637             doOnScreen = 2;
2638         else
2639             doOnScreen = (env.toInt() > 0 ? 1 : 0);
2640     }
2641 
2642     if (doOnScreen == 2) // force
2643         return true;
2644 
2645     if (doOnScreen == 0 && !w->testAttribute(Qt::WA_PaintOnScreen))
2646         return false;
2647 
2648     return w->d_func()->isOpaque;
2649 }
2650 #endif
2651 
2652 /*!
2653     \overload
2654 
2655     Creates and returns a new window surface for the given \a widget.
2656 */
createSurface(QWidget * widget) const2657 QWSWindowSurface* QScreen::createSurface(QWidget *widget) const
2658 {
2659 #ifndef QT_NO_PAINTONSCREEN
2660     if (isWidgetPaintOnScreen(widget) && base())
2661         return new QWSOnScreenSurface(widget);
2662     else
2663 #endif
2664     if (QApplication::type() == QApplication::GuiServer)
2665         return new QWSLocalMemSurface(widget);
2666 #ifndef QT_NO_QWS_MULTIPROCESS
2667     else
2668         return new QWSSharedMemSurface(widget);
2669 #endif
2670 
2671     return 0;
2672 }
2673 
compose(int level,const QRegion & exposed,QRegion & blend,QImage ** blendbuffer,int changing_level)2674 void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
2675                       QImage **blendbuffer, int changing_level)
2676 {
2677     QRect exposed_bounds = exposed.boundingRect();
2678     QWSWindow *win = 0;
2679     do {
2680         win = qwsServer->clientWindows().value(level); // null is background
2681         ++level;
2682     } while (win && !win->paintedRegion().boundingRect().intersects(exposed_bounds));
2683 
2684     QWSWindowSurface *surface = (win ? win->windowSurface() : 0);
2685     bool above_changing = level <= changing_level; // 0 is topmost
2686 
2687     QRegion exposedBelow = exposed;
2688     bool opaque = true;
2689 
2690     if (win) {
2691         opaque = win->isOpaque() || !surface->isBuffered();
2692         if (opaque) {
2693             exposedBelow -= win->paintedRegion();
2694             if (above_changing || !surface->isBuffered())
2695                 blend -= exposed & win->paintedRegion();
2696         } else {
2697             blend += exposed & win->paintedRegion();
2698         }
2699     }
2700     if (win && !exposedBelow.isEmpty()) {
2701         compose(level, exposedBelow, blend, blendbuffer, changing_level);
2702     } else {
2703         QSize blendSize = blend.boundingRect().size();
2704         if (!blendSize.isNull()) {
2705             *blendbuffer = new QImage(blendSize, d_ptr->preferredImageFormat());
2706         }
2707     }
2708 
2709     const QRegion blitRegion = exposed - blend;
2710     if (!win)
2711         paintBackground(blitRegion);
2712     else if (!above_changing && surface->isBuffered())
2713         blit(win, blitRegion);
2714 
2715     QRegion blendRegion = exposed & blend;
2716 
2717     if (win)
2718         blendRegion &= win->paintedRegion();
2719     if (!blendRegion.isEmpty()) {
2720 
2721         QPoint off = blend.boundingRect().topLeft();
2722 
2723         QRasterBuffer rb;
2724         rb.prepare(*blendbuffer);
2725         QSpanData spanData;
2726         spanData.init(&rb, 0);
2727         if (!win) {
2728             const QImage::Format format = (*blendbuffer)->format();
2729             switch (format) {
2730             case QImage::Format_ARGB32_Premultiplied:
2731             case QImage::Format_ARGB32:
2732             case QImage::Format_ARGB8565_Premultiplied:
2733             case QImage::Format_ARGB8555_Premultiplied:
2734             case QImage::Format_ARGB6666_Premultiplied:
2735             case QImage::Format_ARGB4444_Premultiplied:
2736                 spanData.rasterBuffer->compositionMode = QPainter::CompositionMode_Source;
2737                 break;
2738             default:
2739                 break;
2740             }
2741             spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_Source);
2742             spanData.dx = off.x();
2743             spanData.dy = off.y();
2744         } else if (!surface->isBuffered()) {
2745                 return;
2746         } else {
2747             const QImage &img = surface->image();
2748             QPoint winoff = off - win->requestedRegion().boundingRect().topLeft();
2749             // convert win->opacity() from scale [0..255] to [0..256]
2750             int const_alpha = win->opacity();
2751             const_alpha += (const_alpha >> 7);
2752             spanData.type = QSpanData::Texture;
2753             spanData.initTexture(&img, const_alpha);
2754             spanData.dx = winoff.x();
2755             spanData.dy = winoff.y();
2756         }
2757         if (!spanData.blend)
2758             return;
2759 
2760         if (surface)
2761             surface->lock();
2762         const QVector<QRect> rects = blendRegion.rects();
2763         const int nspans = 256;
2764         QT_FT_Span spans[nspans];
2765         for (int i = 0; i < rects.size(); ++i) {
2766             int y = rects.at(i).y() - off.y();
2767             int ye = y + rects.at(i).height();
2768             int x = rects.at(i).x() - off.x();
2769             int len = rects.at(i).width();
2770             while (y < ye) {
2771                 int n = qMin(nspans, ye - y);
2772                 int i = 0;
2773                 while (i < n) {
2774                     spans[i].x = x;
2775                     spans[i].len = len;
2776                     spans[i].y = y + i;
2777                     spans[i].coverage = 255;
2778                     ++i;
2779                 }
2780                 spanData.blend(n, spans, &spanData);
2781                 y += n;
2782             }
2783         }
2784         if (surface)
2785             surface->unlock();
2786     }
2787 }
2788 
paintBackground(const QRegion & r)2789 void QScreen::paintBackground(const QRegion &r)
2790 {
2791     const QBrush &bg = qwsServer->backgroundBrush();
2792     Qt::BrushStyle bs = bg.style();
2793     if (bs == Qt::NoBrush || r.isEmpty())
2794         return;
2795 
2796     if (bs == Qt::SolidPattern) {
2797         solidFill(bg.color(), r);
2798     } else {
2799         const QRect br = r.boundingRect();
2800         QImage img(br.size(), d_ptr->preferredImageFormat());
2801         QPoint off = br.topLeft();
2802         QRasterBuffer rb;
2803         rb.prepare(&img);
2804         QSpanData spanData;
2805         spanData.init(&rb, 0);
2806         spanData.setup(bg, 256, QPainter::CompositionMode_Source);
2807         spanData.dx = off.x();
2808         spanData.dy = off.y();
2809         Q_ASSERT(spanData.blend);
2810 
2811         const QVector<QRect> rects = r.rects();
2812         const int nspans = 256;
2813         QT_FT_Span spans[nspans];
2814         for (int i = 0; i < rects.size(); ++i) {
2815             int y = rects.at(i).y() - off.y();
2816             int ye = y + rects.at(i).height();
2817             int x = rects.at(i).x() - off.x();
2818             int len = rects.at(i).width();
2819             while (y < ye) {
2820                 int n = qMin(nspans, ye - y);
2821                 int i = 0;
2822                 while (i < n) {
2823                     spans[i].x = x;
2824                     spans[i].len = len;
2825                     spans[i].y = y + i;
2826                     spans[i].coverage = 255;
2827                     ++i;
2828                 }
2829                 spanData.blend(n, spans, &spanData);
2830                 y += n;
2831             }
2832         }
2833         blit(img, br.topLeft(), r);
2834     }
2835 }
2836 
2837 /*!
2838     \fn virtual int QScreen::sharedRamSize(void *)
2839 
2840     \internal
2841 */
2842 
2843 /*!
2844     \fn QScreen::setDirty(const QRect& rectangle)
2845 
2846     Marks the given \a rectangle as dirty.
2847 
2848     Note that the default implementation does nothing; reimplement
2849     this function to indicate that the given \a rectangle has been
2850     altered.
2851 */
2852 
setDirty(const QRect &)2853 void QScreen::setDirty(const QRect&)
2854 {
2855 }
2856 
2857 /*!
2858     \fn QScreen::isTransformed() const
2859 
2860     Returns true if the screen is transformed (for instance, rotated
2861     90 degrees); otherwise returns false.
2862 
2863     \sa transformOrientation(), isInterlaced()
2864 */
2865 
isTransformed() const2866 bool QScreen::isTransformed() const
2867 {
2868     return false;
2869 }
2870 
2871 /*!
2872     \fn QScreen::isInterlaced() const
2873 
2874     Returns true if the display is interlaced (i.e. is displaying
2875     images progressively like a television screen); otherwise returns
2876     false.
2877 
2878     If the display is interlaced, the drawing is altered to look
2879     better.
2880 
2881     \sa isTransformed(), linestep()
2882 */
2883 
isInterlaced() const2884 bool QScreen::isInterlaced() const
2885 {
2886     return false;//qws_screen_is_interlaced;;
2887 }
2888 
2889 /*!
2890     \fn QScreen::mapToDevice(const QSize &size) const
2891 
2892     Maps the given \a size from the coordinate space used by the
2893     application to the framebuffer coordinate system. Note that the
2894     default implementation simply returns the given \a size as it is.
2895 
2896     Reimplement this function to use the given device's coordinate
2897     system when mapping.
2898 
2899     \sa mapFromDevice()
2900 */
2901 
mapToDevice(const QSize & s) const2902 QSize QScreen::mapToDevice(const QSize &s) const
2903 {
2904     return s;
2905 }
2906 
2907 /*!
2908     \fn QScreen::mapFromDevice(const QSize &size) const
2909 
2910     Maps the given \a size from the framebuffer coordinate system to
2911     the coordinate space used by the application. Note that the
2912     default implementation simply returns the given \a size as it is.
2913 
2914     Reimplement this function to use the given device's coordinate
2915     system when mapping.
2916 
2917     \sa mapToDevice()
2918 */
2919 
mapFromDevice(const QSize & s) const2920 QSize QScreen::mapFromDevice(const QSize &s) const
2921 {
2922     return s;
2923 }
2924 
2925 /*!
2926     \fn QScreen::mapToDevice(const QPoint &point, const QSize &screenSize) const
2927     \overload
2928 
2929     Maps the given \a point from the coordinate space used by the
2930     application to the framebuffer coordinate system, passing the
2931     device's \a screenSize as argument. Note that the default
2932     implementation returns the given \a point as it is.
2933 */
2934 
mapToDevice(const QPoint & p,const QSize &) const2935 QPoint QScreen::mapToDevice(const QPoint &p, const QSize &) const
2936 {
2937     return p;
2938 }
2939 
2940 /*!
2941     \fn QScreen::mapFromDevice(const QPoint &point, const QSize &screenSize) const
2942     \overload
2943 
2944     Maps the given \a point from the framebuffer coordinate system to
2945     the coordinate space used by the application, passing the device's
2946     \a screenSize as argument. Note that the default implementation
2947     simply returns the given \a point as it is.
2948 */
2949 
mapFromDevice(const QPoint & p,const QSize &) const2950 QPoint QScreen::mapFromDevice(const QPoint &p, const QSize &) const
2951 {
2952     return p;
2953 }
2954 
2955 /*!
2956     \fn QScreen::mapToDevice(const QRect &rectangle, const QSize &screenSize) const
2957     \overload
2958 
2959     Maps the given \a rectangle from the coordinate space used by the
2960     application to the framebuffer coordinate system, passing the
2961     device's \a screenSize as argument. Note that the default
2962     implementation returns the given \a rectangle as it is.
2963 */
2964 
mapToDevice(const QRect & r,const QSize &) const2965 QRect QScreen::mapToDevice(const QRect &r, const QSize &) const
2966 {
2967     return r;
2968 }
2969 
2970 /*!
2971     \fn QScreen::mapFromDevice(const QRect &rectangle, const QSize &screenSize) const
2972     \overload
2973 
2974     Maps the given \a rectangle from the framebuffer coordinate system to
2975     the coordinate space used by the application, passing the device's
2976     \a screenSize as argument. Note that the default implementation
2977     simply returns the given \a rectangle as it is.
2978 */
2979 
mapFromDevice(const QRect & r,const QSize &) const2980 QRect QScreen::mapFromDevice(const QRect &r, const QSize &) const
2981 {
2982     return r;
2983 }
2984 
2985 /*!
2986     \fn QScreen::mapToDevice(const QImage &image) const
2987     \overload
2988 
2989     Maps the given \a image from the coordinate space used by the
2990     application to the framebuffer coordinate system. Note that the
2991     default implementation returns the given \a image as it is.
2992 */
2993 
mapToDevice(const QImage & i) const2994 QImage QScreen::mapToDevice(const QImage &i) const
2995 {
2996     return i;
2997 }
2998 
2999 /*!
3000     \fn QScreen::mapFromDevice(const QImage &image) const
3001     \overload
3002 
3003     Maps the given \a image from the framebuffer coordinate system to
3004     the coordinate space used by the application. Note that the
3005     default implementation simply returns the given \a image as it is.
3006 */
3007 
mapFromDevice(const QImage & i) const3008 QImage QScreen::mapFromDevice(const QImage &i) const
3009 {
3010     return i;
3011 }
3012 
3013 /*!
3014     \fn QScreen::mapToDevice(const QRegion &region, const QSize &screenSize) const
3015     \overload
3016 
3017     Maps the given \a region from the coordinate space used by the
3018     application to the framebuffer coordinate system, passing the
3019     device's \a screenSize as argument. Note that the default
3020     implementation returns the given \a region as it is.
3021 */
3022 
mapToDevice(const QRegion & r,const QSize &) const3023 QRegion QScreen::mapToDevice(const QRegion &r, const QSize &) const
3024 {
3025     return r;
3026 }
3027 
3028 /*!
3029     \fn QScreen::mapFromDevice(const QRegion &region, const QSize &screenSize) const
3030     \overload
3031 
3032     Maps the given \a region from the framebuffer coordinate system to
3033     the coordinate space used by the application, passing the device's
3034     \a screenSize as argument. Note that the default implementation
3035     simply returns the given \a region as it is.
3036 */
3037 
mapFromDevice(const QRegion & r,const QSize &) const3038 QRegion QScreen::mapFromDevice(const QRegion &r, const QSize &) const
3039 {
3040     return r;
3041 }
3042 
3043 /*!
3044     \fn QScreen::transformOrientation() const
3045 
3046     Returns the current rotation as an integer value.
3047 
3048     Note that the default implementation returns 0; reimplement this
3049     function to override this value.
3050 
3051     \sa isTransformed()
3052 */
3053 
transformOrientation() const3054 int QScreen::transformOrientation() const
3055 {
3056     return 0;
3057 }
3058 
pixmapDepth() const3059 int QScreen::pixmapDepth() const
3060 {
3061     return depth();
3062 }
3063 
3064 /*!
3065     \internal
3066 */
memoryNeeded(const QString &)3067 int QScreen::memoryNeeded(const QString&)
3068 {
3069     return 0;
3070 }
3071 
3072 /*!
3073     \internal
3074 */
haltUpdates()3075 void QScreen::haltUpdates()
3076 {
3077 }
3078 
3079 /*!
3080     \internal
3081 */
resumeUpdates()3082 void QScreen::resumeUpdates()
3083 {
3084 }
3085 
3086 /*!
3087     \fn QRegion QScreen::region() const
3088     \since 4.2
3089 
3090     Returns the region covered by this screen driver.
3091 
3092     \sa base(), screenSize()
3093 */
3094 
3095 /*!
3096     \internal
3097 */
setOffset(const QPoint & p)3098 void QScreen::setOffset(const QPoint &p)
3099 {
3100     d_ptr->offset = p;
3101 }
3102 
3103 /*!
3104     \since 4.2
3105 
3106     Returns the logical offset of the screen, i.e., the offset between
3107     (0,0) in screen coordinates and the application coordinate system.
3108 */
offset() const3109 QPoint QScreen::offset() const
3110 {
3111     return d_ptr->offset;
3112 }
3113 
3114 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
setFrameBufferLittleEndian(bool littleEndian)3115 void QScreen::setFrameBufferLittleEndian(bool littleEndian)
3116 {
3117     d_ptr->fb_is_littleEndian = littleEndian;
3118 }
3119 
frameBufferLittleEndian() const3120 bool QScreen::frameBufferLittleEndian() const
3121 {
3122     return d_ptr->fb_is_littleEndian;
3123 }
3124 #endif
3125 
3126 /*!
3127     \fn int QScreen::subScreenIndexAt(const QPoint &position) const
3128     \since 4.2
3129 
3130     Returns the index of the subscreen at the given \a position;
3131     returns -1 if no screen is found.
3132 
3133     The index identifies the subscreen in the list of pointers
3134     returned by the subScreens() function.
3135 
3136     \sa instance(), subScreens()
3137 */
subScreenIndexAt(const QPoint & p) const3138 int QScreen::subScreenIndexAt(const QPoint &p) const
3139 {
3140     const QList<QScreen*> screens = subScreens();
3141     const int n = screens.count();
3142     for (int i = 0; i < n; ++i) {
3143         if (screens.at(i)->region().contains(p))
3144             return i;
3145     }
3146 
3147     return -1;
3148 }
3149 
3150 #if 0
3151 #ifdef QT_LOADABLE_MODULES
3152 #include <dlfcn.h>
3153 
3154 // ### needs update after driver init changes
3155 
3156 static QScreen * qt_dodriver(char * driver,char * a,unsigned char * b)
3157 
3158 {
3159     char buf[200];
3160     strcpy(buf,"/etc/qws/drivers/");
3161     qstrcpy(buf+17,driver);
3162     qDebug("Attempting driver %s",driver);
3163 
3164     void * handle;
3165     handle=dlopen(buf,RTLD_LAZY);
3166     if(handle==0) {
3167         qFatal("Module load error");
3168     }
3169     QScreen *(*qt_get_screen_func)(char *,unsigned char *);
3170     qt_get_screen_func=dlsym(handle,"qt_get_screen");
3171     if(qt_get_screen_func==0) {
3172         qFatal("Couldn't get symbol");
3173     }
3174     QScreen * ret=qt_get_screen_func(a,b);
3175     return ret;
3176 }
3177 
3178 static QScreen * qt_do_entry(char * entry)
3179 {
3180     unsigned char config[256];
3181 
3182     FILE * f=fopen(entry,"r");
3183     if(!f) {
3184         return 0;
3185     }
3186 
3187     int r=fread(config,256,1,f);
3188     if(r<1)
3189         return 0;
3190 
3191     fclose(f);
3192 
3193     unsigned short vendorid=*((unsigned short int *)config);
3194     unsigned short deviceid=*(((unsigned short int *)config)+1);
3195     if(config[0xb]!=3)
3196         return 0;
3197 
3198     if(vendorid==0x1002) {
3199         if(deviceid==0x4c4d) {
3200             qDebug("Compaq Armada/IBM Thinkpad's Mach64 card");
3201             return qt_dodriver("mach64.so",entry,config);
3202         } else if(deviceid==0x4742) {
3203             qDebug("Desktop Rage Pro Mach64 card");
3204             return qt_dodriver("mach64.so",entry,config);
3205         } else {
3206             qDebug("Unrecognised ATI card id %x",deviceid);
3207             return 0;
3208         }
3209     } else {
3210         qDebug("Unrecognised vendor");
3211     }
3212     return 0;
3213 }
3214 
3215 extern bool qws_accel;
3216 
3217 /// ** NOT SUPPPORTED **
3218 
3219 QScreen * qt_probe_bus()
3220 {
3221     if(!qws_accel) {
3222         return qt_dodriver("unaccel.so",0,0);
3223     }
3224 
3225     QT_DIR *dirptr = QT_OPENDIR("/proc/bus/pci");
3226     if(!dirptr)
3227         return qt_dodriver("unaccel.so",0,0);
3228     QT_DIR * dirptr2;
3229     QT_DIRENT *cards;
3230 
3231     QT_DIRENT *busses = QT_READDIR(dirptr);
3232 
3233     while(busses) {
3234         if(busses->d_name[0]!='.') {
3235             char buf[100];
3236             strcpy(buf,"/proc/bus/pci/");
3237             qstrcpy(buf+14,busses->d_name);
3238             int p=strlen(buf);
3239             dirptr2 = QT_OPENDIR(buf);
3240             if(dirptr2) {
3241                 cards = QT_READDIR(dirptr2);
3242                 while(cards) {
3243                     if(cards->d_name[0]!='.') {
3244                         buf[p]='/';
3245                         qstrcpy(buf+p+1,cards->d_name);
3246                         QScreen * ret=qt_do_entry(buf);
3247                         if(ret)
3248                             return ret;
3249                     }
3250                     cards = QT_READDIR(dirptr2);
3251                 }
3252                 QT_CLOSEDIR(dirptr2);
3253             }
3254         }
3255         busses = QT_READDIR(dirptr);
3256     }
3257     QT_CLOSEDIR(dirptr);
3258 
3259     return qt_dodriver("unaccel.so",0,0);
3260 }
3261 
3262 #else
3263 
3264 char *qt_qws_hardcoded_slot = "/proc/bus/pci/01/00.0";
3265 
3266 const unsigned char* qt_probe_bus()
3267 {
3268     const char * slot;
3269     slot=::getenv("QWS_CARD_SLOT");
3270     if(!slot)
3271         slot=qt_qws_hardcoded_slot;
3272     if (slot) {
3273         static unsigned char config[256];
3274         FILE * f=fopen(slot,"r");
3275         if(!f) {
3276             qDebug("Open failure for %s",slot);
3277             slot=0;
3278         } else {
3279             int r=fread((char*)config,256,1,f);
3280             fclose(f);
3281             if(r<1) {
3282                 qDebug("Read failure");
3283                 return 0;
3284             } else {
3285                 return config;
3286             }
3287         }
3288     }
3289     return 0;
3290 }
3291 
3292 #endif
3293 
3294 #endif // 0
3295 
3296 /*!
3297     \internal
3298     \since 4.4
3299 */
setPixmapDataFactory(QPixmapDataFactory * factory)3300 void QScreen::setPixmapDataFactory(QPixmapDataFactory *factory)
3301 {
3302     static bool shownWarning = false;
3303     if (!shownWarning) {
3304         qWarning("QScreen::setPixmapDataFactory() is deprecated - use setGraphicsSystem() instead");
3305         shownWarning = true;
3306     }
3307 
3308     d_ptr->pixmapFactory = factory;
3309 }
3310 
3311 /*!
3312     \internal
3313     \since 4.4
3314 */
pixmapDataFactory() const3315 QPixmapDataFactory* QScreen::pixmapDataFactory() const
3316 {
3317     return d_ptr->pixmapFactory;
3318 }
3319 
3320 /*!
3321     \internal
3322     \since 4.5
3323 */
setGraphicsSystem(QGraphicsSystem * system)3324 void QScreen::setGraphicsSystem(QGraphicsSystem* system)
3325 {
3326     d_ptr->graphicsSystem = system;
3327 }
3328 
3329 /*!
3330     \internal
3331     \since 4.5
3332 */
graphicsSystem() const3333 QGraphicsSystem* QScreen::graphicsSystem() const
3334 {
3335     return d_ptr->graphicsSystem;
3336 }
3337 
3338 /*!
3339     \since 4.4
3340 
3341     Returns the class identifier for the screen object.
3342 */
classId() const3343 QScreen::ClassId QScreen::classId() const
3344 {
3345     return static_cast<ClassId>(d_ptr->classId);
3346 }
3347 
3348 QT_END_NAMESPACE
3349