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 "qdirectfbpixmap.h"
|
---|
43 |
|
---|
44 | #ifndef QT_NO_QWS_DIRECTFB
|
---|
45 |
|
---|
46 | #include "qdirectfbscreen.h"
|
---|
47 | #include "qdirectfbpaintengine.h"
|
---|
48 |
|
---|
49 | #include <QtGui/qbitmap.h>
|
---|
50 | #include <QtCore/qfile.h>
|
---|
51 | #include <directfb.h>
|
---|
52 |
|
---|
53 |
|
---|
54 | QT_BEGIN_NAMESPACE
|
---|
55 |
|
---|
56 | static int global_ser_no = 0;
|
---|
57 |
|
---|
58 | QDirectFBPixmapData::QDirectFBPixmapData(QDirectFBScreen *screen, PixelType pixelType)
|
---|
59 | : QPixmapData(pixelType, DirectFBClass), QDirectFBPaintDevice(screen),
|
---|
60 | alpha(false)
|
---|
61 | {
|
---|
62 | setSerialNumber(0);
|
---|
63 | }
|
---|
64 |
|
---|
65 | QDirectFBPixmapData::~QDirectFBPixmapData()
|
---|
66 | {
|
---|
67 | }
|
---|
68 |
|
---|
69 | void QDirectFBPixmapData::resize(int width, int height)
|
---|
70 | {
|
---|
71 | if (width <= 0 || height <= 0) {
|
---|
72 | invalidate();
|
---|
73 | return;
|
---|
74 | }
|
---|
75 |
|
---|
76 | imageFormat = screen->pixelFormat();
|
---|
77 | dfbSurface = screen->createDFBSurface(QSize(width, height),
|
---|
78 | imageFormat,
|
---|
79 | QDirectFBScreen::TrackSurface);
|
---|
80 | d = QDirectFBScreen::depth(imageFormat);
|
---|
81 | alpha = false;
|
---|
82 | if (!dfbSurface) {
|
---|
83 | invalidate();
|
---|
84 | qWarning("QDirectFBPixmapData::resize(): Unable to allocate surface");
|
---|
85 | return;
|
---|
86 | }
|
---|
87 |
|
---|
88 | w = width;
|
---|
89 | h = height;
|
---|
90 | is_null = (w <= 0 || h <= 0);
|
---|
91 | setSerialNumber(++global_ser_no);
|
---|
92 | }
|
---|
93 |
|
---|
94 | #ifdef QT_DIRECTFB_OPAQUE_DETECTION
|
---|
95 | // mostly duplicated from qimage.cpp (QImageData::checkForAlphaPixels)
|
---|
96 | static bool checkForAlphaPixels(const QImage &img)
|
---|
97 | {
|
---|
98 | const uchar *bits = img.bits();
|
---|
99 | const int bytes_per_line = img.bytesPerLine();
|
---|
100 | const uchar *end_bits = bits + bytes_per_line;
|
---|
101 | const int width = img.width();
|
---|
102 | const int height = img.height();
|
---|
103 | switch (img.format()) {
|
---|
104 | case QImage::Format_Indexed8:
|
---|
105 | return img.hasAlphaChannel();
|
---|
106 | case QImage::Format_ARGB32:
|
---|
107 | case QImage::Format_ARGB32_Premultiplied:
|
---|
108 | for (int y=0; y<height; ++y) {
|
---|
109 | for (int x=0; x<width; ++x) {
|
---|
110 | if ((((uint *)bits)[x] & 0xff000000) != 0xff000000) {
|
---|
111 | return true;
|
---|
112 | }
|
---|
113 | }
|
---|
114 | bits += bytes_per_line;
|
---|
115 | }
|
---|
116 | break;
|
---|
117 |
|
---|
118 | case QImage::Format_ARGB8555_Premultiplied:
|
---|
119 | case QImage::Format_ARGB8565_Premultiplied:
|
---|
120 | for (int y=0; y<height; ++y) {
|
---|
121 | while (bits < end_bits) {
|
---|
122 | if (bits[0] != 0) {
|
---|
123 | return true;
|
---|
124 | }
|
---|
125 | bits += 3;
|
---|
126 | }
|
---|
127 | bits = end_bits;
|
---|
128 | end_bits += bytes_per_line;
|
---|
129 | }
|
---|
130 | break;
|
---|
131 |
|
---|
132 | case QImage::Format_ARGB6666_Premultiplied:
|
---|
133 | for (int y=0; y<height; ++y) {
|
---|
134 | while (bits < end_bits) {
|
---|
135 | if ((bits[0] & 0xfc) != 0) {
|
---|
136 | return true;
|
---|
137 | }
|
---|
138 | bits += 3;
|
---|
139 | }
|
---|
140 | bits = end_bits;
|
---|
141 | end_bits += bytes_per_line;
|
---|
142 | }
|
---|
143 | break;
|
---|
144 |
|
---|
145 | case QImage::Format_ARGB4444_Premultiplied:
|
---|
146 | for (int y=0; y<height; ++y) {
|
---|
147 | while (bits < end_bits) {
|
---|
148 | if ((bits[0] & 0xf0) != 0) {
|
---|
149 | return true;
|
---|
150 | }
|
---|
151 | bits += 2;
|
---|
152 | }
|
---|
153 | bits = end_bits;
|
---|
154 | end_bits += bytes_per_line;
|
---|
155 | }
|
---|
156 | break;
|
---|
157 |
|
---|
158 | default:
|
---|
159 | break;
|
---|
160 | }
|
---|
161 |
|
---|
162 | return false;
|
---|
163 | }
|
---|
164 | #endif // QT_DIRECTFB_OPAQUE_DETECTION
|
---|
165 |
|
---|
166 | bool QDirectFBPixmapData::hasAlphaChannel(const QImage &img, Qt::ImageConversionFlags flags)
|
---|
167 | {
|
---|
168 | if (img.depth() == 1)
|
---|
169 | return true;
|
---|
170 | #ifdef QT_DIRECTFB_OPAQUE_DETECTION
|
---|
171 | return ((flags & Qt::NoOpaqueDetection) ? img.hasAlphaChannel() : checkForAlphaPixels(img));
|
---|
172 | #else
|
---|
173 | Q_UNUSED(flags);
|
---|
174 | return img.hasAlphaChannel();
|
---|
175 | #endif
|
---|
176 | }
|
---|
177 |
|
---|
178 | #ifdef QT_DIRECTFB_IMAGEPROVIDER
|
---|
179 | bool QDirectFBPixmapData::fromFile(const QString &filename, const char *format,
|
---|
180 | Qt::ImageConversionFlags flags)
|
---|
181 | {
|
---|
182 | if (!QFile::exists(filename))
|
---|
183 | return false;
|
---|
184 | if (flags == Qt::AutoColor) {
|
---|
185 | if (filename.startsWith(QLatin1Char(':'))) { // resource
|
---|
186 | QFile file(filename);
|
---|
187 | if (!file.open(QIODevice::ReadOnly))
|
---|
188 | return false;
|
---|
189 | const QByteArray data = file.readAll();
|
---|
190 | file.close();
|
---|
191 | return fromData(reinterpret_cast<const uchar*>(data.constData()), data.size(), format, flags);
|
---|
192 | } else {
|
---|
193 | DFBDataBufferDescription description;
|
---|
194 | description.flags = DBDESC_FILE;
|
---|
195 | const QByteArray fileNameData = filename.toLocal8Bit();
|
---|
196 | description.file = fileNameData.constData();
|
---|
197 | if (fromDataBufferDescription(description)) {
|
---|
198 | return true;
|
---|
199 | }
|
---|
200 | // fall back to Qt
|
---|
201 | }
|
---|
202 | }
|
---|
203 | return QPixmapData::fromFile(filename, format, flags);
|
---|
204 | }
|
---|
205 |
|
---|
206 | bool QDirectFBPixmapData::fromData(const uchar *buffer, uint len, const char *format,
|
---|
207 | Qt::ImageConversionFlags flags)
|
---|
208 | {
|
---|
209 | if (flags == Qt::AutoColor) {
|
---|
210 | DFBDataBufferDescription description;
|
---|
211 | description.flags = DBDESC_MEMORY;
|
---|
212 | description.memory.data = buffer;
|
---|
213 | description.memory.length = len;
|
---|
214 | if (fromDataBufferDescription(description))
|
---|
215 | return true;
|
---|
216 | // fall back to Qt
|
---|
217 | }
|
---|
218 | return QPixmapData::fromData(buffer, len, format, flags);
|
---|
219 | }
|
---|
220 |
|
---|
221 | template <typename T> struct QDirectFBInterfaceCleanupHandler
|
---|
222 | {
|
---|
223 | static void cleanup(T *t) { if (t) t->Release(t); }
|
---|
224 | };
|
---|
225 |
|
---|
226 | template <typename T>
|
---|
227 | class QDirectFBPointer : public QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> >
|
---|
228 | {
|
---|
229 | public:
|
---|
230 | QDirectFBPointer(T *t = 0)
|
---|
231 | : QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> >(t)
|
---|
232 | {}
|
---|
233 | };
|
---|
234 |
|
---|
235 | bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
|
---|
236 | {
|
---|
237 | IDirectFB *dfb = screen->dfb();
|
---|
238 | Q_ASSERT(dfb);
|
---|
239 | DFBResult result = DFB_OK;
|
---|
240 | IDirectFBDataBuffer *dataBufferPtr;
|
---|
241 | if ((result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, &dataBufferPtr)) != DFB_OK) {
|
---|
242 | DirectFBError("QDirectFBPixmapData::fromDataBufferDescription()", result);
|
---|
243 | return false;
|
---|
244 | }
|
---|
245 | QDirectFBPointer<IDirectFBDataBuffer> dataBuffer(dataBufferPtr);
|
---|
246 |
|
---|
247 | IDirectFBImageProvider *providerPtr;
|
---|
248 | if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) {
|
---|
249 | DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result);
|
---|
250 | return false;
|
---|
251 | }
|
---|
252 | QDirectFBPointer<IDirectFBImageProvider> provider(providerPtr);
|
---|
253 |
|
---|
254 | DFBImageDescription imageDescription;
|
---|
255 | result = provider->GetImageDescription(provider.data(), &imageDescription);
|
---|
256 | if (result != DFB_OK) {
|
---|
257 | DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't get image description", result);
|
---|
258 | return false;
|
---|
259 | }
|
---|
260 |
|
---|
261 | if (imageDescription.caps & DICAPS_COLORKEY) {
|
---|
262 | return false;
|
---|
263 | }
|
---|
264 |
|
---|
265 | DFBSurfaceDescription surfaceDescription;
|
---|
266 | if ((result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription)) != DFB_OK) {
|
---|
267 | DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result);
|
---|
268 | return false;
|
---|
269 | }
|
---|
270 |
|
---|
271 | alpha = imageDescription.caps & DICAPS_ALPHACHANNEL;
|
---|
272 | imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat();
|
---|
273 |
|
---|
274 | dfbSurface = screen->createDFBSurface(QSize(surfaceDescription.width, surfaceDescription.height),
|
---|
275 | imageFormat, QDirectFBScreen::TrackSurface);
|
---|
276 |
|
---|
277 | result = provider->RenderTo(provider.data(), dfbSurface, 0);
|
---|
278 | if (result != DFB_OK) {
|
---|
279 | DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't render to surface", result);
|
---|
280 | return false;
|
---|
281 | }
|
---|
282 |
|
---|
283 | w = surfaceDescription.width;
|
---|
284 | h = surfaceDescription.height;
|
---|
285 | is_null = (w <= 0 || h <= 0);
|
---|
286 | d = QDirectFBScreen::depth(imageFormat);
|
---|
287 | setSerialNumber(++global_ser_no);
|
---|
288 |
|
---|
289 | #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
|
---|
290 | screen->setDirectFBImageProvider(providerPtr);
|
---|
291 | provider.take();
|
---|
292 | #endif
|
---|
293 |
|
---|
294 | return true;
|
---|
295 | }
|
---|
296 |
|
---|
297 | #endif
|
---|
298 |
|
---|
299 | void QDirectFBPixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags)
|
---|
300 | {
|
---|
301 | alpha = QDirectFBPixmapData::hasAlphaChannel(img, flags);
|
---|
302 | imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat();
|
---|
303 | QImage image;
|
---|
304 | if ((flags & ~Qt::NoOpaqueDetection) != Qt::AutoColor) {
|
---|
305 | image = img.convertToFormat(imageFormat, flags);
|
---|
306 | flags = Qt::AutoColor;
|
---|
307 | } else if (img.format() == QImage::Format_RGB32 || img.depth() == 1) {
|
---|
308 | image = img.convertToFormat(imageFormat, flags);
|
---|
309 | } else {
|
---|
310 | image = img;
|
---|
311 | }
|
---|
312 |
|
---|
313 | IDirectFBSurface *imageSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface);
|
---|
314 | if (!imageSurface) {
|
---|
315 | qWarning("QDirectFBPixmapData::fromImage()");
|
---|
316 | invalidate();
|
---|
317 | return;
|
---|
318 | }
|
---|
319 |
|
---|
320 | dfbSurface = screen->createDFBSurface(image.size(), imageFormat, QDirectFBScreen::TrackSurface);
|
---|
321 | if (!dfbSurface) {
|
---|
322 | qWarning("QDirectFBPixmapData::fromImage()");
|
---|
323 | invalidate();
|
---|
324 | return;
|
---|
325 | }
|
---|
326 |
|
---|
327 | if (image.hasAlphaChannel()) {
|
---|
328 | dfbSurface->Clear(dfbSurface, 0, 0, 0, 0);
|
---|
329 | dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL);
|
---|
330 | } else {
|
---|
331 | dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
|
---|
332 | }
|
---|
333 |
|
---|
334 | dfbSurface->Blit(dfbSurface, imageSurface, 0, 0, 0);
|
---|
335 | imageSurface->Release(imageSurface);
|
---|
336 |
|
---|
337 | w = image.width();
|
---|
338 | h = image.height();
|
---|
339 | is_null = (w <= 0 || h <= 0);
|
---|
340 | d = QDirectFBScreen::depth(imageFormat);
|
---|
341 | setSerialNumber(++global_ser_no);
|
---|
342 | #ifdef QT_NO_DIRECTFB_OPAQUE_DETECTION
|
---|
343 | Q_UNUSED(flags);
|
---|
344 | #endif
|
---|
345 | }
|
---|
346 |
|
---|
347 | void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
|
---|
348 | {
|
---|
349 | if (data->classId() != DirectFBClass) {
|
---|
350 | QPixmapData::copy(data, rect);
|
---|
351 | return;
|
---|
352 | }
|
---|
353 |
|
---|
354 | const QDirectFBPixmapData *otherData = static_cast<const QDirectFBPixmapData*>(data);
|
---|
355 | #ifdef QT_NO_DIRECTFB_SUBSURFACE
|
---|
356 | if (otherData->lockFlags()) {
|
---|
357 | const_cast<QDirectFBPixmapData*>(otherData)->unlockSurface();
|
---|
358 | }
|
---|
359 | #endif
|
---|
360 | IDirectFBSurface *src = otherData->directFBSurface();
|
---|
361 | alpha = data->hasAlphaChannel();
|
---|
362 | imageFormat = (alpha
|
---|
363 | ? QDirectFBScreen::instance()->alphaPixmapFormat()
|
---|
364 | : QDirectFBScreen::instance()->pixelFormat());
|
---|
365 |
|
---|
366 |
|
---|
367 | dfbSurface = screen->createDFBSurface(rect.size(), imageFormat,
|
---|
368 | QDirectFBScreen::TrackSurface);
|
---|
369 | if (!dfbSurface) {
|
---|
370 | qWarning("QDirectFBPixmapData::copy()");
|
---|
371 | invalidate();
|
---|
372 | return;
|
---|
373 | }
|
---|
374 |
|
---|
375 | if (alpha) {
|
---|
376 | dfbSurface->Clear(dfbSurface, 0, 0, 0, 0);
|
---|
377 | dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL);
|
---|
378 | } else {
|
---|
379 | dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
|
---|
380 | }
|
---|
381 | const DFBRectangle blitRect = { rect.x(), rect.y(),
|
---|
382 | rect.width(), rect.height() };
|
---|
383 | w = rect.width();
|
---|
384 | h = rect.height();
|
---|
385 | d = otherData->d;
|
---|
386 | is_null = (w <= 0 || h <= 0);
|
---|
387 | unlockSurface();
|
---|
388 | DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
|
---|
389 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
390 | dfbSurface->ReleaseSource(dfbSurface);
|
---|
391 | #endif
|
---|
392 | if (result != DFB_OK) {
|
---|
393 | DirectFBError("QDirectFBPixmapData::copy()", result);
|
---|
394 | invalidate();
|
---|
395 | return;
|
---|
396 | }
|
---|
397 |
|
---|
398 | setSerialNumber(++global_ser_no);
|
---|
399 | }
|
---|
400 |
|
---|
401 | static inline bool isOpaqueFormat(QImage::Format format)
|
---|
402 | {
|
---|
403 | switch (format) {
|
---|
404 | case QImage::Format_RGB32:
|
---|
405 | case QImage::Format_RGB16:
|
---|
406 | case QImage::Format_RGB666:
|
---|
407 | case QImage::Format_RGB555:
|
---|
408 | case QImage::Format_RGB888:
|
---|
409 | case QImage::Format_RGB444:
|
---|
410 | return true;
|
---|
411 | default:
|
---|
412 | break;
|
---|
413 | }
|
---|
414 | return false;
|
---|
415 | }
|
---|
416 |
|
---|
417 | void QDirectFBPixmapData::fill(const QColor &color)
|
---|
418 | {
|
---|
419 | if (!serialNumber())
|
---|
420 | return;
|
---|
421 |
|
---|
422 | Q_ASSERT(dfbSurface);
|
---|
423 |
|
---|
424 | alpha |= (color.alpha() < 255);
|
---|
425 |
|
---|
426 | if (alpha && isOpaqueFormat(imageFormat)) {
|
---|
427 | QSize size;
|
---|
428 | dfbSurface->GetSize(dfbSurface, &size.rwidth(), &size.rheight());
|
---|
429 | screen->releaseDFBSurface(dfbSurface);
|
---|
430 | imageFormat = screen->alphaPixmapFormat();
|
---|
431 | d = QDirectFBScreen::depth(imageFormat);
|
---|
432 | dfbSurface = screen->createDFBSurface(size, screen->alphaPixmapFormat(), QDirectFBScreen::TrackSurface);
|
---|
433 | setSerialNumber(++global_ser_no);
|
---|
434 | if (!dfbSurface) {
|
---|
435 | qWarning("QDirectFBPixmapData::fill()");
|
---|
436 | invalidate();
|
---|
437 | return;
|
---|
438 | }
|
---|
439 | }
|
---|
440 |
|
---|
441 | dfbSurface->Clear(dfbSurface, color.red(), color.green(), color.blue(), color.alpha());
|
---|
442 | }
|
---|
443 |
|
---|
444 | QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
|
---|
445 | Qt::TransformationMode mode) const
|
---|
446 | {
|
---|
447 | QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
|
---|
448 | #ifdef QT_NO_DIRECTFB_SUBSURFACE
|
---|
449 | if (lockFlags())
|
---|
450 | that->unlockSurface();
|
---|
451 | #endif
|
---|
452 |
|
---|
453 | if (!dfbSurface || transform.type() != QTransform::TxScale
|
---|
454 | || mode != Qt::FastTransformation)
|
---|
455 | {
|
---|
456 | const QImage *image = that->buffer();
|
---|
457 | Q_ASSERT(image);
|
---|
458 | const QImage transformed = image->transformed(transform, mode);
|
---|
459 | QDirectFBPixmapData *data = new QDirectFBPixmapData(screen, QPixmapData::PixmapType);
|
---|
460 | data->fromImage(transformed, Qt::AutoColor);
|
---|
461 | return QPixmap(data);
|
---|
462 | }
|
---|
463 |
|
---|
464 | const QSize size = transform.mapRect(QRect(0, 0, w, h)).size();
|
---|
465 | if (size.isEmpty())
|
---|
466 | return QPixmap();
|
---|
467 |
|
---|
468 | QDirectFBPixmapData *data = new QDirectFBPixmapData(screen, QPixmapData::PixmapType);
|
---|
469 | data->setSerialNumber(++global_ser_no);
|
---|
470 | DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
|
---|
471 | data->alpha = alpha;
|
---|
472 | if (alpha) {
|
---|
473 | flags = DSBLIT_BLEND_ALPHACHANNEL;
|
---|
474 | }
|
---|
475 | data->dfbSurface = screen->createDFBSurface(size,
|
---|
476 | imageFormat,
|
---|
477 | QDirectFBScreen::TrackSurface);
|
---|
478 | if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
|
---|
479 | data->dfbSurface->Clear(data->dfbSurface, 0, 0, 0, 0);
|
---|
480 | }
|
---|
481 | data->dfbSurface->SetBlittingFlags(data->dfbSurface, flags);
|
---|
482 |
|
---|
483 | const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
|
---|
484 | data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect);
|
---|
485 | data->w = size.width();
|
---|
486 | data->h = size.height();
|
---|
487 | data->is_null = (data->w <= 0 || data->h <= 0);
|
---|
488 |
|
---|
489 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
490 | data->dfbSurface->ReleaseSource(data->dfbSurface);
|
---|
491 | #endif
|
---|
492 | return QPixmap(data);
|
---|
493 | }
|
---|
494 |
|
---|
495 | QImage QDirectFBPixmapData::toImage() const
|
---|
496 | {
|
---|
497 | if (!dfbSurface)
|
---|
498 | return QImage();
|
---|
499 |
|
---|
500 | #if 0
|
---|
501 | // In later versions of DirectFB one can set a flag to tell
|
---|
502 | // DirectFB not to move the surface to videomemory. When that
|
---|
503 | // happens we can use this (hopefully faster) codepath
|
---|
504 | #ifndef QT_NO_DIRECTFB_PREALLOCATED
|
---|
505 | QImage ret(w, h, QDirectFBScreen::getImageFormat(dfbSurface));
|
---|
506 | if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) {
|
---|
507 | if (hasAlphaChannel()) {
|
---|
508 | imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL);
|
---|
509 | imgSurface->Clear(imgSurface, 0, 0, 0, 0);
|
---|
510 | } else {
|
---|
511 | imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX);
|
---|
512 | }
|
---|
513 | imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0);
|
---|
514 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
515 | imgSurface->ReleaseSource(imgSurface);
|
---|
516 | #endif
|
---|
517 | imgSurface->Release(imgSurface);
|
---|
518 | return ret;
|
---|
519 | }
|
---|
520 | #endif
|
---|
521 | #endif
|
---|
522 |
|
---|
523 | QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
|
---|
524 | const QImage *img = that->buffer();
|
---|
525 | return img->copy();
|
---|
526 | }
|
---|
527 |
|
---|
528 | /* This is QPixmapData::paintEngine(), not QPaintDevice::paintEngine() */
|
---|
529 |
|
---|
530 | QPaintEngine *QDirectFBPixmapData::paintEngine() const
|
---|
531 | {
|
---|
532 | if (!engine) {
|
---|
533 | // QDirectFBPixmapData is also a QCustomRasterPaintDevice, so pass
|
---|
534 | // that to the paint engine:
|
---|
535 | QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
|
---|
536 | that->engine = new QDirectFBPaintEngine(that);
|
---|
537 | }
|
---|
538 | return engine;
|
---|
539 | }
|
---|
540 |
|
---|
541 | QImage *QDirectFBPixmapData::buffer()
|
---|
542 | {
|
---|
543 | if (!lockFlgs) {
|
---|
544 | lockSurface(DSLF_READ|DSLF_WRITE);
|
---|
545 | }
|
---|
546 | Q_ASSERT(lockFlgs);
|
---|
547 | Q_ASSERT(!lockedImage.isNull());
|
---|
548 | return &lockedImage;
|
---|
549 | }
|
---|
550 |
|
---|
551 |
|
---|
552 | bool QDirectFBPixmapData::scroll(int dx, int dy, const QRect &rect)
|
---|
553 | {
|
---|
554 | if (!dfbSurface) {
|
---|
555 | return false;
|
---|
556 | }
|
---|
557 | unlockSurface();
|
---|
558 | DFBResult result = dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
|
---|
559 | if (result != DFB_OK) {
|
---|
560 | DirectFBError("QDirectFBPixmapData::scroll", result);
|
---|
561 | return false;
|
---|
562 | }
|
---|
563 | result = dfbSurface->SetPorterDuff(dfbSurface, DSPD_NONE);
|
---|
564 | if (result != DFB_OK) {
|
---|
565 | DirectFBError("QDirectFBPixmapData::scroll", result);
|
---|
566 | return false;
|
---|
567 | }
|
---|
568 |
|
---|
569 | const DFBRectangle source = { rect.x(), rect.y(), rect.width(), rect.height() };
|
---|
570 | result = dfbSurface->Blit(dfbSurface, dfbSurface, &source, source.x + dx, source.y + dy);
|
---|
571 | if (result != DFB_OK) {
|
---|
572 | DirectFBError("QDirectFBPixmapData::scroll", result);
|
---|
573 | return false;
|
---|
574 | }
|
---|
575 |
|
---|
576 | return true;
|
---|
577 | }
|
---|
578 |
|
---|
579 | void QDirectFBPixmapData::invalidate()
|
---|
580 | {
|
---|
581 | if (dfbSurface) {
|
---|
582 | screen->releaseDFBSurface(dfbSurface);
|
---|
583 | dfbSurface = 0;
|
---|
584 | }
|
---|
585 | setSerialNumber(0);
|
---|
586 | alpha = false;
|
---|
587 | d = w = h = 0;
|
---|
588 | is_null = true;
|
---|
589 | imageFormat = QImage::Format_Invalid;
|
---|
590 | }
|
---|
591 |
|
---|
592 | Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_pixmap(const QPixmap &pixmap)
|
---|
593 | {
|
---|
594 | const QPixmapData *data = pixmap.pixmapData();
|
---|
595 | if (!data || data->classId() != QPixmapData::DirectFBClass)
|
---|
596 | return 0;
|
---|
597 | const QDirectFBPixmapData *dfbData = static_cast<const QDirectFBPixmapData*>(data);
|
---|
598 | return dfbData->directFBSurface();
|
---|
599 | }
|
---|
600 |
|
---|
601 | QT_END_NAMESPACE
|
---|
602 |
|
---|
603 | #endif // QT_NO_QWS_DIRECTFB
|
---|