source: trunk/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp

Last change on this file 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: 60.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the plugins 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 qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdirectfbscreen.h"
43#include "qdirectfbwindowsurface.h"
44#include "qdirectfbpixmap.h"
45#include "qdirectfbmouse.h"
46#include "qdirectfbkeyboard.h"
47#include <QtGui/qwsdisplay_qws.h>
48#include <QtGui/qcolor.h>
49#include <QtGui/qapplication.h>
50#include <QtGui/qwindowsystem_qws.h>
51#include <QtGui/private/qgraphicssystem_qws_p.h>
52#include <QtGui/private/qwssignalhandler_p.h>
53#include <QtCore/qvarlengtharray.h>
54#include <QtCore/qvector.h>
55#include <QtCore/qrect.h>
56
57#ifndef QT_NO_QWS_DIRECTFB
58
59QT_BEGIN_NAMESPACE
60
61class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem
62{
63 Q_OBJECT
64public:
65 QDirectFBScreenPrivate(QDirectFBScreen *qptr);
66 ~QDirectFBScreenPrivate();
67
68 void setFlipFlags(const QStringList &args);
69 QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
70public slots:
71#ifdef QT_DIRECTFB_WM
72 void onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event);
73#endif
74public:
75 IDirectFB *dfb;
76 DFBSurfaceFlipFlags flipFlags;
77 QDirectFBScreen::DirectFBFlags directFBFlags;
78 QImage::Format alphaPixmapFormat;
79 IDirectFBScreen *dfbScreen;
80#ifdef QT_NO_DIRECTFB_WM
81 IDirectFBSurface *primarySurface;
82 QColor backgroundColor;
83#endif
84#ifndef QT_NO_DIRECTFB_LAYER
85 IDirectFBDisplayLayer *dfbLayer;
86#endif
87 QSet<IDirectFBSurface*> allocatedSurfaces;
88
89#ifndef QT_NO_DIRECTFB_MOUSE
90 QDirectFBMouseHandler *mouse;
91#endif
92#ifndef QT_NO_DIRECTFB_KEYBOARD
93 QDirectFBKeyboardHandler *keyboard;
94#endif
95#if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
96 IDirectFBImageProvider *imageProvider;
97#endif
98 IDirectFBSurface *cursorSurface;
99 qint64 cursorImageKey;
100
101 QDirectFBScreen *q;
102 static QDirectFBScreen *instance;
103};
104
105QDirectFBScreen *QDirectFBScreenPrivate::instance = 0;
106
107QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *qptr)
108 : QWSGraphicsSystem(qptr), dfb(0), flipFlags(DSFLIP_NONE),
109 directFBFlags(QDirectFBScreen::NoFlags), alphaPixmapFormat(QImage::Format_Invalid),
110 dfbScreen(0)
111#ifdef QT_NO_DIRECTFB_WM
112 , primarySurface(0)
113#endif
114#ifndef QT_NO_DIRECTFB_LAYER
115 , dfbLayer(0)
116#endif
117#ifndef QT_NO_DIRECTFB_MOUSE
118 , mouse(0)
119#endif
120#ifndef QT_NO_DIRECTFB_KEYBOARD
121 , keyboard(0)
122#endif
123#if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
124 , imageProvider(0)
125#endif
126 , cursorSurface(0)
127 , cursorImageKey(0)
128 , q(qptr)
129{
130#ifndef QT_NO_QWS_SIGNALHANDLER
131 QWSSignalHandler::instance()->addObject(this);
132#endif
133#ifdef QT_DIRECTFB_WM
134 connect(QWSServer::instance(), SIGNAL(windowEvent(QWSWindow*,QWSServer::WindowEvent)),
135 this, SLOT(onWindowEvent(QWSWindow*,QWSServer::WindowEvent)));
136#endif
137}
138
139QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
140{
141#ifndef QT_NO_DIRECTFB_MOUSE
142 delete mouse;
143#endif
144#ifndef QT_NO_DIRECTFB_KEYBOARD
145 delete keyboard;
146#endif
147#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
148 if (imageProvider)
149 imageProvider->Release(imageProvider);
150#endif
151
152 for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) {
153 (*it)->Release(*it);
154 }
155
156#ifdef QT_NO_DIRECTFB_WM
157 if (primarySurface)
158 primarySurface->Release(primarySurface);
159#endif
160
161#ifndef QT_NO_DIRECTFB_LAYER
162 if (dfbLayer)
163 dfbLayer->Release(dfbLayer);
164#endif
165
166 if (dfbScreen)
167 dfbScreen->Release(dfbScreen);
168
169 if (dfb)
170 dfb->Release(dfb);
171}
172
173IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &image, QImage::Format format, SurfaceCreationOptions options, DFBResult *resultPtr)
174{
175 if (image.isNull()) // assert?
176 return 0;
177
178 if (QDirectFBScreen::getSurfacePixelFormat(format) == DSPF_UNKNOWN) {
179 format = QDirectFBPixmapData::hasAlphaChannel(image) ? d_ptr->alphaPixmapFormat : pixelFormat();
180 }
181 if (image.format() != format) {
182 return createDFBSurface(image.convertToFormat(format), format, options | NoPreallocated, resultPtr);
183 }
184
185 DFBSurfaceDescription description;
186 memset(&description, 0, sizeof(DFBSurfaceDescription));
187 description.width = image.width();
188 description.height = image.height();
189 description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT;
190 initSurfaceDescriptionPixelFormat(&description, format);
191 bool doMemCopy = true;
192#ifdef QT_DIRECTFB_PREALLOCATED
193 if (!(options & NoPreallocated)) {
194 doMemCopy = false;
195 description.flags |= DSDESC_PREALLOCATED;
196 description.preallocated[0].data = const_cast<uchar*>(image.bits());
197 description.preallocated[0].pitch = image.bytesPerLine();
198 description.preallocated[1].data = 0;
199 description.preallocated[1].pitch = 0;
200 }
201#endif
202 DFBResult result;
203 IDirectFBSurface *surface = createDFBSurface(description, options, &result);
204 if (resultPtr)
205 *resultPtr = result;
206 if (!surface) {
207 DirectFBError("Couldn't create surface createDFBSurface(QImage, QImage::Format, SurfaceCreationOptions)", result);
208 return 0;
209 }
210 if (doMemCopy) {
211 int bplDFB;
212 uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bplDFB);
213 if (mem) {
214 const int height = image.height();
215 const int bplQt = image.bytesPerLine();
216 if (bplQt == bplDFB && bplQt == (image.width() * image.depth() / 8)) {
217 memcpy(mem, image.bits(), image.byteCount());
218 } else {
219 for (int i=0; i<height; ++i) {
220 memcpy(mem, image.scanLine(i), bplQt);
221 mem += bplDFB;
222 }
223 }
224 surface->Unlock(surface);
225 }
226 }
227#ifdef QT_DIRECTFB_PALETTE
228 if (image.colorCount() != 0 && surface)
229 QDirectFBScreen::setSurfaceColorTable(surface, image);
230#endif
231 return surface;
232}
233
234IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
235 QImage::Format format,
236 SurfaceCreationOptions options,
237 DFBResult *result)
238{
239 Q_ASSERT(src);
240 QSize size;
241 src->GetSize(src, &size.rwidth(), &size.rheight());
242 IDirectFBSurface *surface = createDFBSurface(size, format, options, result);
243 DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlphaChannel(surface)
244 ? DSBLIT_BLEND_ALPHACHANNEL
245 : DSBLIT_NOFX;
246 if (flags & DSBLIT_BLEND_ALPHACHANNEL)
247 surface->Clear(surface, 0, 0, 0, 0);
248
249 surface->SetBlittingFlags(surface, flags);
250 surface->Blit(surface, src, 0, 0, 0);
251#if (Q_DIRECTFB_VERSION >= 0x010000)
252 surface->ReleaseSource(surface);
253#endif
254 return surface;
255}
256
257IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size,
258 QImage::Format format,
259 SurfaceCreationOptions options,
260 DFBResult *result)
261{
262 DFBSurfaceDescription desc;
263 memset(&desc, 0, sizeof(DFBSurfaceDescription));
264 desc.flags |= DSDESC_WIDTH|DSDESC_HEIGHT;
265 if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format))
266 return 0;
267 desc.width = size.width();
268 desc.height = size.height();
269 return createDFBSurface(desc, options, result);
270}
271
272IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options, DFBResult *resultPtr)
273{
274 DFBResult tmp;
275 DFBResult &result = (resultPtr ? *resultPtr : tmp);
276 result = DFB_OK;
277 IDirectFBSurface *newSurface = 0;
278
279 if (!d_ptr->dfb) {
280 qWarning("QDirectFBScreen::createDFBSurface() - not connected");
281 return 0;
282 }
283
284 if (d_ptr->directFBFlags & VideoOnly
285 && !(desc.flags & DSDESC_PREALLOCATED)
286 && (!(desc.flags & DSDESC_CAPS) || !(desc.caps & DSCAPS_SYSTEMONLY))) {
287 // Add the video only capability. This means the surface will be created in video ram
288 if (!(desc.flags & DSDESC_CAPS)) {
289 desc.caps = DSCAPS_VIDEOONLY;
290 desc.flags |= DSDESC_CAPS;
291 } else {
292 desc.caps |= DSCAPS_VIDEOONLY;
293 }
294 result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface);
295 if (result != DFB_OK
296#ifdef QT_NO_DEBUG
297 && (desc.flags & DSDESC_CAPS) && (desc.caps & DSCAPS_PRIMARY)
298#endif
299 ) {
300 qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\n"
301 " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s",
302 desc.flags, desc.caps, desc.width, desc.height,
303 desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat),
304 desc.preallocated[0].data, desc.preallocated[0].pitch,
305 DirectFBErrorString(result));
306 }
307 desc.caps &= ~DSCAPS_VIDEOONLY;
308 }
309
310 if (d_ptr->directFBFlags & SystemOnly)
311 desc.caps |= DSCAPS_SYSTEMONLY;
312
313 if (!newSurface)
314 result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface);
315
316 if (result != DFB_OK) {
317 qWarning("QDirectFBScreen::createDFBSurface() Failed!\n"
318 " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s",
319 desc.flags, desc.caps, desc.width, desc.height,
320 desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat),
321 desc.preallocated[0].data, desc.preallocated[0].pitch,
322 DirectFBErrorString(result));
323 return 0;
324 }
325
326 Q_ASSERT(newSurface);
327
328 if (options & TrackSurface) {
329 d_ptr->allocatedSurfaces.insert(newSurface);
330 }
331
332 return newSurface;
333}
334
335#ifdef QT_DIRECTFB_SUBSURFACE
336IDirectFBSurface *QDirectFBScreen::getSubSurface(IDirectFBSurface *surface,
337 const QRect &rect,
338 SurfaceCreationOptions options,
339 DFBResult *resultPtr)
340{
341 Q_ASSERT(!(options & NoPreallocated));
342 Q_ASSERT(surface);
343 DFBResult res;
344 DFBResult &result = (resultPtr ? *resultPtr : res);
345 IDirectFBSurface *subSurface = 0;
346 if (rect.isNull()) {
347 result = surface->GetSubSurface(surface, 0, &subSurface);
348 } else {
349 const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() };
350 result = surface->GetSubSurface(surface, &subRect, &subSurface);
351 }
352 if (result != DFB_OK) {
353 DirectFBError("Can't get sub surface", result);
354 } else if (options & TrackSurface) {
355 d_ptr->allocatedSurfaces.insert(subSurface);
356 }
357 return subSurface;
358}
359#endif
360
361
362void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface)
363{
364 Q_ASSERT(QDirectFBScreen::instance());
365 Q_ASSERT(surface);
366 surface->Release(surface);
367 if (!d_ptr->allocatedSurfaces.remove(surface))
368 qWarning("QDirectFBScreen::releaseDFBSurface() - %p not in list", surface);
369
370 //qDebug("Released surface at %p. New count = %d", surface, d_ptr->allocatedSurfaces.count());
371}
372
373QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const
374{
375 return d_ptr->directFBFlags;
376}
377
378IDirectFB *QDirectFBScreen::dfb()
379{
380 return d_ptr->dfb;
381}
382
383#ifdef QT_NO_DIRECTFB_WM
384IDirectFBSurface *QDirectFBScreen::primarySurface()
385{
386 return d_ptr->primarySurface;
387}
388#endif
389
390#ifndef QT_NO_DIRECTFB_LAYER
391IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer()
392{
393 return d_ptr->dfbLayer;
394}
395#endif
396
397DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format format)
398{
399 switch (format) {
400#ifndef QT_NO_DIRECTFB_PALETTE
401 case QImage::Format_Indexed8:
402 return DSPF_LUT8;
403#endif
404 case QImage::Format_RGB888:
405 return DSPF_RGB24;
406 case QImage::Format_ARGB4444_Premultiplied:
407 return DSPF_ARGB4444;
408#if (Q_DIRECTFB_VERSION >= 0x010100)
409 case QImage::Format_RGB444:
410 return DSPF_RGB444;
411 case QImage::Format_RGB555:
412 return DSPF_RGB555;
413#endif
414 case QImage::Format_RGB16:
415 return DSPF_RGB16;
416#if (Q_DIRECTFB_VERSION >= 0x010000)
417 case QImage::Format_ARGB6666_Premultiplied:
418 return DSPF_ARGB6666;
419 case QImage::Format_RGB666:
420 return DSPF_RGB18;
421#endif
422 case QImage::Format_RGB32:
423 return DSPF_RGB32;
424 case QImage::Format_ARGB32_Premultiplied:
425 case QImage::Format_ARGB32:
426 return DSPF_ARGB;
427 default:
428 return DSPF_UNKNOWN;
429 };
430}
431
432QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface)
433{
434 DFBSurfacePixelFormat format;
435 surface->GetPixelFormat(surface, &format);
436
437 switch (format) {
438 case DSPF_LUT8:
439 return QImage::Format_Indexed8;
440 case DSPF_RGB24:
441 return QImage::Format_RGB888;
442 case DSPF_ARGB4444:
443 return QImage::Format_ARGB4444_Premultiplied;
444#if (Q_DIRECTFB_VERSION >= 0x010100)
445 case DSPF_RGB444:
446 return QImage::Format_RGB444;
447 case DSPF_RGB555:
448#endif
449 case DSPF_ARGB1555:
450 return QImage::Format_RGB555;
451 case DSPF_RGB16:
452 return QImage::Format_RGB16;
453#if (Q_DIRECTFB_VERSION >= 0x010000)
454 case DSPF_ARGB6666:
455 return QImage::Format_ARGB6666_Premultiplied;
456 case DSPF_RGB18:
457 return QImage::Format_RGB666;
458#endif
459 case DSPF_RGB32:
460 return QImage::Format_RGB32;
461 case DSPF_ARGB: {
462 DFBSurfaceCapabilities caps;
463 const DFBResult result = surface->GetCapabilities(surface, &caps);
464 Q_ASSERT(result == DFB_OK);
465 Q_UNUSED(result);
466 return (caps & DSCAPS_PREMULTIPLIED
467 ? QImage::Format_ARGB32_Premultiplied
468 : QImage::Format_ARGB32); }
469 default:
470 break;
471 }
472 return QImage::Format_Invalid;
473}
474
475DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer,
476 int length)
477{
478 DFBSurfaceDescription description;
479 memset(&description, 0, sizeof(DFBSurfaceDescription));
480
481 description.flags = DSDESC_CAPS|DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT|DSDESC_PREALLOCATED;
482 description.caps = DSCAPS_PREMULTIPLIED;
483 description.width = length;
484 description.height = 1;
485 description.pixelformat = DSPF_ARGB;
486 description.preallocated[0].data = (void*)buffer;
487 description.preallocated[0].pitch = length * sizeof(uint);
488 description.preallocated[1].data = 0;
489 description.preallocated[1].pitch = 0;
490 return description;
491}
492
493#ifndef QT_NO_DIRECTFB_PALETTE
494void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface,
495 const QImage &image)
496{
497 if (!surface)
498 return;
499
500 const int numColors = image.colorCount();
501 if (numColors == 0)
502 return;
503
504 QVarLengthArray<DFBColor, 256> colors(numColors);
505 for (int i = 0; i < numColors; ++i) {
506 QRgb c = image.color(i);
507 colors[i].a = qAlpha(c);
508 colors[i].r = qRed(c);
509 colors[i].g = qGreen(c);
510 colors[i].b = qBlue(c);
511 }
512
513 IDirectFBPalette *palette;
514 DFBResult result;
515 result = surface->GetPalette(surface, &palette);
516 if (result != DFB_OK) {
517 DirectFBError("QDirectFBScreen::setSurfaceColorTable GetPalette",
518 result);
519 return;
520 }
521 result = palette->SetEntries(palette, colors.data(), numColors, 0);
522 if (result != DFB_OK) {
523 DirectFBError("QDirectFBScreen::setSurfaceColorTable SetEntries",
524 result);
525 }
526 palette->Release(palette);
527}
528
529#endif // QT_NO_DIRECTFB_PALETTE
530
531#if defined QT_DIRECTFB_CURSOR
532class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor
533{
534public:
535 QDirectFBScreenCursor();
536 virtual void set(const QImage &image, int hotx, int hoty);
537 virtual void move(int x, int y);
538 virtual void show();
539 virtual void hide();
540private:
541#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
542 ~QDirectFBScreenCursor();
543 bool createWindow();
544 IDirectFBWindow *window;
545#endif
546 IDirectFBDisplayLayer *layer;
547};
548
549QDirectFBScreenCursor::QDirectFBScreenCursor()
550{
551 IDirectFB *fb = QDirectFBScreen::instance()->dfb();
552 if (!fb)
553 qFatal("QDirectFBScreenCursor: DirectFB not initialized");
554
555 layer = QDirectFBScreen::instance()->dfbDisplayLayer();
556 Q_ASSERT(layer);
557
558 enable = false;
559 hwaccel = true;
560 supportsAlpha = true;
561#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
562 window = 0;
563 DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
564 if (result != DFB_OK) {
565 DirectFBError("QDirectFBScreenCursor::hide: "
566 "Unable to set cooperative level", result);
567 }
568 result = layer->SetCursorOpacity(layer, 0);
569 if (result != DFB_OK) {
570 DirectFBError("QDirectFBScreenCursor::hide: "
571 "Unable to set cursor opacity", result);
572 }
573
574 result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
575 if (result != DFB_OK) {
576 DirectFBError("QDirectFBScreenCursor::hide: "
577 "Unable to set cooperative level", result);
578 }
579#endif
580}
581
582#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
583QDirectFBScreenCursor::~QDirectFBScreenCursor()
584{
585 if (window) {
586 window->Release(window);
587 window = 0;
588 }
589}
590
591bool QDirectFBScreenCursor::createWindow()
592{
593 Q_ASSERT(!window);
594 Q_ASSERT(!cursor.isNull());
595 DFBWindowDescription description;
596 memset(&description, 0, sizeof(DFBWindowDescription));
597 description.flags = DWDESC_POSX|DWDESC_POSY|DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|DWDESC_PIXELFORMAT|DWDESC_SURFACE_CAPS;
598 description.width = cursor.width();
599 description.height = cursor.height();
600 description.posx = pos.x() - hotspot.x();
601 description.posy = pos.y() - hotspot.y();
602#if (Q_DIRECTFB_VERSION >= 0x010100)
603 description.flags |= DWDESC_OPTIONS;
604 description.options = DWOP_GHOST|DWOP_ALPHACHANNEL;
605#endif
606 description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER;
607 const QImage::Format format = QDirectFBScreen::instance()->alphaPixmapFormat();
608 description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
609 if (QDirectFBScreen::isPremultiplied(format))
610 description.surface_caps = DSCAPS_PREMULTIPLIED;
611
612 DFBResult result = layer->CreateWindow(layer, &description, &window);
613 if (result != DFB_OK) {
614 DirectFBError("QDirectFBScreenCursor::createWindow: Unable to create window", result);
615 return false;
616 }
617 result = window->SetOpacity(window, 255);
618 if (result != DFB_OK) {
619 DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set opacity ", result);
620 return false;
621 }
622
623 result = window->SetStackingClass(window, DWSC_UPPER);
624 if (result != DFB_OK) {
625 DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set stacking class ", result);
626 return false;
627 }
628
629 result = window->RaiseToTop(window);
630 if (result != DFB_OK) {
631 DirectFBError("QDirectFBScreenCursor::createWindow: Unable to raise window ", result);
632 return false;
633 }
634
635 return true;
636}
637#endif
638
639void QDirectFBScreenCursor::move(int x, int y)
640{
641 pos = QPoint(x, y);
642#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
643 if (window) {
644 const QPoint p = pos - hotspot;
645 DFBResult result = window->MoveTo(window, p.x(), p.y());
646 if (result != DFB_OK) {
647 DirectFBError("QDirectFBScreenCursor::move: Unable to move window", result);
648 }
649 }
650#else
651 layer->WarpCursor(layer, x, y);
652#endif
653}
654
655void QDirectFBScreenCursor::hide()
656{
657 if (enable) {
658 enable = false;
659 DFBResult result;
660#ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
661 result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
662 if (result != DFB_OK) {
663 DirectFBError("QDirectFBScreenCursor::hide: "
664 "Unable to set cooperative level", result);
665 }
666 result = layer->SetCursorOpacity(layer, 0);
667 if (result != DFB_OK) {
668 DirectFBError("QDirectFBScreenCursor::hide: "
669 "Unable to set cursor opacity", result);
670 }
671 result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
672 if (result != DFB_OK) {
673 DirectFBError("QDirectFBScreenCursor::hide: "
674 "Unable to set cooperative level", result);
675 }
676#else
677 if (window) {
678 result = window->SetOpacity(window, 0);
679 if (result != DFB_OK) {
680 DirectFBError("QDirectFBScreenCursor::hide: "
681 "Unable to set window opacity", result);
682 }
683 }
684#endif
685 }
686}
687
688void QDirectFBScreenCursor::show()
689{
690 if (!enable) {
691 enable = true;
692 DFBResult result;
693 result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
694 if (result != DFB_OK) {
695 DirectFBError("QDirectFBScreenCursor::show: "
696 "Unable to set cooperative level", result);
697 }
698 result = layer->SetCursorOpacity(layer,
699#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
700 0
701#else
702 255
703#endif
704 );
705 if (result != DFB_OK) {
706 DirectFBError("QDirectFBScreenCursor::show: "
707 "Unable to set cursor shape", result);
708 }
709 result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
710 if (result != DFB_OK) {
711 DirectFBError("QDirectFBScreenCursor::show: "
712 "Unable to set cooperative level", result);
713 }
714#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
715 if (window) {
716 DFBResult result = window->SetOpacity(window, 255);
717 if (result != DFB_OK) {
718 DirectFBError("QDirectFBScreenCursor::show: "
719 "Unable to set window opacity", result);
720 }
721 }
722#endif
723 }
724}
725
726void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
727{
728 QDirectFBScreen *screen = QDirectFBScreen::instance();
729 if (!screen)
730 return;
731
732 if (image.isNull()) {
733 cursor = QImage();
734 hide();
735 } else {
736 cursor = image.convertToFormat(screen->alphaPixmapFormat());
737 size = cursor.size();
738 hotspot = QPoint(hotx, hoty);
739 DFBResult result = DFB_OK;
740 IDirectFBSurface *surface = screen->createDFBSurface(cursor, screen->alphaPixmapFormat(),
741 QDirectFBScreen::DontTrackSurface, &result);
742 if (!surface) {
743 DirectFBError("QDirectFBScreenCursor::set: Unable to create surface", result);
744 return;
745 }
746#ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
747 result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
748 if (result != DFB_OK) {
749 DirectFBError("QDirectFBScreenCursor::show: "
750 "Unable to set cooperative level", result);
751 }
752 result = layer->SetCursorShape(layer, surface, hotx, hoty);
753 if (result != DFB_OK) {
754 DirectFBError("QDirectFBScreenCursor::show: "
755 "Unable to set cursor shape", result);
756 }
757 result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
758 if (result != DFB_OK) {
759 DirectFBError("QDirectFBScreenCursor::show: "
760 "Unable to set cooperative level", result);
761 }
762#else
763 if (window || createWindow()) {
764 QSize windowSize;
765 result = window->GetSize(window, &windowSize.rwidth(), &windowSize.rheight());
766 if (result != DFB_OK) {
767 DirectFBError("QDirectFBScreenCursor::set: "
768 "Unable to get window size", result);
769 }
770 result = window->Resize(window, size.width(), size.height());
771 if (result != DFB_OK) {
772 DirectFBError("QDirectFBScreenCursor::set: Unable to resize window", result);
773 }
774
775 IDirectFBSurface *windowSurface;
776 result = window->GetSurface(window, &windowSurface);
777 if (result != DFB_OK) {
778 DirectFBError("QDirectFBScreenCursor::set: Unable to get window surface", result);
779 } else {
780 result = windowSurface->Clear(windowSurface, 0, 0, 0, 0);
781 if (result != DFB_OK) {
782 DirectFBError("QDirectFBScreenCursor::set: Unable to clear surface", result);
783 }
784
785 result = windowSurface->Blit(windowSurface, surface, 0, 0, 0);
786 if (result != DFB_OK) {
787 DirectFBError("QDirectFBScreenCursor::set: Unable to blit to surface", result);
788 }
789 }
790 result = windowSurface->Flip(windowSurface, 0, DSFLIP_NONE);
791 if (result != DFB_OK) {
792 DirectFBError("QDirectFBScreenCursor::set: Unable to flip window", result);
793 }
794
795 windowSurface->Release(windowSurface);
796 }
797#endif
798 surface->Release(surface);
799 show();
800 }
801
802}
803#endif // QT_DIRECTFB_CURSOR
804
805QDirectFBScreen::QDirectFBScreen(int display_id)
806 : QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this))
807{
808 QDirectFBScreenPrivate::instance = this;
809}
810
811QDirectFBScreen::~QDirectFBScreen()
812{
813 if (QDirectFBScreenPrivate::instance == this)
814 QDirectFBScreenPrivate::instance = 0;
815 delete d_ptr;
816}
817
818QDirectFBScreen *QDirectFBScreen::instance()
819{
820 return QDirectFBScreenPrivate::instance;
821}
822
823int QDirectFBScreen::depth(DFBSurfacePixelFormat format)
824{
825 switch (format) {
826 case DSPF_A1:
827 return 1;
828 case DSPF_A8:
829 case DSPF_RGB332:
830 case DSPF_LUT8:
831 case DSPF_ALUT44:
832 return 8;
833 case DSPF_I420:
834 case DSPF_YV12:
835 case DSPF_NV12:
836 case DSPF_NV21:
837#if (Q_DIRECTFB_VERSION >= 0x010100)
838 case DSPF_RGB444:
839#endif
840 return 12;
841#if (Q_DIRECTFB_VERSION >= 0x010100)
842 case DSPF_RGB555:
843 return 15;
844#endif
845 case DSPF_ARGB1555:
846 case DSPF_RGB16:
847 case DSPF_YUY2:
848 case DSPF_UYVY:
849 case DSPF_NV16:
850 case DSPF_ARGB2554:
851 case DSPF_ARGB4444:
852 return 16;
853 case DSPF_RGB24:
854 return 24;
855 case DSPF_RGB32:
856 case DSPF_ARGB:
857 case DSPF_AiRGB:
858 return 32;
859 case DSPF_UNKNOWN:
860 default:
861 return 0;
862 };
863 return 0;
864}
865
866int QDirectFBScreen::depth(QImage::Format format)
867{
868 int depth = 0;
869 switch(format) {
870 case QImage::Format_Invalid:
871 case QImage::NImageFormats:
872 Q_ASSERT(false);
873 case QImage::Format_Mono:
874 case QImage::Format_MonoLSB:
875 depth = 1;
876 break;
877 case QImage::Format_Indexed8:
878 depth = 8;
879 break;
880 case QImage::Format_RGB32:
881 case QImage::Format_ARGB32:
882 case QImage::Format_ARGB32_Premultiplied:
883 depth = 32;
884 break;
885 case QImage::Format_RGB555:
886 case QImage::Format_RGB16:
887 case QImage::Format_RGB444:
888 case QImage::Format_ARGB4444_Premultiplied:
889 depth = 16;
890 break;
891 case QImage::Format_RGB666:
892 case QImage::Format_ARGB6666_Premultiplied:
893 case QImage::Format_ARGB8565_Premultiplied:
894 case QImage::Format_ARGB8555_Premultiplied:
895 case QImage::Format_RGB888:
896 depth = 24;
897 break;
898 }
899 return depth;
900}
901
902void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
903{
904 QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$"));
905 int index = args.indexOf(flipRegexp);
906 if (index >= 0) {
907 const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','),
908 QString::SkipEmptyParts);
909 flipFlags = DSFLIP_NONE;
910 foreach(const QString &flip, flips) {
911 if (flip == QLatin1String("wait"))
912 flipFlags |= DSFLIP_WAIT;
913 else if (flip == QLatin1String("blit"))
914 flipFlags |= DSFLIP_BLIT;
915 else if (flip == QLatin1String("onsync"))
916 flipFlags |= DSFLIP_ONSYNC;
917 else if (flip == QLatin1String("pipeline"))
918 flipFlags |= DSFLIP_PIPELINE;
919 else
920 qWarning("QDirectFBScreen: Unknown flip argument: %s",
921 qPrintable(flip));
922 }
923 } else {
924 flipFlags = DSFLIP_BLIT|DSFLIP_ONSYNC;
925 }
926}
927
928#ifdef QT_DIRECTFB_WM
929void QDirectFBScreenPrivate::onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event)
930{
931 if (event == QWSServer::Raise) {
932 QWSWindowSurface *windowSurface = window->windowSurface();
933 if (windowSurface && windowSurface->key() == QLatin1String("directfb")) {
934 static_cast<QDirectFBWindowSurface*>(windowSurface)->raise();
935 }
936 }
937}
938#endif
939
940QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const
941{
942 if (type == QPixmapData::BitmapType)
943 return QWSGraphicsSystem::createPixmapData(type);
944
945 return new QDirectFBPixmapData(q, type);
946}
947
948#if (Q_DIRECTFB_VERSION >= 0x000923)
949#ifdef QT_NO_DEBUG
950struct FlagDescription;
951static const FlagDescription *accelerationDescriptions = 0;
952static const FlagDescription *blitDescriptions = 0;
953static const FlagDescription *drawDescriptions = 0;
954#else
955struct FlagDescription {
956 const char *name;
957 uint flag;
958};
959
960static const FlagDescription accelerationDescriptions[] = {
961 { "DFXL_NONE", DFXL_NONE },
962 { "DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE },
963 { "DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE },
964 { "DFXL_DRAWLINE", DFXL_DRAWLINE },
965 { "DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE },
966 { "DFXL_BLIT", DFXL_BLIT },
967 { "DFXL_STRETCHBLIT", DFXL_STRETCHBLIT },
968 { "DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES },
969 { "DFXL_DRAWSTRING", DFXL_DRAWSTRING },
970 { 0, 0 }
971};
972
973static const FlagDescription blitDescriptions[] = {
974 { "DSBLIT_NOFX", DSBLIT_NOFX },
975 { "DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL },
976 { "DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA },
977 { "DSBLIT_COLORIZE", DSBLIT_COLORIZE },
978 { "DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY },
979 { "DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY },
980 { "DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY },
981 { "DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY },
982 { "DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY },
983 { "DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE },
984#if (Q_DIRECTFB_VERSION >= 0x000923)
985 { "DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR },
986 { "DSBLIT_XOR", DSBLIT_XOR },
987#endif
988#if (Q_DIRECTFB_VERSION >= 0x010000)
989 { "DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION },
990#endif
991 { 0, 0 }
992};
993
994static const FlagDescription drawDescriptions[] = {
995 { "DSDRAW_NOFX", DSDRAW_NOFX },
996 { "DSDRAW_BLEND", DSDRAW_BLEND },
997 { "DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY },
998 { "DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY },
999 { "DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY },
1000 { "DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY },
1001 { "DSDRAW_XOR", DSDRAW_XOR },
1002 { 0, 0 }
1003};
1004#endif
1005
1006static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags)
1007{
1008#ifdef QT_NO_DEBUG
1009 Q_UNUSED(mask);
1010 Q_UNUSED(flags);
1011 return QByteArray("");
1012#else
1013 if (!mask)
1014 return flags[0].name;
1015
1016 QStringList list;
1017 for (int i=1; flags[i].name; ++i) {
1018 if (mask & flags[i].flag) {
1019 list.append(QString::fromLatin1(flags[i].name));
1020 }
1021 }
1022 Q_ASSERT(!list.isEmpty());
1023 return (QLatin1Char(' ') + list.join(QLatin1String("|"))).toLatin1();
1024#endif
1025}
1026static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface)
1027{
1028 DFBResult result;
1029 DFBGraphicsDeviceDescription dev;
1030
1031 result = fb->GetDeviceDescription(fb, &dev);
1032 if (result != DFB_OK) {
1033 DirectFBError("Error reading graphics device description", result);
1034 return;
1035 }
1036
1037 DFBSurfacePixelFormat pixelFormat;
1038 primarySurface->GetPixelFormat(primarySurface, &pixelFormat);
1039
1040 qDebug("Device: %s (%s), Driver: %s v%i.%i (%s) Pixelformat: %d (%d)\n"
1041 "acceleration: 0x%x%s\nblit: 0x%x%s\ndraw: 0x%0x%s\nvideo: %iKB\n",
1042 dev.name, dev.vendor, dev.driver.name, dev.driver.major,
1043 dev.driver.minor, dev.driver.vendor, DFB_PIXELFORMAT_INDEX(pixelFormat),
1044 QDirectFBScreen::getImageFormat(primarySurface), dev.acceleration_mask,
1045 flagDescriptions(dev.acceleration_mask, accelerationDescriptions).constData(),
1046 dev.blitting_flags, flagDescriptions(dev.blitting_flags, blitDescriptions).constData(),
1047 dev.drawing_flags, flagDescriptions(dev.drawing_flags, drawDescriptions).constData(),
1048 (dev.video_memory >> 10));
1049}
1050#endif
1051
1052static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value)
1053{
1054 Q_ASSERT(value);
1055 QRegExp rx(QString::fromLatin1("%1=?(\\d+)").arg(variable));
1056 rx.setCaseSensitivity(Qt::CaseInsensitive);
1057 if (arguments.indexOf(rx) != -1) {
1058 *value = rx.cap(1).toInt();
1059 return true;
1060 }
1061 return false;
1062}
1063
1064static inline QColor colorFromName(const QString &name)
1065{
1066 QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"));
1067 rx.setCaseSensitivity(Qt::CaseInsensitive);
1068 if (rx.exactMatch(name)) {
1069 Q_ASSERT(rx.captureCount() == 4);
1070 int ints[4];
1071 int i;
1072 for (i=0; i<4; ++i) {
1073 bool ok;
1074 ints[i] = rx.cap(i + 1).toUInt(&ok, 16);
1075 if (!ok || ints[i] > 255)
1076 break;
1077 }
1078 if (i == 4)
1079 return QColor(ints[0], ints[1], ints[2], ints[3]);
1080 }
1081 return QColor(name);
1082}
1083
1084bool QDirectFBScreen::connect(const QString &displaySpec)
1085{
1086 DFBResult result = DFB_OK;
1087
1088 { // pass command line arguments to DirectFB
1089 const QStringList args = QCoreApplication::arguments();
1090 int argc = args.size();
1091 char **argv = new char*[argc];
1092
1093 for (int i = 0; i < argc; ++i)
1094 argv[i] = qstrdup(args.at(i).toLocal8Bit().constData());
1095
1096 result = DirectFBInit(&argc, &argv);
1097 if (result != DFB_OK) {
1098 DirectFBError("QDirectFBScreen: error initializing DirectFB",
1099 result);
1100 }
1101 delete[] argv;
1102 }
1103
1104 const QStringList displayArgs = displaySpec.split(QLatin1Char(':'),
1105 QString::SkipEmptyParts);
1106
1107 d_ptr->setFlipFlags(displayArgs);
1108
1109 result = DirectFBCreate(&d_ptr->dfb);
1110 if (result != DFB_OK) {
1111 DirectFBError("QDirectFBScreen: error creating DirectFB interface",
1112 result);
1113 return false;
1114 }
1115
1116 if (displayArgs.contains(QLatin1String("videoonly"), Qt::CaseInsensitive))
1117 d_ptr->directFBFlags |= VideoOnly;
1118
1119 if (displayArgs.contains(QLatin1String("systemonly"), Qt::CaseInsensitive)) {
1120 if (d_ptr->directFBFlags & VideoOnly) {
1121 qWarning("QDirectFBScreen: error. videoonly and systemonly are mutually exclusive");
1122 } else {
1123 d_ptr->directFBFlags |= SystemOnly;
1124 }
1125 }
1126
1127 if (displayArgs.contains(QLatin1String("boundingrectflip"), Qt::CaseInsensitive)) {
1128 d_ptr->directFBFlags |= BoundingRectFlip;
1129 } else if (displayArgs.contains(QLatin1String("nopartialflip"), Qt::CaseInsensitive)) {
1130 d_ptr->directFBFlags |= NoPartialFlip;
1131 }
1132
1133#ifdef QT_DIRECTFB_IMAGECACHE
1134 int imageCacheSize = 4 * 1024 * 1024; // 4 MB
1135 setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize);
1136 QDirectFBPaintEngine::initImageCache(imageCacheSize);
1137#endif
1138
1139#ifndef QT_NO_DIRECTFB_WM
1140 if (displayArgs.contains(QLatin1String("fullscreen")))
1141#endif
1142 d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN);
1143
1144 const bool forcePremultiplied = displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive);
1145
1146 DFBSurfaceDescription description;
1147 memset(&description, 0, sizeof(DFBSurfaceDescription));
1148 IDirectFBSurface *surface;
1149
1150#ifdef QT_NO_DIRECTFB_WM
1151 description.flags = DSDESC_CAPS;
1152 if (::setIntOption(displayArgs, QLatin1String("width"), &description.width))
1153 description.flags |= DSDESC_WIDTH;
1154 if (::setIntOption(displayArgs, QLatin1String("height"), &description.height))
1155 description.flags |= DSDESC_HEIGHT;
1156
1157 description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE;
1158 struct {
1159 const char *name;
1160 const DFBSurfaceCapabilities cap;
1161 } const capabilities[] = {
1162 { "static_alloc", DSCAPS_STATIC_ALLOC },
1163 { "triplebuffer", DSCAPS_TRIPLE },
1164 { "interlaced", DSCAPS_INTERLACED },
1165 { "separated", DSCAPS_SEPARATED },
1166// { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported
1167 { 0, DSCAPS_NONE }
1168 };
1169 for (int i=0; capabilities[i].name; ++i) {
1170 if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive))
1171 description.caps |= capabilities[i].cap;
1172 }
1173
1174 if (forcePremultiplied) {
1175 description.caps |= DSCAPS_PREMULTIPLIED;
1176 }
1177
1178 // We don't track the primary surface as it's released in disconnect
1179 d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result);
1180 if (!d_ptr->primarySurface) {
1181 DirectFBError("QDirectFBScreen: error creating primary surface",
1182 result);
1183 return false;
1184 }
1185
1186 surface = d_ptr->primarySurface;
1187#else
1188 description.flags = DSDESC_WIDTH|DSDESC_HEIGHT;
1189 description.width = description.height = 1;
1190 surface = createDFBSurface(description, DontTrackSurface, &result);
1191 if (!surface) {
1192 DirectFBError("QDirectFBScreen: error creating surface", result);
1193 return false;
1194 }
1195#endif
1196 // Work out what format we're going to use for surfaces with an alpha channel
1197 QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface);
1198 d_ptr->alphaPixmapFormat = pixelFormat;
1199
1200 switch (pixelFormat) {
1201 case QImage::Format_RGB666:
1202 d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied;
1203 break;
1204 case QImage::Format_RGB444:
1205 d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied;
1206 break;
1207 case QImage::Format_RGB32:
1208 pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
1209 // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps
1210 break;
1211 case QImage::Format_Indexed8:
1212 qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8 pixelformat.");
1213 return false;
1214 case QImage::NImageFormats:
1215 case QImage::Format_Invalid:
1216 case QImage::Format_Mono:
1217 case QImage::Format_MonoLSB:
1218 case QImage::Format_RGB888:
1219 case QImage::Format_RGB16:
1220 case QImage::Format_RGB555:
1221 d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
1222 break;
1223 case QImage::Format_ARGB32:
1224 if (forcePremultiplied)
1225 d_ptr->alphaPixmapFormat = pixelFormat = QImage::Format_ARGB32_Premultiplied;
1226 case QImage::Format_ARGB32_Premultiplied:
1227 case QImage::Format_ARGB4444_Premultiplied:
1228 case QImage::Format_ARGB8555_Premultiplied:
1229 case QImage::Format_ARGB8565_Premultiplied:
1230 case QImage::Format_ARGB6666_Premultiplied:
1231 // works already
1232 break;
1233 }
1234 setPixelFormat(pixelFormat);
1235 QScreen::d = QDirectFBScreen::depth(pixelFormat);
1236 data = 0;
1237 lstep = 0;
1238 size = 0;
1239
1240 if (result != DFB_OK) {
1241 DirectFBError("QDirectFBScreen::connect: "
1242 "Unable to get screen!", result);
1243 return false;
1244 }
1245 const QString qws_size = QString::fromLatin1(qgetenv("QWS_SIZE"));
1246 if (!qws_size.isEmpty()) {
1247 QRegExp rx(QLatin1String("(\\d+)x(\\d+)"));
1248 if (!rx.exactMatch(qws_size)) {
1249 qWarning("QDirectFBScreen::connect: Can't parse QWS_SIZE=\"%s\"", qPrintable(qws_size));
1250 } else {
1251 int *ints[2] = { &w, &h };
1252 for (int i=0; i<2; ++i) {
1253 *ints[i] = rx.cap(i + 1).toInt();
1254 if (*ints[i] <= 0) {
1255 qWarning("QDirectFBScreen::connect: %s is not a positive integer",
1256 qPrintable(rx.cap(i + 1)));
1257 w = h = 0;
1258 break;
1259 }
1260 }
1261 }
1262 }
1263
1264 setIntOption(displayArgs, QLatin1String("width"), &w);
1265 setIntOption(displayArgs, QLatin1String("height"), &h);
1266
1267#ifndef QT_NO_DIRECTFB_LAYER
1268 int layerId = DLID_PRIMARY;
1269 setIntOption(displayArgs, QLatin1String("layerid"), &layerId);
1270
1271 result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, static_cast<DFBDisplayLayerID>(layerId),
1272 &d_ptr->dfbLayer);
1273 if (result != DFB_OK) {
1274 DirectFBError("QDirectFBScreen::connect: "
1275 "Unable to get display layer!", result);
1276 return false;
1277 }
1278 result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen);
1279#else
1280 result = d_ptr->dfb->GetScreen(d_ptr->dfb, 0, &d_ptr->dfbScreen);
1281#endif
1282
1283 if (w <= 0 || h <= 0) {
1284#ifdef QT_NO_DIRECTFB_WM
1285 result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h);
1286#elif (Q_DIRECTFB_VERSION >= 0x010000)
1287 IDirectFBSurface *layerSurface;
1288 if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) {
1289 result = layerSurface->GetSize(layerSurface, &w, &h);
1290 layerSurface->Release(layerSurface);
1291 }
1292 if (w <= 0 || h <= 0) {
1293 result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
1294 }
1295#else
1296 qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n"
1297 "query the size of the primary surface in windowed mode. You have to specify\n"
1298 "the size of the display using QWS_SIZE=[0-9]x[0-9] or\n"
1299 "QWS_DISPLAY=directfb:width=[0-9]:height=[0-9]");
1300 return false;
1301#endif
1302 if (result != DFB_OK) {
1303 DirectFBError("QDirectFBScreen::connect: "
1304 "Unable to get screen size!", result);
1305 return false;
1306 }
1307 }
1308
1309
1310 dw = w;
1311 dh = h;
1312
1313 Q_ASSERT(dw != 0 && dh != 0);
1314
1315 physWidth = physHeight = -1;
1316 setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth);
1317 setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight);
1318 const int dpi = 72;
1319 if (physWidth < 0)
1320 physWidth = qRound(dw * 25.4 / dpi);
1321 if (physHeight < 0)
1322 physHeight = qRound(dh * 25.4 / dpi);
1323
1324 setGraphicsSystem(d_ptr);
1325
1326#if (Q_DIRECTFB_VERSION >= 0x000923)
1327 if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
1328 printDirectFBInfo(d_ptr->dfb, surface);
1329#endif
1330#ifdef QT_DIRECTFB_WM
1331 surface->Release(surface);
1332 QColor backgroundColor;
1333#else
1334 QColor &backgroundColor = d_ptr->backgroundColor;
1335#endif
1336
1337 QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)"));
1338 backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive);
1339 if (displayArgs.indexOf(backgroundColorRegExp) != -1) {
1340 backgroundColor = colorFromName(backgroundColorRegExp.cap(1));
1341 }
1342#ifdef QT_NO_DIRECTFB_WM
1343 if (!backgroundColor.isValid())
1344 backgroundColor = Qt::green;
1345 d_ptr->primarySurface->Clear(d_ptr->primarySurface, backgroundColor.red(),
1346 backgroundColor.green(), backgroundColor.blue(),
1347 backgroundColor.alpha());
1348 d_ptr->primarySurface->Flip(d_ptr->primarySurface, 0, d_ptr->flipFlags);
1349#else
1350 if (backgroundColor.isValid()) {
1351 DFBResult result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_ADMINISTRATIVE);
1352 if (result != DFB_OK) {
1353 DirectFBError("QDirectFBScreen::connect "
1354 "Unable to set cooperative level", result);
1355 }
1356 result = d_ptr->dfbLayer->SetBackgroundColor(d_ptr->dfbLayer, backgroundColor.red(), backgroundColor.green(),
1357 backgroundColor.blue(), backgroundColor.alpha());
1358 if (result != DFB_OK) {
1359 DirectFBError("QDirectFBScreenCursor::connect: "
1360 "Unable to set background color", result);
1361 }
1362
1363 result = d_ptr->dfbLayer->SetBackgroundMode(d_ptr->dfbLayer, DLBM_COLOR);
1364 if (result != DFB_OK) {
1365 DirectFBError("QDirectFBScreenCursor::connect: "
1366 "Unable to set background mode", result);
1367 }
1368
1369 result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_SHARED);
1370 if (result != DFB_OK) {
1371 DirectFBError("QDirectFBScreen::connect "
1372 "Unable to set cooperative level", result);
1373 }
1374
1375 }
1376#endif
1377
1378 return true;
1379}
1380
1381void QDirectFBScreen::disconnect()
1382{
1383#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
1384 if (d_ptr->imageProvider)
1385 d_ptr->imageProvider->Release(d_ptr->imageProvider);
1386#endif
1387#ifdef QT_NO_DIRECTFB_WM
1388 d_ptr->primarySurface->Release(d_ptr->primarySurface);
1389 d_ptr->primarySurface = 0;
1390#endif
1391
1392 foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces)
1393 surf->Release(surf);
1394 d_ptr->allocatedSurfaces.clear();
1395
1396#ifndef QT_NO_DIRECTFB_LAYER
1397 d_ptr->dfbLayer->Release(d_ptr->dfbLayer);
1398 d_ptr->dfbLayer = 0;
1399#endif
1400
1401 d_ptr->dfbScreen->Release(d_ptr->dfbScreen);
1402 d_ptr->dfbScreen = 0;
1403
1404 d_ptr->dfb->Release(d_ptr->dfb);
1405 d_ptr->dfb = 0;
1406}
1407
1408bool QDirectFBScreen::initDevice()
1409{
1410#ifndef QT_NO_DIRECTFB_MOUSE
1411 if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) {
1412 QWSServer::instance()->setDefaultMouse("None");
1413 d_ptr->mouse = new QDirectFBMouseHandler;
1414 }
1415#endif
1416#ifndef QT_NO_DIRECTFB_KEYBOARD
1417 if (qgetenv("QWS_KEYBOARD").isEmpty()) {
1418 QWSServer::instance()->setDefaultKeyboard("None");
1419 d_ptr->keyboard = new QDirectFBKeyboardHandler(QString());
1420 }
1421#endif
1422
1423#ifdef QT_DIRECTFB_CURSOR
1424 qt_screencursor = new QDirectFBScreenCursor;
1425#elif !defined QT_NO_QWS_CURSOR
1426 QScreenCursor::initSoftwareCursor();
1427#endif
1428 return true;
1429}
1430
1431void QDirectFBScreen::shutdownDevice()
1432{
1433#ifndef QT_NO_DIRECTFB_MOUSE
1434 delete d_ptr->mouse;
1435 d_ptr->mouse = 0;
1436#endif
1437#ifndef QT_NO_DIRECTFB_KEYBOARD
1438 delete d_ptr->keyboard;
1439 d_ptr->keyboard = 0;
1440#endif
1441
1442#ifndef QT_NO_QWS_CURSOR
1443 delete qt_screencursor;
1444 qt_screencursor = 0;
1445#endif
1446}
1447
1448void QDirectFBScreen::setMode(int width, int height, int depth)
1449{
1450 d_ptr->dfb->SetVideoMode(d_ptr->dfb, width, height, depth);
1451}
1452
1453void QDirectFBScreen::blank(bool on)
1454{
1455 d_ptr->dfbScreen->SetPowerMode(d_ptr->dfbScreen,
1456 (on ? DSPM_ON : DSPM_SUSPEND));
1457}
1458
1459QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const
1460{
1461#ifdef QT_NO_DIRECTFB_WM
1462 if (QApplication::type() == QApplication::GuiServer) {
1463 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
1464 } else {
1465 return QScreen::createSurface(widget);
1466 }
1467#else
1468 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
1469#endif
1470}
1471
1472QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const
1473{
1474 if (key == QLatin1String("directfb")) {
1475 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this));
1476 }
1477 return QScreen::createSurface(key);
1478}
1479
1480#if defined QT_NO_DIRECTFB_WM
1481struct PaintCommand {
1482 PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {}
1483 IDirectFBSurface *dfbSurface;
1484 QImage image;
1485 QPoint windowPosition;
1486 QRegion source;
1487 quint8 windowOpacity;
1488 DFBSurfaceBlittingFlags blittingFlags;
1489};
1490
1491static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos)
1492{
1493 source.x = sourceGlobal.x() - pos.x();
1494 source.y = sourceGlobal.y() - pos.y();
1495 source.w = sourceGlobal.width();
1496 source.h = sourceGlobal.height();
1497}
1498#endif
1499
1500void QDirectFBScreen::exposeRegion(QRegion r, int)
1501{
1502 Q_UNUSED(r);
1503#if defined QT_NO_DIRECTFB_WM
1504
1505 r &= region();
1506 if (r.isEmpty()) {
1507 return;
1508 }
1509 r = r.boundingRect();
1510
1511 IDirectFBSurface *primary = d_ptr->primarySurface;
1512 const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
1513 QVarLengthArray<PaintCommand, 4> commands(windows.size());
1514 QRegion region = r;
1515 int idx = 0;
1516 for (int i=0; i<windows.size(); ++i) {
1517 QWSWindowSurface *surface = windows.at(i)->windowSurface();
1518 if (!surface)
1519 continue;
1520
1521 const QRect windowGeometry = surface->geometry();
1522 const QRegion intersection = region & windowGeometry;
1523 if (intersection.isEmpty()) {
1524 continue;
1525 }
1526
1527 PaintCommand &cmd = commands[idx];
1528
1529 if (surface->key() == QLatin1String("directfb")) {
1530 const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface);
1531 cmd.dfbSurface = ws->directFBSurface();
1532
1533 if (!cmd.dfbSurface) {
1534 continue;
1535 }
1536 } else {
1537 cmd.image = surface->image();
1538 if (cmd.image.isNull()) {
1539 continue;
1540 }
1541 }
1542 ++idx;
1543
1544 cmd.windowPosition = windowGeometry.topLeft();
1545 cmd.source = intersection;
1546 if (windows.at(i)->isOpaque()) {
1547 region -= intersection;
1548 if (region.isEmpty())
1549 break;
1550 } else {
1551 cmd.windowOpacity = windows.at(i)->opacity();
1552 cmd.blittingFlags = cmd.windowOpacity == 255
1553 ? DSBLIT_BLEND_ALPHACHANNEL
1554 : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA);
1555 }
1556 }
1557
1558 solidFill(d_ptr->backgroundColor, region);
1559
1560 while (idx > 0) {
1561 const PaintCommand &cmd = commands[--idx];
1562 Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull());
1563 IDirectFBSurface *surface;
1564 if (cmd.dfbSurface) {
1565 surface = cmd.dfbSurface;
1566 } else {
1567 Q_ASSERT(!cmd.image.isNull());
1568 DFBResult result;
1569 surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result);
1570 Q_ASSERT((result != DFB_OK) == !surface);
1571 if (result != DFB_OK) {
1572 DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result);
1573 continue;
1574 }
1575 }
1576
1577 primary->SetBlittingFlags(primary, cmd.blittingFlags);
1578 if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) {
1579 primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity);
1580 }
1581 const QRegion &region = cmd.source;
1582 const int rectCount = region.rectCount();
1583 DFBRectangle source;
1584 if (rectCount == 1) {
1585 ::initParameters(source, region.boundingRect(), cmd.windowPosition);
1586 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
1587 } else {
1588 const QVector<QRect> rects = region.rects();
1589 for (int i=0; i<rectCount; ++i) {
1590 ::initParameters(source, rects.at(i), cmd.windowPosition);
1591 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
1592 }
1593 }
1594 if (surface != cmd.dfbSurface) {
1595 surface->Release(surface);
1596 }
1597 }
1598
1599 primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff);
1600
1601#if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR
1602 if (QScreenCursor *cursor = QScreenCursor::instance()) {
1603 const QRect cursorRectangle = cursor->boundingRect();
1604 if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) {
1605 const QImage image = cursor->image();
1606 if (image.cacheKey() != d_ptr->cursorImageKey) {
1607 if (d_ptr->cursorSurface) {
1608 releaseDFBSurface(d_ptr->cursorSurface);
1609 }
1610 d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface);
1611 d_ptr->cursorImageKey = image.cacheKey();
1612 }
1613
1614 Q_ASSERT(d_ptr->cursorSurface);
1615 primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL);
1616 primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y());
1617 }
1618 }
1619#endif
1620 flipSurface(primary, d_ptr->flipFlags, r, QPoint());
1621 primary->SetBlittingFlags(primary, DSBLIT_NOFX);
1622#endif
1623}
1624
1625void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
1626{
1627#ifdef QT_DIRECTFB_WM
1628 Q_UNUSED(color);
1629 Q_UNUSED(region);
1630#else
1631 QDirectFBScreen::solidFill(d_ptr->primarySurface, color, region);
1632#endif
1633}
1634
1635static inline void clearRect(IDirectFBSurface *surface, const QColor &color, const QRect &rect)
1636{
1637 Q_ASSERT(surface);
1638 const DFBRegion region = { rect.left(), rect.top(), rect.right(), rect.bottom() };
1639 // could just reinterpret_cast this to a DFBRegion
1640 surface->SetClip(surface, &region);
1641 surface->Clear(surface, color.red(), color.green(), color.blue(), color.alpha());
1642}
1643
1644void QDirectFBScreen::solidFill(IDirectFBSurface *surface, const QColor &color, const QRegion &region)
1645{
1646 if (region.isEmpty())
1647 return;
1648
1649 const int n = region.rectCount();
1650 if (n == 1) {
1651 clearRect(surface, color, region.boundingRect());
1652 } else {
1653 const QVector<QRect> rects = region.rects();
1654 for (int i=0; i<n; ++i) {
1655 clearRect(surface, color, rects.at(i));
1656 }
1657 }
1658 surface->SetClip(surface, 0);
1659}
1660
1661QImage::Format QDirectFBScreen::alphaPixmapFormat() const
1662{
1663 return d_ptr->alphaPixmapFormat;
1664}
1665
1666bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description,
1667 QImage::Format format)
1668{
1669 const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
1670 if (pixelformat == DSPF_UNKNOWN)
1671 return false;
1672 description->flags |= DSDESC_PIXELFORMAT;
1673 description->pixelformat = pixelformat;
1674 if (QDirectFBScreen::isPremultiplied(format)) {
1675 if (!(description->flags & DSDESC_CAPS)) {
1676 description->caps = DSCAPS_PREMULTIPLIED;
1677 description->flags |= DSDESC_CAPS;
1678 } else {
1679 description->caps |= DSCAPS_PREMULTIPLIED;
1680 }
1681 }
1682 return true;
1683}
1684
1685uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl)
1686{
1687 void *mem = 0;
1688 const DFBResult result = surface->Lock(surface, flags, &mem, bpl);
1689 if (result != DFB_OK) {
1690 DirectFBError("QDirectFBScreen::lockSurface()", result);
1691 }
1692
1693 return reinterpret_cast<uchar*>(mem);
1694}
1695
1696static inline bool isFullUpdate(IDirectFBSurface *surface, const QRegion &region, const QPoint &offset)
1697{
1698 if (offset == QPoint(0, 0) && region.rectCount() == 1) {
1699 QSize size;
1700 surface->GetSize(surface, &size.rwidth(), &size.rheight());
1701 if (region.boundingRect().size() == size)
1702 return true;
1703 }
1704 return false;
1705}
1706
1707void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags,
1708 const QRegion &region, const QPoint &offset)
1709{
1710 if (d_ptr->directFBFlags & NoPartialFlip
1711 || (!(flipFlags & DSFLIP_BLIT) && QT_PREPEND_NAMESPACE(isFullUpdate(surface, region, offset)))) {
1712 surface->Flip(surface, 0, flipFlags);
1713 } else {
1714 if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.rectCount() > 1) {
1715 const QVector<QRect> rects = region.rects();
1716 const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT;
1717 for (int i=0; i<rects.size(); ++i) {
1718 const QRect &r = rects.at(i);
1719 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
1720 r.right() + offset.x(),
1721 r.bottom() + offset.y() };
1722 surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags);
1723 }
1724 } else {
1725 const QRect r = region.boundingRect();
1726 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
1727 r.right() + offset.x(),
1728 r.bottom() + offset.y() };
1729 surface->Flip(surface, &dfbReg, flipFlags);
1730 }
1731 }
1732}
1733
1734#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
1735void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider)
1736{
1737 Q_ASSERT(provider);
1738 if (d_ptr->imageProvider)
1739 d_ptr->imageProvider->Release(d_ptr->imageProvider);
1740 d_ptr->imageProvider = provider;
1741}
1742#endif
1743
1744void QDirectFBScreen::waitIdle()
1745{
1746 d_ptr->dfb->WaitIdle(d_ptr->dfb);
1747}
1748
1749#ifdef QT_DIRECTFB_WM
1750IDirectFBWindow *QDirectFBScreen::windowForWidget(const QWidget *widget) const
1751{
1752 if (widget) {
1753 const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
1754 if (surface && surface->key() == QLatin1String("directfb")) {
1755 return static_cast<const QDirectFBWindowSurface*>(surface)->directFBWindow();
1756 }
1757 }
1758 return 0;
1759}
1760#endif
1761
1762IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const
1763{
1764 Q_ASSERT(widget);
1765 if (!widget->isVisible() || widget->size().isNull())
1766 return 0;
1767
1768 const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
1769 if (surface && surface->key() == QLatin1String("directfb")) {
1770 return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect);
1771 }
1772 return 0;
1773}
1774
1775#ifdef QT_DIRECTFB_SUBSURFACE
1776IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const
1777{
1778 Q_ASSERT(widget);
1779 QRect rect;
1780 IDirectFBSurface *surface = surfaceForWidget(widget, &rect);
1781 IDirectFBSurface *subSurface = 0;
1782 if (surface) {
1783 if (!area.isNull())
1784 rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0)));
1785 if (!rect.isNull()) {
1786 const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() };
1787 const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface);
1788 if (result != DFB_OK) {
1789 DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result);
1790 }
1791 }
1792 }
1793 return subSurface;
1794}
1795#endif
1796
1797Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_widget(const QWidget *widget, QRect *rect)
1798{
1799 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->surfaceForWidget(widget, rect) : 0;
1800}
1801#ifdef QT_DIRECTFB_SUBSURFACE
1802Q_GUI_EXPORT IDirectFBSurface *qt_directfb_subsurface_for_widget(const QWidget *widget, const QRect &area)
1803{
1804 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->subSurfaceForWidget(widget, area) : 0;
1805}
1806#endif
1807#ifdef QT_DIRECTFB_WM
1808Q_GUI_EXPORT IDirectFBWindow *qt_directfb_window_for_widget(const QWidget *widget)
1809{
1810 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->windowForWidget(widget) : 0;
1811}
1812
1813#endif
1814
1815QT_END_NAMESPACE
1816
1817#include "qdirectfbscreen.moc"
1818#endif // QT_NO_QWS_DIRECTFB
1819
Note: See TracBrowser for help on using the repository browser.