|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 |
|
59 QT_BEGIN_NAMESPACE |
|
60 |
|
61 class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem |
|
62 { |
|
63 Q_OBJECT |
|
64 public: |
|
65 QDirectFBScreenPrivate(QDirectFBScreen *qptr); |
|
66 ~QDirectFBScreenPrivate(); |
|
67 |
|
68 void setFlipFlags(const QStringList &args); |
|
69 QPixmapData *createPixmapData(QPixmapData::PixelType type) const; |
|
70 public slots: |
|
71 #ifdef QT_DIRECTFB_WM |
|
72 void onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event); |
|
73 #endif |
|
74 public: |
|
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 |
|
105 QDirectFBScreen *QDirectFBScreenPrivate::instance = 0; |
|
106 |
|
107 QDirectFBScreenPrivate::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 |
|
139 QDirectFBScreenPrivate::~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 |
|
173 IDirectFBSurface *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.numBytes()); |
|
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.numColors() != 0 && surface) |
|
229 QDirectFBScreen::setSurfaceColorTable(surface, image); |
|
230 #endif |
|
231 return surface; |
|
232 } |
|
233 |
|
234 IDirectFBSurface *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 |
|
257 IDirectFBSurface *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 |
|
272 IDirectFBSurface *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 |
|
336 IDirectFBSurface *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 |
|
362 void 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 |
|
373 QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const |
|
374 { |
|
375 return d_ptr->directFBFlags; |
|
376 } |
|
377 |
|
378 IDirectFB *QDirectFBScreen::dfb() |
|
379 { |
|
380 return d_ptr->dfb; |
|
381 } |
|
382 |
|
383 #ifdef QT_NO_DIRECTFB_WM |
|
384 IDirectFBSurface *QDirectFBScreen::primarySurface() |
|
385 { |
|
386 return d_ptr->primarySurface; |
|
387 } |
|
388 #endif |
|
389 |
|
390 #ifndef QT_NO_DIRECTFB_LAYER |
|
391 IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer() |
|
392 { |
|
393 return d_ptr->dfbLayer; |
|
394 } |
|
395 #endif |
|
396 |
|
397 DFBSurfacePixelFormat 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 |
|
432 QImage::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 |
|
475 DFBSurfaceDescription 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 |
|
494 void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface, |
|
495 const QImage &image) |
|
496 { |
|
497 if (!surface) |
|
498 return; |
|
499 |
|
500 const int numColors = image.numColors(); |
|
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 |
|
532 class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor |
|
533 { |
|
534 public: |
|
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(); |
|
540 private: |
|
541 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
|
542 ~QDirectFBScreenCursor(); |
|
543 bool createWindow(); |
|
544 IDirectFBWindow *window; |
|
545 #endif |
|
546 IDirectFBDisplayLayer *layer; |
|
547 }; |
|
548 |
|
549 QDirectFBScreenCursor::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 |
|
583 QDirectFBScreenCursor::~QDirectFBScreenCursor() |
|
584 { |
|
585 if (window) { |
|
586 window->Release(window); |
|
587 window = 0; |
|
588 } |
|
589 } |
|
590 |
|
591 bool 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 |
|
639 void 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 |
|
655 void 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 |
|
688 void 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 |
|
726 void 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 |
|
805 QDirectFBScreen::QDirectFBScreen(int display_id) |
|
806 : QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this)) |
|
807 { |
|
808 QDirectFBScreenPrivate::instance = this; |
|
809 } |
|
810 |
|
811 QDirectFBScreen::~QDirectFBScreen() |
|
812 { |
|
813 if (QDirectFBScreenPrivate::instance == this) |
|
814 QDirectFBScreenPrivate::instance = 0; |
|
815 delete d_ptr; |
|
816 } |
|
817 |
|
818 QDirectFBScreen *QDirectFBScreen::instance() |
|
819 { |
|
820 return QDirectFBScreenPrivate::instance; |
|
821 } |
|
822 |
|
823 int 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 |
|
866 int 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 |
|
902 void 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; |
|
925 } |
|
926 } |
|
927 |
|
928 #ifdef QT_DIRECTFB_WM |
|
929 void 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 |
|
940 QPixmapData *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 |
|
950 struct FlagDescription; |
|
951 static const FlagDescription *accelerationDescriptions = 0; |
|
952 static const FlagDescription *blitDescriptions = 0; |
|
953 static const FlagDescription *drawDescriptions = 0; |
|
954 #else |
|
955 struct FlagDescription { |
|
956 const char *name; |
|
957 uint flag; |
|
958 }; |
|
959 |
|
960 static 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 |
|
973 static 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 |
|
994 static 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 |
|
1006 static 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 } |
|
1026 static 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 |
|
1052 static 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 |
|
1064 static inline QColor colorFromName(const QString &name) |
|
1065 { |
|
1066 QRegExp rx("#([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.numCaptures() == 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 |
|
1084 bool 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 } |
|
1130 |
|
1131 #ifdef QT_DIRECTFB_IMAGECACHE |
|
1132 int imageCacheSize = 4 * 1024 * 1024; // 4 MB |
|
1133 setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize); |
|
1134 QDirectFBPaintEngine::initImageCache(imageCacheSize); |
|
1135 #endif |
|
1136 |
|
1137 #ifndef QT_NO_DIRECTFB_WM |
|
1138 if (displayArgs.contains(QLatin1String("fullscreen"))) |
|
1139 #endif |
|
1140 d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN); |
|
1141 |
|
1142 DFBSurfaceDescription description; |
|
1143 memset(&description, 0, sizeof(DFBSurfaceDescription)); |
|
1144 IDirectFBSurface *surface; |
|
1145 |
|
1146 #ifdef QT_NO_DIRECTFB_WM |
|
1147 description.flags = DSDESC_CAPS; |
|
1148 if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) |
|
1149 description.flags |= DSDESC_WIDTH; |
|
1150 if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) |
|
1151 description.flags |= DSDESC_HEIGHT; |
|
1152 |
|
1153 description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; |
|
1154 struct { |
|
1155 const char *name; |
|
1156 const DFBSurfaceCapabilities cap; |
|
1157 } const capabilities[] = { |
|
1158 { "static_alloc", DSCAPS_STATIC_ALLOC }, |
|
1159 { "triplebuffer", DSCAPS_TRIPLE }, |
|
1160 { "interlaced", DSCAPS_INTERLACED }, |
|
1161 { "separated", DSCAPS_SEPARATED }, |
|
1162 // { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported |
|
1163 { 0, DSCAPS_NONE } |
|
1164 }; |
|
1165 for (int i=0; capabilities[i].name; ++i) { |
|
1166 if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive)) |
|
1167 description.caps |= capabilities[i].cap; |
|
1168 } |
|
1169 |
|
1170 if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) { |
|
1171 description.caps |= DSCAPS_PREMULTIPLIED; |
|
1172 } |
|
1173 |
|
1174 // We don't track the primary surface as it's released in disconnect |
|
1175 d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result); |
|
1176 if (!d_ptr->primarySurface) { |
|
1177 DirectFBError("QDirectFBScreen: error creating primary surface", |
|
1178 result); |
|
1179 return false; |
|
1180 } |
|
1181 |
|
1182 surface = d_ptr->primarySurface; |
|
1183 #else |
|
1184 description.flags = DSDESC_WIDTH|DSDESC_HEIGHT; |
|
1185 description.width = description.height = 1; |
|
1186 surface = createDFBSurface(description, DontTrackSurface, &result); |
|
1187 if (!surface) { |
|
1188 DirectFBError("QDirectFBScreen: error creating surface", result); |
|
1189 return false; |
|
1190 } |
|
1191 #endif |
|
1192 // Work out what format we're going to use for surfaces with an alpha channel |
|
1193 QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface); |
|
1194 d_ptr->alphaPixmapFormat = pixelFormat; |
|
1195 |
|
1196 switch (pixelFormat) { |
|
1197 case QImage::Format_RGB666: |
|
1198 d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied; |
|
1199 break; |
|
1200 case QImage::Format_RGB444: |
|
1201 d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied; |
|
1202 break; |
|
1203 case QImage::Format_RGB32: |
|
1204 pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; |
|
1205 // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps |
|
1206 break; |
|
1207 case QImage::Format_Indexed8: |
|
1208 qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8 pixelformat."); |
|
1209 return false; |
|
1210 case QImage::NImageFormats: |
|
1211 case QImage::Format_Invalid: |
|
1212 case QImage::Format_Mono: |
|
1213 case QImage::Format_MonoLSB: |
|
1214 case QImage::Format_RGB888: |
|
1215 case QImage::Format_RGB16: |
|
1216 case QImage::Format_RGB555: |
|
1217 d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; |
|
1218 break; |
|
1219 case QImage::Format_ARGB32: |
|
1220 case QImage::Format_ARGB32_Premultiplied: |
|
1221 case QImage::Format_ARGB4444_Premultiplied: |
|
1222 case QImage::Format_ARGB8555_Premultiplied: |
|
1223 case QImage::Format_ARGB8565_Premultiplied: |
|
1224 case QImage::Format_ARGB6666_Premultiplied: |
|
1225 // works already |
|
1226 break; |
|
1227 } |
|
1228 setPixelFormat(pixelFormat); |
|
1229 QScreen::d = QDirectFBScreen::depth(pixelFormat); |
|
1230 data = 0; |
|
1231 lstep = 0; |
|
1232 size = 0; |
|
1233 |
|
1234 if (result != DFB_OK) { |
|
1235 DirectFBError("QDirectFBScreen::connect: " |
|
1236 "Unable to get screen!", result); |
|
1237 return false; |
|
1238 } |
|
1239 const QString qws_size = QString::fromLatin1(qgetenv("QWS_SIZE")); |
|
1240 if (!qws_size.isEmpty()) { |
|
1241 QRegExp rx(QLatin1String("(\\d+)x(\\d+)")); |
|
1242 if (!rx.exactMatch(qws_size)) { |
|
1243 qWarning("QDirectFBScreen::connect: Can't parse QWS_SIZE=\"%s\"", qPrintable(qws_size)); |
|
1244 } else { |
|
1245 int *ints[2] = { &w, &h }; |
|
1246 for (int i=0; i<2; ++i) { |
|
1247 *ints[i] = rx.cap(i + 1).toInt(); |
|
1248 if (*ints[i] <= 0) { |
|
1249 qWarning("QDirectFBScreen::connect: %s is not a positive integer", |
|
1250 qPrintable(rx.cap(i + 1))); |
|
1251 w = h = 0; |
|
1252 break; |
|
1253 } |
|
1254 } |
|
1255 } |
|
1256 } |
|
1257 |
|
1258 setIntOption(displayArgs, QLatin1String("width"), &w); |
|
1259 setIntOption(displayArgs, QLatin1String("height"), &h); |
|
1260 |
|
1261 #ifndef QT_NO_DIRECTFB_LAYER |
|
1262 result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, DLID_PRIMARY, |
|
1263 &d_ptr->dfbLayer); |
|
1264 if (result != DFB_OK) { |
|
1265 DirectFBError("QDirectFBScreen::connect: " |
|
1266 "Unable to get primary display layer!", result); |
|
1267 return false; |
|
1268 } |
|
1269 result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen); |
|
1270 #else |
|
1271 result = d_ptr->dfb->GetScreen(d_ptr->dfb, 0, &d_ptr->dfbScreen); |
|
1272 #endif |
|
1273 |
|
1274 if (w <= 0 || h <= 0) { |
|
1275 #ifdef QT_NO_DIRECTFB_WM |
|
1276 result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); |
|
1277 #elif (Q_DIRECTFB_VERSION >= 0x010000) |
|
1278 result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); |
|
1279 #else |
|
1280 qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n" |
|
1281 "query the size of the primary surface in windowed mode. You have to specify\n" |
|
1282 "the size of the display using QWS_SIZE=[0-9]x[0-9] or\n" |
|
1283 "QWS_DISPLAY=directfb:width=[0-9]:height=[0-9]"); |
|
1284 return false; |
|
1285 #endif |
|
1286 if (result != DFB_OK) { |
|
1287 DirectFBError("QDirectFBScreen::connect: " |
|
1288 "Unable to get screen size!", result); |
|
1289 return false; |
|
1290 } |
|
1291 } |
|
1292 |
|
1293 |
|
1294 dw = w; |
|
1295 dh = h; |
|
1296 |
|
1297 Q_ASSERT(dw != 0 && dh != 0); |
|
1298 |
|
1299 physWidth = physHeight = -1; |
|
1300 setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth); |
|
1301 setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight); |
|
1302 const int dpi = 72; |
|
1303 if (physWidth < 0) |
|
1304 physWidth = qRound(dw * 25.4 / dpi); |
|
1305 if (physHeight < 0) |
|
1306 physHeight = qRound(dh * 25.4 / dpi); |
|
1307 |
|
1308 setGraphicsSystem(d_ptr); |
|
1309 |
|
1310 #if (Q_DIRECTFB_VERSION >= 0x000923) |
|
1311 if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive)) |
|
1312 printDirectFBInfo(d_ptr->dfb, surface); |
|
1313 #endif |
|
1314 #ifdef QT_DIRECTFB_WM |
|
1315 surface->Release(surface); |
|
1316 QColor backgroundColor; |
|
1317 #else |
|
1318 QColor &backgroundColor = d_ptr->backgroundColor; |
|
1319 #endif |
|
1320 |
|
1321 QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)")); |
|
1322 backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive); |
|
1323 if (displayArgs.indexOf(backgroundColorRegExp) != -1) { |
|
1324 backgroundColor = colorFromName(backgroundColorRegExp.cap(1)); |
|
1325 } |
|
1326 #ifdef QT_NO_DIRECTFB_WM |
|
1327 if (!backgroundColor.isValid()) |
|
1328 backgroundColor = Qt::green; |
|
1329 d_ptr->primarySurface->Clear(d_ptr->primarySurface, backgroundColor.red(), |
|
1330 backgroundColor.green(), backgroundColor.blue(), |
|
1331 backgroundColor.alpha()); |
|
1332 d_ptr->primarySurface->Flip(d_ptr->primarySurface, 0, d_ptr->flipFlags); |
|
1333 #else |
|
1334 if (backgroundColor.isValid()) { |
|
1335 DFBResult result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_ADMINISTRATIVE); |
|
1336 if (result != DFB_OK) { |
|
1337 DirectFBError("QDirectFBScreen::connect " |
|
1338 "Unable to set cooperative level", result); |
|
1339 } |
|
1340 result = d_ptr->dfbLayer->SetBackgroundColor(d_ptr->dfbLayer, backgroundColor.red(), backgroundColor.green(), |
|
1341 backgroundColor.blue(), backgroundColor.alpha()); |
|
1342 if (result != DFB_OK) { |
|
1343 DirectFBError("QDirectFBScreenCursor::connect: " |
|
1344 "Unable to set background color", result); |
|
1345 } |
|
1346 |
|
1347 result = d_ptr->dfbLayer->SetBackgroundMode(d_ptr->dfbLayer, DLBM_COLOR); |
|
1348 if (result != DFB_OK) { |
|
1349 DirectFBError("QDirectFBScreenCursor::connect: " |
|
1350 "Unable to set background mode", result); |
|
1351 } |
|
1352 |
|
1353 result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_SHARED); |
|
1354 if (result != DFB_OK) { |
|
1355 DirectFBError("QDirectFBScreen::connect " |
|
1356 "Unable to set cooperative level", result); |
|
1357 } |
|
1358 |
|
1359 } |
|
1360 #endif |
|
1361 |
|
1362 return true; |
|
1363 } |
|
1364 |
|
1365 void QDirectFBScreen::disconnect() |
|
1366 { |
|
1367 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
|
1368 if (d_ptr->imageProvider) |
|
1369 d_ptr->imageProvider->Release(d_ptr->imageProvider); |
|
1370 #endif |
|
1371 #ifdef QT_NO_DIRECTFB_WM |
|
1372 d_ptr->primarySurface->Release(d_ptr->primarySurface); |
|
1373 d_ptr->primarySurface = 0; |
|
1374 #endif |
|
1375 |
|
1376 foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces) |
|
1377 surf->Release(surf); |
|
1378 d_ptr->allocatedSurfaces.clear(); |
|
1379 |
|
1380 #ifndef QT_NO_DIRECTFB_LAYER |
|
1381 d_ptr->dfbLayer->Release(d_ptr->dfbLayer); |
|
1382 d_ptr->dfbLayer = 0; |
|
1383 #endif |
|
1384 |
|
1385 d_ptr->dfbScreen->Release(d_ptr->dfbScreen); |
|
1386 d_ptr->dfbScreen = 0; |
|
1387 |
|
1388 d_ptr->dfb->Release(d_ptr->dfb); |
|
1389 d_ptr->dfb = 0; |
|
1390 } |
|
1391 |
|
1392 bool QDirectFBScreen::initDevice() |
|
1393 { |
|
1394 #ifndef QT_NO_DIRECTFB_MOUSE |
|
1395 if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) { |
|
1396 QWSServer::instance()->setDefaultMouse("None"); |
|
1397 d_ptr->mouse = new QDirectFBMouseHandler; |
|
1398 } |
|
1399 #endif |
|
1400 #ifndef QT_NO_DIRECTFB_KEYBOARD |
|
1401 if (qgetenv("QWS_KEYBOARD").isEmpty()) { |
|
1402 QWSServer::instance()->setDefaultKeyboard("None"); |
|
1403 d_ptr->keyboard = new QDirectFBKeyboardHandler(QString()); |
|
1404 } |
|
1405 #endif |
|
1406 |
|
1407 #ifdef QT_DIRECTFB_CURSOR |
|
1408 qt_screencursor = new QDirectFBScreenCursor; |
|
1409 #elif !defined QT_NO_QWS_CURSOR |
|
1410 QScreenCursor::initSoftwareCursor(); |
|
1411 #endif |
|
1412 return true; |
|
1413 } |
|
1414 |
|
1415 void QDirectFBScreen::shutdownDevice() |
|
1416 { |
|
1417 #ifndef QT_NO_DIRECTFB_MOUSE |
|
1418 delete d_ptr->mouse; |
|
1419 d_ptr->mouse = 0; |
|
1420 #endif |
|
1421 #ifndef QT_NO_DIRECTFB_KEYBOARD |
|
1422 delete d_ptr->keyboard; |
|
1423 d_ptr->keyboard = 0; |
|
1424 #endif |
|
1425 |
|
1426 #ifndef QT_NO_QWS_CURSOR |
|
1427 delete qt_screencursor; |
|
1428 qt_screencursor = 0; |
|
1429 #endif |
|
1430 } |
|
1431 |
|
1432 void QDirectFBScreen::setMode(int width, int height, int depth) |
|
1433 { |
|
1434 d_ptr->dfb->SetVideoMode(d_ptr->dfb, width, height, depth); |
|
1435 } |
|
1436 |
|
1437 void QDirectFBScreen::blank(bool on) |
|
1438 { |
|
1439 d_ptr->dfbScreen->SetPowerMode(d_ptr->dfbScreen, |
|
1440 (on ? DSPM_ON : DSPM_SUSPEND)); |
|
1441 } |
|
1442 |
|
1443 QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const |
|
1444 { |
|
1445 #ifdef QT_NO_DIRECTFB_WM |
|
1446 if (QApplication::type() == QApplication::GuiServer) { |
|
1447 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); |
|
1448 } else { |
|
1449 return QScreen::createSurface(widget); |
|
1450 } |
|
1451 #else |
|
1452 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); |
|
1453 #endif |
|
1454 } |
|
1455 |
|
1456 QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const |
|
1457 { |
|
1458 if (key == QLatin1String("directfb")) { |
|
1459 return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); |
|
1460 } |
|
1461 return QScreen::createSurface(key); |
|
1462 } |
|
1463 |
|
1464 #if defined QT_NO_DIRECTFB_WM |
|
1465 struct PaintCommand { |
|
1466 PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {} |
|
1467 IDirectFBSurface *dfbSurface; |
|
1468 QImage image; |
|
1469 QPoint windowPosition; |
|
1470 QRegion source; |
|
1471 quint8 windowOpacity; |
|
1472 DFBSurfaceBlittingFlags blittingFlags; |
|
1473 }; |
|
1474 |
|
1475 static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos) |
|
1476 { |
|
1477 source.x = sourceGlobal.x() - pos.x(); |
|
1478 source.y = sourceGlobal.y() - pos.y(); |
|
1479 source.w = sourceGlobal.width(); |
|
1480 source.h = sourceGlobal.height(); |
|
1481 } |
|
1482 #endif |
|
1483 |
|
1484 void QDirectFBScreen::exposeRegion(QRegion r, int) |
|
1485 { |
|
1486 Q_UNUSED(r); |
|
1487 #if defined QT_NO_DIRECTFB_WM |
|
1488 |
|
1489 r &= region(); |
|
1490 if (r.isEmpty()) { |
|
1491 return; |
|
1492 } |
|
1493 r = r.boundingRect(); |
|
1494 |
|
1495 IDirectFBSurface *primary = d_ptr->primarySurface; |
|
1496 const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows(); |
|
1497 QVarLengthArray<PaintCommand, 4> commands(windows.size()); |
|
1498 QRegion region = r; |
|
1499 int idx = 0; |
|
1500 for (int i=0; i<windows.size(); ++i) { |
|
1501 QWSWindowSurface *surface = windows.at(i)->windowSurface(); |
|
1502 if (!surface) |
|
1503 continue; |
|
1504 |
|
1505 const QRect windowGeometry = surface->geometry(); |
|
1506 const QRegion intersection = region & windowGeometry; |
|
1507 if (intersection.isEmpty()) { |
|
1508 continue; |
|
1509 } |
|
1510 |
|
1511 PaintCommand &cmd = commands[idx]; |
|
1512 |
|
1513 if (surface->key() == QLatin1String("directfb")) { |
|
1514 const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface); |
|
1515 cmd.dfbSurface = ws->directFBSurface(); |
|
1516 |
|
1517 if (!cmd.dfbSurface) { |
|
1518 continue; |
|
1519 } |
|
1520 } else { |
|
1521 cmd.image = surface->image(); |
|
1522 if (cmd.image.isNull()) { |
|
1523 continue; |
|
1524 } |
|
1525 } |
|
1526 ++idx; |
|
1527 |
|
1528 cmd.windowPosition = windowGeometry.topLeft(); |
|
1529 cmd.source = intersection; |
|
1530 if (windows.at(i)->isOpaque()) { |
|
1531 region -= intersection; |
|
1532 if (region.isEmpty()) |
|
1533 break; |
|
1534 } else { |
|
1535 cmd.windowOpacity = windows.at(i)->opacity(); |
|
1536 cmd.blittingFlags = cmd.windowOpacity == 255 |
|
1537 ? DSBLIT_BLEND_ALPHACHANNEL |
|
1538 : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA); |
|
1539 } |
|
1540 } |
|
1541 if (!region.isEmpty()) { |
|
1542 solidFill(d_ptr->backgroundColor, region); |
|
1543 } |
|
1544 |
|
1545 while (idx > 0) { |
|
1546 const PaintCommand &cmd = commands[--idx]; |
|
1547 Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull()); |
|
1548 IDirectFBSurface *surface; |
|
1549 if (cmd.dfbSurface) { |
|
1550 surface = cmd.dfbSurface; |
|
1551 } else { |
|
1552 Q_ASSERT(!cmd.image.isNull()); |
|
1553 DFBResult result; |
|
1554 surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result); |
|
1555 Q_ASSERT((result != DFB_OK) == !surface); |
|
1556 if (result != DFB_OK) { |
|
1557 DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result); |
|
1558 continue; |
|
1559 } |
|
1560 } |
|
1561 |
|
1562 primary->SetBlittingFlags(primary, cmd.blittingFlags); |
|
1563 if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) { |
|
1564 primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity); |
|
1565 } |
|
1566 const QRegion ®ion = cmd.source; |
|
1567 const int rectCount = region.numRects(); |
|
1568 DFBRectangle source; |
|
1569 if (rectCount == 1) { |
|
1570 ::initParameters(source, region.boundingRect(), cmd.windowPosition); |
|
1571 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y); |
|
1572 } else { |
|
1573 const QVector<QRect> rects = region.rects(); |
|
1574 for (int i=0; i<rectCount; ++i) { |
|
1575 ::initParameters(source, rects.at(i), cmd.windowPosition); |
|
1576 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y); |
|
1577 } |
|
1578 } |
|
1579 if (surface != cmd.dfbSurface) { |
|
1580 surface->Release(surface); |
|
1581 } |
|
1582 } |
|
1583 |
|
1584 primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff); |
|
1585 |
|
1586 #if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR |
|
1587 if (QScreenCursor *cursor = QScreenCursor::instance()) { |
|
1588 const QRect cursorRectangle = cursor->boundingRect(); |
|
1589 if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) { |
|
1590 const QImage image = cursor->image(); |
|
1591 if (image.cacheKey() != d_ptr->cursorImageKey) { |
|
1592 if (d_ptr->cursorSurface) { |
|
1593 releaseDFBSurface(d_ptr->cursorSurface); |
|
1594 } |
|
1595 d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface); |
|
1596 d_ptr->cursorImageKey = image.cacheKey(); |
|
1597 } |
|
1598 |
|
1599 Q_ASSERT(d_ptr->cursorSurface); |
|
1600 primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL); |
|
1601 primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y()); |
|
1602 } |
|
1603 } |
|
1604 #endif |
|
1605 flipSurface(primary, d_ptr->flipFlags, r, QPoint()); |
|
1606 primary->SetBlittingFlags(primary, DSBLIT_NOFX); |
|
1607 #endif |
|
1608 } |
|
1609 |
|
1610 void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) |
|
1611 { |
|
1612 #ifdef QT_DIRECTFB_WM |
|
1613 Q_UNUSED(color); |
|
1614 Q_UNUSED(region); |
|
1615 #else |
|
1616 if (region.isEmpty()) |
|
1617 return; |
|
1618 |
|
1619 d_ptr->primarySurface->SetColor(d_ptr->primarySurface, |
|
1620 color.red(), color.green(), color.blue(), |
|
1621 color.alpha()); |
|
1622 const int n = region.numRects(); |
|
1623 if (n == 1) { |
|
1624 const QRect r = region.boundingRect(); |
|
1625 d_ptr->primarySurface->FillRectangle(d_ptr->primarySurface, r.x(), r.y(), r.width(), r.height()); |
|
1626 } else { |
|
1627 const QVector<QRect> rects = region.rects(); |
|
1628 QVarLengthArray<DFBRectangle, 32> rectArray(n); |
|
1629 for (int i=0; i<n; ++i) { |
|
1630 const QRect &r = rects.at(i); |
|
1631 rectArray[i].x = r.x(); |
|
1632 rectArray[i].y = r.y(); |
|
1633 rectArray[i].w = r.width(); |
|
1634 rectArray[i].h = r.height(); |
|
1635 } |
|
1636 d_ptr->primarySurface->FillRectangles(d_ptr->primarySurface, rectArray.constData(), n); |
|
1637 } |
|
1638 #endif |
|
1639 } |
|
1640 |
|
1641 QImage::Format QDirectFBScreen::alphaPixmapFormat() const |
|
1642 { |
|
1643 return d_ptr->alphaPixmapFormat; |
|
1644 } |
|
1645 |
|
1646 bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, |
|
1647 QImage::Format format) |
|
1648 { |
|
1649 const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); |
|
1650 if (pixelformat == DSPF_UNKNOWN) |
|
1651 return false; |
|
1652 description->flags |= DSDESC_PIXELFORMAT; |
|
1653 description->pixelformat = pixelformat; |
|
1654 if (QDirectFBScreen::isPremultiplied(format)) { |
|
1655 if (!(description->flags & DSDESC_CAPS)) { |
|
1656 description->caps = DSCAPS_PREMULTIPLIED; |
|
1657 description->flags |= DSDESC_CAPS; |
|
1658 } else { |
|
1659 description->caps |= DSCAPS_PREMULTIPLIED; |
|
1660 } |
|
1661 } |
|
1662 return true; |
|
1663 } |
|
1664 |
|
1665 uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) |
|
1666 { |
|
1667 void *mem; |
|
1668 const DFBResult result = surface->Lock(surface, flags, &mem, bpl); |
|
1669 if (result != DFB_OK) { |
|
1670 DirectFBError("QDirectFBScreen::lockSurface()", result); |
|
1671 } |
|
1672 |
|
1673 return reinterpret_cast<uchar*>(mem); |
|
1674 } |
|
1675 |
|
1676 |
|
1677 void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, |
|
1678 const QRegion ®ion, const QPoint &offset) |
|
1679 { |
|
1680 if (!(flipFlags & DSFLIP_BLIT)) { |
|
1681 surface->Flip(surface, 0, flipFlags); |
|
1682 } else { |
|
1683 if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.numRects() > 1) { |
|
1684 const QVector<QRect> rects = region.rects(); |
|
1685 const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; |
|
1686 for (int i=0; i<rects.size(); ++i) { |
|
1687 const QRect &r = rects.at(i); |
|
1688 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), |
|
1689 r.right() + offset.x(), |
|
1690 r.bottom() + offset.y() }; |
|
1691 surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); |
|
1692 } |
|
1693 } else { |
|
1694 const QRect r = region.boundingRect(); |
|
1695 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), |
|
1696 r.right() + offset.x(), |
|
1697 r.bottom() + offset.y() }; |
|
1698 surface->Flip(surface, &dfbReg, flipFlags); |
|
1699 } |
|
1700 } |
|
1701 } |
|
1702 |
|
1703 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
|
1704 void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider) |
|
1705 { |
|
1706 Q_ASSERT(provider); |
|
1707 if (d_ptr->imageProvider) |
|
1708 d_ptr->imageProvider->Release(d_ptr->imageProvider); |
|
1709 d_ptr->imageProvider = provider; |
|
1710 } |
|
1711 #endif |
|
1712 |
|
1713 void QDirectFBScreen::waitIdle() |
|
1714 { |
|
1715 d_ptr->dfb->WaitIdle(d_ptr->dfb); |
|
1716 } |
|
1717 |
|
1718 #ifdef QT_DIRECTFB_WM |
|
1719 IDirectFBWindow *QDirectFBScreen::windowForWidget(const QWidget *widget) const |
|
1720 { |
|
1721 if (widget) { |
|
1722 const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface()); |
|
1723 if (surface && surface->key() == QLatin1String("directfb")) { |
|
1724 return static_cast<const QDirectFBWindowSurface*>(surface)->directFBWindow(); |
|
1725 } |
|
1726 } |
|
1727 return 0; |
|
1728 } |
|
1729 #endif |
|
1730 |
|
1731 IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const |
|
1732 { |
|
1733 Q_ASSERT(widget); |
|
1734 if (!widget->isVisible() || widget->size().isNull()) |
|
1735 return 0; |
|
1736 |
|
1737 const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface()); |
|
1738 if (surface && surface->key() == QLatin1String("directfb")) { |
|
1739 return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect); |
|
1740 } |
|
1741 return 0; |
|
1742 } |
|
1743 |
|
1744 #ifdef QT_DIRECTFB_SUBSURFACE |
|
1745 IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const |
|
1746 { |
|
1747 Q_ASSERT(widget); |
|
1748 QRect rect; |
|
1749 IDirectFBSurface *surface = surfaceForWidget(widget, &rect); |
|
1750 IDirectFBSurface *subSurface = 0; |
|
1751 if (surface) { |
|
1752 if (!area.isNull()) |
|
1753 rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0))); |
|
1754 if (!rect.isNull()) { |
|
1755 const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() }; |
|
1756 const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface); |
|
1757 if (result != DFB_OK) { |
|
1758 DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result); |
|
1759 } |
|
1760 } |
|
1761 } |
|
1762 return subSurface; |
|
1763 } |
|
1764 #endif |
|
1765 |
|
1766 #ifndef QT_DIRECTFB_PLUGIN |
|
1767 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_widget(const QWidget *widget, QRect *rect) |
|
1768 { |
|
1769 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->surfaceForWidget(widget, rect) : 0; |
|
1770 } |
|
1771 #ifdef QT_DIRECTFB_SUBSURFACE |
|
1772 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_subsurface_for_widget(const QWidget *widget, const QRect &area) |
|
1773 { |
|
1774 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->subSurfaceForWidget(widget, area) : 0; |
|
1775 } |
|
1776 #endif |
|
1777 #ifdef QT_DIRECTFB_WM |
|
1778 Q_GUI_EXPORT IDirectFBWindow *qt_directfb_window_for_widget(const QWidget *widget) |
|
1779 { |
|
1780 return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->windowForWidget(widget) : 0; |
|
1781 } |
|
1782 |
|
1783 #endif |
|
1784 #endif |
|
1785 |
|
1786 QT_END_NAMESPACE |
|
1787 |
|
1788 #include "qdirectfbscreen.moc" |
|
1789 #endif // QT_NO_QWS_DIRECTFB |
|
1790 |