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 "qdirectpainter_qws.h"
43
44 #include "qscreen_qws.h"
45 #include "private/qobject_p.h"
46 #include "private/qapplication_p.h"
47 #include "qwsdisplay_qws.h"
48 #include "qwidget.h"
49 #include "qimage.h"
50 #include <qwsevent_qws.h>
51 #include <private/qwindowsurface_qws_p.h>
52 #include <private/qwsdisplay_qws_p.h>
53
54 QT_BEGIN_NAMESPACE
55
56 #ifdef Q_WS_QWS
57 #ifndef QT_NO_DIRECTPAINTER
58
59 /*!
60 \class QDirectPainter
61 \ingroup painting
62 \ingroup qws
63
64 \brief The QDirectPainter class provides direct access to the
65 underlying hardware in Qt for Embedded Linux.
66
67 Note that this class is only available in \l{Qt for Embedded Linux}.
68
69 QDirectPainter allows a client application to reserve a region of
70 the framebuffer and render directly onto the screen. There are two
71 ways of using the QDirectPainter class: You can either reserve a
72 region using the provided static functions, or you can instantiate
73 an object and make use of its more dynamic API.
74
75 \tableofcontents
76
77 \section1 Dynamic Allocation
78
79 By instantiating a QDirectPainter object using the default
80 QDirectPainter::NonReserved surface flag, the client application
81 only gets some control over the reserved region, i.e., it can
82 still render directly onto the screen but the allocated region may
83 change (for example, if a window with a higher focus requests
84 parts of the same region). The currently allocated region can be
85 retrieved using the allocatedRegion() function, while the
86 requestedRegion() function returns the originally reserved
87 region.
88
89
90 \section1 Static Allocation
91
92
93 Using the static approach, the client application gets complete
94 control over the reserved region, i.e., the affected region will
95 never be modified by the screen driver.
96
97 To create a static region, pass the QDirectPainter::Reserved
98 surface flag to the constructor. After the reserved region is
99 reported through regionChanged(), the allocated region will not
100 change, unless setRegion() is called.
101
102 If QDirectPainter::ReservedSynchronous is passed to the
103 constructor, calls to setRegion() will block until the region is
104 reserved, meaning that allocatedRegion() will be available immediately.
105 Note that in the current version setRegion() will cause the application
106 event loop to be entered, potentially causing reentrancy issues.
107
108 \section1 Rendering
109
110 To draw on a given region, the application must first get hold of
111 a pointer to the framebuffer. In most cases, this pointer can be
112 retrieved using the QDirectPainter::frameBuffer() function. But
113 note that if the current screen has subscreens, you must query the
114 screen driver instead to identify the correct subscreen. A pointer
115 to the current screen driver can always be retrieved using the
116 static QScreen::instance() function. Then use QScreen's \l
117 {QScreen::}{subScreenIndexAt()} and \l {QScreen::}{subScreens()}
118 functions to access the correct subscreen, and the subscreen's \l
119 {QScreen::}{base()} function to retrieve a pointer to the
120 framebuffer.
121
122 Depending on the hardware, it might be necessary to lock the
123 framebuffer for exclusive use while writing to it. This is
124 possible using the lock() and unlock() functions. Note that
125 calling lock() will prevent all other applications from working
126 until unlock() is called.
127
128 In addition, QDirectPainter provides several functions returning
129 information about the framebuffer: the linestep() function returns
130 the length (in bytes) of each scanline of the framebuffer while
131 the screenDepth(), screenWidth() and screenHeight() function
132 return the screen metrics.
133
134 \sa QScreen, QWSEmbedWidget, {Qt for Embedded Linux Architecture}
135 */
136
137 /*!
138 \enum QDirectPainter::SurfaceFlag
139
140 This enum describes the behavior of the region reserved by this
141 QDirectPainter object.
142
143 \value NonReserved The allocated region may change, e.g., if a
144 window with a higher focus requests parts of the same region. See
145 also \l {Dynamic Allocation}.
146
147 \value Reserved The allocated region will never change. See also
148 \l {Static Allocation}.
149
150 \value ReservedSynchronous The allocated region will never change and
151 each function that changes the allocated region will be blocking.
152
153 \sa allocatedRegion()
154 */
155
156 /*!
157 \fn QRegion QDirectPainter::region()
158 \obsolete
159
160 Use QDirectPainter::allocatedRegion() instead.
161 */
162
getPrimaryScreen()163 static inline QScreen *getPrimaryScreen()
164 {
165 QScreen *screen = QScreen::instance();
166 if (!screen->base()) {
167 QList<QScreen*> subScreens = screen->subScreens();
168 if (subScreens.size() < 1)
169 return 0;
170 screen = subScreens.at(0);
171 }
172 return screen;
173 }
174
screenS()175 static inline QSize screenS()
176 {
177 QScreen *screen = getPrimaryScreen();
178 if (!screen)
179 return QSize();
180 return QSize(screen->width(), screen->height());
181 }
182
devS()183 static inline QSize devS()
184 {
185 QScreen *screen = getPrimaryScreen();
186 if (!screen)
187 return QSize();
188 return QSize(screen->deviceWidth(), screen->deviceHeight());
189 }
190
191
192 class QDirectPainterPrivate : public QObjectPrivate
193 {
194 Q_DECLARE_PUBLIC(QDirectPainter);
195 public:
196
QDirectPainterPrivate()197 QDirectPainterPrivate() : surface(0), seenRegion(false) {}
198
~QDirectPainterPrivate()199 ~QDirectPainterPrivate() {
200 if (QPaintDevice::qwsDisplay()) { // make sure not in QApplication destructor
201 qApp->d_func()->directPainters->remove(surface->windowId());
202 surface->setGeometry(QRect());
203 }
204 delete surface;
205 }
206
207 QWSDirectPainterSurface *surface;
208 QRegion requested_region;
209
210 static QDirectPainter *staticPainter;
211 bool seenRegion;
212 };
213
214 QDirectPainter *QDirectPainterPrivate::staticPainter = 0;
215
qt_directpainter_region(QDirectPainter * dp,const QRegion & alloc,int type)216 void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type)
217 {
218 QDirectPainterPrivate *d = dp->d_func();
219
220 QRegion r = alloc;
221 QScreen *screen = d->surface->screen();
222 if (screen->isTransformed()) {
223 const QSize screenSize(screen->width(), screen->height());
224 r = screen->mapToDevice(r, screenSize);
225 }
226 if (type == QWSRegionEvent::Allocation) {
227 d->surface->setClipRegion(alloc);
228 d->seenRegion = true;
229 if (dp != QDirectPainterPrivate::staticPainter) {
230 if (!d->surface->flushingRegionEvents) // recursion guard
231 dp->regionChanged(r);
232 }
233 }
234 }
235
236 #ifndef QT_NO_QWSEMBEDWIDGET
qt_directpainter_embedevent(QDirectPainter * dp,const QWSEmbedEvent * event)237 void qt_directpainter_embedevent(QDirectPainter *dp, const QWSEmbedEvent *event)
238 {
239 if (event->type | QWSEmbedEvent::Region) {
240 QScreen *screen = dp->d_func()->surface->screen();
241 QRegion r = event->region;
242 if (screen->isTransformed()) {
243 const QSize screenSize(screen->width(), screen->height());
244 r = screen->mapToDevice(r, screenSize);
245 }
246 dp->setRegion(r);
247 }
248 }
249 #endif
250
251 /*!
252 Constructs a QDirectPainter object with the given \a parent and
253 surface \a flag.
254 */
QDirectPainter(QObject * parent,SurfaceFlag flag)255 QDirectPainter::QDirectPainter(QObject *parent, SurfaceFlag flag)
256 :QObject(*new QDirectPainterPrivate, parent)
257 {
258 Q_D(QDirectPainter);
259 d->surface = new QWSDirectPainterSurface(true, flag);
260
261 if (flag != NonReserved)
262 d->surface->setReserved();
263
264 QApplicationPrivate *ad = qApp->d_func();
265 if (!ad->directPainters)
266 ad->directPainters = new QMap<WId, QDirectPainter*>;
267 ad->directPainters->insert(d->surface->windowId(), this);
268 }
269
270 /*!
271 Destroys this QDirectPainter object, releasing the reserved region.
272
273 \sa allocatedRegion()
274 */
~QDirectPainter()275 QDirectPainter::~QDirectPainter()
276 {
277 /* should not be necessary
278 if (this == QDirectPainterPrivate::staticPainter)
279 QDirectPainterPrivate::staticPainter = 0;
280 */
281 }
282
283 /*!
284 \fn void QDirectPainter::setGeometry(const QRect &rectangle)
285 \since 4.2
286
287 Request to reserve the given \a rectangle of the framebuffer.
288
289 Note that the actually allocated region might differ from the
290 requested one, e.g., if the given region overlaps with the
291 region of another QDirectPainter object.
292
293 \sa geometry(), allocatedRegion(), setRegion()
294 */
setGeometry(const QRect & rect)295 void QDirectPainter::setGeometry(const QRect &rect)
296 {
297 setRegion(rect);
298 }
299
300 /*!
301 \since 4.2
302
303 Returns the bounding rectangle of the requested region.
304
305 \sa setGeometry(), requestedRegion()
306 */
geometry() const307 QRect QDirectPainter::geometry() const
308 {
309 Q_D(const QDirectPainter);
310 return d->requested_region.boundingRect();
311 }
312
313 /*!
314 \since 4.2
315
316 Requests to reserve the given \a region of the framebuffer.
317
318 Note that the actually allocated region might differ from the
319 requested one, e.g., if the given region overlaps with the region
320 of another QDirectPainter object.
321
322 \sa requestedRegion(), allocatedRegion(), {Dynamic Allocation}
323 */
setRegion(const QRegion & region)324 void QDirectPainter::setRegion(const QRegion ®ion)
325 {
326 Q_D(QDirectPainter);
327 d->requested_region = region;
328
329 const QScreen *screen = d->surface->screen();
330 if (screen->isTransformed()) {
331 const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
332 const QRegion r = screen->mapFromDevice(region, devSize);
333 d->surface->setRegion(r);
334 } else {
335 d->surface->setRegion(region);
336 }
337 }
338
339 /*!
340 \since 4.2
341
342 Returns the region requested by this QDirectPainter.
343
344 Note that if the QDirectPainter::Reserved flag is set, the region
345 returned by this function will always be equivalent to the region
346 returned by the allocatedRegion() function. Otherwise they might
347 differ (see \l {Dynamic Allocation} for details).
348
349 \sa geometry(), setRegion(), allocatedRegion()
350 */
requestedRegion() const351 QRegion QDirectPainter::requestedRegion() const
352 {
353 Q_D(const QDirectPainter);
354 return d->requested_region;
355 }
356
357 /*!
358 \since 4.2
359
360 Returns the currently reserved region.
361
362 Note that if the QDirectPainter::Reserved flag is set, the region
363 returned by this function will always be equivalent to the region
364 returned by the requestedRegion() function. Otherwise they might
365 differ (see \l {Dynamic Allocation} for details).
366
367 \sa requestedRegion(), geometry()
368 */
allocatedRegion() const369 QRegion QDirectPainter::allocatedRegion() const
370 {
371 Q_D(const QDirectPainter);
372 const QScreen *screen = d->surface->screen();
373 if (screen->isTransformed()) {
374 const QSize screenSize(screen->width(), screen->height());
375 return screen->mapToDevice(d->surface->region(), screenSize);
376 } else {
377 return d->surface->region();
378 }
379 }
380
381 /*!
382 \since 4.2
383
384 Returns the window system identifier of the widget.
385 */
winId() const386 WId QDirectPainter::winId() const
387 {
388 Q_D(const QDirectPainter);
389 return d->surface->windowId();
390 }
391
392 /*!
393 \fn void QDirectPainter::regionChanged(const QRegion &newRegion)
394 \since 4.2
395
396 This function is called when the allocated region changes.
397
398 This function is not called for region changes that happen while the
399 startPainting() function is executing.
400
401 Note that the given region, \a newRegion, is not guaranteed to be correct at the
402 time you access the display. To prevent reentrancy problems you should
403 always call startPainting() before updating the display and then use
404 allocatedRegion() to retrieve the correct region.
405
406 \sa allocatedRegion(), startPainting(), {Dynamic Allocation}
407 */
regionChanged(const QRegion & region)408 void QDirectPainter::regionChanged(const QRegion ®ion)
409 {
410 Q_UNUSED(region);
411 }
412
413 /*!
414 \since 4.2
415
416 Call this function before you start updating the pixels in the
417 allocated region. The hardware will be notified, if necessary,
418 that you are about to start painting operations.
419
420 Set \a lockDisplay if you want startPainting() and endPainting()
421 to lock() and unlock() the display automatically.
422
423 Note that for a NonReserved direct painter, you must call
424 allocatedRegion() after calling this function, since the allocated
425 region is only guaranteed to be correct after this function has
426 returned.
427
428 The regionChanged() function will not be called between startPainting()
429 and endPainting().
430
431 \sa endPainting(), flush()
432 */
startPainting(bool lockDisplay)433 void QDirectPainter::startPainting(bool lockDisplay)
434 {
435 Q_D(QDirectPainter);
436 d->surface->setLocking(lockDisplay);
437
438 const QScreen *screen = d->surface->screen();
439 if (screen->isTransformed()) {
440 const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
441 const QRegion r = screen->mapFromDevice(d->surface->region(), devSize);
442 d->surface->beginPaint(r);
443 } else {
444 d->surface->beginPaint(d->surface->region());
445 }
446 }
447
448 /*!
449 \since 4.2
450
451 Call this function when you are done updating the screen. It will
452 notify the hardware, if necessary, that your painting operations
453 have ended.
454 */
endPainting()455 void QDirectPainter::endPainting()
456 {
457 Q_D(QDirectPainter);
458
459 const QScreen *screen = d->surface->screen();
460 if (screen->isTransformed()) {
461 const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
462 const QRegion r = screen->mapFromDevice(d->surface->region(), devSize);
463 d->surface->endPaint(r);
464 } else {
465 d->surface->endPaint(d->surface->region());
466 }
467 }
468
469 /*!
470 \since 4.3
471 \overload
472
473 This function will automatically call flush() to flush the
474 \a region to the display before notifying the hardware, if
475 necessary, that painting operations have ended.
476 */
endPainting(const QRegion & region)477 void QDirectPainter::endPainting(const QRegion ®ion)
478 {
479 endPainting();
480 flush(region);
481 }
482
483 /*!
484 \since 4.3
485
486 Flushes the \a region onto the screen.
487 */
flush(const QRegion & region)488 void QDirectPainter::flush(const QRegion ®ion)
489 {
490 Q_D(QDirectPainter);
491
492 const QScreen *screen = d->surface->screen();
493 if (screen->isTransformed()) {
494 const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
495 const QRegion r = screen->mapFromDevice(region, devSize);
496 d->surface->flush(0, r, QPoint());
497 } else {
498 d->surface->flush(0, region, QPoint());
499 }
500 }
501
502 /*!
503 \since 4.2
504
505 Raises the reserved region to the top of the widget stack.
506
507 After this call the reserved region will be visually in front of
508 any overlapping widgets.
509
510 \sa lower(), requestedRegion()
511 */
raise()512 void QDirectPainter::raise()
513 {
514 QWidget::qwsDisplay()->setAltitude(winId(),QWSChangeAltitudeCommand::Raise);
515 }
516
517 /*!
518 \since 4.2
519
520 Lowers the reserved region to the bottom of the widget stack.
521
522 After this call the reserved region will be visually behind (and
523 therefore obscured by) any overlapping widgets.
524
525 \sa raise(), requestedRegion()
526 */
lower()527 void QDirectPainter::lower()
528 {
529 QWidget::qwsDisplay()->setAltitude(winId(),QWSChangeAltitudeCommand::Lower);
530 }
531
532
533 /*!
534 \fn QRegion QDirectPainter::reserveRegion(const QRegion ®ion)
535
536 Attempts to reserve the \a region and returns the region that is
537 actually reserved.
538
539 This function also releases the previously reserved region if
540 any. If not released explicitly, the region will be released on
541 application exit.
542
543 \sa allocatedRegion(), {Static Allocation}
544
545 \obsolete
546
547 Construct a QDirectPainter using QDirectPainter::ReservedSynchronous instead.
548 */
reserveRegion(const QRegion & reg)549 QRegion QDirectPainter::reserveRegion(const QRegion ®)
550 {
551 if (!QDirectPainterPrivate::staticPainter)
552 QDirectPainterPrivate::staticPainter = new QDirectPainter(qApp, ReservedSynchronous);
553
554 QDirectPainter *dp = QDirectPainterPrivate::staticPainter;
555 dp->setRegion(reg);
556
557 return dp->allocatedRegion();
558 }
559
560 /*!
561 Returns a pointer to the beginning of the display memory.
562
563 Note that it is the application's responsibility to limit itself
564 to modifying only the reserved region.
565
566 Do not use this pointer if the current screen has subscreens,
567 query the screen driver instead: A pointer to the current screen
568 driver can always be retrieved using the static
569 QScreen::instance() function. Then use QScreen's \l
570 {QScreen::}{subScreenIndexAt()} and \l {QScreen::}{subScreens()}
571 functions to access the correct subscreen, and the subscreen's \l
572 {QScreen::}{base()} function to retrieve a pointer to the
573 framebuffer.
574
575 \sa requestedRegion(), allocatedRegion(), linestep()
576 */
frameBuffer()577 uchar* QDirectPainter::frameBuffer()
578 {
579 QScreen *screen = getPrimaryScreen();
580 if (!screen)
581 return 0;
582 return screen->base();
583 }
584
585 /*!
586 \since 4.2
587
588 Returns the reserved region.
589
590 \sa reserveRegion(), frameBuffer()
591
592 \obsolete
593
594 Use allocatedRegion() instead.
595 */
reservedRegion()596 QRegion QDirectPainter::reservedRegion()
597 {
598 return QDirectPainterPrivate::staticPainter
599 ? QDirectPainterPrivate::staticPainter->allocatedRegion() : QRegion();
600 }
601
602 /*!
603 Returns the bit depth of the display.
604
605 \sa screenHeight(), screenWidth()
606 */
screenDepth()607 int QDirectPainter::screenDepth()
608 {
609 QScreen *screen = getPrimaryScreen();
610 if (!screen)
611 return 0;
612 return screen->depth();
613 }
614
615 /*!
616 Returns the width of the display in pixels.
617
618 \sa screenHeight(), screenDepth()
619 */
screenWidth()620 int QDirectPainter::screenWidth()
621 {
622 QScreen *screen = getPrimaryScreen();
623 if (!screen)
624 return 0;
625 return screen->deviceWidth();
626 }
627
628 /*!
629 Returns the height of the display in pixels.
630
631 \sa screenWidth(), screenDepth()
632 */
screenHeight()633 int QDirectPainter::screenHeight()
634 {
635 QScreen *screen = getPrimaryScreen();
636 if (!screen)
637 return 0;
638 return screen->deviceHeight();
639 }
640
641 /*!
642 Returns the length (in bytes) of each scanline of the framebuffer.
643
644 \sa frameBuffer()
645 */
linestep()646 int QDirectPainter::linestep()
647 {
648 QScreen *screen = getPrimaryScreen();
649 if (!screen)
650 return 0;
651 return screen->linestep();
652 }
653
654
655 /*!
656 Locks access to the framebuffer.
657
658 Note that calling this function will prevent all other
659 applications from updating the display until unlock() is called.
660
661 \sa unlock()
662 */
lock()663 void QDirectPainter::lock()
664 {
665 QWSDisplay::grab(true);
666 }
667 /*!
668 Unlocks the lock on the framebuffer (set using the lock()
669 function), allowing other applications to access the screen.
670
671 \sa lock()
672 */
unlock()673 void QDirectPainter::unlock()
674 {
675 QWSDisplay::ungrab();
676 }
677
678 #endif //QT_NO_DIRECTPAINTER
679
680 #endif
681
682 QT_END_NAMESPACE
683