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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®)
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 ®ion)
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 ®ion, 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 ®ion, 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