summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp694
1 files changed, 470 insertions, 224 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 1844c0d..8be0355 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -56,21 +56,29 @@
class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem
{
+ Q_OBJECT
public:
QDirectFBScreenPrivate(QDirectFBScreen *qptr);
~QDirectFBScreenPrivate();
void setFlipFlags(const QStringList &args);
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
-
+public slots:
+#ifdef QT_DIRECTFB_WM
+ void onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event);
+#endif
+public:
IDirectFB *dfb;
- IDirectFBSurface *dfbSurface;
DFBSurfaceFlipFlags flipFlags;
+ QDirectFBScreen::DirectFBFlags directFBFlags;
+ QImage::Format alphaPixmapFormat;
+ IDirectFBScreen *dfbScreen;
+#ifdef QT_NO_DIRECTFB_WM
+ IDirectFBSurface *primarySurface;
+#endif
#ifndef QT_NO_DIRECTFB_LAYER
IDirectFBDisplayLayer *dfbLayer;
#endif
- IDirectFBScreen *dfbScreen;
-
QSet<IDirectFBSurface*> allocatedSurfaces;
#ifndef QT_NO_DIRECTFB_MOUSE
@@ -79,31 +87,43 @@ public:
#ifndef QT_NO_DIRECTFB_KEYBOARD
QDirectFBKeyboardHandler *keyboard;
#endif
- QDirectFBScreen::DirectFBFlags directFBFlags;
- QImage::Format alphaPixmapFormat;
+#if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+ IDirectFBImageProvider *imageProvider;
+#endif
QColor backgroundColor;
QDirectFBScreen *q;
};
+#include "qdirectfbscreen.moc"
+
QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *qptr)
- : QWSGraphicsSystem(qptr), dfb(0), dfbSurface(0), flipFlags(DSFLIP_NONE)
+ : QWSGraphicsSystem(qptr), dfb(0), flipFlags(DSFLIP_NONE),
+ directFBFlags(QDirectFBScreen::NoFlags), alphaPixmapFormat(QImage::Format_Invalid),
+ dfbScreen(0)
+#ifdef QT_NO_DIRECTFB_WM
+ , primarySurface(0)
+#endif
#ifndef QT_NO_DIRECTFB_LAYER
, dfbLayer(0)
#endif
- , dfbScreen(0)
#ifndef QT_NO_DIRECTFB_MOUSE
, mouse(0)
#endif
#ifndef QT_NO_DIRECTFB_KEYBOARD
, keyboard(0)
#endif
- , directFBFlags(QDirectFBScreen::NoFlags)
- , alphaPixmapFormat(QImage::Format_Invalid)
+#if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+ , imageProvider(0)
+#endif
, q(qptr)
{
#ifndef QT_NO_QWS_SIGNALHANDLER
QWSSignalHandler::instance()->addObject(this);
#endif
+#ifdef QT_DIRECTFB_WM
+ connect(QWSServer::instance(), SIGNAL(windowEvent(QWSWindow*, QWSServer::WindowEvent)),
+ this, SLOT(onWindowEvent(QWSWindow*, QWSServer::WindowEvent)));
+#endif
}
QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
@@ -114,13 +134,19 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
#ifndef QT_NO_DIRECTFB_KEYBOARD
delete keyboard;
#endif
+#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+ if (imageProvider)
+ imageProvider->Release(imageProvider);
+#endif
for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) {
(*it)->Release(*it);
}
- if (dfbSurface)
- dfbSurface->Release(dfbSurface);
+#ifdef QT_NO_DIRECTFB_WM
+ if (primarySurface)
+ primarySurface->Release(primarySurface);
+#endif
#ifndef QT_NO_DIRECTFB_LAYER
if (dfbLayer)
@@ -134,64 +160,77 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
dfb->Release(dfb);
}
-
-
-// creates a preallocated surface with the same format as the image if
-// possible.
-
-IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCreationOptions options)
+IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &image, QImage::Format format, SurfaceCreationOptions options, DFBResult *resultPtr)
{
- if (img.isNull()) // assert?
+ if (image.isNull()) // assert?
return 0;
- if (QDirectFBScreen::getSurfacePixelFormat(img.format()) == DSPF_UNKNOWN) {
- QImage image = img.convertToFormat(img.hasAlphaChannel()
- ? d_ptr->alphaPixmapFormat
- : pixelFormat());
- IDirectFBSurface *tmp = createDFBSurface(image, false);
- if (!tmp) {
- qWarning("Couldn't create surface createDFBSurface(QImage, bool)");
- return 0;
- }
- IDirectFBSurface *surface = copyDFBSurface(tmp, image.format(), options);
- tmp->Release(tmp);
- return surface;
+ if (QDirectFBScreen::getSurfacePixelFormat(format) == DSPF_UNKNOWN) {
+ format = QDirectFBPixmapData::hasAlphaChannel(image) ? d_ptr->alphaPixmapFormat : pixelFormat();
+ }
+ if (image.format() != format) {
+ return createDFBSurface(image.convertToFormat(format), format, options | NoPreallocated, resultPtr);
}
- IDirectFBSurface *surface = createDFBSurface(QDirectFBScreen::getSurfaceDescription(img), options);
-#ifdef QT_NO_DIRECTFB_PREALLOCATED
- if (surface) {
- int bpl;
- uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bpl);
+ DFBSurfaceDescription description;
+ memset(&description, 0, sizeof(DFBSurfaceDescription));
+ description.width = image.width();
+ description.height = image.height();
+ description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT;
+ initSurfaceDescriptionPixelFormat(&description, format);
+ bool doMemCopy = true;
+#ifdef QT_DIRECTFB_PREALLOCATED
+ if (!(options & NoPreallocated)) {
+ doMemCopy = false;
+ description.flags |= DSDESC_PREALLOCATED;
+ description.preallocated[0].data = const_cast<uchar*>(image.bits());
+ description.preallocated[0].pitch = image.bytesPerLine();
+ description.preallocated[1].data = 0;
+ description.preallocated[1].pitch = 0;
+ }
+#endif
+ DFBResult result;
+ IDirectFBSurface *surface = createDFBSurface(description, options, &result);
+ if (resultPtr)
+ *resultPtr = result;
+ if (!surface) {
+ DirectFBError("Couldn't create surface createDFBSurface(QImage, QImage::Format, SurfaceCreationOptions)", result);
+ return 0;
+ }
+ if (doMemCopy) {
+ int bplDFB;
+ uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bplDFB);
if (mem) {
- const int h = img.height();
- const int w = img.width() * img.depth() / 8;
- for (int i = 0; i < h; ++i) {
- memcpy(mem, img.scanLine(i), w);
- mem += bpl;
+ const int height = image.height();
+ const int bplQt = image.bytesPerLine();
+ if (bplQt == bplDFB && bplQt == (image.width() * image.depth() / 8)) {
+ memcpy(mem, image.bits(), image.numBytes());
+ } else {
+ for (int i=0; i<height; ++i) {
+ memcpy(mem, image.scanLine(i), bplQt);
+ mem += bplDFB;
+ }
}
surface->Unlock(surface);
}
}
-#endif
-#ifndef QT_NO_DIRECTFB_PALETTE
- if (img.numColors() != 0 && surface)
- QDirectFBScreen::setSurfaceColorTable(surface, img);
+#ifdef QT_DIRECTFB_PALETTE
+ if (image.numColors() != 0 && surface)
+ QDirectFBScreen::setSurfaceColorTable(surface, image);
#endif
return surface;
}
IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
QImage::Format format,
- SurfaceCreationOptions options)
+ SurfaceCreationOptions options,
+ DFBResult *result)
{
Q_ASSERT(src);
QSize size;
src->GetSize(src, &size.rwidth(), &size.rheight());
- IDirectFBSurface *surface = createDFBSurface(size, format, options);
- DFBSurfacePixelFormat dspf;
- src->GetPixelFormat(src, &dspf);
- DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlpha(dspf)
+ IDirectFBSurface *surface = createDFBSurface(size, format, options, result);
+ DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlphaChannel(surface)
? DSBLIT_BLEND_ALPHACHANNEL
: DSBLIT_NOFX;
if (flags & DSBLIT_BLEND_ALPHACHANNEL)
@@ -207,7 +246,8 @@ IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size,
QImage::Format format,
- SurfaceCreationOptions options)
+ SurfaceCreationOptions options,
+ DFBResult *result)
{
DFBSurfaceDescription desc;
memset(&desc, 0, sizeof(DFBSurfaceDescription));
@@ -216,12 +256,14 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size,
return 0;
desc.width = size.width();
desc.height = size.height();
- return createDFBSurface(desc, options);
+ return createDFBSurface(desc, options, result);
}
-IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options)
+IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options, DFBResult *resultPtr)
{
- DFBResult result = DFB_OK;
+ DFBResult tmp;
+ DFBResult &result = (resultPtr ? *resultPtr : tmp);
+ result = DFB_OK;
IDirectFBSurface *newSurface = 0;
if (!d_ptr->dfb) {
@@ -283,68 +325,6 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc,
return newSurface;
}
-IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img,
- QImage::Format pixmapFormat,
- SurfaceCreationOptions options)
-{
- QImage image = img;
- if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN
-#ifdef QT_NO_DIRECTFB_PREALLOCATED
- || image.format() != pixmapFormat
-#endif
-#ifdef QT_NO_DIRECTFB_PALETTE
- || image.numColors() != 0
-#endif
- ) {
- image = image.convertToFormat(pixmapFormat);
- }
-
- IDirectFBSurface *dfbSurface = createDFBSurface(image.size(), pixmapFormat, options);
- if (!dfbSurface) {
- qWarning("QDirectFBScreen::copyToDFBSurface() Couldn't create surface");
- return 0;
- }
-
-#ifndef QT_NO_DIRECTFB_PREALLOCATED
- IDirectFBSurface *imgSurface = createDFBSurface(image, DontTrackSurface);
- if (!imgSurface) {
- qWarning("QDirectFBScreen::copyToDFBSurface()");
- QDirectFBScreen::releaseDFBSurface(dfbSurface);
- return 0;
- }
-
- Q_ASSERT(imgSurface);
- DFBSurfaceBlittingFlags flags = img.hasAlphaChannel()
- ? DSBLIT_BLEND_ALPHACHANNEL
- : DSBLIT_NOFX;
- if (flags & DSBLIT_BLEND_ALPHACHANNEL)
- dfbSurface->Clear(dfbSurface, 0, 0, 0, 0);
-
- dfbSurface->SetBlittingFlags(dfbSurface, flags);
- DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0);
- if (result != DFB_OK)
- DirectFBError("QDirectFBScreen::copyToDFBSurface()", result);
- imgSurface->Release(imgSurface);
-#if (Q_DIRECTFB_VERSION >= 0x010000)
- dfbSurface->ReleaseSource(dfbSurface);
-#endif
-#else // QT_NO_DIRECTFB_PREALLOCATED
- Q_ASSERT(image.format() == pixmapFormat);
- int bpl;
- uchar *mem = QDirectFBScreen::lockSurface(dfbSurface, DSLF_WRITE, &bpl);
- if (mem) {
- const int h = image.height();
- const int w = image.width() * image.depth() / 8;
- for (int i=0; i<h; ++i) {
- memcpy(mem, image.scanLine(i), w);
- mem += bpl;
- }
- dfbSurface->Unlock(dfbSurface);
- }
-#endif
- return dfbSurface;
-}
-
void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface)
{
Q_ASSERT(QDirectFBScreen::instance());
@@ -366,10 +346,12 @@ IDirectFB *QDirectFBScreen::dfb()
return d_ptr->dfb;
}
-IDirectFBSurface *QDirectFBScreen::dfbSurface()
+#ifdef QT_NO_DIRECTFB_WM
+IDirectFBSurface *QDirectFBScreen::primarySurface()
{
- return d_ptr->dfbSurface;
+ return d_ptr->primarySurface;
}
+#endif
#ifndef QT_NO_DIRECTFB_LAYER
IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer()
@@ -456,36 +438,6 @@ QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface)
return QImage::Format_Invalid;
}
-DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image)
-{
- DFBSurfaceDescription description;
- memset(&description, 0, sizeof(DFBSurfaceDescription));
-
- const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format());
-
- if (format == DSPF_UNKNOWN || image.isNull()) {
- description.flags = DSDESC_NONE;
- return description;
- }
-
- description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT;
- QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, image.format());
- description.width = image.width();
- description.height = image.height();
-#ifndef QT_NO_DIRECTFB_PREALLOCATED
- description.flags |= DSDESC_PREALLOCATED;
- description.preallocated[0].data = (void*)(image.bits());
- description.preallocated[0].pitch = image.bytesPerLine();
- description.preallocated[1].data = 0;
- description.preallocated[1].pitch = 0;
-#endif
-
- if (QDirectFBScreen::isPremultiplied(image.format()))
- description.caps = DSCAPS_PREMULTIPLIED;
-
- return description;
-}
-
DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer,
int length)
{
@@ -501,7 +453,7 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer,
description.preallocated[0].pitch = length * sizeof(uint);
description.preallocated[1].data = 0;
description.preallocated[1].pitch = 0;
-return description;
+ return description;
}
#ifndef QT_NO_DIRECTFB_PALETTE
@@ -542,7 +494,15 @@ void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface,
#endif // QT_NO_DIRECTFB_PALETTE
-#if !defined(QT_NO_DIRECTFB_LAYER) && !defined(QT_NO_QWS_CURSOR)
+#ifndef QT_NO_QWS_CURSOR
+#if defined QT_DIRECTFB_WM && defined QT_DIRECTFB_WINDOW_AS_CURSOR
+#define QT_DIRECTFB_CURSOR
+#elif defined QT_DIRECTFB_LAYER
+#define QT_DIRECTFB_CURSOR
+#endif
+#endif
+
+#if defined QT_DIRECTFB_CURSOR
class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor
{
public:
@@ -552,6 +512,11 @@ public:
virtual void show();
virtual void hide();
private:
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+ ~QDirectFBScreenCursor();
+ bool createWindow();
+ IDirectFBWindow *window;
+#endif
IDirectFBDisplayLayer *layer;
};
@@ -567,11 +532,95 @@ QDirectFBScreenCursor::QDirectFBScreenCursor()
enable = false;
hwaccel = true;
supportsAlpha = true;
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+ window = 0;
+ DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to set cooperative level", result);
+ }
+ result = layer->SetCursorOpacity(layer, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to set cursor opacity", result);
+ }
+
+ result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to set cooperative level", result);
+ }
+#endif
+}
+
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+QDirectFBScreenCursor::~QDirectFBScreenCursor()
+{
+ if (window) {
+ window->Release(window);
+ window = 0;
+ }
+}
+
+bool QDirectFBScreenCursor::createWindow()
+{
+ Q_ASSERT(!window);
+ Q_ASSERT(!cursor.isNull());
+ DFBWindowDescription description;
+ memset(&description, 0, sizeof(DFBWindowDescription));
+ description.flags = DWDESC_POSX|DWDESC_POSY|DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|DWDESC_OPTIONS|DWDESC_PIXELFORMAT|DWDESC_SURFACE_CAPS;
+ description.width = cursor.width();
+ description.height = cursor.height();
+ description.posx = pos.x() - hotspot.x();
+ description.posy = pos.y() - hotspot.y();
+ description.options = DWOP_GHOST|DWOP_ALPHACHANNEL;
+ description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER;
+ const QImage::Format format = QDirectFBScreen::instance()->alphaPixmapFormat();
+ description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
+ if (QDirectFBScreen::isPremultiplied(format))
+ description.surface_caps = DSCAPS_PREMULTIPLIED;
+
+ DFBResult result = layer->CreateWindow(layer, &description, &window);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::createWindow: Unable to create window", result);
+ return false;
+ }
+ result = window->SetOpacity(window, 255);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set opacity ", result);
+ return false;
+ }
+
+ result = window->SetStackingClass(window, DWSC_UPPER);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set stacking class ", result);
+ return false;
+ }
+
+ result = window->RaiseToTop(window);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::createWindow: Unable to raise window ", result);
+ return false;
+ }
+
+ return true;
}
+#endif
void QDirectFBScreenCursor::move(int x, int y)
{
+ pos = QPoint(x, y);
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+ if (window) {
+ const QPoint p = pos - hotspot;
+ DFBResult result = window->MoveTo(window, p.x(), p.y());
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::move: Unable to move window", result);
+ }
+ }
+#else
layer->WarpCursor(layer, x, y);
+#endif
}
void QDirectFBScreenCursor::hide()
@@ -579,6 +628,7 @@ void QDirectFBScreenCursor::hide()
if (enable) {
enable = false;
DFBResult result;
+#ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if (result != DFB_OK) {
DirectFBError("QDirectFBScreenCursor::hide: "
@@ -594,6 +644,15 @@ void QDirectFBScreenCursor::hide()
DirectFBError("QDirectFBScreenCursor::hide: "
"Unable to set cooperative level", result);
}
+#else
+ if (window) {
+ result = window->SetOpacity(window, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to set window opacity", result);
+ }
+ }
+#endif
}
}
@@ -607,7 +666,13 @@ void QDirectFBScreenCursor::show()
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cooperative level", result);
}
- result = layer->SetCursorOpacity(layer, 255);
+ result = layer->SetCursorOpacity(layer,
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+ 0
+#else
+ 255
+#endif
+ );
if (result != DFB_OK) {
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cursor shape", result);
@@ -617,6 +682,15 @@ void QDirectFBScreenCursor::show()
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cooperative level", result);
}
+#ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
+ if (window) {
+ DFBResult result = window->SetOpacity(window, 255);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::show: "
+ "Unable to set window opacity", result);
+ }
+ }
+#endif
}
}
@@ -633,12 +707,15 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
cursor = image.convertToFormat(screen->alphaPixmapFormat());
size = cursor.size();
hotspot = QPoint(hotx, hoty);
- IDirectFBSurface *surface = screen->createDFBSurface(cursor, QDirectFBScreen::DontTrackSurface);
+ DFBResult result = DFB_OK;
+ IDirectFBSurface *surface = screen->createDFBSurface(cursor, screen->alphaPixmapFormat(),
+ QDirectFBScreen::DontTrackSurface, &result);
if (!surface) {
- qWarning("QDirectFBScreenCursor::set: Unable to create surface");
+ DirectFBError("QDirectFBScreenCursor::set: Unable to create surface", result);
return;
}
- DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+#ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
+ result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if (result != DFB_OK) {
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cooperative level", result);
@@ -648,17 +725,53 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cursor shape", result);
}
- surface->Release(surface);
result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
if (result != DFB_OK) {
DirectFBError("QDirectFBScreenCursor::show: "
"Unable to set cooperative level", result);
}
+#else
+ if (window || createWindow()) {
+ QSize windowSize;
+ result = window->GetSize(window, &windowSize.rwidth(), &windowSize.rheight());
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: "
+ "Unable to get window size", result);
+ }
+ result = window->Resize(window, size.width(), size.height());
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to resize window", result);
+ }
+
+ IDirectFBSurface *windowSurface;
+ result = window->GetSurface(window, &windowSurface);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to get window surface", result);
+ } else {
+ result = windowSurface->Clear(windowSurface, 0, 0, 0, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to clear surface", result);
+ }
+
+ result = windowSurface->Blit(windowSurface, surface, 0, 0, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to blit to surface", result);
+ }
+ }
+ result = windowSurface->Flip(windowSurface, 0, DSFLIP_NONE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to flip window", result);
+ }
+
+ windowSurface->Release(windowSurface);
+ }
+#endif
+ surface->Release(surface);
show();
}
}
-#endif // QT_NO_DIRECTFB_LAYER
+#endif // QT_DIRECTFB_CURSOR
QDirectFBScreen::QDirectFBScreen(int display_id)
: QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this))
@@ -713,6 +826,42 @@ int QDirectFBScreen::depth(DFBSurfacePixelFormat format)
return 0;
}
+int QDirectFBScreen::depth(QImage::Format format)
+{
+ int depth = 0;
+ switch(format) {
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ Q_ASSERT(false);
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ depth = 1;
+ break;
+ case QImage::Format_Indexed8:
+ depth = 8;
+ break;
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ depth = 32;
+ break;
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB444:
+ case QImage::Format_ARGB4444_Premultiplied:
+ depth = 16;
+ break;
+ case QImage::Format_RGB666:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_RGB888:
+ depth = 24;
+ break;
+ }
+ return depth;
+}
+
void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
{
QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$"));
@@ -739,6 +888,18 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
}
}
+#ifdef QT_DIRECTFB_WM
+void QDirectFBScreenPrivate::onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event)
+{
+ if (event == QWSServer::Raise) {
+ QWSWindowSurface *windowSurface = window->windowSurface();
+ if (windowSurface && windowSurface->key() == QLatin1String("directfb")) {
+ static_cast<QDirectFBWindowSurface*>(windowSurface)->raise();
+ }
+ }
+}
+#endif
+
QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const
{
if (type == QPixmapData::BitmapType)
@@ -747,6 +908,7 @@ QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ
return new QDirectFBPixmapData(q, type);
}
+#if (Q_DIRECTFB_VERSION >= 0x000923)
#ifdef QT_NO_DEBUG
struct FlagDescription;
static const FlagDescription *accelerationDescriptions = 0;
@@ -804,9 +966,6 @@ static const FlagDescription drawDescriptions[] = {
};
#endif
-
-
-#if (Q_DIRECTFB_VERSION >= 0x000923)
static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags)
{
#ifdef QT_NO_DEBUG
@@ -865,6 +1024,36 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var
return false;
}
+static inline int depth(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ return 1;
+ case QImage::Format_Indexed8:
+ return 8;
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ return 32;
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_RGB666:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_RGB888:
+ return 24;
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB16:
+ case QImage::Format_ARGB4444_Premultiplied:
+ return 16;
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
+ }
+ return -1;
+}
+
bool QDirectFBScreen::connect(const QString &displaySpec)
{
DFBResult result = DFB_OK;
@@ -925,7 +1114,9 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
DFBSurfaceDescription description;
memset(&description, 0, sizeof(DFBSurfaceDescription));
+ IDirectFBSurface *surface;
+#ifdef QT_NO_DIRECTFB_WM
description.flags = DSDESC_CAPS;
if (::setIntOption(displayArgs, QLatin1String("width"), &description.width))
description.flags |= DSDESC_WIDTH;
@@ -954,17 +1145,28 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
}
// We don't track the primary surface as it's released in disconnect
- d_ptr->dfbSurface = createDFBSurface(description, DontTrackSurface);
- if (!d_ptr->dfbSurface) {
+ d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result);
+ if (!d_ptr->primarySurface) {
DirectFBError("QDirectFBScreen: error creating primary surface",
result);
return false;
}
+ surface = d_ptr->primarySurface;
+#else
+ description.flags = DSDESC_WIDTH|DSDESC_HEIGHT;
+ description.width = description.height = 1;
+ surface = createDFBSurface(description, DontTrackSurface, &result);
+ if (!surface) {
+ DirectFBError("QDirectFBScreen: error creating surface", result);
+ return false;
+ }
+#endif
// Work out what format we're going to use for surfaces with an alpha channel
- d_ptr->alphaPixmapFormat = QDirectFBScreen::getImageFormat(d_ptr->dfbSurface);
- setPixelFormat(d_ptr->alphaPixmapFormat);
- switch (d_ptr->alphaPixmapFormat) {
+ QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface);
+ d_ptr->alphaPixmapFormat = pixelFormat;
+
+ switch (pixelFormat) {
case QImage::Format_RGB666:
d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied;
break;
@@ -972,9 +1174,9 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied;
break;
case QImage::Format_RGB32:
- qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the RGB32 pixelformat. "
- "We recommmend using ARGB instead");
- return false;
+ pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
+ // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps
+ break;
case QImage::Format_Indexed8:
qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8 pixelformat.");
return false;
@@ -996,31 +1198,11 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
// works already
break;
}
- d_ptr->dfbSurface->GetSize(d_ptr->dfbSurface, &w, &h);
-
+ setPixelFormat(pixelFormat);
+ QScreen::d = ::depth(pixelFormat);
data = 0;
lstep = 0;
size = 0;
- dw = w;
- dh = h;
-
- DFBSurfacePixelFormat format;
- result = d_ptr->dfbSurface->GetPixelFormat(d_ptr->dfbSurface, &format);
- if (result == DFB_OK)
- QScreen::d = depth(format);
- else
- DirectFBError("QDirectFBScreen: error getting surface format", result);
-
- setPixelFormat(getImageFormat(d_ptr->dfbSurface));
-
- physWidth = physHeight = -1;
- ::setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth);
- ::setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight);
- const int dpi = 72;
- if (physWidth < 0)
- physWidth = qRound(dw * 25.4 / dpi);
- if (physHeight < 0)
- physHeight = qRound(dh * 25.4 / dpi);
#ifndef QT_NO_DIRECTFB_LAYER
result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, DLID_PRIMARY,
@@ -1039,12 +1221,35 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
"Unable to get screen!", result);
return false;
}
+ result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::connect: "
+ "Unable to get screen size!", result);
+ return false;
+ }
+
+ dw = w;
+ dh = h;
+
+ Q_ASSERT(dw != 0 && dh != 0);
+
+ physWidth = physHeight = -1;
+ ::setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth);
+ ::setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight);
+ const int dpi = 72;
+ if (physWidth < 0)
+ physWidth = qRound(dw * 25.4 / dpi);
+ if (physHeight < 0)
+ physHeight = qRound(dh * 25.4 / dpi);
setGraphicsSystem(d_ptr);
#if (Q_DIRECTFB_VERSION >= 0x000923)
if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
- printDirectFBInfo(d_ptr->dfb, d_ptr->dfbSurface);
+ printDirectFBInfo(d_ptr->dfb, surface);
+#endif
+#ifndef QT_NO_DIRECTFB_WM
+ surface->Release(surface);
#endif
QRegExp backgroundColorRegExp("bgcolor=?(.+)");
@@ -1060,8 +1265,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
void QDirectFBScreen::disconnect()
{
- d_ptr->dfbSurface->Release(d_ptr->dfbSurface);
- d_ptr->dfbSurface = 0;
+#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+ if (d_ptr->imageProvider)
+ d_ptr->imageProvider->Release(d_ptr->imageProvider);
+#endif
+#ifdef QT_NO_DIRECTFB_WM
+ d_ptr->primarySurface->Release(d_ptr->primarySurface);
+ d_ptr->primarySurface = 0;
+#endif
foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces)
surf->Release(surf);
@@ -1157,25 +1368,9 @@ QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const
// QT_NO_DIRECTFB_WM isn't set), exposeRegion will simply return. If
// QT_NO_DIRECTFB_WM is set, exposeRegion will compose only non-directFB
// window surfaces. Normal, directFB surfaces are handled by DirectFB.
-static inline bool needExposeRegion()
-{
-#ifdef QT_NO_DIRECTFB_WM
- return true;
-#endif
-#ifdef QT_NO_DIRECTFB_LAYER
-#ifndef QT_NO_QWS_CURSOR
- return true;
-#endif
-#endif
- return false;
-}
-
void QDirectFBScreen::exposeRegion(QRegion r, int changing)
{
- if (!needExposeRegion()) {
- return;
- }
-
+#ifdef QT_NO_DIRECTFB_WM
const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
if (changing < 0 || changing >= windows.size())
return;
@@ -1209,9 +1404,9 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing)
const DFBRectangle rect = {
source.x(), source.y(), source.width(), source.height()
};
- d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, &rect,
- windowGeometry.x() + source.x(),
- windowGeometry.y() + source.y());
+ d_ptr->primarySurface->Blit(d_ptr->primarySurface, surface, &rect,
+ windowGeometry.x() + source.x(),
+ windowGeometry.y() + source.y());
} else {
const QVector<QRect> rects = insideWindow.rects();
QVarLengthArray<DFBRectangle, 16> dfbRectangles(n);
@@ -1227,8 +1422,8 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing)
dfbPoints[i].x = (windowGeometry.x() + source.x());
dfbPoints[i].y = (windowGeometry.y() + source.y());
}
- d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, surface, dfbRectangles.constData(),
- dfbPoints.constData(), n);
+ d_ptr->primarySurface->BatchBlit(d_ptr->primarySurface, surface, dfbRectangles.constData(),
+ dfbPoints.constData(), n);
}
}
}
@@ -1238,30 +1433,38 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing)
const QRect cursorRectangle = cursor->boundingRect();
if (cursor->isVisible() && !cursor->isAccelerated() && cursorRectangle.intersects(brect)) {
const QImage image = cursor->image();
- IDirectFBSurface *surface = createDFBSurface(image, QDirectFBScreen::DontTrackSurface);
- d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_BLEND_ALPHACHANNEL);
- d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, 0, cursorRectangle.x(), cursorRectangle.y());
+ IDirectFBSurface *surface = createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface);
+ d_ptr->primarySurface->SetBlittingFlags(d_ptr->primarySurface, DSBLIT_BLEND_ALPHACHANNEL);
+ d_ptr->primarySurface->Blit(d_ptr->primarySurface, surface, 0, cursorRectangle.x(), cursorRectangle.y());
surface->Release(surface);
#if (Q_DIRECTFB_VERSION >= 0x010000)
- d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface);
+ d_ptr->primarySurface->ReleaseSource(d_ptr->primarySurface);
#endif
}
}
- flipSurface(d_ptr->dfbSurface, d_ptr->flipFlags, r, QPoint());
+ flipSurface(d_ptr->primarySurface, d_ptr->flipFlags, r, QPoint());
+#else
+ Q_UNUSED(r);
+ Q_UNUSED(changing);
+#endif
}
void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
{
+#ifdef QT_DIRECTFB_WM
+ Q_UNUSED(color);
+ Q_UNUSED(region);
+#else
if (region.isEmpty())
return;
- d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface,
+ d_ptr->primarySurface->SetColor(d_ptr->primarySurface,
color.red(), color.green(), color.blue(),
color.alpha());
const int n = region.numRects();
if (n > 1) {
const QRect r = region.boundingRect();
- d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, r.x(), r.y(), r.width(), r.height());
+ d_ptr->primarySurface->FillRectangle(d_ptr->primarySurface, r.x(), r.y(), r.width(), r.height());
} else {
const QVector<QRect> rects = region.rects();
QVarLengthArray<DFBRectangle, 32> rectArray(n);
@@ -1272,8 +1475,9 @@ void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
rectArray[i].w = r.width();
rectArray[i].h = r.height();
}
- d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, rectArray.constData(), n);
+ d_ptr->primarySurface->FillRectangles(d_ptr->primarySurface, rectArray.constData(), n);
}
+#endif
}
void QDirectFBScreen::erase(const QRegion &region)
@@ -1305,10 +1509,10 @@ bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *d
return true;
}
-uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int *bpl)
+uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl)
{
void *mem;
- const DFBResult result = surface->Lock(surface, static_cast<DFBSurfaceLockFlags>(flags), static_cast<void**>(&mem), bpl);
+ const DFBResult result = surface->Lock(surface, flags, &mem, bpl);
if (result != DFB_OK) {
DirectFBError("QDirectFBScreen::lockSurface()", result);
}
@@ -1343,4 +1547,46 @@ void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags
}
}
+#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider)
+{
+ Q_ASSERT(provider);
+ if (d_ptr->imageProvider)
+ d_ptr->imageProvider->Release(d_ptr->imageProvider);
+ d_ptr->imageProvider = provider;
+}
+#endif
+
+IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const
+{
+ Q_ASSERT(widget);
+ if (!widget->isVisible() || widget->size().isNull())
+ return 0;
+
+ const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
+ if (surface && surface->key() == QLatin1String("directfb")) {
+ return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect);
+ }
+ return 0;
+}
+
+IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const
+{
+ Q_ASSERT(widget);
+ QRect rect;
+ IDirectFBSurface *surface = surfaceForWidget(widget, &rect);
+ IDirectFBSurface *subSurface = 0;
+ if (surface) {
+ if (!area.isNull())
+ rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0)));
+ if (!rect.isNull()) {
+ const DFBRectangle subRect = {rect.x(), rect.y(), rect.width(), rect.height() };
+ const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result);
+ }
+ }
+ }
+ return subSurface;
+}