bb5fa0b288b2dfe75b2bd0d2b53568acdc25695e
[profile/ivi/qtbase.git] / src / plugins / platforms / directfb / qdirectfbblitter.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdirectfbblitter.h"
43 #include "qdirectfbconvenience.h"
44
45 #include <QtGui/private/qpixmap_blitter_p.h>
46
47 #include <QDebug>
48 #include <QFile>
49
50 #include <directfb.h>
51
52 QT_BEGIN_NAMESPACE
53
54 static QBlittable::Capabilities dfb_blitter_capabilities()
55 {
56     return QBlittable::Capabilities(QBlittable::SolidRectCapability
57                                     |QBlittable::SourcePixmapCapability
58                                     |QBlittable::SourceOverPixmapCapability
59                                     |QBlittable::SourceOverScaledPixmapCapability);
60 }
61
62 QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
63     : QBlittable(rect, dfb_blitter_capabilities())
64         , m_surface(surface)
65 {
66         m_surface->AddRef(m_surface.data());
67 }
68
69 QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha)
70     : QBlittable(rect, dfb_blitter_capabilities())
71 {
72     DFBSurfaceDescription surfaceDesc;
73     memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
74     surfaceDesc.width = rect.width();
75     surfaceDesc.height = rect.height();
76
77     if (alpha) {
78         surfaceDesc.caps = DSCAPS_PREMULTIPLIED;
79         surfaceDesc.pixelformat = QDirectFbBlitter::alphaPixmapFormat();
80         surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT);
81     } else {
82         surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
83         surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat();
84     }
85
86
87     IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
88     dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr());
89     m_surface->Clear(m_surface.data(), 0, 0, 0, 0);
90 }
91
92 QDirectFbBlitter::~QDirectFbBlitter()
93 {
94     unlock();
95 }
96
97 DFBSurfacePixelFormat QDirectFbBlitter::alphaPixmapFormat()
98 {
99     return DSPF_ARGB;
100 }
101
102 DFBSurfacePixelFormat QDirectFbBlitter::pixmapFormat()
103 {
104     return DSPF_RGB32;
105 }
106
107 DFBSurfacePixelFormat QDirectFbBlitter::selectPixmapFormat(bool withAlpha)
108 {
109     return withAlpha ? alphaPixmapFormat() : pixmapFormat();
110 }
111
112 void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color)
113 {
114     m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
115 //    When the blitter api supports non opaque blits, also remember to change
116 //    qpixmap_blitter.cpp::fill
117 //    DFBSurfaceDrawingFlags drawingFlags = color.alpha() ? DSDRAW_BLEND : DSDRAW_NOFX;
118 //    m_surface->SetDrawingFlags(m_surface, drawingFlags);
119     m_surface->SetDrawingFlags(m_surface.data(), DSDRAW_NOFX);
120     m_surface->FillRectangle(m_surface.data(), rect.x(), rect.y(),
121                               rect.width(), rect.height());
122 }
123
124 void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect)
125 {
126     QPlatformPixmap *data = pixmap.handle();
127     Q_ASSERT(data->width() && data->height());
128     Q_ASSERT(data->classId() == QPlatformPixmap::BlitterClass);
129     QBlittablePlatformPixmap *blitPm = static_cast<QBlittablePlatformPixmap*>(data);
130     QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable());
131     dfbBlitter->unlock();
132
133     IDirectFBSurface *s = dfbBlitter->m_surface.data();
134
135     DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX;
136     DFBSurfacePorterDuffRule porterDuff = DSPD_SRC;
137     if (pixmap.hasAlpha()) {
138         blittingFlags = DSBLIT_BLEND_ALPHACHANNEL;
139         porterDuff = DSPD_SRC_OVER;
140     }
141
142     m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags));
143     m_surface->SetPorterDuff(m_surface.data(), porterDuff);
144     m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
145
146     const DFBRectangle sRect = { srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height() };
147
148     DFBResult result;
149     if (rect.width() == srcRect.width() && rect.height() == srcRect.height())
150         result = m_surface->Blit(m_surface.data(), s, &sRect, rect.x(), rect.y());
151     else {
152         const DFBRectangle dRect = { rect.x(), rect.y(), rect.width(), rect.height() };
153         result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect);
154     }
155     if (result != DFB_OK)
156         DirectFBError("QDirectFBBlitter::drawPixmap()", result);
157 }
158
159 QImage *QDirectFbBlitter::doLock()
160 {
161     Q_ASSERT(m_surface);
162     Q_ASSERT(size().isValid());
163
164     void *mem;
165     int bpl;
166     const DFBResult result = m_surface->Lock(m_surface.data(), DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl);
167     if (result == DFB_OK) {
168         DFBSurfacePixelFormat dfbFormat;
169         DFBSurfaceCapabilities dfbCaps;
170         m_surface->GetPixelFormat(m_surface.data(), &dfbFormat);
171         m_surface->GetCapabilities(m_surface.data(), &dfbCaps);
172         QImage::Format format = QDirectFbConvenience::imageFormatFromSurfaceFormat(dfbFormat, dfbCaps);
173         int w, h;
174         m_surface->GetSize(m_surface.data(), &w, &h);
175         m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format);
176     } else {
177         DirectFBError("Failed to lock image", result);
178     }
179
180     return &m_image;
181 }
182
183 bool QDirectFbBlitterPlatformPixmap::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
184 {
185     DFBResult result;
186     IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
187
188     // Create a data buffer
189     QDirectFBPointer<IDirectFBDataBuffer> dataBuffer;
190     result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, dataBuffer.outPtr());
191     if (result != DFB_OK) {
192         DirectFBError(QDFB_PRETTY, result);
193         return false;
194     }
195
196     // Create the image provider
197     QDirectFBPointer<IDirectFBImageProvider> provider;
198     result = dataBuffer->CreateImageProvider(dataBuffer.data(), provider.outPtr());
199     if (result != DFB_OK) {
200         DirectFBError(QDFB_PRETTY, result);
201         return false;
202     }
203
204     // Extract image information
205     DFBImageDescription imageDescription;
206     result = provider->GetImageDescription(provider.data(), &imageDescription);
207     if (result != DFB_OK) {
208         DirectFBError(QDFB_PRETTY, result);
209         return false;
210     }
211
212     // Can we handle this directlu?
213     if (imageDescription.caps & DICAPS_COLORKEY)
214         return false;
215
216     DFBSurfaceDescription surfaceDescription;
217     result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription);
218     if (result != DFB_OK) {
219         DirectFBError(QDFB_PRETTY, result);
220         return false;
221     }
222
223     m_alpha = imageDescription.caps & DICAPS_ALPHACHANNEL;
224     resize(surfaceDescription.width, surfaceDescription.height);
225     // TODO: FIXME; update d
226
227
228     result = provider->RenderTo(provider.data(), dfbBlitter()->dfbSurface(), 0);
229     if (result != DFB_OK) {
230         DirectFBError(QDFB_PRETTY, result);
231         return false;
232     }
233
234     return true;
235 }
236
237 bool QDirectFbBlitterPlatformPixmap::fromFile(const QString &filename, const char *format,
238                                               Qt::ImageConversionFlags flags)
239 {
240     // If we can't find the file, pass it on to the base class as it is
241     // trying harder by appending various extensions to the path.
242     if (!QFile::exists(filename))
243         return QBlittablePlatformPixmap::fromFile(filename, format, flags);
244
245     // Stop if there is a requirement for colors
246     if (flags != Qt::AutoColor)
247         return QBlittablePlatformPixmap::fromFile(filename, format, flags);
248
249     // Deal with resources
250     if (filename.startsWith(QLatin1Char(':'))) { // resource
251         QFile file(filename);
252         if (!file.open(QIODevice::ReadOnly))
253             return false;
254         const QByteArray data = file.readAll();
255         file.close();
256         return fromData(reinterpret_cast<const uchar*>(data.constData()), data.size(), format, flags);
257     }
258
259     // Try to use directfb to load it.
260     DFBDataBufferDescription description;
261     description.flags = DBDESC_FILE;
262     const QByteArray fileNameData = filename.toLocal8Bit();
263     description.file = fileNameData.constData();
264     if (fromDataBufferDescription(description))
265         return true;
266
267     // Fallback
268     return QBlittablePlatformPixmap::fromFile(filename, format, flags);
269 }
270
271 void QDirectFbBlitter::doUnlock()
272 {
273     m_surface->Unlock(m_surface.data());
274 }
275
276 QT_END_NAMESPACE