Qt 4.8
qscreenqnx_qws.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 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 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 "qscreenqnx_qws.h"
43 
44 #include <qapplication.h>
45 #include <qregexp.h>
46 
47 #include <gf/gf.h>
48 
50 
51 // This struct holds all the pointers to QNX's internals
53 {
55  : device(0), display(0), layer(0), hwSurface(0), memSurface(0), context(0)
56  {}
58  { cleanup(); }
59 
60  void cleanup();
61 
62  gf_dev_t device;
63  gf_dev_info_t deviceInfo;
64  gf_display_t display;
65  gf_display_info_t displayInfo;
66  gf_layer_t layer;
67  gf_surface_t hwSurface;
68  gf_surface_t memSurface;
69  gf_surface_info_t memSurfaceInfo;
70  gf_context_t context;
71 };
72 
74 {
75  if (context) {
76  gf_context_free(context);
77  context = 0;
78  }
79  if (memSurface) {
80  gf_surface_free(memSurface);
81  memSurface = 0;
82  }
83  if (hwSurface) {
84  gf_surface_free(hwSurface);
85  hwSurface = 0;
86  }
87  if (layer) {
88  gf_layer_detach(layer);
89  layer = 0;
90  }
91  if (display) {
92  gf_display_detach(display);
93  display = 0;
94  }
95  if (device) {
96  gf_dev_detach(device);
97  device = 0;
98  }
99 }
100 
101 
145 QQnxScreen::QQnxScreen(int display_id)
146  : QScreen(display_id), d(new QQnxScreenContext)
147 {
148 }
149 
154 {
155  delete d;
156 }
157 
162 {
163 #ifndef QT_NO_QWS_CURSOR
165 #endif
166 
167  return true;
168 }
169 
177 static inline bool attachDevice(QQnxScreenContext * const d, const char *name)
178 {
179  int ret = gf_dev_attach(&d->device, name, &d->deviceInfo);
180  if (ret != GF_ERR_OK) {
181  qWarning("QQnxScreen: gf_dev_attach(%s) failed with error code %d", name, ret);
182  return false;
183  }
184  return true;
185 }
186 
194 static inline bool attachDisplay(QQnxScreenContext * const d, int displayIndex)
195 {
196  int ret = gf_display_attach(&d->display, d->device, displayIndex, &d->displayInfo);
197  if (ret != GF_ERR_OK) {
198  qWarning("QQnxScreen: gf_display_attach(%d) failed with error code %d", displayIndex, ret);
199  return false;
200  }
201  return true;
202 }
203 
211 static inline bool attachLayer(QQnxScreenContext * const d, int layerIndex)
212 {
213  unsigned flags = QApplication::type() != QApplication::GuiServer ? GF_LAYER_ATTACH_PASSIVE : 0;
214  int ret = gf_layer_attach(&d->layer, d->display, layerIndex, flags);
215  if (ret != GF_ERR_OK) {
216  qWarning("QQnxScreen: gf_layer_attach(%d) failed with error code %d", layerIndex, ret);
217  return false;
218  }
219 
220  return true;
221 }
222 
227 static inline bool createHwSurface(QQnxScreenContext * const d, int w, int h)
228 {
229  int ret = gf_surface_create_layer(&d->hwSurface, &d->layer, 1, 0,
230  w, h, d->displayInfo.format, 0, 0);
231  if (ret != GF_ERR_OK) {
232  qWarning("QQnxScreen: gf_surface_create_layer(%dx%d) failed with error code %d", w, h, ret);
233  return false;
234  }
235 
236  gf_layer_set_surfaces(d->layer, &d->hwSurface, 1);
237 
238  gf_layer_enable(d->layer);
239 
240  ret = gf_layer_update(d->layer, 0);
241  if (ret != GF_ERR_OK) {
242  qWarning("QQnxScreen: gf_layer_update() failed with error code %d\n", ret);
243  return false;
244  }
245 
246  ret = gf_context_create(&d->context);
247  if (ret != GF_ERR_OK) {
248  qWarning("QQnxScreen: gf_context_create() failed with error code %d", ret);
249  return false;
250  }
251 
252  ret = gf_context_set_surface(d->context, d->hwSurface);
253  if (ret != GF_ERR_OK) {
254  qWarning("QQnxScreen: gf_context_set_surface() failed with error code %d", ret);
255  return false;
256  }
257 
258  return true;
259 }
260 
266 static inline bool createMemSurface(QQnxScreenContext * const d, int w, int h)
267 {
268 #ifndef QT_NO_QWS_MULTIPROCESS
270  unsigned sidlist[64];
271  int n = gf_surface_sidlist(d->device, sidlist); // undocumented API
272  for (int i = 0; i < n; ++i) {
273  int ret = gf_surface_attach_by_sid(&d->memSurface, d->device, sidlist[i]);
274  if (ret == GF_ERR_OK) {
275  gf_surface_get_info(d->memSurface, &d->memSurfaceInfo);
276  if (d->memSurfaceInfo.sid != unsigned(GF_SID_INVALID)) {
277  // can we use the surface's vaddr?
278  unsigned flags = GF_SURFACE_CPU_LINEAR_READABLE | GF_SURFACE_CPU_LINEAR_WRITEABLE;
279  if ((d->memSurfaceInfo.flags & flags) == flags)
280  return true;
281  }
282 
283  gf_surface_free(d->memSurface);
284  d->memSurface = 0;
285  }
286  }
287  qWarning("QQnxScreen: cannot attach to an usable surface; create a new one.");
288  }
289 #endif
290  int ret = gf_surface_create(&d->memSurface, d->device, w, h, d->displayInfo.format, 0,
291  GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE
292  | GF_SURFACE_CREATE_PHYS_CONTIG | GF_SURFACE_CREATE_SHAREABLE);
293  if (ret != GF_ERR_OK) {
294  qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d",
295  w, h, ret);
296  return false;
297  }
298 
299  gf_surface_get_info(d->memSurface, &d->memSurfaceInfo);
300 
301  if (d->memSurfaceInfo.sid == unsigned(GF_SID_INVALID)) {
302  qWarning("QQnxScreen: gf_surface_get_info() failed.");
303  return false;
304  }
305 
306  return true;
307 }
308 
320 bool QQnxScreen::connect(const QString &displaySpec)
321 {
322  const QStringList params = displaySpec.split(QLatin1Char(':'), QString::SkipEmptyParts);
323 
324  // default to device 0
325  int deviceIndex = 0;
326  if (!params.isEmpty()) {
327  QRegExp deviceRegExp(QLatin1String("^device=(.+)$"));
328  if (params.indexOf(deviceRegExp) != -1)
329  deviceIndex = deviceRegExp.cap(1).toInt();
330  }
331 
332  if (!attachDevice(d, GF_DEVICE_INDEX(deviceIndex)))
333  return false;
334 
335  qDebug("QQnxScreen: Attached to Device, number of displays: %d", d->deviceInfo.ndisplays);
336 
337  // default to display id passed to constructor
338  int displayIndex = displayId;
339  if (!params.isEmpty()) {
340  QRegExp displayRegexp(QLatin1String("^display=(\\d+)$"));
341  if (params.indexOf(displayRegexp) != -1)
342  displayIndex = displayRegexp.cap(1).toInt();
343  }
344 
345  if (!attachDisplay(d, displayIndex))
346  return false;
347 
348  qDebug("QQnxScreen: Attached to Display %d, resolution %dx%d, refresh %d Hz",
349  displayIndex, d->displayInfo.xres, d->displayInfo.yres, d->displayInfo.refresh);
350 
351  // default to main_layer_index from the displayInfo struct
352  int layerIndex = d->displayInfo.main_layer_index;
353  if (!params.isEmpty()) {
354  QRegExp layerRegexp(QLatin1String("^layer=(\\d+)$"));
355  if (params.indexOf(layerRegexp) != -1)
356  layerIndex = layerRegexp.cap(1).toInt();
357  }
358 
359  if (!attachLayer(d, layerIndex))
360  return false;
361 
362  // determine the pixel format and the pixel type
363  switch (d->displayInfo.format) {
364 #if defined(QT_QWS_DEPTH_32) || defined(QT_QWS_DEPTH_GENERIC)
365  case GF_FORMAT_ARGB8888:
367  // fall through
368  case GF_FORMAT_BGRA8888:
370  break;
371 #endif
372 #if defined(QT_QWS_DEPTH_24)
373  case GF_FORMAT_BGR888:
376  break;
377 #endif
378 #if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_GENERIC)
379  case GF_FORMAT_PACK_RGB565:
380  case GF_FORMAT_PKLE_RGB565:
381  case GF_FORMAT_PKBE_RGB565:
382 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
383  setFrameBufferLittleEndian((d->displayInfo.format & GF_FORMAT_PKLE) == GF_FORMAT_PKLE);
384 #endif
386  break;
387 #endif
388  default:
389  return false;
390  }
391 
392  // tell QWSDisplay the width and height of the display
393  w = dw = d->displayInfo.xres;
394  h = dh = d->displayInfo.yres;
395  QScreen::d = (d->displayInfo.format & GF_FORMAT_BPP); // colour depth
396 
397  // assume 72 dpi as default, to calculate the physical dimensions if not specified
398  const int defaultDpi = 72;
399  // Handle display physical size
400  physWidth = qRound(dw * 25.4 / defaultDpi);
401  physHeight = qRound(dh * 25.4 / defaultDpi);
402  if (!params.isEmpty()) {
403  QRegExp mmWidthRegexp(QLatin1String("^mmWidth=(\\d+)$"));
404  if (params.indexOf(mmWidthRegexp) != -1)
405  physWidth = mmWidthRegexp.cap(1).toInt();
406 
407  QRegExp mmHeightRegexp(QLatin1String("^mmHeight=(\\d+)$"));
408  if (params.indexOf(mmHeightRegexp) != -1)
409  physHeight = mmHeightRegexp.cap(1).toInt();
410  }
411 
413  // create a hardware surface with our dimensions. In the old days, it was possible
414  // to get a pointer directly to the hw surface, so we could blit directly. Now, we
415  // have to use one indirection more, because it's not guaranteed that the hw surface
416  // is mappable into our process.
417  if (!createHwSurface(d, w, h))
418  return false;
419  }
420 
421  // create an in-memory linear surface that is used by QWS. QWS will blit directly in here.
422  if (!createMemSurface(d, w, h))
423  return false;
424 
425  // set the address of the in-memory buffer that QWS is blitting to
426  data = d->memSurfaceInfo.vaddr;
427  // set the line stepping
428  lstep = d->memSurfaceInfo.stride;
429 
430  // the overall size of the in-memory buffer is linestep * height
431  size = mapsize = lstep * h;
432 
433  // done, the driver should be connected to the display now.
434  return true;
435 }
436 
441 {
442  d->cleanup();
443 }
444 
449 {
450 }
451 
459 void QQnxScreen::setMode(int,int,int)
460 {
461  qWarning("QQnxScreen: Unable to change mode, use io-display instead.");
462 }
463 
468 {
469  gf_modeinfo_t displayMode;
470  for (int i = 0; gf_display_query_mode(d->display, i, &displayMode) == GF_ERR_OK; ++i) {
471  switch (displayMode.primary_format) {
472 #if defined(QT_QWS_DEPTH_32) || defined(QT_QWS_DEPTH_GENERIC)
473  case GF_FORMAT_ARGB8888:
474  case GF_FORMAT_BGRA8888:
475  if (depth == 32)
476  return true;
477  break;
478 #endif
479 #if defined(QT_QWS_DEPTH_24)
480  case GF_FORMAT_BGR888:
481  if (depth == 24)
482  return true;
483  break;
484 #endif
485 #if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_GENERIC)
486  case GF_FORMAT_PACK_RGB565:
487  case GF_FORMAT_PKLE_RGB565:
488  case GF_FORMAT_PKBE_RGB565:
489  if (depth == 16)
490  return true;
491  break;
492 #endif
493  default:
494  break;
495  }
496  }
497 
498  return false;
499 }
500 
504 void QQnxScreen::blank(bool on)
505 {
506  int ret = gf_display_set_dpms(d->display, on ? GF_DPMS_OFF : GF_DPMS_ON);
507  if (ret != GF_ERR_OK)
508  qWarning("QQnxScreen: gf_display_set_dpms() failed with error code %d", ret);
509 }
510 
514 void QQnxScreen::exposeRegion(QRegion r, int changing)
515 {
516  // here is where the actual magic happens. QWS will call exposeRegion whenever
517  // a region on the screen is dirty and needs to be updated on the actual screen.
518 
519  // first, call the parent implementation. The parent implementation will update
520  // the region on our in-memory surface
521  QScreen::exposeRegion(r, changing);
522 
523 #ifndef QT_NO_QWS_TRANSFORMED
524  if (qt_screen->isTransformed())
525  return;
526 #endif
527  // now our in-memory surface should be up to date with the latest changes.
528 
529  if (!d->hwSurface)
530  return;
531 
532  // the code below copies the region from the in-memory surface to the hardware.
533 
534  // start drawing.
535  int ret = gf_draw_begin(d->context);
536  if (ret != GF_ERR_OK) {
537  qWarning("QQnxScreen: gf_draw_begin() failed with error code %d", ret);
538  return;
539  }
540  QVector<QRect> rects = r.rects();
541  Q_FOREACH (QRect rect, rects) {
542  if (!rect.isEmpty()) {
543  // blit the changed region from the memory surface to the hardware surface
544  ret = gf_draw_blit2(d->context, d->memSurface, d->hwSurface,
545  rect.x(), rect.y(), rect.right(), rect.bottom(), rect.x(), rect.y());
546  if (ret != GF_ERR_OK)
547  qWarning("QQnxScreen: gf_draw_blit2() failed with error code %d", ret);
548  }
549  }
550  // flush all drawing commands (in our case, a single blit)
551  ret = gf_draw_flush(d->context);
552  if (ret != GF_ERR_OK)
553  qWarning("QQnxScreen: gf_draw_flush() failed with error code %d", ret);
554 
555  // tell QNX that we're done drawing.
556  gf_draw_end(d->context);
557 }
558 
559 #ifndef QT_NO_QWS_TRANSFORMED
561 {
562  //This function is called only when the screen is transformed
563  if (!qt_screen->isTransformed())
564  return;
565 
566  if (!d->hwSurface)
567  return;
568 
569  int ret = gf_draw_begin(d->context);
570 
571  if (ret != GF_ERR_OK) {
572  qWarning("QQnxScreen: gf_draw_begin() failed with error code %d in setDirty", ret);
573  return;
574  }
575 
576  // blit the changed region from the memory surface to the hardware surface
577  ret = gf_draw_blit2(d->context, d->memSurface, d->hwSurface,
578  r.x(), r.y(), r.x()+ r.width(), r.y()+r.height(), r.x(), r.y());
579  if (ret != GF_ERR_OK)
580  qWarning("QQnxScreen: gf_draw_blit2() failed with error code %d in setDirty", ret);
581 
582  ret = gf_draw_flush(d->context);
583  if (ret != GF_ERR_OK)
584  qWarning("QQnxScreen: gf_draw_flush() failed with error code %d in setDirty", ret);
585 
586  // tell QNX that we're done drawing.
587  gf_draw_end(d->context);
588 }
589 #endif
590 
Q_GUI_EXPORT QScreen * qt_screen
Definition: qscreen_qws.cpp:69
double d
Definition: qnumeric_p.h:62
QString cap(int nth=0) const
Returns the text captured by the nth subexpression.
Definition: qregexp.cpp:4310
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int d
the pixel depth
Definition: qscreen_qws.h:327
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
gf_surface_t hwSurface
bool supportsDepth(int) const
Reimplemented Function
void setDirty(const QRect &)
Marks the given rectangle as dirty.
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
void shutdownDevice()
Reimplemented Function
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int physHeight
the physical height of the screen in millimeters.
Definition: qscreen_qws.h:340
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
The QString class provides a Unicode character string.
Definition: qstring.h:83
int size
the number of bytes in the visible region of the frame buffer
Definition: qscreen_qws.h:334
static bool attachDevice(QQnxScreenContext *const d, const char *name)
Attaches to the named device name.
static void initSoftwareCursor()
Initializes the screen cursor.
PixelType pixeltype
set to BGRPixel
Definition: qscreen_qws.h:328
int physWidth
the physical width of the screen in millimeters.
Definition: qscreen_qws.h:339
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
~QQnxScreen()
Destroys this QQnxScreen object.
bool connect(const QString &displaySpec)
Connects to QNX&#39;s io-display based device based on the displaySpec parameters from the QWS_DISPLAY en...
void setPixelFormat(QImage::Format format)
Sets the screen&#39;s pixel format to format.
Q_CORE_EXPORT void qDebug(const char *,...)
void blank(bool on)
Reimplemented Function
uchar * data
points to the first visible pixel in the frame buffer.
Definition: qscreen_qws.h:311
void disconnect()
Reimplemented Function
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool createHwSurface(QQnxScreenContext *const d, int w, int h)
const char * name
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
int w
the logical width of the screen.
Definition: qscreen_qws.h:324
Q_CORE_EXPORT void qWarning(const char *,...)
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
int displayId
Definition: qscreen_qws.h:337
gf_context_t context
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
int dw
the device width
Definition: qscreen_qws.h:331
int dh
the device height
Definition: qscreen_qws.h:332
void exposeRegion(QRegion r, int changing)
Reimplemented Function
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
QQnxScreen(int display_id)
Constructs a QQnxScreen object.
void setFrameBufferLittleEndian(bool littleEndian)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
virtual bool isTransformed() const
Returns true if the screen is transformed (for instance, rotated 90 degrees); otherwise returns false...
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
gf_dev_info_t deviceInfo
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
gf_surface_t memSurface
static bool attachLayer(QQnxScreenContext *const d, int layerIndex)
Attaches to the layer layerIndex.
The QScreen class is a base class for screen drivers in Qt for Embedded Linux.
Definition: qscreen_qws.h:191
gf_surface_info_t memSurfaceInfo
static bool attachDisplay(QQnxScreenContext *const d, int displayIndex)
Attaches to the display at index displayIndex.
void setMode(int, int, int)
QQnxScreen doesn&#39;t support setting the mode, use io-display instead.
gf_display_t display
int lstep
the number of bytes representing a line in the frame buffer.
Definition: qscreen_qws.h:325
#define Q_FOREACH(variable, container)
Same as foreach(variable, container).
Definition: qglobal.h:2435
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
gf_display_info_t displayInfo
int h
the logical height of the screen.
Definition: qscreen_qws.h:326
virtual void exposeRegion(QRegion r, int changing)
This function is called by the Qt for Embedded Linux server whenever a screen update is required...
int mapsize
the total number of bytes in the frame buffer
Definition: qscreen_qws.h:335
QQnxScreenContext *const d
static Type type()
Returns the type of application (Tty , GuiClient, or GuiServer).
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static bool createMemSurface(QQnxScreenContext *const d, int w, int h)
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
int depth() const
Returns the depth of the framebuffer, in bits per pixel.
Definition: qscreen_qws.h:229
bool initDevice()
Reimplemented Function