Qt 4.8
qdirectfbwindowsurface.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdirectfbwindowsurface.h"
43 #include "qdirectfbscreen.h"
44 #include "qdirectfbpaintengine.h"
45 
46 #include <private/qwidget_p.h>
47 #include <qwidget.h>
48 #include <qwindowsystem_qws.h>
49 #include <qpaintdevice.h>
50 #include <qvarlengtharray.h>
51 
52 #ifndef QT_NO_QWS_DIRECTFB
53 
55 
58 #ifndef QT_NO_DIRECTFB_WM
59  , dfbWindow(0)
60 #endif
61  , flipFlags(flip)
62  , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
63  , flushPending(false)
64 {
65 #ifdef QT_NO_DIRECTFB_WM
66  mode = Offscreen;
67 #endif
69 #ifdef QT_DIRECTFB_TIMING
70  frames = 0;
71  timer.start();
72 #endif
73 }
74 
77 #ifndef QT_NO_DIRECTFB_WM
78  , dfbWindow(0)
79 #endif
80  , flipFlags(flip)
81  , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
82  , flushPending(false)
83 {
84  SurfaceFlags flags = 0;
85  if (!widget || widget->window()->windowOpacity() == 0xff)
86  flags |= Opaque;
87 #ifdef QT_NO_DIRECTFB_WM
88  if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) {
89  flags = RegionReserved;
90  mode = Primary;
91  } else {
92  mode = Offscreen;
93  flags = Buffered;
94  }
95 #endif
96  setSurfaceFlags(flags);
97 #ifdef QT_DIRECTFB_TIMING
98  frames = 0;
99  timer.start();
100 #endif
101 }
102 
104 {
105  releaseSurface();
106  // these are not tracked by QDirectFBScreen so we don't want QDirectFBPaintDevice to release it
107 }
108 
110 {
111  return true;
112 }
113 
114 #ifdef QT_DIRECTFB_WM
116 {
117  if (IDirectFBWindow *window = directFBWindow()) {
118  window->RaiseToTop(window);
119  }
120 }
121 
123 {
124  return dfbWindow;
125 }
126 
128 {
129  IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
130  if (!layer)
131  qFatal("QDirectFBWindowSurface: Unable to get primary display layer!");
132 
133  updateIsOpaque();
134 
135  DFBWindowDescription description;
136  memset(&description, 0, sizeof(DFBWindowDescription));
137 
138  description.flags = DWDESC_CAPS|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT;
139  description.caps = DWCAPS_NODECORATION;
140  description.surface_caps = DSCAPS_NONE;
142 
143  if (!(surfaceFlags() & Opaque)) {
145  description.caps |= DWCAPS_ALPHACHANNEL;
146 #if (Q_DIRECTFB_VERSION >= 0x010200)
147  description.flags |= DWDESC_OPTIONS;
148  description.options |= DWOP_ALPHACHANNEL;
149 #endif
150  }
151  description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(imageFormat);
152  description.posx = rect.x();
153  description.posy = rect.y();
154  description.width = rect.width();
155  description.height = rect.height();
156 
158  description.surface_caps = DSCAPS_PREMULTIPLIED;
159 
161  description.surface_caps |= DSCAPS_VIDEOONLY;
162 
163  DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow);
164 
165  if (result != DFB_OK)
166  DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result);
167 
168  if (window()) {
169  if (window()->windowFlags() & Qt::WindowStaysOnTopHint) {
170  dfbWindow->SetStackingClass(dfbWindow, DWSC_UPPER);
171  }
172  DFBWindowID winid;
173  result = dfbWindow->GetID(dfbWindow, &winid);
174  if (result != DFB_OK) {
175  DirectFBError("QDirectFBWindowSurface::createWindow. Can't get ID", result);
176  } else {
177  window()->setProperty("_q_DirectFBWindowID", winid);
178  }
179  }
180 
182  dfbWindow->GetSurface(dfbWindow, &dfbSurface);
183 }
184 
185 static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect)
186 {
187  DFBResult result = DFB_OK;
188  const bool isMove = old.isEmpty() || rect.topLeft() != old.topLeft();
189  const bool isResize = rect.size() != old.size();
190 
191 #if (Q_DIRECTFB_VERSION >= 0x010000)
192  if (isResize && isMove) {
193  result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(),
194  rect.width(), rect.height());
195  } else if (isResize) {
196  result = dfbWindow->Resize(dfbWindow,
197  rect.width(), rect.height());
198  } else if (isMove) {
199  result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
200  }
201 #else
202  if (isResize) {
203  result = dfbWindow->Resize(dfbWindow,
204  rect.width(), rect.height());
205  }
206  if (isMove) {
207  result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
208  }
209 #endif
210  return result;
211 }
212 #endif // QT_NO_DIRECTFB_WM
213 
215 {
216  const QRect oldRect = geometry();
217  if (oldRect == rect)
218  return;
219 
220  IDirectFBSurface *oldSurface = dfbSurface;
221  const bool sizeChanged = oldRect.size() != rect.size();
222  if (sizeChanged) {
223  delete engine;
224  engine = 0;
225  releaseSurface();
227  }
228 
229  if (rect.isNull()) {
230 #ifndef QT_NO_DIRECTFB_WM
231  if (dfbWindow) {
232  if (window())
233  window()->setProperty("_q_DirectFBWindowID", QVariant());
234 
235  dfbWindow->Release(dfbWindow);
236  dfbWindow = 0;
237  }
238 #endif
240 #ifdef QT_DIRECTFB_SUBSURFACE
241  Q_ASSERT(!subSurface);
242 #endif
243  } else {
244 #ifdef QT_DIRECTFB_WM
245  if (!dfbWindow) {
246  createWindow(rect);
247  } else {
248  setWindowGeometry(dfbWindow, oldRect, rect);
249  Q_ASSERT(!sizeChanged || !dfbSurface);
250  if (sizeChanged)
251  dfbWindow->GetSurface(dfbWindow, &dfbSurface);
252  }
253 #else
254  IDirectFBSurface *primarySurface = screen->primarySurface();
255  DFBResult result = DFB_OK;
256  if (mode == Primary) {
257  Q_ASSERT(primarySurface);
258  if (rect == screen->region().boundingRect()) {
259  dfbSurface = primarySurface;
260  } else {
261  const DFBRectangle r = { rect.x(), rect.y(),
262  rect.width(), rect.height() };
263  result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface);
264  }
265  } else { // mode == Offscreen
266  if (!dfbSurface) {
269  }
270  }
271  if (result != DFB_OK)
272  DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result);
273 #endif
274  }
275  if (oldSurface != dfbSurface) {
277  }
278 
279  if (oldRect.size() != rect.size()) {
281  } else {
283  }
284 }
285 
287 {
288  QByteArray state(sizeof(SurfaceFlags) + sizeof(DFBWindowID), 0);
289  char *ptr = state.data();
290  SurfaceFlags flags = surfaceFlags();
291  memcpy(ptr, &flags, sizeof(SurfaceFlags));
292  ptr += sizeof(SurfaceFlags);
293  DFBWindowID did = (DFBWindowID)(-1);
294  if (dfbWindow)
295  dfbWindow->GetID(dfbWindow, &did);
296  memcpy(ptr, &did, sizeof(DFBWindowID));
297  return state;
298 }
299 
301 {
302  const char *ptr = state.constData();
303  IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
304  SurfaceFlags flags;
305  memcpy(&flags, ptr, sizeof(SurfaceFlags));
306 
307  setSurfaceFlags(flags);
308  ptr += sizeof(SurfaceFlags);
309  DFBWindowID id;
310  memcpy(&id, ptr, sizeof(DFBWindowID));
311  if (dfbSurface)
312  dfbSurface->Release(dfbSurface);
313  if (id != (DFBWindowID)-1) {
314  IDirectFBWindow *dw;
315  layer->GetWindow(layer, id, &dw);
316  if (dw->GetSurface(dw, &dfbSurface) != DFB_OK)
317  dfbSurface = 0;
318  dw->Release(dw);
319  }
320  else {
321  dfbSurface = 0;
322  }
323 }
324 
325 bool QDirectFBWindowSurface::scroll(const QRegion &region, int dx, int dy)
326 {
327  if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.rectCount() != 1)
328  return false;
329  if (flushPending) {
330  dfbSurface->Flip(dfbSurface, 0, DSFLIP_BLIT);
331  } else {
332  flushPending = true;
333  }
334  dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
335  const QRect r = region.boundingRect();
336  const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() };
337  dfbSurface->Blit(dfbSurface, dfbSurface, &rect, r.x() + dx, r.y() + dy);
338  return true;
339 }
340 
342 {
343  setGeometry(geometry().translated(moveBy));
344  return true;
345 }
346 
348 {
349  SurfaceFlags flags = surfaceFlags();
350  if (opaque != (flags & Opaque)) {
351  if (opaque) {
352  flags |= Opaque;
353  } else {
354  flags &= ~Opaque;
355  }
356  setSurfaceFlags(flags);
357  }
358 }
359 
360 
362  const QPoint &offset)
363 {
364  QWidget *win = window();
365  if (!win)
366  return;
367 
368 #if !defined(QT_NO_QWS_PROXYSCREEN) && !defined(QT_NO_GRAPHICSVIEW)
369  QWExtra *extra = qt_widget_private(widget)->extraData();
370  if (extra && extra->proxyWidget)
371  return;
372 #else
373  Q_UNUSED(widget);
374 #endif
375 
376  const quint8 windowOpacity = quint8(win->windowOpacity() * 0xff);
377  const QRect windowGeometry = geometry();
378 #ifdef QT_DIRECTFB_WM
379  quint8 currentOpacity;
381  dfbWindow->GetOpacity(dfbWindow, &currentOpacity);
382  if (currentOpacity != windowOpacity) {
383  dfbWindow->SetOpacity(dfbWindow, windowOpacity);
384  }
385 
386  screen->flipSurface(dfbSurface, flipFlags, region, offset);
387 #else
388  setOpaque(windowOpacity == 0xff);
389  if (mode == Offscreen) {
390  screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0);
391  } else {
392  screen->flipSurface(dfbSurface, flipFlags, region, offset);
393  }
394 #endif
395 
396 #ifdef QT_DIRECTFB_TIMING
397  enum { Secs = 3 };
398  ++frames;
399  if (timer.elapsed() >= Secs * 1000) {
400  qDebug("%d fps", int(double(frames) / double(Secs)));
401  frames = 0;
402  timer.restart();
403  }
404 #endif
405  flushPending = false;
406 }
407 
409 {
410  if (!engine) {
411  engine = new QDirectFBPaintEngine(this);
412  }
413 
414  if (dfbSurface) {
415  const QWidget *win = window();
416  if (win && win->testAttribute(Qt::WA_NoSystemBackground)) {
418  }
419  }
420  flushPending = true;
421 }
422 
424 {
425 #ifdef QT_NO_DIRECTFB_SUBSURFACE
426  unlockSurface();
427 #endif
428 }
429 
431 {
432  return dfbSurface;
433 }
434 
435 
437 {
438  Q_ASSERT(widget);
439  if (!dfbSurface)
440  return 0;
441  QWidget *win = window();
442  Q_ASSERT(win);
443  if (rect) {
444  if (win == widget) {
445  *rect = widget->rect();
446  } else {
447  *rect = QRect(widget->mapTo(win, QPoint(0, 0)), widget->size());
448  }
449  }
450 
451  Q_ASSERT(win == widget || win->isAncestorOf(widget));
452  return dfbSurface;
453 }
454 
456 {
457  if (dfbSurface) {
458 #ifdef QT_DIRECTFB_SUBSURFACE
459  releaseSubSurface();
460 #else
461  unlockSurface();
462 #endif
463 #ifdef QT_NO_DIRECTFB_WM
464  Q_ASSERT(screen->primarySurface());
465  if (dfbSurface != screen->primarySurface())
466 #endif
467 
468  dfbSurface->Release(dfbSurface);
469  dfbSurface = 0;
470  }
471 }
472 
474 {
475  const QWidget *win = window();
476  Q_ASSERT(win);
478  setOpaque(true);
479  return;
480  }
481 
482  if (qFuzzyCompare(static_cast<float>(win->windowOpacity()), 1.0f)) {
483  const QPalette &pal = win->palette();
484 
485  if (win->autoFillBackground()) {
486  const QBrush &autoFillBrush = pal.brush(win->backgroundRole());
487  if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
488  setOpaque(true);
489  return;
490  }
491  }
492 
493  if (win->isWindow() && !win->testAttribute(Qt::WA_NoSystemBackground)) {
494  const QBrush &windowBrush = win->palette().brush(QPalette::Window);
495  if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
496  setOpaque(true);
497  return;
498  }
499  }
500  }
501  setOpaque(false);
502 }
503 
505 
506 #endif // QT_NO_QWS_DIRECTFB
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
void flush(QWidget *widget, const QRegion &region, const QPoint &offset)
Flushes the given region from the specified widget onto the screen.
QRect geometry() const
Returns the currently allocated area on the screen.
QPalette palette
the widget&#39;s palette
Definition: qwidget.h:180
The QWSWindowSurface class provides the drawing area for top-level windows in Qt for Embedded Linux...
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
double windowOpacity
The level of opacity for the window.
Definition: qwidget.h:201
static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect)
IDirectFBSurface * createDFBSurface(const QImage &image, QImage::Format format, SurfaceCreationOptions options, DFBResult *result=0)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
IDirectFBSurface * directFBSurface() const
IDirectFBWindow * directFBWindow() const
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
DirectFBFlags directFBFlags() const
QPoint mapTo(QWidget *, const QPoint &) const
Translates the widget coordinate pos to the coordinate system of parent.
Definition: qwidget.cpp:4409
QRect rect(const QWidget *widget) const
Returns the rectangle for widget in the coordinates of this window surface.
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition: qwidget.h:945
static bool isPremultiplied(QImage::Format format)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QDirectFBScreen * screen
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object&#39;s name property to value.
Definition: qobject.cpp:3755
IDirectFBDisplayLayer * dfbDisplayLayer()
virtual void setGeometry(const QRect &rect)
Sets the currently allocated area to be the given rect.
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
QPalette::ColorRole backgroundRole() const
Returns the background role of the widget.
Definition: qwidget.cpp:4677
virtual QPoint offset(const QWidget *widget) const
Returns the offset of widget in the coordinates of this window surface.
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
Definition: qglobal.h:2030
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
unsigned char quint8
Definition: qglobal.h:934
EventLoopTimerRef timer
void setSurfaceFlags(SurfaceFlags type)
Sets the surface flags describing the contents of this surface, to be the given flags.
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QImage::Format alphaPixmapFormat() const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool autoFillBackground
whether the widget background is filled automatically
Definition: qwidget.h:218
int rectCount() const
Returns the number of rectangles that will be returned in rects().
Definition: qregion.cpp:4461
QDirectFBPaintEngine * engine
QDirectFBWindowSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen *scr)
QGraphicsProxyWidget * proxyWidget
Definition: qwidget_p.h:251
Q_CORE_EXPORT void qDebug(const char *,...)
virtual QRegion region() const
Returns the region covered by this screen driver.
Definition: qscreen_qws.h:284
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
bool move(const QPoint &offset)
Move the surface with the given offset.
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
const T * ptr(const T &t)
QSize size
the size of the widget excluding any window frame
Definition: qwidget.h:165
static DFBSurfacePixelFormat getSurfacePixelFormat(QImage::Format format)
static QImage::Format getImageFormat(IDirectFBSurface *surface)
Qt::BrushStyle style() const
Returns the brush style.
Definition: qbrush.h:182
bool isOpaque() const
Returns true if the brush is fully opaque otherwise false.
Definition: qbrush.cpp:910
IDirectFBSurface * dfbSurface
const QBrush & brush(ColorGroup cg, ColorRole cr) const
Returns the brush in the specified color group, used for the given color role.
Definition: qpalette.cpp:874
void endPaint(const QRegion &)
This function is called after painting onto the surface has ended, with the region in which the paint...
IDirectFBSurface * surfaceForWidget(const QWidget *widget, QRect *rect) const
SurfaceFlags surfaceFlags() const
Returns the surface flags describing the contents of this surface.
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
void solidFill(const QColor &color, const QRegion &region)
Fills the given region of the screen with the specified color.
Q_CORE_EXPORT void qFatal(const char *,...)
bool scroll(const QRegion &area, int dx, int dy)
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative...
QImage::Format pixelFormat() const
Returns the pixel format of the screen, or QImage::Format_Invalid if the pixel format is not a suppor...
DFBSurfaceFlipFlags flipFlags
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:168
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
bool isValid() const
Implement this function to return true if the surface is a valid surface for the given top-level wind...
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
bool isAncestorOf(const QWidget *child) const
Returns true if this widget is a parent, (or grandparent and so on to any level), of the given child...
Definition: qwidget.cpp:8573
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QWidget * window() const
Returns the window for this widget, i.e.
Definition: qwidget.cpp:4492
void beginPaint(const QRegion &)
This function is called before painting onto the surface begins, with the region in which the paintin...
QRegion translated(int dx, int dy) const
Returns a copy of the region that is translated dx along the x axis and dy along the y axis...
Definition: qregion.cpp:743
QWExtra * extraData() const
Definition: qwidget_p.h:999
void setPermanentState(const QByteArray &state)
Implement this function to attach a server-side surface instance to the corresponding client side ins...
Q_GUI_EXPORT QWidgetPrivate * qt_widget_private(QWidget *widget)
Definition: qwidget.cpp:12920
void flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, const QRegion &region, const QPoint &offset)
void exposeRegion(QRegion r, int changing)
This function is called by the Qt for Embedded Linux server whenever a screen update is required...
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void setGeometry(const QRect &rect)
Sets the currently allocated area to be the given rect.
QWidget * window() const
Returns a pointer to the top-level window associated with this surface.
virtual void setGeometry(const QRect &rect)
Sets the currently allocated area to be the given rect.
void createWindow(const QRect &rect)
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
QByteArray permanentState() const
Implement this function to return the data required for creating a server-side representation of the ...
The QPalette class contains color groups for each widget state.
Definition: qpalette.h:61