source: trunk/src/gui/painting/qwindowsurface_qws.cpp@ 776

Last change on this file since 776 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 38.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwindowsurface_qws_p.h"
43#include <qwidget.h>
44#include <qscreen_qws.h>
45#include <qwsmanager_qws.h>
46#include <qapplication.h>
47#include <qwsdisplay_qws.h>
48#include <qrgb.h>
49#include <qpaintengine.h>
50#include <qdesktopwidget.h>
51#include <private/qapplication_p.h>
52#include <private/qwsdisplay_qws_p.h>
53#include <private/qwidget_p.h>
54#include <private/qwsmanager_p.h>
55#include <private/qwslock_p.h>
56#include <private/qbackingstore_p.h>
57#include <stdio.h>
58
59QT_BEGIN_NAMESPACE
60
61#ifdef Q_BACKINGSTORE_SUBSURFACES
62
63typedef QMap<int, QWSWindowSurface*> SurfaceMap;
64Q_GLOBAL_STATIC(SurfaceMap, winIdToSurfaceMap);
65
66QWSWindowSurface* qt_findWindowSurface(int winId)
67{
68 return winIdToSurfaceMap()->value(winId);
69}
70
71static void qt_insertWindowSurface(int winId, QWSWindowSurface *surface)
72{
73 if (!surface)
74 winIdToSurfaceMap()->remove(winId);
75 else
76 winIdToSurfaceMap()->insert(winId, surface);
77}
78
79#endif // Q_BACKINGSTORE_SUBSURFACES
80
81inline bool isWidgetOpaque(const QWidget *w)
82{
83 return w->d_func()->isOpaque && !w->testAttribute(Qt::WA_TranslucentBackground);
84}
85
86static inline QScreen *getScreen(const QWidget *w)
87{
88 const QList<QScreen*> subScreens = qt_screen->subScreens();
89 if (subScreens.isEmpty())
90 return qt_screen;
91
92 const int screen = QApplication::desktop()->screenNumber(w);
93
94 return qt_screen->subScreens().at(screen < 0 ? 0 : screen);
95}
96
97static int bytesPerPixel(QImage::Format format)
98{
99 switch (format) {
100 case QImage::Format_Invalid:
101 return 0;
102#ifndef QT_NO_DEBUG
103 case QImage::Format_Mono:
104 case QImage::Format_MonoLSB:
105 qFatal("QWSWindowSurface: Invalid backingstore format: %i",
106 int(format));
107#endif
108 case QImage::Format_Indexed8:
109 return 1;
110 case QImage::Format_RGB32:
111 case QImage::Format_ARGB32:
112 case QImage::Format_ARGB32_Premultiplied:
113 return 4;
114 case QImage::Format_RGB16:
115 case QImage::Format_RGB555:
116 case QImage::Format_RGB444:
117 case QImage::Format_ARGB4444_Premultiplied:
118 return 2;
119 case QImage::Format_ARGB8565_Premultiplied:
120 case QImage::Format_ARGB8555_Premultiplied:
121 case QImage::Format_ARGB6666_Premultiplied:
122 case QImage::Format_RGB666:
123 case QImage::Format_RGB888:
124 return 3;
125 default:
126#ifndef QT_NO_DEBUG
127 qFatal("QWSWindowSurface: Invalid backingstore format: %i",
128 int(format));
129#endif
130 return 0;
131 }
132}
133
134static inline int nextMulOf4(int n)
135{
136 return ((n + 3) & 0xfffffffc);
137}
138
139static inline void setImageMetrics(QImage &img, QWidget *window) {
140 QScreen *myScreen = getScreen(window);
141 if (myScreen) {
142 int dpmx = myScreen->width()*1000 / myScreen->physicalWidth();
143 int dpmy = myScreen->height()*1000 / myScreen->physicalHeight();
144 img.setDotsPerMeterX(dpmx);
145 img.setDotsPerMeterY(dpmy);
146 }
147}
148
149void QWSWindowSurface::invalidateBuffer()
150{
151
152 QWidget *win = window();
153 if (win) {
154 win->d_func()->invalidateBuffer(win->rect());
155#ifndef QT_NO_QWS_MANAGER
156 QTLWExtra *topextra = win->d_func()->extra->topextra;
157 QWSManager *manager = topextra->qwsManager;
158 if (manager)
159 manager->d_func()->dirtyRegion(QDecoration::All,
160 QDecoration::Normal);
161#endif
162 }
163}
164
165QWSWindowSurfacePrivate::QWSWindowSurfacePrivate()
166 : flags(0),
167#ifdef QT_QWS_CLIENTBLIT
168 directId(-1),
169#endif
170 winId(0)
171{
172}
173
174void QWSWindowSurfacePrivate::setWinId(int id)
175{
176 winId = id;
177}
178
179int QWSWindowSurface::winId() const
180{
181 // XXX: the widget winId may change during the lifetime of the widget!!!
182
183 const QWidget *win = window();
184 if (win && win->isWindow())
185 return win->internalWinId();
186
187#ifdef Q_BACKINGSTORE_SUBSURFACES
188 if (!d_ptr->winId) {
189 QWSWindowSurface *that = const_cast<QWSWindowSurface*>(this);
190 QWSDisplay *display = QWSDisplay::instance();
191 const int id = display->takeId();
192 qt_insertWindowSurface(id, that);
193 that->d_ptr->winId = id;
194
195 if (win)
196 display->nameRegion(id, win->objectName(), win->windowTitle());
197 else
198 display->nameRegion(id, QString(), QString());
199
200 display->setAltitude(id, 1, true); // XXX
201 }
202#endif
203
204 return d_ptr->winId;
205}
206
207void QWSWindowSurface::setWinId(int id)
208{
209 d_ptr->winId = id;
210}
211
212/*!
213 \class QWSWindowSurface
214 \since 4.2
215 \ingroup qws
216 \preliminary
217 \internal
218
219 \brief The QWSWindowSurface class provides the drawing area for top-level
220 windows in Qt for Embedded Linux.
221
222 Note that this class is only available in Qt for Embedded Linux.
223
224 In \l{Qt for Embedded Linux}, the default behavior is for each client to
225 render its widgets into memory while the server is responsible for
226 putting the contents of the memory onto the
227 screen. QWSWindowSurface is used by the window system to implement
228 the associated memory allocation.
229
230 When a screen update is required, the server runs through all the
231 top-level windows that intersect with the region that is about to
232 be updated, and ensures that the associated clients have updated
233 their memory buffer. Then the server uses the screen driver to
234 copy the content of the memory to the screen. To locate the
235 relevant parts of memory, the driver is provided with the list of
236 top-level windows that intersect with the given region. Associated
237 with each of the top-level windows there is a window surface
238 representing the drawing area of the window.
239
240 When deriving from the QWSWindowSurface class, e.g., when adding
241 an \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
242 {accelerated graphics driver}, there are several pure virtual
243 functions that must be implemented. In addition, QWSWindowSurface
244 provides several virtual functions that can be reimplemented to
245 customize the drawing process.
246
247 \tableofcontents
248
249 \section1 Pure Virtual Functions
250
251 There are in fact two window surface instances for each top-level
252 window; one used by the application when drawing a window, and
253 another used by the server application to perform window
254 compositioning. Implement the attach() to create the server-side
255 representation of the surface. The data() function must be
256 implemented to provide the required data.
257
258 Implement the key() function to uniquely identify the surface
259 class, and the isValid() function to determine is a surface
260 corresponds to a given widget.
261
262 The geometry() function must be implemented to let the window
263 system determine the area required by the window surface
264 (QWSWindowSurface also provides a corresponding virtual
265 setGeometry() function that is called whenever the area necessary
266 for the top-level window to be drawn, changes). The image()
267 function is called by the window system during window
268 compositioning, and must be implemented to return an image of the
269 top-level window.
270
271 Finally, the paintDevice() function must be implemented to return
272 the appropriate paint device, and the scroll() function must be
273 implemented to scroll the given region of the surface the given
274 number of pixels.
275
276 \section1 Virtual Functions
277
278 When painting onto the surface, the window system will always call
279 the beginPaint() function before any painting operations are
280 performed. Likewise the endPaint() function is automatically
281 called when the painting is done. Reimplement the painterOffset()
282 function to alter the offset that is applied when drawing.
283
284 The window system uses the flush() function to put a given region
285 of the widget onto the screen, and the release() function to
286 deallocate the screen region corresponding to this window surface.
287
288 \section1 Other Members
289
290 QWSWindowSurface provides the window() function returning a
291 pointer to the top-level window the surface is representing. The
292 currently visible region of the associated widget can be retrieved
293 and set using the clipRegion() and setClipRegion() functions,
294 respectively.
295
296 When the window system performs the window compositioning, it uses
297 the SurfaceFlag enum describing the surface content. The currently
298 set surface flags can be retrieved and altered using the
299 surfaceFlags() and setSurfaceFlags() functions. In addition,
300 QWSWindowSurface provides the isBuffered(), isOpaque() and
301 isRegionReserved() convenience functions.
302
303 \sa {Qt for Embedded Linux Architecture#Drawing on Screen}{Qt for
304 Embedded Linux Architecture}
305*/
306
307/*!
308 \enum QWSWindowSurface::SurfaceFlag
309
310 This enum is used to describe the window surface's contents. It
311 is used by the screen driver to handle region allocation and
312 composition.
313
314 \value RegionReserved The surface contains a reserved area. Once
315 allocated, a reserved area can not not be changed by the window
316 system, i.e., no other widgets can be drawn on top of this.
317
318 \value Buffered
319 The surface is in a memory area which is not part of a framebuffer.
320 (A top-level window with QWidget::windowOpacity() other than 1.0 must use
321 a buffered surface in order to making blending with the background work.)
322
323 \value Opaque
324 The surface contains only opaque pixels.
325
326 \sa surfaceFlags(), setSurfaceFlags()
327*/
328
329/*!
330 \fn bool QWSWindowSurface::isValid() const
331 \since 4.3
332
333 Implement this function to return true if the surface is a valid
334 surface for the given top-level \a window; otherwise return
335 false.
336
337 \sa window(), key()
338*/
339
340/*!
341 \fn QString QWSWindowSurface::key() const
342
343 Implement this function to return a string that uniquely
344 identifies the class of this surface.
345
346 \sa window(), isValid()
347*/
348
349/*!
350 \fn QByteArray QWSWindowSurface::permanentState() const
351 \since 4.3
352
353 Implement this function to return the data required for creating a
354 server-side representation of the surface.
355
356 \sa attach()
357*/
358
359/*!
360 \fn void QWSWindowSurface::setPermanentState(const QByteArray &data)
361 \since 4.3
362
363 Implement this function to attach a server-side surface instance
364 to the corresponding client side instance using the given \a
365 data. Return true if successful; otherwise return false.
366
367 \sa data()
368*/
369
370/*!
371 \fn const QImage QWSWindowSurface::image() const
372
373 Implement this function to return an image of the top-level window.
374
375 \sa geometry()
376*/
377
378/*!
379 \fn bool QWSWindowSurface::isRegionReserved() const
380
381 Returns true if the QWSWindowSurface::RegionReserved is set; otherwise
382 returns false.
383
384 \sa surfaceFlags()
385*/
386
387/*!
388 \fn bool QWSWindowSurface::isBuffered() const
389
390 Returns true if the QWSWindowSurface::Buffered is set; otherwise returns false.
391
392 \sa surfaceFlags()
393*/
394
395/*!
396 \fn bool QWSWindowSurface::isOpaque() const
397
398 Returns true if the QWSWindowSurface::Opaque is set; otherwise
399 returns false.
400
401 \sa surfaceFlags()
402*/
403
404
405/*!
406 Constructs an empty surface.
407*/
408QWSWindowSurface::QWSWindowSurface()
409 : QWindowSurface(0), d_ptr(new QWSWindowSurfacePrivate)
410{
411}
412
413/*!
414 Constructs an empty surface for the given top-level \a widget.
415*/
416QWSWindowSurface::QWSWindowSurface(QWidget *widget)
417 : QWindowSurface(widget), d_ptr(new QWSWindowSurfacePrivate)
418{
419}
420
421QWSWindowSurface::~QWSWindowSurface()
422{
423#ifdef Q_BACKINGSTORE_SUBSURFACES
424 if (d_ptr->winId)
425 winIdToSurfaceMap()->remove(d_ptr->winId);
426#endif
427
428 delete d_ptr;
429}
430
431/*!
432 Returns the offset to be used when painting.
433
434 \sa paintDevice()
435*/
436QPoint QWSWindowSurface::painterOffset() const
437{
438 const QWidget *w = window();
439 if (!w)
440 return QPoint();
441 return w->geometry().topLeft() - w->frameGeometry().topLeft();
442}
443
444void QWSWindowSurface::beginPaint(const QRegion &)
445{
446 lock();
447}
448
449void QWSWindowSurface::endPaint(const QRegion &)
450{
451 unlock();
452}
453
454// XXX: documentation!!!
455QByteArray QWSWindowSurface::transientState() const
456{
457 return QByteArray();
458}
459
460QByteArray QWSWindowSurface::permanentState() const
461{
462 return QByteArray();
463}
464
465void QWSWindowSurface::setTransientState(const QByteArray &state)
466{
467 Q_UNUSED(state);
468}
469
470void QWSWindowSurface::setPermanentState(const QByteArray &state)
471{
472 Q_UNUSED(state);
473}
474
475bool QWSWindowSurface::lock(int timeout)
476{
477 Q_UNUSED(timeout);
478 return true;
479}
480
481void QWSWindowSurface::unlock()
482{
483}
484
485#ifdef QT_QWS_CLIENTBLIT
486/*! \internal */
487const QRegion QWSWindowSurface::directRegion() const
488{
489 return d_ptr->direct;
490}
491
492/*! \internal */
493int QWSWindowSurface::directRegionId() const
494{
495 return d_ptr->directId;
496}
497
498/*! \internal */
499void QWSWindowSurface::setDirectRegion(const QRegion &r, int id)
500{
501 d_ptr->direct = r;
502 d_ptr->directId = id;
503}
504#endif
505
506/*!
507 Returns the region currently visible on the screen.
508
509 \sa setClipRegion()
510*/
511const QRegion QWSWindowSurface::clipRegion() const
512{
513 return d_ptr->clip;
514}
515
516/*!
517 Sets the region currently visible on the screen to be the given \a
518 clip region.
519
520 \sa clipRegion()
521*/
522void QWSWindowSurface::setClipRegion(const QRegion &clip)
523{
524 if (clip == d_ptr->clip)
525 return;
526
527 QRegion expose = (clip - d_ptr->clip);
528 d_ptr->clip = clip;
529
530 if (expose.isEmpty() || clip.isEmpty())
531 return; // No repaint or flush required.
532
533 QWidget *win = window();
534 if (!win)
535 return;
536
537 if (isBuffered()) {
538 // No repaint required. Flush exposed area via the backing store.
539 win->d_func()->syncBackingStore(expose);
540 return;
541 }
542
543#ifndef QT_NO_QWS_MANAGER
544 // Invalidate exposed decoration area.
545 if (win && win->isWindow()) {
546 QTLWExtra *topextra = win->d_func()->extra->topextra;
547 if (QWSManager *manager = topextra->qwsManager) {
548 QRegion decorationExpose(manager->region());
549 decorationExpose.translate(-win->geometry().topLeft());
550 decorationExpose &= expose;
551 if (!decorationExpose.isEmpty()) {
552 expose -= decorationExpose;
553 manager->d_func()->dirtyRegion(QDecoration::All, QDecoration::Normal, decorationExpose);
554 }
555 }
556 }
557#endif
558
559 // Invalidate exposed widget area.
560 win->d_func()->invalidateBuffer(expose);
561}
562
563/*!
564 Returns the surface flags describing the contents of this surface.
565
566 \sa isBuffered(), isOpaque(), isRegionReserved()
567*/
568QWSWindowSurface::SurfaceFlags QWSWindowSurface::surfaceFlags() const
569{
570 return d_ptr->flags;
571}
572
573/*!
574 Sets the surface flags describing the contents of this surface, to
575 be the given \a flags.
576
577 \sa surfaceFlags()
578*/
579void QWSWindowSurface::setSurfaceFlags(SurfaceFlags flags)
580{
581 d_ptr->flags = flags;
582}
583
584void QWSWindowSurface::setGeometry(const QRect &rect)
585{
586 QRegion mask = rect;
587
588 const QWidget *win = window();
589 if (win) {
590#ifndef QT_NO_QWS_MANAGER
591 if (win->isWindow()) {
592 QTLWExtra *topextra = win->d_func()->extra->topextra;
593 QWSManager *manager = topextra->qwsManager;
594
595 if (manager) {
596 // The frame geometry is the bounding rect of manager->region,
597 // which could be too much, so we need to clip.
598 mask &= (manager->region() + win->geometry());
599 }
600 }
601#endif
602
603 const QRegion winMask = win->mask();
604 if (!winMask.isEmpty())
605 mask &= winMask.translated(win->geometry().topLeft());
606 }
607
608 setGeometry(rect, mask);
609}
610
611void QWSWindowSurface::setGeometry(const QRect &rect, const QRegion &mask)
612{
613 if (rect == geometry()) // XXX: && mask == prevMask
614 return;
615
616 const bool isResize = rect.size() != geometry().size();
617 const bool needsRepaint = isResize || !isBuffered();
618
619 QWindowSurface::setGeometry(rect);
620
621 const QRegion region = mask & rect;
622 QWidget *win = window();
623 // Only request regions for widgets visible on the screen.
624 // (Added the !win check for compatibility reasons, because
625 // there was no "if (win)" check before).
626 const bool requestQWSRegion = !win || !win->testAttribute(Qt::WA_DontShowOnScreen);
627 if (requestQWSRegion)
628 QWidget::qwsDisplay()->requestRegion(winId(), key(), permanentState(), region);
629
630 if (needsRepaint)
631 invalidateBuffer();