Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdirectfbblitter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qdirectfbblitter.h"
6
7#include <QtGui/private/qpixmap_blitter_p.h>
8
9#include <QDebug>
10#include <QFile>
11
12#include <directfb.h>
13
15
27
28QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
30 , m_surface(surface)
31 , m_debugPaint(false)
32{
33 m_surface->AddRef(m_surface.data());
34
35 DFBSurfaceCapabilities surfaceCaps;
36 m_surface->GetCapabilities(m_surface.data(), &surfaceCaps);
37 m_premult = (surfaceCaps & DSCAPS_PREMULTIPLIED);
38 if (qEnvironmentVariableIntValue("QT_DIRECTFB_BLITTER_DEBUGPAINT"))
39 m_debugPaint = true;
40}
41
44 , m_premult(false)
45 , m_debugPaint(false)
46{
47 DFBSurfaceDescription surfaceDesc;
48 memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
49 surfaceDesc.width = rect.width();
50 surfaceDesc.height = rect.height();
51
52 // force alpha format to get AlphaFillRectCapability and ExtendedPixmapCapability support
53 alpha = true;
54
55 if (alpha) {
56 m_premult = true;
57 surfaceDesc.caps = DSCAPS_PREMULTIPLIED;
58 surfaceDesc.pixelformat = QDirectFbBlitter::alphaPixmapFormat();
59 surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT);
60 } else {
61 surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
62 surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat();
63 }
64
65 if (qEnvironmentVariableIntValue("QT_DIRECTFB_BLITTER_DEBUGPAINT"))
66 m_debugPaint = true;
67
68 IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
69 dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr());
70 m_surface->Clear(m_surface.data(), 0, 0, 0, 0);
71}
72
77
79{
80 return DSPF_ARGB;
81}
82
83DFBSurfacePixelFormat QDirectFbBlitter::pixmapFormat()
84{
85 return DSPF_RGB32;
86}
87
88DFBSurfacePixelFormat QDirectFbBlitter::selectPixmapFormat(bool withAlpha)
89{
90 return withAlpha ? alphaPixmapFormat() : pixmapFormat();
91}
92
97
102
104{
105 int x, y, w, h;
106 DFBResult result;
107
108 // check parameters
109 rect.toRect().getRect(&x, &y ,&w, &h);
110 if ((w <= 0) || (h <= 0)) return;
111
112 if ((cmode == QPainter::CompositionMode_Source) || (color.alpha() == 255)) {
113 // CompositionMode_Source case or CompositionMode_SourceOver with opaque color
114
115 m_surface->SetDrawingFlags(m_surface.data(),
116 DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_NOFX | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_NOFX));
117 m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC);
118
119 } else {
120 // CompositionMode_SourceOver case
121
122 // check if operation is useless
123 if (color.alpha() == 0)
124 return;
125
126 m_surface->SetDrawingFlags(m_surface.data(),
127 DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_BLEND));
128 m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC_OVER);
129 }
130
131 // set color
132 m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
133
134 // perform fill
135 result = m_surface->FillRectangle(m_surface.data(), x, y, w, h);
136 if (result != DFB_OK)
137 DirectFBError("QDirectFBBlitter::alphaFillRect()", result);
138 if (m_debugPaint)
139 drawDebugRect(QRect(x, y, w, h), QColor(Qt::blue));
140}
141
143{
144 QRect sQRect = subrect.toRect();
145 QRect dQRect = rect.toRect();
146 DFBRectangle sRect(sQRect.x(), sQRect.y(), sQRect.width(), sQRect.height());
147 DFBRectangle dRect(dQRect.x(), dQRect.y(), dQRect.width(), dQRect.height());
148 DFBResult result;
149
150 // skip if dst too small
151 if ((dRect.w <= 0) || (dRect.h <= 0)) return;
152
153 // correct roundings if needed
154 if (sRect.w <= 0) sRect.w = 1;
155 if (sRect.h <= 0) sRect.h = 1;
156
158 QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable());
159 dfbBlitter->unlock();
160
161 IDirectFBSurface *s = dfbBlitter->m_surface.data();
162
163 DFBSurfaceBlittingFlags blittingFlags = DFBSurfaceBlittingFlags(DSBLIT_BLEND_ALPHACHANNEL);
164 DFBSurfacePorterDuffRule porterDuff = (cmode == QPainter::CompositionMode_SourceOver) ? DSPD_SRC_OVER : DSPD_SRC;
165
166 if (opacity != 1.0)
167 {
168 blittingFlags = DFBSurfaceBlittingFlags(blittingFlags | DSBLIT_BLEND_COLORALPHA | (m_premult ? DSBLIT_SRC_PREMULTCOLOR : 0));
169 m_surface->SetColor(m_surface.data(), 0xff, 0xff, 0xff, (u8) (opacity * 255.0));
170 }
171
172 m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags));
173 m_surface->SetPorterDuff(m_surface.data(), porterDuff);
174
176 m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
177
178 if ((sRect.w == dRect.w) && (sRect.h == dRect.h)) {
179 result = m_surface->Blit(m_surface.data(), s, &sRect, dRect.x, dRect.y);
180 if (result != DFB_OK)
181 DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result);
182 if (m_debugPaint)
183 drawDebugRect(QRect(dRect.x, dRect.y, sRect.w, sRect.h), QColor(Qt::green));
184 } else {
185 result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect);
186 if (result != DFB_OK)
187 DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result);
188 if (m_debugPaint)
189 drawDebugRect(QRect(dRect.x, dRect.y, dRect.w, dRect.h), QColor(Qt::red));
190 }
191}
192
194{
196
198 static_cast<QDirectFbTextureGlyphCache *>(fontEngine->glyphCache(cacheKey, glyphFormat, state->transform()));
199 if (!cache) {
200 cache = new QDirectFbTextureGlyphCache(glyphFormat, state->transform());
201 fontEngine->setGlyphCache(cacheKey, cache);
202 }
203
204 cache->populate(fontEngine, numGlyphs, glyphs, positions);
205 cache->fillInPendingGlyphs();
206
207 if (cache->image().width() == 0 || cache->image().height() == 0)
208 return false;
209
210 const int margin = fontEngine->glyphMargin(glyphFormat);
211
212 QVarLengthArray<DFBRectangle, 64> sourceRects(numGlyphs);
213 QVarLengthArray<DFBPoint, 64> destPoints(numGlyphs);
214 int nGlyphs = 0;
215
216 for (int i=0; i<numGlyphs; ++i) {
217
218 QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x);
219 QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], QFixedPoint(subPixelPosition, 0));
220 const QTextureGlyphCache::Coord &c = cache->coords[glyph];
221 if (c.isNull())
222 continue;
223
224 int x = qFloor(positions[i].x) + c.baseLineX - margin;
225 int y = qRound(positions[i].y) - c.baseLineY - margin;
226
227 // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
228 // c.x, c.y,
229 // c.w, c.h,
230 // c.baseLineX, c.baseLineY,
231 // glyphs[i],
232 // x, y,
233 // positions[i].x.toInt(), positions[i].y.toInt());
234
235 sourceRects[nGlyphs].x = c.x;
236 sourceRects[nGlyphs].y = c.y;
237 sourceRects[nGlyphs].w = c.w;
238 sourceRects[nGlyphs].h = c.h;
239 destPoints[nGlyphs].x = x;
240 destPoints[nGlyphs].y = y;
241 ++nGlyphs;
242 }
243
244 const QColor color = state->pen().color();
245 m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
246
247 m_surface->SetSrcBlendFunction(m_surface.data(), DSBF_SRCALPHA);
248 m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
249
250 int flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
251 if (color.alpha() != 0xff)
252 flags |= DSBLIT_BLEND_COLORALPHA;
253 m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(flags));
254
255 const QRasterPaintEngineState *rs = static_cast<const QRasterPaintEngineState*>(state);
256 if (rs->clip && rs->clip->enabled) {
257 Q_ASSERT(rs->clip->hasRectClip);
258 DFBRegion dfbClip;
259 dfbClip.x1 = rs->clip->clipRect.x();
260 dfbClip.y1 = rs->clip->clipRect.y();
261 dfbClip.x2 = rs->clip->clipRect.right();
262 dfbClip.y2 = rs->clip->clipRect.bottom();
263 m_surface->SetClip(m_surface.data(), &dfbClip);
264 }
265
266 m_surface->BatchBlit(m_surface.data(), cache->sourceSurface(), sourceRects.constData(), destPoints.constData(), nGlyphs);
267
268 if (m_debugPaint) {
269 for (int i = 0; i < nGlyphs; ++i) {
270 drawDebugRect(QRect(destPoints[i].x, destPoints[i].y, sourceRects[i].w, sourceRects[i].h), QColor(Qt::yellow));
271 }
272 }
273
274 if (rs->clip && rs->clip->enabled)
275 m_surface->SetClip(m_surface.data(), 0);
276 return true;
277}
278
280{
282 Q_ASSERT(size().isValid());
283
284 void *mem;
285 int bpl;
286 const DFBResult result = m_surface->Lock(m_surface.data(), DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl);
287 if (result == DFB_OK) {
288 DFBSurfacePixelFormat dfbFormat;
289 DFBSurfaceCapabilities dfbCaps;
290 m_surface->GetPixelFormat(m_surface.data(), &dfbFormat);
291 m_surface->GetCapabilities(m_surface.data(), &dfbCaps);
293 int w, h;
294 m_surface->GetSize(m_surface.data(), &w, &h);
295 m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format);
296 } else {
297 DirectFBError("Failed to lock image", result);
298 }
299
300 return &m_image;
301}
302
303bool QDirectFbBlitterPlatformPixmap::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
304{
305 DFBResult result;
306 IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
307
308 // Create a data buffer
309 QDirectFBPointer<IDirectFBDataBuffer> dataBuffer;
310 result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, dataBuffer.outPtr());
311 if (result != DFB_OK) {
312 DirectFBError(QDFB_PRETTY, result);
313 return false;
314 }
315
316 // Create the image provider
317 QDirectFBPointer<IDirectFBImageProvider> provider;
318 result = dataBuffer->CreateImageProvider(dataBuffer.data(), provider.outPtr());
319 if (result != DFB_OK) {
320 DirectFBError(QDFB_PRETTY, result);
321 return false;
322 }
323
324 // Extract image information
325 DFBImageDescription imageDescription;
326 result = provider->GetImageDescription(provider.data(), &imageDescription);
327 if (result != DFB_OK) {
328 DirectFBError(QDFB_PRETTY, result);
329 return false;
330 }
331
332 // Can we handle this directlu?
333 if (imageDescription.caps & DICAPS_COLORKEY)
334 return false;
335
336 DFBSurfaceDescription surfaceDescription;
337 result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription);
338 if (result != DFB_OK) {
339 DirectFBError(QDFB_PRETTY, result);
340 return false;
341 }
342
343 m_alpha = imageDescription.caps & DICAPS_ALPHACHANNEL;
344 resize(surfaceDescription.width, surfaceDescription.height);
345 // TODO: FIXME; update d
346
347
348 result = provider->RenderTo(provider.data(), dfbBlitter()->dfbSurface(), 0);
349 if (result != DFB_OK) {
350 DirectFBError(QDFB_PRETTY, result);
351 return false;
352 }
353
354 return true;
355}
356
358 Qt::ImageConversionFlags flags)
359{
360 // If we can't find the file, pass it on to the base class as it is
361 // trying harder by appending various extensions to the path.
362 if (!QFile::exists(filename))
364
365 // Stop if there is a requirement for colors
366 if (flags != Qt::AutoColor)
368
369 // Deal with resources
370 if (filename.startsWith(u':'))
372
373 // Try to use directfb to load it.
374 DFBDataBufferDescription description;
375 description.flags = DBDESC_FILE;
376 const QByteArray fileNameData = filename.toLocal8Bit();
377 description.file = fileNameData.constData();
378 if (fromDataBufferDescription(description))
379 return true;
380
381 // Fallback
383}
384
386{
387 m_surface->Unlock(m_surface.data());
388}
389
390void QDirectFbBlitter::drawDebugRect(const QRect &rect, const QColor &color)
391{
392 int x, y, w, h;
393 DFBResult result;
394
395 // check parameters
396 rect.getRect(&x, &y ,&w, &h);
397 if ((w <= 0) || (h <= 0)) return;
398
399 m_surface->SetDrawingFlags(m_surface.data(),
400 DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_BLEND));
401 m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC_OVER);
402
403 // set color
404 m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 120);
405
406 result = m_surface->DrawLine(m_surface.data(), x, y, x + w-1, y);
407 if (result != DFB_OK)
408 DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
409 result = m_surface->DrawLine(m_surface.data(), x + w-1, y, x + w-1, y + h-1);
410 if (result != DFB_OK)
411 DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
412 result = m_surface->DrawLine(m_surface.data(), x + w-1, y + h-1, x, y + h-1);
413 if (result != DFB_OK)
414 DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
415 result = m_surface->DrawLine(m_surface.data(), x, y + h-1, x, y);
416 if (result != DFB_OK)
417 DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
418
419 m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 10);
420 result = m_surface->FillRectangle(m_surface.data(), x, y, w, h);
421 if (result != DFB_OK)
422 DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
423}
424
430
432{
433 if (m_surface.isNull()) {
434 const QImage &source = image();
435 DFBSurfaceDescription desc;
436 memset(&desc, 0, sizeof(desc));
437 desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED | DSDESC_CAPS);
438 desc.width = source.width();
439 desc.height = source.height();
440 desc.caps = DSCAPS_SYSTEMONLY;
441
442 switch (source.format()) {
444 desc.pixelformat = DSPF_A1;
445 break;
447 desc.pixelformat = DSPF_A8;
448 break;
449 default:
450 qFatal("QDirectFBTextureGlyphCache: Unsupported source texture image format.");
451 break;
452 }
453
454 desc.preallocated[0].data = const_cast<void*>(static_cast<const void*>(source.bits()));
455 desc.preallocated[0].pitch = source.bytesPerLine();
456 desc.preallocated[1].data = 0;
457 desc.preallocated[1].pitch = 0;
458
459 IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
460 dfb->CreateSurface(dfb , &desc, m_surface.outPtr());
461 }
462 return m_surface.data();
463}
464
void resize(int width, int height) override
QSize size() const
@ SourceOverPixmapCapability
@ DrawScaledCachedGlyphsCapability
@ SourcePixmapCapability
@ OpacityPixmapCapability
@ SolidRectCapability
@ AlphaFillRectCapability
@ SourceOverScaledPixmapCapability
void unlock()
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
bool fromFile(const QString &filename, const char *format, Qt::ImageConversionFlags flags) override
QDirectFbBlitter * dfbBlitter() const
static DFBSurfacePixelFormat selectPixmapFormat(bool withAlpha)
bool drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine) override
void alphaFillRect(const QRectF &rect, const QColor &color, QPainter::CompositionMode cmode) override
QDirectFbBlitter(const QSize &size, IDirectFBSurface *surface)
static DFBSurfacePixelFormat pixmapFormat()
QImage * doLock() override
QDirectFBPointer< IDirectFBSurface > m_surface
void drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity) override
static DFBSurfacePixelFormat alphaPixmapFormat()
void doUnlock() override
void fillRect(const QRectF &rect, const QColor &color) override
void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect) override
static QImage::Format imageFormatFromSurfaceFormat(const DFBSurfacePixelFormat format, const DFBSurfaceCapabilities caps)
static IDirectFB * dfbInterface()
void resizeTextureData(int width, int height) override
IDirectFBSurface * sourceSurface()
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
void setGlyphCache(const void *key, QFontEngineGlyphCache *data)
virtual int glyphMargin(GlyphFormat format)
QFixed subPixelPositionForX(QFixed x) const
QFontEngineGlyphCache * glyphCache(const void *key, GlyphFormat format, const QTransform &transform, const QColor &color=QColor()) const
virtual void resizeTextureData(int width, int height) override
const QImage & image() const
\inmodule QtGui
Definition qimage.h:37
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_Alpha8
Definition qimage.h:65
@ Format_Mono
Definition qimage.h:43
The QPaintEngineState class provides information about the active paint engine's current state....
CompositionMode
Defines the modes supported for digital image compositing.
Definition qpainter.h:97
@ CompositionMode_SourceOver
Definition qpainter.h:98
@ CompositionMode_Source
Definition qpainter.h:101
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
virtual bool fromFile(const QString &filename, const char *format, Qt::ImageConversionFlags flags)
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
T * data() const noexcept
Returns the value of the pointer referenced by this object.
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
QByteArray toLocal8Bit() const &
Definition qstring.h:638
QCache< int, Employee > cache
[0]
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
@ AutoColor
Definition qnamespace.h:478
@ blue
Definition qnamespace.h:37
@ yellow
Definition qnamespace.h:40
@ green
Definition qnamespace.h:36
@ red
Definition qnamespace.h:35
static const QCssKnownValue positions[NumKnownPositionModes - 1]
static QT_BEGIN_NAMESPACE QBlittable::Capabilities dfb_blitter_capabilities()
#define QDFB_PRETTY
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
static QByteArray cacheKey(Args &&...args)
#define qFatal
Definition qlogging.h:168
int qFloor(T v)
Definition qmath.h:42
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum const void GLbitfield GLsizei numGlyphs
GLint GLsizei width
GLuint color
[2]
GLbitfield flags
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint64EXT * result
[6]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
unsigned int glyph_t
unsigned char uchar
Definition qtypes.h:32
double qreal
Definition qtypes.h:187
widget render & pixmap