source: trunk/src/gui/embedded/qscreenvfb_qws.cpp@ 890

Last change on this file since 890 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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#ifndef QT_NO_QWS_QVFB
43
44#define QTOPIA_QVFB_BRIGHTNESS
45
46#include <stdlib.h>
47#include <sys/types.h>
48#include <sys/ipc.h>
49#include <sys/shm.h>
50#include <sys/stat.h>
51#include <unistd.h>
52#include <fcntl.h>
53#include <errno.h>
54
55#include <qvfbhdr.h>
56#include <qscreenvfb_qws.h>
57#include <qkbdvfb_qws.h>
58#include <qmousevfb_qws.h>
59#include <qwindowsystem_qws.h>
60#include <qsocketnotifier.h>
61#include <qapplication.h>
62#include <qscreen_qws.h>
63#include <qmousedriverfactory_qws.h>
64#include <qkbddriverfactory_qws.h>
65#include <qdebug.h>
66
67QT_BEGIN_NAMESPACE
68
69class QVFbScreenPrivate
70{
71public:
72 QVFbScreenPrivate();
73 ~QVFbScreenPrivate();
74
75 bool success;
76 unsigned char *shmrgn;
77 int brightness;
78 bool blank;
79 QVFbHeader *hdr;
80 QWSMouseHandler *mouse;
81#ifndef QT_NO_QWS_KEYBOARD
82 QWSKeyboardHandler *keyboard;
83#endif
84};
85
86QVFbScreenPrivate::QVFbScreenPrivate()
87 : mouse(0)
88
89{
90#ifndef QT_NO_QWS_KEYBOARD
91 keyboard = 0;
92#endif
93 brightness = 255;
94 blank = false;
95}
96
97QVFbScreenPrivate::~QVFbScreenPrivate()
98{
99 delete mouse;
100#ifndef QT_NO_QWS_KEYBOARD
101 delete keyboard;
102#endif
103}
104
105/*!
106 \internal
107
108 \class QVFbScreen
109 \ingroup qws
110
111 \brief The QVFbScreen class implements a screen driver for the
112 virtual framebuffer.
113
114 Note that this class is only available in \l{Qt for Embedded Linux}.
115 Custom screen drivers can be added by subclassing the
116 QScreenDriverPlugin class, using the QScreenDriverFactory class to
117 dynamically load the driver into the application, but there should
118 only be one screen object per application.
119
120 The Qt for Embedded Linux platform provides a \l{The Virtual
121 Framebuffer}{virtual framebuffer} for development and debugging;
122 the virtual framebuffer allows Qt for Embedded Linux applications to be
123 developed on a desktop machine, without switching between consoles
124 and X11.
125
126 \sa QScreen, QScreenDriverPlugin, {Running Applications}
127*/
128
129/*!
130 \fn bool QVFbScreen::connect(const QString & displaySpec)
131 \reimp
132*/
133
134/*!
135 \fn void QVFbScreen::disconnect()
136 \reimp
137*/
138
139/*!
140 \fn bool QVFbScreen::initDevice()
141 \reimp
142*/
143
144/*!
145 \fn void QVFbScreen::restore()
146 \reimp
147*/
148
149/*!
150 \fn void QVFbScreen::save()
151 \reimp
152*/
153
154/*!
155 \fn void QVFbScreen::setDirty(const QRect & r)
156 \reimp
157*/
158
159/*!
160 \fn void QVFbScreen::setMode(int nw, int nh, int nd)
161 \reimp
162*/
163
164/*!
165 \fn void QVFbScreen::shutdownDevice()
166 \reimp
167*/
168
169/*!
170 \fn QVFbScreen::QVFbScreen(int displayId)
171
172 Constructs a QVNCScreen object. The \a displayId argument
173 identifies the Qt for Embedded Linux server to connect to.
174*/
175QVFbScreen::QVFbScreen(int display_id)
176 : QScreen(display_id, VFbClass), d_ptr(new QVFbScreenPrivate)
177{
178 d_ptr->shmrgn = 0;
179 d_ptr->hdr = 0;
180 data = 0;
181}
182
183/*!
184 Destroys this QVFbScreen object.
185*/
186QVFbScreen::~QVFbScreen()
187{
188 delete d_ptr;
189}
190
191static QVFbScreen *connected = 0;
192
193bool QVFbScreen::connect(const QString &displaySpec)
194{
195 QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
196 if (displayArgs.contains(QLatin1String("Gray")))
197 grayscale = true;
198
199 key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLocal8Bit(), 'b');
200
201 if (key == -1)
202 return false;
203
204#if Q_BYTE_ORDER == Q_BIG_ENDIAN
205#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
206 if (displayArgs.contains(QLatin1String("littleendian")))
207#endif
208 QScreen::setFrameBufferLittleEndian(true);
209#endif
210
211 int shmId = shmget(key, 0, 0);
212 if (shmId != -1)
213 d_ptr->shmrgn = (unsigned char *)shmat(shmId, 0, 0);
214 else
215 return false;
216
217 if ((long)d_ptr->shmrgn == -1 || d_ptr->shmrgn == 0) {
218 qDebug("No shmrgn %ld", (long)d_ptr->shmrgn);
219 return false;
220 }
221
222 d_ptr->hdr = (QVFbHeader *)d_ptr->shmrgn;
223 data = d_ptr->shmrgn + d_ptr->hdr->dataoffset;
224
225 dw = w = d_ptr->hdr->width;
226 dh = h = d_ptr->hdr->height;
227 d = d_ptr->hdr->depth;
228
229 switch (d) {
230 case 1:
231 setPixelFormat(QImage::Format_Mono);
232 break;
233 case 8:
234 setPixelFormat(QImage::Format_Indexed8);
235 break;
236 case 12:
237 setPixelFormat(QImage::Format_RGB444);
238 break;
239 case 15:
240 setPixelFormat(QImage::Format_RGB555);
241 break;
242 case 16:
243 setPixelFormat(QImage::Format_RGB16);
244 break;
245 case 18:
246 setPixelFormat(QImage::Format_RGB666);
247 break;
248 case 24:
249 setPixelFormat(QImage::Format_RGB888);
250 break;
251 case 32:
252 setPixelFormat(QImage::Format_ARGB32_Premultiplied);
253 break;
254 }
255
256 lstep = d_ptr->hdr->linestep;
257
258 // Handle display physical size spec.
259 int dimIdxW = -1;
260 int dimIdxH = -1;
261 for (int i = 0; i < displayArgs.size(); ++i) {
262 if (displayArgs.at(i).startsWith(QLatin1String("mmWidth"))) {
263 dimIdxW = i;
264 break;
265 }
266 }
267 for (int i = 0; i < displayArgs.size(); ++i) {
268 if (displayArgs.at(i).startsWith(QLatin1String("mmHeight"))) {
269 dimIdxH = i;
270 break;
271 }
272 }
273 if (dimIdxW >= 0) {
274 bool ok;
275 int pos = 7;
276 if (displayArgs.at(dimIdxW).at(pos) == QLatin1Char('='))
277 ++pos;
278 int pw = displayArgs.at(dimIdxW).mid(pos).toInt(&ok);
279 if (ok) {
280 physWidth = pw;
281 if (dimIdxH < 0)
282 physHeight = dh*physWidth/dw;
283 }
284 }
285 if (dimIdxH >= 0) {
286 bool ok;
287 int pos = 8;
288 if (displayArgs.at(dimIdxH).at(pos) == QLatin1Char('='))
289 ++pos;
290 int ph = displayArgs.at(dimIdxH).mid(pos).toInt(&ok);
291 if (ok) {
292 physHeight = ph;
293 if (dimIdxW < 0)
294 physWidth = dw*physHeight/dh;
295 }
296 }
297 if (dimIdxW < 0 && dimIdxH < 0) {
298 const int dpi = 72;
299 physWidth = qRound(dw * 25.4 / dpi);
300 physHeight = qRound(dh * 25.4 / dpi);
301 }
302
303 qDebug("Connected to VFB server %s: %d x %d x %d %dx%dmm (%dx%ddpi)", displaySpec.toLatin1().data(),
304 w, h, d, physWidth, physHeight, qRound(dw*25.4/physWidth), qRound(dh*25.4/physHeight) );
305
306 size = lstep * h;
307 mapsize = size;
308 screencols = d_ptr->hdr->numcols;
309 memcpy(screenclut, d_ptr->hdr->clut, sizeof(QRgb) * screencols);
310
311 connected = this;
312
313 if (qgetenv("QT_QVFB_BGR").toInt())
314 pixeltype = BGRPixel;
315
316 return true;
317}
318
319void QVFbScreen::disconnect()
320{
321 connected = 0;
322 if ((long)d_ptr->shmrgn != -1 && d_ptr->shmrgn) {
323 if (qApp->type() == QApplication::GuiServer && d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
324 d_ptr->hdr->serverVersion = 0;
325 }
326 shmdt((char*)d_ptr->shmrgn);
327 }
328}
329
330bool QVFbScreen::initDevice()
331{
332#ifndef QT_NO_QWS_MOUSE_QVFB
333 const QString mouseDev = QT_VFB_MOUSE_PIPE(displayId);
334 d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
335 qwsServer->setDefaultMouse("None");
336 if (d_ptr->mouse)
337 d_ptr->mouse->setScreen(this);
338#endif
339
340#if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
341 const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId);
342 d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
343 qwsServer->setDefaultKeyboard("None");
344#endif
345
346 if (d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader))
347 d_ptr->hdr->serverVersion = QT_VERSION;
348
349 if(d==8) {
350 screencols=256;
351 if (grayscale) {
352 // Build grayscale palette
353 for(int loopc=0;loopc<256;loopc++) {
354 screenclut[loopc]=qRgb(loopc,loopc,loopc);
355 }
356 } else {
357 // 6x6x6 216 color cube
358 int idx = 0;
359 for(int ir = 0x0; ir <= 0xff; ir+=0x33) {
360 for(int ig = 0x0; ig <= 0xff; ig+=0x33) {
361 for(int ib = 0x0; ib <= 0xff; ib+=0x33) {
362 screenclut[idx]=qRgb(ir, ig, ib);
363 idx++;
364 }
365 }
366 }
367 screencols=idx;
368 }
369 memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
370 d_ptr->hdr->numcols = screencols;
371 } else if (d == 4) {
372 int val = 0;
373 for (int idx = 0; idx < 16; idx++, val += 17) {
374 screenclut[idx] = qRgb(val, val, val);
375 }
376 screencols = 16;
377 memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
378 d_ptr->hdr->numcols = screencols;
379 } else if (d == 1) {
380 screencols = 2;
381 screenclut[1] = qRgb(0xff, 0xff, 0xff);
382 screenclut[0] = qRgb(0, 0, 0);
383 memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
384 d_ptr->hdr->numcols = screencols;
385 }
386
387#ifndef QT_NO_QWS_CURSOR
388 QScreenCursor::initSoftwareCursor();
389#endif
390 return true;
391}
392
393void QVFbScreen::shutdownDevice()
394{
395}
396
397void QVFbScreen::setMode(int ,int ,int)
398{
399}
400
401// save the state of the graphics card
402// This is needed so that e.g. we can restore the palette when switching
403// between linux virtual consoles.
404void QVFbScreen::save()
405{
406 // nothing to do.
407}
408
409// restore the state of the graphics card.
410void QVFbScreen::restore()
411{
412}
413void QVFbScreen::setDirty(const QRect& rect)
414{
415 const QRect r = rect.translated(-offset());
416 d_ptr->hdr->dirty = true;
417 d_ptr->hdr->update = d_ptr->hdr->update.united(r);
418}
419
420void QVFbScreen::setBrightness(int b)
421{
422 if (connected) {
423 connected->d_ptr->brightness = b;
424
425 QVFbHeader *hdr = connected->d_ptr->hdr;
426 if (hdr->viewerVersion < 0x040400) // brightness not supported
427 return;
428
429 const int br = connected->d_ptr->blank ? 0 : b;
430 if (hdr->brightness != br) {
431 hdr->brightness = br;
432 connected->setDirty(connected->region().boundingRect());
433 }
434 }
435}
436
437void QVFbScreen::blank(bool on)
438{
439 d_ptr->blank = on;
440 setBrightness(connected->d_ptr->brightness);
441}
442
443#endif // QT_NO_QWS_QVFB
444
445QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.