1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the plugins of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include "qdirectfbblitter.h"
43
#include "qdirectfbconvenience.h"
45
#include <QtGui/private/qpixmap_blitter_p.h>
54
static QBlittable::Capabilities dfb_blitter_capabilities()
56
return QBlittable::Capabilities(QBlittable::SolidRectCapability
57
|QBlittable::SourcePixmapCapability
58
|QBlittable::SourceOverPixmapCapability
59
|QBlittable::SourceOverScaledPixmapCapability
60
|QBlittable::AlphaFillRectCapability
61
|QBlittable::OpacityPixmapCapability);
64
QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
65
: QBlittable(rect, dfb_blitter_capabilities())
68
m_surface->AddRef(m_surface.data());
70
DFBSurfaceCapabilities surfaceCaps;
71
m_surface->GetCapabilities(m_surface.data(), &surfaceCaps);
72
m_premult = (surfaceCaps & DSCAPS_PREMULTIPLIED);
75
QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha)
76
: QBlittable(rect, dfb_blitter_capabilities()), m_premult(false)
78
DFBSurfaceDescription surfaceDesc;
79
memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
80
surfaceDesc.width = rect.width();
81
surfaceDesc.height = rect.height();
83
// force alpha format to get AlphaFillRectCapability and ExtendedPixmapCapability support
88
surfaceDesc.caps = DSCAPS_PREMULTIPLIED;
89
surfaceDesc.pixelformat = QDirectFbBlitter::alphaPixmapFormat();
90
surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT);
92
surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
93
surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat();
96
IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
97
dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr());
98
m_surface->Clear(m_surface.data(), 0, 0, 0, 0);
101
QDirectFbBlitter::~QDirectFbBlitter()
106
DFBSurfacePixelFormat QDirectFbBlitter::alphaPixmapFormat()
111
DFBSurfacePixelFormat QDirectFbBlitter::pixmapFormat()
116
DFBSurfacePixelFormat QDirectFbBlitter::selectPixmapFormat(bool withAlpha)
118
return withAlpha ? alphaPixmapFormat() : pixmapFormat();
121
void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color)
123
alphaFillRect(rect, color, QPainter::CompositionMode_Source);
126
void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect)
128
drawPixmapOpacity(rect, pixmap, srcRect, QPainter::CompositionMode_SourceOver, 1.0);
131
void QDirectFbBlitter::alphaFillRect(const QRectF &rect, const QColor &color, QPainter::CompositionMode cmode)
137
rect.toRect().getRect(&x, &y ,&w, &h);
138
if ((w <= 0) || (h <= 0)) return;
140
if ((cmode == QPainter::CompositionMode_Source) || (color.alpha() == 255)) {
141
// CompositionMode_Source case or CompositionMode_SourceOver with opaque color
143
m_surface->SetDrawingFlags(m_surface.data(),
144
DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_NOFX | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_NOFX));
145
m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC);
148
// CompositionMode_SourceOver case
150
// check if operation is useless
151
if (color.alpha() == 0)
154
m_surface->SetDrawingFlags(m_surface.data(),
155
DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_BLEND));
156
m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC_OVER);
160
m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
163
result = m_surface->FillRectangle(m_surface.data(), x, y, w, h);
164
if (result != DFB_OK)
165
DirectFBError("QDirectFBBlitter::alphaFillRect()", result);
168
void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity)
170
QRect sQRect = subrect.toRect();
171
QRect dQRect = rect.toRect();
172
DFBRectangle sRect = { sQRect.x(), sQRect.y(), sQRect.width(), sQRect.height() };
173
DFBRectangle dRect = { dQRect.x(), dQRect.y(), dQRect.width(), dQRect.height() };
176
// skip if dst too small
177
if ((dRect.w <= 0) || (dRect.h <= 0)) return;
179
// correct roundings if needed
180
if (sRect.w <= 0) sRect.w = 1;
181
if (sRect.h <= 0) sRect.h = 1;
183
QDirectFbBlitterPlatformPixmap *blitPm = static_cast<QDirectFbBlitterPlatformPixmap *>(pixmap.handle());
184
QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable());
185
dfbBlitter->unlock();
187
IDirectFBSurface *s = dfbBlitter->m_surface.data();
189
DFBSurfaceBlittingFlags blittingFlags = DFBSurfaceBlittingFlags(DSBLIT_BLEND_ALPHACHANNEL);
190
DFBSurfacePorterDuffRule porterDuff = (cmode == QPainter::CompositionMode_SourceOver) ? DSPD_SRC_OVER : DSPD_SRC;
194
blittingFlags = DFBSurfaceBlittingFlags(blittingFlags | DSBLIT_BLEND_COLORALPHA | (m_premult ? DSBLIT_SRC_PREMULTCOLOR : 0));
195
m_surface->SetColor(m_surface.data(), 0xff, 0xff, 0xff, (u8) (opacity * 255.0));
198
m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags));
199
m_surface->SetPorterDuff(m_surface.data(), porterDuff);
201
if (cmode == QPainter::CompositionMode_SourceOver)
202
m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
204
if ((sRect.w == dRect.w) && (sRect.h == dRect.h))
205
result = m_surface->Blit(m_surface.data(), s, &sRect, dRect.x, dRect.y);
207
result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect);
209
if (result != DFB_OK)
210
DirectFBError("QDirectFBBlitter::drawPixmapExtended()", result);
213
QImage *QDirectFbBlitter::doLock()
216
Q_ASSERT(size().isValid());
220
const DFBResult result = m_surface->Lock(m_surface.data(), DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl);
221
if (result == DFB_OK) {
222
DFBSurfacePixelFormat dfbFormat;
223
DFBSurfaceCapabilities dfbCaps;
224
m_surface->GetPixelFormat(m_surface.data(), &dfbFormat);
225
m_surface->GetCapabilities(m_surface.data(), &dfbCaps);
226
QImage::Format format = QDirectFbConvenience::imageFormatFromSurfaceFormat(dfbFormat, dfbCaps);
228
m_surface->GetSize(m_surface.data(), &w, &h);
229
m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format);
231
DirectFBError("Failed to lock image", result);
237
bool QDirectFbBlitterPlatformPixmap::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
240
IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
242
// Create a data buffer
243
QDirectFBPointer<IDirectFBDataBuffer> dataBuffer;
244
result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, dataBuffer.outPtr());
245
if (result != DFB_OK) {
246
DirectFBError(QDFB_PRETTY, result);
250
// Create the image provider
251
QDirectFBPointer<IDirectFBImageProvider> provider;
252
result = dataBuffer->CreateImageProvider(dataBuffer.data(), provider.outPtr());
253
if (result != DFB_OK) {
254
DirectFBError(QDFB_PRETTY, result);
258
// Extract image information
259
DFBImageDescription imageDescription;
260
result = provider->GetImageDescription(provider.data(), &imageDescription);
261
if (result != DFB_OK) {
262
DirectFBError(QDFB_PRETTY, result);
266
// Can we handle this directlu?
267
if (imageDescription.caps & DICAPS_COLORKEY)
270
DFBSurfaceDescription surfaceDescription;
271
result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription);
272
if (result != DFB_OK) {
273
DirectFBError(QDFB_PRETTY, result);
277
m_alpha = imageDescription.caps & DICAPS_ALPHACHANNEL;
278
resize(surfaceDescription.width, surfaceDescription.height);
279
// TODO: FIXME; update d
282
result = provider->RenderTo(provider.data(), dfbBlitter()->dfbSurface(), 0);
283
if (result != DFB_OK) {
284
DirectFBError(QDFB_PRETTY, result);
291
bool QDirectFbBlitterPlatformPixmap::fromFile(const QString &filename, const char *format,
292
Qt::ImageConversionFlags flags)
294
// If we can't find the file, pass it on to the base class as it is
295
// trying harder by appending various extensions to the path.
296
if (!QFile::exists(filename))
297
return QBlittablePlatformPixmap::fromFile(filename, format, flags);
299
// Stop if there is a requirement for colors
300
if (flags != Qt::AutoColor)
301
return QBlittablePlatformPixmap::fromFile(filename, format, flags);
303
// Deal with resources
304
if (filename.startsWith(QLatin1Char(':')))
305
return QBlittablePlatformPixmap::fromFile(filename, format, flags);
307
// Try to use directfb to load it.
308
DFBDataBufferDescription description;
309
description.flags = DBDESC_FILE;
310
const QByteArray fileNameData = filename.toLocal8Bit();
311
description.file = fileNameData.constData();
312
if (fromDataBufferDescription(description))
316
return QBlittablePlatformPixmap::fromFile(filename, format, flags);
319
void QDirectFbBlitter::doUnlock()
321
m_surface->Unlock(m_surface.data());