summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/directfb')
-rw-r--r--src/plugins/gfxdrivers/directfb/directfb.pro40
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp321
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.h69
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp272
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbmouse.h73
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp196
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h83
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp1261
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h114
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp363
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h83
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp1064
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.h136
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreenplugin.cpp75
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp393
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbsurface.h102
16 files changed, 4645 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro
new file mode 100644
index 0000000..96eb536
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/directfb.pro
@@ -0,0 +1,40 @@
+TARGET = qdirectfbscreen
+include(../../qpluginbase.pri)
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers
+
+# These defines might be necessary if your DirectFB driver doesn't
+# support all of the DirectFB API.
+#
+#DEFINES += QT_NO_DIRECTFB_WM
+#DEFINES += QT_NO_DIRECTFB_LAYER
+#DEFINES += QT_NO_DIRECTFB_PALETTE
+#DEFINES += QT_NO_DIRECTFB_PREALLOCATED
+#DEFINES += QT_NO_DIRECTFB_MOUSE
+#DEFINES += QT_NO_DIRECTFB_KEYBOARD
+
+target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers
+INSTALLS += target
+
+HEADERS = \
+ qdirectfbscreen.h \
+ qdirectfbsurface.h \
+ qdirectfbpaintengine.h \
+ qdirectfbpaintdevice.h \
+ qdirectfbpixmap.h \
+ qdirectfbkeyboard.h \
+ qdirectfbmouse.h
+
+SOURCES = \
+ qdirectfbscreen.cpp \
+ qdirectfbscreenplugin.cpp \
+ qdirectfbsurface.cpp \
+ qdirectfbpaintengine.cpp \
+ qdirectfbpaintdevice.cpp \
+ qdirectfbpixmap.cpp \
+ qdirectfbkeyboard.cpp \
+ qdirectfbmouse.cpp
+
+QMAKE_CXXFLAGS += $$QT_CFLAGS_DIRECTFB
+LIBS += $$QT_LIBS_DIRECTFB
+
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp
new file mode 100644
index 0000000..cd19f69
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbkeyboard.h"
+
+#ifndef QT_NO_DIRECTFB
+
+#include "qdirectfbscreen.h"
+#include <qobject.h>
+#include <qsocketnotifier.h>
+#include <qhash.h>
+
+#include <directfb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+class KeyMap : public QHash<DFBInputDeviceKeySymbol, Qt::Key>
+{
+public:
+ KeyMap();
+};
+
+Q_GLOBAL_STATIC(KeyMap, keymap);
+
+class QDirectFBKeyboardHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QDirectFBKeyboardHandlerPrivate(QDirectFBKeyboardHandler *handler);
+ ~QDirectFBKeyboardHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+private:
+ QDirectFBKeyboardHandler *handler;
+ IDirectFBEventBuffer *eventBuffer;
+ QSocketNotifier *keyboardNotifier;
+ DFBEvent event;
+ int bytesRead;
+
+private slots:
+ void readKeyboardData();
+};
+
+QDirectFBKeyboardHandlerPrivate::QDirectFBKeyboardHandlerPrivate(QDirectFBKeyboardHandler *h)
+ : handler(h), eventBuffer(0)
+{
+ Q_ASSERT(qt_screen);
+
+ IDirectFB *fb = QDirectFBScreen::instance()->dfb();
+ if (!fb) {
+ qCritical("QDirectFBKeyboardHandler: DirectFB not initialized");
+ return;
+ }
+
+ DFBResult result;
+ result = fb->CreateInputEventBuffer(fb, DICAPS_KEYS, DFB_TRUE,
+ &eventBuffer);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBKeyboardHandler: "
+ "Unable to create input event buffer", result);
+ return;
+ }
+
+ int fd;
+ result = eventBuffer->CreateFileDescriptor(eventBuffer, &fd);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBKeyboardHandler: "
+ "Unable to create file descriptor", result);
+ return;
+ }
+
+ int flags = ::fcntl(fd, F_GETFL, 0);
+ ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+ memset(&event, 0, sizeof(event));
+ bytesRead = 0;
+
+
+ keyboardNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(keyboardNotifier, SIGNAL(activated(int)),
+ this, SLOT(readKeyboardData()));
+ resume();
+}
+
+void QDirectFBKeyboardHandlerPrivate::suspend()
+{
+ keyboardNotifier->setEnabled(false);
+}
+
+void QDirectFBKeyboardHandlerPrivate::resume()
+{
+ eventBuffer->Reset(eventBuffer);
+ keyboardNotifier->setEnabled(true);
+}
+
+QDirectFBKeyboardHandlerPrivate::~QDirectFBKeyboardHandlerPrivate()
+{
+ if (eventBuffer)
+ eventBuffer->Release(eventBuffer);
+}
+
+void QDirectFBKeyboardHandlerPrivate::readKeyboardData()
+{
+ if(!qt_screen)
+ return;
+
+ for (;;) {
+ // GetEvent returns DFB_UNSUPPORTED after CreateFileDescriptor().
+ // This seems stupid and I really hope it's a bug which will be fixed.
+
+ // DFBResult ret = eventBuffer->GetEvent(eventBuffer, &event);
+
+ char *buf = reinterpret_cast<char*>(&event);
+ int ret = ::read(keyboardNotifier->socket(),
+ buf + bytesRead, sizeof(DFBEvent) - bytesRead);
+ if (ret == -1) {
+ if (errno != EAGAIN)
+ qWarning("QDirectFBKeyboardHandlerPrivate::readKeyboardData(): %s",
+ strerror(errno));
+ return;
+ }
+
+ Q_ASSERT(ret >= 0);
+ bytesRead += ret;
+ if (bytesRead < int(sizeof(DFBEvent)))
+ break;
+ bytesRead = 0;
+
+ Q_ASSERT(event.clazz == DFEC_INPUT);
+
+ const DFBInputEvent input = event.input;
+
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ if (input.flags & DIEF_MODIFIERS) {
+ if (input.modifiers & DIMM_SHIFT)
+ modifiers |= Qt::ShiftModifier;
+ if (input.modifiers & DIMM_CONTROL)
+ modifiers |= Qt::ControlModifier;
+ if (input.modifiers & DIMM_ALT)
+ modifiers |= Qt::AltModifier;
+ if (input.modifiers & DIMM_ALTGR)
+ modifiers |= Qt::AltModifier;
+ if (input.modifiers & DIMM_META)
+ modifiers |= Qt::MetaModifier;
+ }
+ // Not implemented:
+ // if (input.modifiers & DIMM_SUPER)
+ // if (input.modifiers & DIMM_HYPER)
+
+ if ( !(input.flags & DIEF_KEYSYMBOL) ||
+ !(input.flags & DIEF_KEYID) ||
+ !(input.type & (DIET_KEYPRESS | DIET_KEYRELEASE)) )
+ {
+ static int warningCount = 0;
+ if (!warningCount) {
+ qWarning("QDirectFBKeyboardHandler - Getting unexpected non-keyboard related events");
+ warningCount = 100;
+ }
+ else
+ warningCount--;
+ break;
+ }
+
+ bool press = input.type & DIET_KEYPRESS;
+ DFBInputDeviceKeySymbol symbol = input.key_symbol;
+ int unicode = -1;
+ int keycode = 0;
+
+ keycode = keymap()->value(symbol);
+ if (keycode == 0 && DFB_KEY_TYPE(symbol) == DIKT_UNICODE)
+ unicode = symbol;
+
+ if (unicode != -1 || keycode != 0) {
+ handler->processKeyEvent(unicode, keycode,
+ modifiers, press, false);
+ }
+ }
+}
+
+QDirectFBKeyboardHandler::QDirectFBKeyboardHandler(const QString &device)
+ : QWSKeyboardHandler()
+{
+ Q_UNUSED(device);
+ d = new QDirectFBKeyboardHandlerPrivate(this);
+}
+
+QDirectFBKeyboardHandler::~QDirectFBKeyboardHandler()
+{
+ delete d;
+}
+
+KeyMap::KeyMap()
+{
+ insert(DIKS_BACKSPACE , Qt::Key_Backspace);
+ insert(DIKS_TAB , Qt::Key_Tab);
+ insert(DIKS_RETURN , Qt::Key_Return);
+ insert(DIKS_ESCAPE , Qt::Key_Escape);
+ insert(DIKS_DELETE , Qt::Key_Delete);
+
+ insert(DIKS_CURSOR_LEFT , Qt::Key_Left);
+ insert(DIKS_CURSOR_RIGHT , Qt::Key_Right);
+ insert(DIKS_CURSOR_UP , Qt::Key_Up);
+ insert(DIKS_CURSOR_DOWN , Qt::Key_Down);
+ insert(DIKS_INSERT , Qt::Key_Insert);
+ insert(DIKS_HOME , Qt::Key_Home);
+ insert(DIKS_END , Qt::Key_End);
+ insert(DIKS_PAGE_UP , Qt::Key_PageUp);
+ insert(DIKS_PAGE_DOWN , Qt::Key_PageDown);
+ insert(DIKS_PRINT , Qt::Key_Print);
+ insert(DIKS_PAUSE , Qt::Key_Pause);
+ insert(DIKS_SELECT , Qt::Key_Select);
+ insert(DIKS_GOTO , Qt::Key_OpenUrl);
+ insert(DIKS_CLEAR , Qt::Key_Clear);
+ insert(DIKS_MENU , Qt::Key_Menu);
+ insert(DIKS_HELP , Qt::Key_Help);
+
+ insert(DIKS_INTERNET , Qt::Key_HomePage);
+ insert(DIKS_MAIL , Qt::Key_LaunchMail);
+ insert(DIKS_FAVORITES , Qt::Key_Favorites);
+
+ insert(DIKS_BACK , Qt::Key_Back);
+ insert(DIKS_FORWARD , Qt::Key_Forward);
+ insert(DIKS_VOLUME_UP , Qt::Key_VolumeUp);
+ insert(DIKS_VOLUME_DOWN , Qt::Key_VolumeDown);
+ insert(DIKS_MUTE , Qt::Key_VolumeMute);
+ insert(DIKS_PLAYPAUSE , Qt::Key_Pause);
+ insert(DIKS_PLAY , Qt::Key_MediaPlay);
+ insert(DIKS_STOP , Qt::Key_MediaStop);
+ insert(DIKS_RECORD , Qt::Key_MediaRecord);
+ insert(DIKS_PREVIOUS , Qt::Key_MediaPrevious);
+ insert(DIKS_NEXT , Qt::Key_MediaNext);
+
+ insert(DIKS_F1 , Qt::Key_F1);
+ insert(DIKS_F2 , Qt::Key_F2);
+ insert(DIKS_F3 , Qt::Key_F3);
+ insert(DIKS_F4 , Qt::Key_F4);
+ insert(DIKS_F5 , Qt::Key_F5);
+ insert(DIKS_F6 , Qt::Key_F6);
+ insert(DIKS_F7 , Qt::Key_F7);
+ insert(DIKS_F8 , Qt::Key_F8);
+ insert(DIKS_F9 , Qt::Key_F9);
+ insert(DIKS_F10 , Qt::Key_F10);
+ insert(DIKS_F11 , Qt::Key_F11);
+ insert(DIKS_F12 , Qt::Key_F12);
+
+ insert(DIKS_SHIFT , Qt::Key_Shift);
+ insert(DIKS_CONTROL , Qt::Key_Control);
+ insert(DIKS_ALT , Qt::Key_Alt);
+ insert(DIKS_ALTGR , Qt::Key_AltGr);
+
+ insert(DIKS_META , Qt::Key_Meta);
+ insert(DIKS_SUPER , Qt::Key_Super_L); // ???
+ insert(DIKS_HYPER , Qt::Key_Hyper_L); // ???
+
+ insert(DIKS_CAPS_LOCK , Qt::Key_CapsLock);
+ insert(DIKS_NUM_LOCK , Qt::Key_NumLock);
+ insert(DIKS_SCROLL_LOCK , Qt::Key_ScrollLock);
+
+ insert(DIKS_DEAD_ABOVEDOT , Qt::Key_Dead_Abovedot);
+ insert(DIKS_DEAD_ABOVERING , Qt::Key_Dead_Abovering);
+ insert(DIKS_DEAD_ACUTE , Qt::Key_Dead_Acute);
+ insert(DIKS_DEAD_BREVE , Qt::Key_Dead_Breve);
+ insert(DIKS_DEAD_CARON , Qt::Key_Dead_Caron);
+ insert(DIKS_DEAD_CEDILLA , Qt::Key_Dead_Cedilla);
+ insert(DIKS_DEAD_CIRCUMFLEX , Qt::Key_Dead_Circumflex);
+ insert(DIKS_DEAD_DIAERESIS , Qt::Key_Dead_Diaeresis);
+ insert(DIKS_DEAD_DOUBLEACUTE , Qt::Key_Dead_Doubleacute);
+ insert(DIKS_DEAD_GRAVE , Qt::Key_Dead_Grave);
+ insert(DIKS_DEAD_IOTA , Qt::Key_Dead_Iota);
+ insert(DIKS_DEAD_MACRON , Qt::Key_Dead_Macron);
+ insert(DIKS_DEAD_OGONEK , Qt::Key_Dead_Ogonek);
+ insert(DIKS_DEAD_SEMIVOICED_SOUND , Qt::Key_Dead_Semivoiced_Sound);
+ insert(DIKS_DEAD_TILDE , Qt::Key_Dead_Tilde);
+ insert(DIKS_DEAD_VOICED_SOUND , Qt::Key_Dead_Voiced_Sound);
+}
+
+#include "qdirectfbkeyboard.moc"
+
+#endif // QT_NO_DIRECTFB
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.h b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.h
new file mode 100644
index 0000000..234a266
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTFBKEYBOARD_H
+#define QDIRECTFBKEYBOARD_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_DIRECTFB
+
+class QDirectFBKeyboardHandlerPrivate;
+
+class QDirectFBKeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ QDirectFBKeyboardHandler(const QString &device);
+ ~QDirectFBKeyboardHandler();
+
+private:
+ QDirectFBKeyboardHandlerPrivate *d;
+};
+
+#endif // QT_NO_DIRECTFB
+
+QT_END_HEADER
+
+#endif // QDIRECTFBKEYBOARD_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp
new file mode 100644
index 0000000..f4d9b46
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbmouse.h"
+
+#include "qdirectfbscreen.h"
+#include <qsocketnotifier.h>
+
+#include <directfb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+class QDirectFBMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h);
+ ~QDirectFBMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+private:
+ QDirectFBMouseHandler *handler;
+ IDirectFBEventBuffer *eventBuffer;
+#ifndef QT_NO_DIRECTFB_LAYER
+ IDirectFBDisplayLayer *layer;
+#endif
+ QSocketNotifier *mouseNotifier;
+
+ QPoint prevPoint;
+ Qt::MouseButtons prevbuttons;
+
+ DFBEvent event;
+ uint bytesRead;
+
+private slots:
+ void readMouseData();
+};
+
+QDirectFBMouseHandlerPrivate::QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h)
+ : handler(h), eventBuffer(0)
+{
+ DFBResult result;
+
+ QScreen *screen = QScreen::instance();
+ if (!screen) {
+ qCritical("QDirectFBMouseHandler: no screen instance found");
+ return;
+ }
+
+ IDirectFB *fb = QDirectFBScreen::instance()->dfb();
+ if (!fb) {
+ qCritical("QDirectFBMouseHandler: DirectFB not initialized");
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_LAYER
+ layer = QDirectFBScreen::instance()->dfbDisplayLayer();
+ if (!layer) {
+ qCritical("QDirectFBMouseHandler: Unable to get primary display layer");
+ return;
+ }
+#endif
+
+ DFBInputDeviceCapabilities caps;
+ caps = DFBInputDeviceCapabilities(DICAPS_BUTTONS | DICAPS_AXES);
+ result = fb->CreateInputEventBuffer(fb, caps, DFB_TRUE, &eventBuffer);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler: "
+ "Unable to create input event buffer", result);
+ return;
+ }
+
+ int fd;
+ result = eventBuffer->CreateFileDescriptor(eventBuffer, &fd);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler: "
+ "Unable to create file descriptor", result);
+ return;
+ }
+
+ int flags = ::fcntl(fd, F_GETFL, 0);
+ ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+ // DirectFB seems to assume that the mouse always starts centered
+ prevPoint = QPoint(screen->deviceWidth() / 2, screen->deviceHeight() / 2);
+ prevbuttons = Qt::NoButton;
+ memset(&event, 0, sizeof(event));
+ bytesRead = 0;
+
+ mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+ resume();
+}
+
+QDirectFBMouseHandlerPrivate::~QDirectFBMouseHandlerPrivate()
+{
+ if (eventBuffer)
+ eventBuffer->Release(eventBuffer);
+}
+
+void QDirectFBMouseHandlerPrivate::suspend()
+{
+ mouseNotifier->setEnabled(false);
+}
+
+void QDirectFBMouseHandlerPrivate::resume()
+{
+ eventBuffer->Reset(eventBuffer);
+ mouseNotifier->setEnabled(true);
+}
+
+void QDirectFBMouseHandlerPrivate::readMouseData()
+{
+ if (!QScreen::instance())
+ return;
+
+ for (;;) {
+ // GetEvent returns DFB_UNSUPPORTED after CreateFileDescriptor().
+ // This seems stupid and I really hope it's a bug which will be fixed.
+
+ // DFBResult ret = eventBuffer->GetEvent(eventBuffer, &event);
+
+ char *buf = reinterpret_cast<char*>(&event);
+ int ret = ::read(mouseNotifier->socket(),
+ buf + bytesRead, sizeof(DFBEvent) - bytesRead);
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN)
+ return;
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData(): %s",
+ strerror(errno));
+ return;
+ }
+
+ Q_ASSERT(ret >= 0);
+ bytesRead += ret;
+ if (bytesRead < sizeof(DFBEvent))
+ break;
+ bytesRead = 0;
+
+ Q_ASSERT(event.clazz == DFEC_INPUT);
+
+ const DFBInputEvent input = event.input;
+ int x = prevPoint.x();
+ int y = prevPoint.y();
+ int wheel = 0;
+
+ if (input.type == DIET_AXISMOTION) {
+#ifdef QT_NO_DIRECTFB_LAYER
+ if (input.flags & DIEF_AXISABS) {
+ switch (input.axis) {
+ case DIAI_X: x = input.axisabs; break;
+ case DIAI_Y: y = input.axisabs; break;
+ default:
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
+ "unknown axis (absolute) %d", input.axis);
+ break;
+ }
+ } else if (input.flags & DIEF_AXISREL) {
+ switch (input.axis) {
+ case DIAI_X: x += input.axisrel; break;
+ case DIAI_Y: y += input.axisrel; break;
+ case DIAI_Z: wheel = -120 * input.axisrel; break;
+ default:
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
+ "unknown axis (releative) %d", input.axis);
+ }
+ }
+#else
+ if (input.axis == DIAI_X || input.axis == DIAI_Y) {
+ DFBResult result = layer->GetCursorPosition(layer, &x, &y);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler::readMouseData",
+ result);
+ }
+ } else if (input.axis == DIAI_Z) {
+ Q_ASSERT(input.flags & DIEF_AXISREL);
+ wheel = input.axisrel;
+ wheel *= -120;
+ }
+#endif
+ }
+
+ Qt::MouseButtons buttons = Qt::NoButton;
+ if (input.flags & DIEF_BUTTONS) {
+ if (input.buttons & DIBM_LEFT)
+ buttons |= Qt::LeftButton;
+ if (input.buttons & DIBM_MIDDLE)
+ buttons |= Qt::MidButton;
+ if (input.buttons & DIBM_RIGHT)
+ buttons |= Qt::RightButton;
+ }
+
+ QPoint p = QPoint(x, y);
+ handler->limitToScreen(p);
+
+ if (p == prevPoint && wheel == 0 && buttons == prevbuttons)
+ continue;
+
+ prevPoint = p;
+ prevbuttons = buttons;
+
+ handler->mouseChanged(p, buttons, wheel);
+ }
+}
+
+QDirectFBMouseHandler::QDirectFBMouseHandler(const QString &driver,
+ const QString &device)
+ : QWSMouseHandler(driver, device)
+{
+ d = new QDirectFBMouseHandlerPrivate(this);
+}
+
+QDirectFBMouseHandler::~QDirectFBMouseHandler()
+{
+ delete d;
+}
+
+void QDirectFBMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+void QDirectFBMouseHandler::resume()
+{
+ d->resume();
+}
+
+#include "qdirectfbmouse.moc"
+
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h
new file mode 100644
index 0000000..e81a4ba
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTFBMOUSE_H
+#define QDIRECTFBMOUSE_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_DIRECTFB
+
+class QDirectFBMouseHandlerPrivate;
+
+class QDirectFBMouseHandler : public QWSMouseHandler
+{
+public:
+ explicit QDirectFBMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ ~QDirectFBMouseHandler();
+
+ void suspend();
+ void resume();
+
+protected:
+ QDirectFBMouseHandlerPrivate *d;
+};
+
+#endif // QT_NO_DIRECTFB
+
+QT_END_HEADER
+
+#endif // QDIRECTFBMOUSE_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp
new file mode 100644
index 0000000..d1802e4
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_DIRECTFB
+
+#include "qdirectfbscreen.h"
+#include "qdirectfbpaintdevice.h"
+
+
+IDirectFBSurface *QDirectFBPaintDevice::directFbSurface() const
+{
+ return dfbSurface;
+}
+
+
+// Locks the dfb surface and creates a QImage (lockedImage) from the pointer
+void QDirectFBPaintDevice::lockDirectFB() {
+
+ if (lockedImage)
+ return; // Already locked
+
+ void *mem;
+ int w, h;
+ int bpl;
+ DFBSurfacePixelFormat format;
+
+ DFBResult result = dfbSurface->Lock(dfbSurface, DSLF_WRITE, &mem, &bpl);
+ if (result != DFB_OK || !mem) {
+ DirectFBError("QDirectFBPixmapData::buffer()", result);
+ return;
+ }
+
+ dfbSurface->GetSize(dfbSurface, &w, &h);
+ dfbSurface->GetPixelFormat(dfbSurface, &format);
+
+ lockedImage = new QImage(static_cast<uchar*>(mem), w, h, bpl,
+ QDirectFBScreen::getImageFormat(format));
+}
+
+
+void QDirectFBPaintDevice::unlockDirectFB()
+{
+ if (!lockedImage)
+ return;
+
+ dfbSurface->Unlock(dfbSurface);
+ delete lockedImage;
+ lockedImage = 0;
+}
+
+
+void* QDirectFBPaintDevice::memory() const
+{
+ QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this);
+ that->lockDirectFB();
+ Q_ASSERT(that->lockedImage);
+ return that->lockedImage->bits();
+}
+
+
+QImage::Format QDirectFBPaintDevice::format() const
+{
+ DFBSurfacePixelFormat dfbFormat;
+ dfbSurface->GetPixelFormat(dfbSurface, &dfbFormat);
+ return QDirectFBScreen::getImageFormat(dfbFormat);
+}
+
+
+int QDirectFBPaintDevice::bytesPerLine() const
+{
+ // Can only get the stride when we lock the surface
+ QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this);
+ that->lockDirectFB();
+ Q_ASSERT(that->lockedImage);
+ return that->lockedImage->bytesPerLine();
+}
+
+
+QSize QDirectFBPaintDevice::size() const
+{
+ int w, h;
+ dfbSurface->GetSize(dfbSurface, &w, &h);
+ return QSize(w, h);
+}
+
+
+int QDirectFBPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ if (!dfbSurface)
+ return 0;
+
+ int w, h;
+ dfbSurface->GetSize(dfbSurface, &w, &h);
+
+ int dpmX, dpmY; // Dots-per-meter ;-)
+
+ // Do some common calculations:
+ switch (metric) {
+ case QPaintDevice::PdmWidthMM:
+ case QPaintDevice::PdmPhysicalDpiX:
+ case QPaintDevice::PdmDpiX:
+ dpmX = (screen->deviceWidth() * 1000) / screen->physicalWidth();
+ break;
+ case QPaintDevice::PdmHeightMM:
+ case QPaintDevice::PdmPhysicalDpiY:
+ case QPaintDevice::PdmDpiY:
+ dpmY = (screen->deviceHeight() * 1000) / screen->physicalHeight();
+ break;
+ default:
+ break;
+ }
+
+ // Now use those calculations
+ switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return w;
+ case QPaintDevice::PdmHeight:
+ return h;
+ case QPaintDevice::PdmWidthMM:
+ return (w * 1000) / dpmX;
+ case QPaintDevice::PdmHeightMM:
+ return (h * 1000) / dpmY;
+ case QPaintDevice::PdmPhysicalDpiX:
+ case QPaintDevice::PdmDpiX:
+ return (dpmX * 254) / 10000; // 0.0254 meters-per-inch
+ case QPaintDevice::PdmPhysicalDpiY:
+ case QPaintDevice::PdmDpiY:
+ return (dpmY * 254) / 10000; // 0.0254 meters-per-inch
+ case QPaintDevice::PdmDepth:
+ DFBSurfacePixelFormat format;
+ dfbSurface->GetPixelFormat(dfbSurface, &format);
+ return QDirectFBScreen::depth(format);
+ case QPaintDevice::PdmNumColors: {
+ if (lockedImage)
+ return lockedImage->numColors();
+
+ DFBResult result;
+ IDirectFBPalette *palette = 0;
+ unsigned int numColors = 0;
+
+ result = dfbSurface->GetPalette(dfbSurface, &palette);
+ if ((result != DFB_OK) || !palette)
+ return 0;
+
+ result = palette->GetSize(palette, &numColors);
+ palette->Release(palette);
+ if (result != DFB_OK)
+ return 0;
+
+ return numColors;
+ }
+ default:
+ qCritical("QDirectFBPaintDevice::metric(): Unhandled metric!");
+ return 0;
+ }
+}
+
+#endif
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h
new file mode 100644
index 0000000..c28d37c
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTFBPAINTDEVICE_H
+#define QDIRECTFBPAINTDEVICE_H
+
+#include <private/qpaintengine_raster_p.h>
+#include <directfb.h>
+#include "qdirectfbscreen.h"
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+// Inherited by both window surface and pixmap
+class QDirectFBPaintDevice : public QCustomRasterPaintDevice
+{
+public:
+ QDirectFBPaintDevice(QDirectFBScreen *scr = QDirectFBScreen::instance())
+ : QCustomRasterPaintDevice(0),
+ dfbSurface(0),
+ lockedImage(0),
+ screen(scr) {}
+
+ IDirectFBSurface *directFbSurface() const;
+
+ void lockDirectFB();
+ void unlockDirectFB();
+
+ // Reimplemented from QCustomRasterPaintDevice:
+ void* memory() const;
+ QImage::Format format() const;
+ int bytesPerLine() const;
+ QSize size() const;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+
+protected:
+ IDirectFBSurface *dfbSurface;
+ QImage *lockedImage;
+ QDirectFBScreen *screen;
+};
+
+QT_END_HEADER
+
+#endif //QDIRECTFBPAINTDEVICE_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
new file mode 100644
index 0000000..4fc4035
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -0,0 +1,1261 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbpaintengine.h"
+
+#ifndef QT_NO_DIRECTFB
+
+#include "qdirectfbsurface.h"
+#include "qdirectfbscreen.h"
+#include "qdirectfbpixmap.h"
+#include <directfb.h>
+#include <qtransform.h>
+#include <qvarlengtharray.h>
+#include <qcache.h>
+#include <qmath.h>
+#include <private/qpixmapdata_p.h>
+#include <private/qpixmap_raster_p.h>
+
+static inline uint ALPHA_MUL(uint x, uint a)
+{
+ uint t = x * a;
+ t = ((t + (t >> 8) + 0x80) >> 8) & 0xff;
+ return t;
+}
+
+static inline QRect mapRect(const QTransform &transform, const QRect &rect)
+{
+ return (transform.isIdentity() ? rect : transform.mapRect(rect));
+}
+
+static inline QRect mapRect(const QTransform &transform, const QRectF &rect)
+{
+ return (transform.isIdentity() ? rect : transform.mapRect(rect)).
+ toRect();
+}
+
+class SurfaceCache
+{
+public:
+ SurfaceCache();
+ ~SurfaceCache();
+
+ inline IDirectFBSurface *getSurface(const uint *buffer, int size);
+ inline void clear();
+
+private:
+ IDirectFBSurface *surface;
+ uint *buffer;
+ int bufsize;
+};
+
+SurfaceCache::SurfaceCache()
+ : surface(0), buffer(0), bufsize(0)
+{
+}
+
+class CachedImage
+{
+public:
+ CachedImage(const QImage &image);
+ ~CachedImage();
+
+ IDirectFBSurface *surface() { return s; }
+
+private:
+ IDirectFBSurface *s;
+};
+
+CachedImage::CachedImage(const QImage &image)
+ : s(0)
+{
+ IDirectFBSurface *tmpSurface = 0;
+ DFBSurfaceDescription description;
+ description = QDirectFBScreen::getSurfaceDescription(image);
+ QDirectFBScreen* screen = QDirectFBScreen::instance();
+
+ tmpSurface = screen->createDFBSurface(&description);
+ if (!tmpSurface) {
+ qWarning("CachedImage CreateSurface failed!");
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(tmpSurface, image);
+#endif
+
+ description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED);
+
+ s = screen->createDFBSurface(&description);
+ if (!s)
+ qWarning("QDirectFBPaintEngine failed caching image");
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(s, image);
+#endif
+
+ if (s) {
+ s->SetBlittingFlags(s, DSBLIT_NOFX);
+ s->Blit(s, tmpSurface, 0, 0, 0);
+ s->ReleaseSource(s);
+ }
+ if (tmpSurface)
+ screen->releaseDFBSurface(tmpSurface);
+}
+
+CachedImage::~CachedImage()
+{
+ if (s && QDirectFBScreen::instance())
+ QDirectFBScreen::instance()->releaseDFBSurface(s);
+}
+
+static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
+
+IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size)
+{
+ if (buffer == buf && bufsize == size)
+ return surface;
+
+ clear();
+
+ DFBSurfaceDescription description;
+ description = QDirectFBScreen::getSurfaceDescription(buf, size);
+
+ surface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ if (!surface)
+ qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface");
+
+ buffer = const_cast<uint*>(buf);
+ bufsize = size;
+
+ return surface;
+}
+
+void SurfaceCache::clear()
+{
+ if (surface)
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+ surface = 0;
+ buffer = 0;
+ bufsize = 0;
+}
+
+SurfaceCache::~SurfaceCache()
+{
+ clear();
+}
+
+class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate
+{
+public:
+ QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p);
+ ~QDirectFBPaintEnginePrivate();
+
+ IDirectFBSurface *surface;
+
+ QPen pen;
+ QBrush brush;
+
+ bool antialiased;
+
+ bool simplePen;
+ bool simpleBrush;
+
+ bool matrixRotShear;
+ bool matrixScale;
+
+ void setTransform(const QTransform &m);
+ void setPen(const QPen &pen);
+ void setBrush(const QBrush &brush);
+ void setCompositionMode(QPainter::CompositionMode mode);
+ void setOpacity(const qreal value);
+ void setRenderHints(QPainter::RenderHints hints);
+
+ inline void setDFBColor(const QColor &color) const;
+
+ inline bool lock();
+ inline void unlock();
+
+ inline bool dfbCanHandleClip(const QRect &rect) const;
+ inline bool dfbCanHandleClip(const QRectF &rect) const;
+ inline bool dfbCanHandleClip() const;
+
+ void drawLines(const QLine *lines, int count) const;
+ void drawLines(const QLineF *lines, int count) const;
+
+ void fillRegion(const QRegion &r) const;
+ void fillRects(const QRect *rects, int count) const;
+ void drawRects(const QRect *rects, int count) const;
+ void fillRects(const QRectF *rects, int count) const;
+ void drawRects(const QRectF *rects, int count) const;
+
+ void drawPixmap(const QRectF &dest,
+ const QPixmap &pixmap, const QRectF &src);
+ void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap);
+ void drawImage(const QRectF &dest, const QImage &image, const QRectF &src);
+
+ void updateClip();
+ void updateFlags();
+ inline void setClipDirty();
+ void systemStateChanged(); //Needed to be notified when system clip changes
+
+ void begin(QPaintDevice *device);
+ void end();
+
+ SurfaceCache *surfaceCache;
+
+private:
+// QRegion rectsToClippedRegion(const QRect *rects, int n) const;
+// QRegion rectsToClippedRegion(const QRectF *rects, int n) const;
+
+ IDirectFB *fb;
+ DFBSurfaceDescription fbDescription;
+ int fbWidth;
+ int fbHeight;
+
+ quint8 opacity;
+ QTransform transform;
+
+ quint32 drawFlags;
+ quint32 blitFlags;
+ quint32 duffFlags;
+ bool dirtyFlags;
+ bool dirtyClip;
+ bool dfbHandledClip;
+
+ QDirectFBPaintEngine *q;
+};
+
+QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
+ : surface(0), antialiased(false), simplePen(false),
+ simpleBrush(false), matrixRotShear(false), matrixScale(false), fbWidth(-1), fbHeight(-1),
+ opacity(255), drawFlags(0), blitFlags(0), duffFlags(0), dirtyFlags(false), dirtyClip(true),
+ dfbHandledClip(false), q(p)
+{
+ fb = QDirectFBScreen::instance()->dfb();
+ surfaceCache = new SurfaceCache;
+ static int cacheLimit = qgetenv("QT_DIRECTFB_IMAGECACHE").toInt();
+ if (cacheLimit > 0)
+ imageCache.setMaxCost(cacheLimit * 1024);
+}
+
+QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate()
+{
+ unlock();
+ delete surfaceCache;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const
+{
+ // TODO: Check to see if DirectFB can handle the clip for the given rect
+ return dfbHandledClip;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const
+{
+ // TODO: Check to see if DirectFB can handle the clip for the given rect
+ return dfbHandledClip;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const
+{
+ return dfbHandledClip;
+}
+
+void QDirectFBPaintEnginePrivate::setClipDirty()
+{
+ dirtyClip = true;
+}
+
+
+bool QDirectFBPaintEnginePrivate::lock()
+{
+ // We will potentially get a new pointer to the buffer after a
+ // lock so we need to call the base implementation of prepare so
+ // it updates its rasterBuffer to point to the new buffer address.
+ if (device->devType() == QInternal::CustomRaster) {
+ prepare(static_cast<QCustomRasterPaintDevice*>(device));
+ return true;
+ }
+ return false;
+}
+
+void QDirectFBPaintEnginePrivate::unlock()
+{
+ QPaintDevice *device = q->paintDevice();
+ if (!device) //XXX This should probably be an assert
+ return;
+
+ Q_ASSERT(device->devType() == QInternal::CustomRaster);
+ QDirectFBPaintDevice* dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
+ dfbDevice->unlockDirectFB();
+}
+
+void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m)
+{
+ transform = m;
+ matrixRotShear = (transform.m12() != 0 || transform.m21() != 0);
+ matrixScale = (transform.m11() != 1 || transform.m22() != 1);
+}
+
+void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device)
+{
+ QDirectFBPaintDevice* dfbDevice = 0;
+
+ if (device->devType() == QInternal::CustomRaster)
+ dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
+ else if (device->devType() == QInternal::Pixmap) {
+ QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData();
+ if (data->classId() == QPixmapData::DirectFBClass) {
+ QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data);
+ dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData);
+ }
+ }
+
+ if (dfbDevice)
+ surface = dfbDevice->directFbSurface();
+
+ if (!surface) {
+ qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
+ device->devType());
+ }
+
+ surface->GetSize(surface, &fbWidth, &fbHeight);
+
+ setTransform(QTransform());
+ antialiased = false;
+ drawFlags = DSDRAW_BLEND;
+ blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
+ duffFlags = DSPD_SRC_OVER;
+ opacity = 255;
+ dirtyFlags = true;
+ dirtyClip = true;
+ setPen(q->state()->pen);
+ setDFBColor(pen.color());
+}
+
+void QDirectFBPaintEnginePrivate::end()
+{
+ surface->ReleaseSource(surface);
+ surface->SetClip(surface, NULL);
+ surface = 0;
+}
+
+void QDirectFBPaintEnginePrivate::setPen(const QPen &p)
+{
+ pen = p;
+ simplePen = (pen.style() == Qt::NoPen) ||
+ (pen.style() == Qt::SolidLine && !antialiased
+ && (pen.widthF() <= 1 && !matrixScale));
+}
+
+void QDirectFBPaintEnginePrivate::setBrush(const QBrush &b)
+{
+ // TODO: accelerate texture pattern
+ brush = b;
+ simpleBrush = (brush.style() == Qt::NoBrush) ||
+ (brush.style() == Qt::SolidPattern && !antialiased);
+}
+
+void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
+{
+ drawFlags &= ~(DSDRAW_XOR);
+ blitFlags &= ~(DSBLIT_XOR);
+
+ // TODO: check these mappings!!!!
+ quint32 duff = DSPD_NONE;
+ quint32 blit = blitFlags;
+
+ switch (mode) {
+ case QPainter::CompositionMode_SourceOver:
+ duff = DSPD_SRC_OVER;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_DestinationOver:
+ duff = DSPD_DST_OVER;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_Clear:
+ duff = DSPD_CLEAR;
+ blit &= ~DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_Source:
+ duff = DSPD_SRC;
+ blit &= ~DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_Destination:
+ blit &= ~DSBLIT_BLEND_ALPHACHANNEL;
+ return;
+ case QPainter::CompositionMode_SourceIn:
+ duff = DSPD_SRC_IN;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_DestinationIn:
+ duff = DSPD_DST_IN;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_SourceOut:
+ duff = DSPD_SRC_OUT;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_DestinationOut:
+ duff = DSPD_DST_OUT;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_SourceAtop:
+ duff = DSPD_SRC_OVER;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ break;
+ case QPainter::CompositionMode_DestinationAtop:
+ duff = DSPD_DST_OVER;
+ break;
+ case QPainter::CompositionMode_Xor:
+ duff = DSPD_NONE;
+ blit |= DSBLIT_BLEND_ALPHACHANNEL;
+ drawFlags |= DSDRAW_XOR;
+ blit |= DSBLIT_XOR;
+ dirtyFlags = true;
+ break;
+ default:
+ qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): "
+ "mode %d not implemented", mode);
+ break;
+ }
+
+ if (duff != duffFlags || blit != blitFlags) {
+ duffFlags = duff;
+ blitFlags = blit;
+ dirtyFlags = true;
+ }
+}
+
+void QDirectFBPaintEnginePrivate::setOpacity(const qreal value)
+{
+ const bool wasOpaque = (opacity == 255);
+ opacity = quint8(value * 255);
+ const bool opaque = (opacity == 255);
+
+ if (opaque == wasOpaque)
+ return;
+
+ if (opaque)
+ blitFlags &= ~(DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR);
+ else
+ blitFlags |= (DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR);
+
+ dirtyFlags = true;
+}
+
+void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
+{
+ const bool old = antialiased;
+ antialiased = bool(hints & QPainter::Antialiasing);
+ if (old != antialiased) {
+ setPen(q->state()->pen);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::updateFlags()
+{
+ if (!dirtyFlags)
+ return;
+ surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawFlags));
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags));
+ surface->SetPorterDuff(surface, DFBSurfacePorterDuffRule(duffFlags));
+ dirtyFlags = false;
+}
+
+void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) const
+{
+ const quint8 alpha = (opacity == 255 ?
+ color.alpha() : ALPHA_MUL(color.alpha(), opacity));
+ surface->SetColor(surface,
+ color.red(), color.green(), color.blue(), alpha);
+}
+
+void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) const
+{
+ QVarLengthArray<DFBRegion> regions(n);
+
+ for (int i = 0; i < n; ++i) {
+ const QLine l = transform.map(lines[i]);
+
+ // TODO: clip!
+
+ regions[i].x1 = l.x1();
+ regions[i].y1 = l.y1();
+ regions[i].x2 = l.x2();
+ regions[i].y2 = l.y2();
+ }
+ surface->DrawLines(surface, regions.data(), n);
+}
+
+void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) const
+{
+ QVarLengthArray<DFBRegion> regions(n);
+
+ for (int i = 0; i < n; ++i) {
+ const QLine l = transform.map(lines[i]).toLine();
+
+ // TODO: clip!
+
+ regions[i].x1 = l.x1();
+ regions[i].y1 = l.y1();
+ regions[i].x2 = l.x2();
+ regions[i].y2 = l.y2();
+ }
+ surface->DrawLines(surface, regions.data(), n);
+}
+
+/* ### Commented out until it can be implemented properly using raster's QClipData
+QRegion QDirectFBPaintEnginePrivate::rectsToClippedRegion(const QRect *rects,
+ int n) const
+{
+ QRegion region;
+
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ region += clip & r;
+ }
+
+ return region;
+}
+
+QRegion QDirectFBPaintEnginePrivate::rectsToClippedRegion(const QRectF *rects,
+ int n) const
+{
+ QRegion region;
+
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ region += clip & r;
+ }
+
+ return region;
+}
+*/
+
+void QDirectFBPaintEnginePrivate::fillRegion(const QRegion &region) const
+{
+ const QVector<QRect> rects = region.rects();
+ const int n = rects.size();
+ QVarLengthArray<DFBRectangle> dfbRects(n);
+
+ for (int i = 0; i < n; ++i) {
+ const QRect r = rects.at(i);
+ dfbRects[i].x = r.x();
+ dfbRects[i].y = r.y();
+ dfbRects[i].w = r.width();
+ dfbRects[i].h = r.height();
+
+ }
+ surface->FillRectangles(surface, dfbRects.data(), n);
+}
+
+void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) const
+{
+ QVarLengthArray<DFBRectangle> dfbRects(n);
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ dfbRects[i].x = r.x();
+ dfbRects[i].y = r.y();
+ dfbRects[i].w = r.width();
+ dfbRects[i].h = r.height();
+ }
+ surface->FillRectangles(surface, dfbRects.data(), n);
+}
+
+void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) const
+{
+ QVarLengthArray<DFBRectangle> dfbRects(n);
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ dfbRects[i].x = r.x();
+ dfbRects[i].y = r.y();
+ dfbRects[i].w = r.width();
+ dfbRects[i].h = r.height();
+ }
+ surface->FillRectangles(surface, dfbRects.data(), n);
+}
+
+void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) const
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ surface->DrawRectangle(surface, r.x(), r.y(),
+ r.width() + 1, r.height() + 1);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) const
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ surface->DrawRectangle(surface, r.x(), r.y(),
+ r.width() + 1, r.height() + 1);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest,
+ const QPixmap &pixmap,
+ const QRectF &src)
+{
+ surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
+
+ const bool changeFlags = !pixmap.hasAlphaChannel()
+ && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL);
+ if (changeFlags) {
+ quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL;
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags));
+ }
+
+ QPixmapData *data = pixmap.pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
+ QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
+ IDirectFBSurface *s = dfbData->directFbSurface();
+ const QRect sr = src.toRect();
+ const QRect dr = ::mapRect(transform, dest);
+ const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
+ DFBResult result;
+
+ if (dr.size() == sr.size()) {
+ result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
+ } else {
+ const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
+ result = surface->StretchBlit(surface, s, &sRect, &dRect);
+ }
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
+ if (changeFlags)
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags));
+}
+
+void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest,
+ const QPixmap &pixmap)
+{
+ surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
+
+ const bool changeFlags = !pixmap.hasAlphaChannel()
+ && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL);
+ if (changeFlags) {
+ quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL;
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags));
+ }
+
+ QPixmapData *data = pixmap.pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
+ QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
+ IDirectFBSurface *s = dfbData->directFbSurface();
+ const QRect dr = ::mapRect(transform, dest);
+ DFBResult result = DFB_OK;
+
+ if (!matrixScale && dr == QRect(0, 0, fbWidth, fbHeight)) {
+ result = surface->TileBlit(surface, s, 0, 0, 0);
+ } else if (!matrixScale) {
+ const int dx = pixmap.width();
+ const int dy = pixmap.height();
+ const DFBRectangle rect = { 0, 0, dx, dy };
+ QVarLengthArray<DFBRectangle> rects;
+ QVarLengthArray<DFBPoint> points;
+
+ for (int y = dr.y(); y <= dr.bottom(); y += dy) {
+ for (int x = dr.x(); x <= dr.right(); x += dx) {
+ rects.append(rect);
+ const DFBPoint point = { x, y };
+ points.append(point);
+ }
+ }
+ result = surface->BatchBlit(surface, s, rects.constData(),
+ points.constData(), points.size());
+ } else {
+ const QRect sr = ::mapRect(transform, QRect(0, 0, pixmap.width(), pixmap.height()));
+ const int dx = sr.width();
+ const int dy = sr.height();
+ const DFBRectangle sRect = { 0, 0, dx, dy };
+
+ for (int y = dr.y(); y <= dr.bottom(); y += dy) {
+ for (int x = dr.x(); x <= dr.right(); x += dx) {
+ const DFBRectangle dRect = { x, y, dx, dy };
+ result = surface->StretchBlit(surface, s, &sRect, &dRect);
+ if (result != DFB_OK) {
+ y = dr.bottom() + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result);
+
+ if (changeFlags)
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags));
+}
+
+void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest,
+ const QImage &srcImage,
+ const QRectF &src)
+{
+ QImage image = srcImage;
+ if (QDirectFBScreen::getSurfacePixelFormat(image) == DSPF_UNKNOWN) {
+ QImage::Format format;
+ if (image.hasAlphaChannel())
+ format = QImage::Format_ARGB32_Premultiplied;
+ else
+ format = QImage::Format_RGB32;
+ image = image.convertToFormat(format);
+ }
+
+ CachedImage *img = imageCache[image.cacheKey()];
+ IDirectFBSurface *imgSurface = 0;
+ bool doRelease = false;
+
+ if (img) {
+ imgSurface = img->surface();
+ } else {
+ const int cost = image.width() * image.height() * image.depth() / 8;
+ if (cost <= imageCache.maxCost()) {
+ img = new CachedImage(image);
+ imgSurface = img->surface();
+ if (imgSurface) {
+ imageCache.insert(image.cacheKey(), img, cost);
+ } else {
+ delete img;
+ img = 0;
+ }
+ }
+
+ if (!imgSurface) {
+ DFBSurfaceDescription description;
+
+ description = QDirectFBScreen::getSurfaceDescription(image);
+ imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ if (!imgSurface) {
+ qWarning("QDirectFBPaintEnginePrivate::drawImage");
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(surface, image);
+#endif
+ doRelease = (imgSurface != 0);
+ }
+ }
+
+ const QRect sr = src.toRect();
+ const QRect dr = ::mapRect(transform, dest);
+ const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
+
+ surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
+
+ const bool changeFlags = !image.hasAlphaChannel()
+ && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL);
+ if (changeFlags) {
+ quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL;
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags));
+ }
+ if (dr.size() == sr.size()) {
+ surface->Blit(surface, imgSurface, &sRect, dr.x(), dr.y());
+ } else {
+ const DFBRectangle dRect = { dr.x(), dr.y(),
+ dr.width(), dr.height() };
+ surface->StretchBlit(surface, imgSurface, &sRect, &dRect);
+ }
+ if (changeFlags)
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags));
+ if (doRelease)
+ QDirectFBScreen::instance()->releaseDFBSurface(imgSurface);
+}
+
+void QDirectFBPaintEnginePrivate::updateClip()
+{
+ if (!dirtyClip)
+ return;
+
+ if (!clip() || !clip()->enabled) {
+ surface->SetClip(surface, NULL);
+ dfbHandledClip = true;
+ }
+ else if (clip()->hasRectClip) {
+ const DFBRegion r = {
+ clip()->clipRect.x(),
+ clip()->clipRect.y(),
+ clip()->clipRect.x() + clip()->clipRect.width(),
+ clip()->clipRect.y() + clip()->clipRect.height()
+ };
+ surface->SetClip(surface, &r);
+
+ dfbHandledClip = true;
+ }
+ else
+ dfbHandledClip = false;
+
+ dirtyClip = false;
+}
+
+void QDirectFBPaintEnginePrivate::systemStateChanged()
+{
+ setClipDirty();
+ QRasterPaintEnginePrivate::systemStateChanged();
+}
+
+QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device)
+ : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device)
+{
+}
+
+QDirectFBPaintEngine::~QDirectFBPaintEngine()
+{
+}
+
+bool QDirectFBPaintEngine::begin(QPaintDevice *device)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->begin(device);
+ const bool status = QRasterPaintEngine::begin(device);
+
+ // XXX: QRasterPaintEngine::begin() resets the capabilities
+ gccaps |= PorterDuff;
+
+ return status;
+}
+
+bool QDirectFBPaintEngine::end()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->end();
+ return QRasterPaintEngine::end();
+}
+
+
+
+void QDirectFBPaintEngine::clipEnabledChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setClipDirty();
+ QRasterPaintEngine::clipEnabledChanged();
+}
+
+void QDirectFBPaintEngine::penChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setPen(state()->pen);
+
+ QRasterPaintEngine::penChanged();
+}
+
+void QDirectFBPaintEngine::brushChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setBrush(state()->brush);
+
+ QRasterPaintEngine::brushChanged();
+}
+
+void QDirectFBPaintEngine::opacityChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setOpacity(state()->opacity);
+
+ QRasterPaintEngine::opacityChanged();
+}
+
+void QDirectFBPaintEngine::compositionModeChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setCompositionMode(state()->compositionMode());
+
+ QRasterPaintEngine::compositionModeChanged();
+}
+
+void QDirectFBPaintEngine::renderHintsChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setRenderHints(state()->renderHints);
+ QRasterPaintEngine::renderHintsChanged();
+}
+
+void QDirectFBPaintEngine::transformChanged()
+{
+ Q_D(QDirectFBPaintEngine);
+ const bool old = d->matrixScale;
+ d->setTransform(state()->transform());
+ if (d->matrixScale != old) {
+ d->setPen(state()->pen);
+ }
+ QRasterPaintEngine::transformChanged();
+}
+
+void QDirectFBPaintEngine::setState(QPainterState *s)
+{
+ Q_D(QDirectFBPaintEngine);
+ QRasterPaintEngine::setState(s);
+ if (d->surface)
+ d->updateClip();
+ d->setPen(state()->pen);
+ d->setBrush(state()->brush);
+ d->setOpacity(state()->opacity);
+ d->setCompositionMode(state()->compositionMode());
+ d->setTransform(state()->transform());
+}
+
+void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setClipDirty();
+ QRasterPaintEngine::clip(path, op);
+}
+
+void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->setClipDirty();
+ QRasterPaintEngine::clip(rect, op);
+}
+
+
+void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simpleBrush || !d->simplePen) {
+ d->lock();
+ QRasterPaintEngine::drawRects(rects, rectCount);
+ return;
+ }
+
+ d->unlock();
+
+ if (d->brush != Qt::NoBrush) {
+ d->updateFlags();
+ d->setDFBColor(d->brush.color());
+ d->fillRects(rects, rectCount);
+ }
+ if (d->pen != Qt::NoPen) {
+ d->updateFlags();
+ d->setDFBColor(d->pen.color());
+ d->drawRects(rects, rectCount);
+ }
+}
+
+void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simpleBrush || !d->simplePen) {
+ d->lock();
+ QRasterPaintEngine::drawRects(rects, rectCount);
+ return;
+ }
+
+ d->unlock();
+
+ if (d->brush != Qt::NoBrush) {
+ d->updateFlags();
+ d->setDFBColor(d->brush.color());
+ d->fillRects(rects, rectCount);
+ }
+ if (d->pen != Qt::NoPen) {
+ d->updateFlags();
+ d->setDFBColor(d->pen.color());
+ d->drawRects(rects, rectCount);
+ }
+}
+
+void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (!d->simplePen || !d->dfbCanHandleClip()) {
+ d->lock();
+ QRasterPaintEngine::drawLines(lines, lineCount);
+ return;
+ }
+
+ if (d->pen != Qt::NoPen) {
+ d->unlock();
+ d->updateFlags();
+ d->setDFBColor(d->pen.color());
+ d->drawLines(lines, lineCount);
+ }
+}
+
+void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (!d->simplePen || !d->dfbCanHandleClip()) {
+ d->lock();
+ QRasterPaintEngine::drawLines(lines, lineCount);
+ return;
+ }
+
+ if (d->pen != Qt::NoPen) {
+ d->unlock();
+ d->updateFlags();
+ d->setDFBColor(d->pen.color());
+ d->drawLines(lines, lineCount);
+ }
+}
+
+void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image,
+ const QRectF &sr,
+ Qt::ImageConversionFlags flags)
+{
+ Q_D(QDirectFBPaintEngine);
+ Q_UNUSED(flags); // XXX
+
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
+ d->updateClip();
+ if (!d->dfbCanHandleClip(r) || d->matrixRotShear)
+#endif
+ {
+ d->lock();
+ QRasterPaintEngine::drawImage(r, image, sr, flags);
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
+ d->unlock();
+ d->updateFlags();
+ d->drawImage(r, image, sr);
+#endif
+}
+
+void QDirectFBPaintEngine::drawImage(const QPointF &p, const QImage &img)
+{
+ drawImage(QRectF(p, img.size()), img, img.rect());
+}
+
+void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap,
+ const QRectF &sr)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+
+ if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
+ d->lock();
+ QRasterPaintEngine::drawPixmap(r, pixmap, sr);
+ }
+ else if (!d->dfbCanHandleClip(r) || d->matrixRotShear) {
+ const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ d->lock();
+ QRasterPaintEngine::drawImage(r, *img, sr);
+ }
+ else {
+ d->unlock();
+ d->updateFlags();
+ d->drawPixmap(r, pixmap, sr);
+ }
+}
+
+void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm)
+{
+ drawPixmap(QRectF(p, pm.size()), pm, pm.rect());
+}
+
+void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
+ const QPixmap &pixmap,
+ const QPointF &sp)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
+ d->lock();
+ QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp);
+ }
+ else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) {
+ QImage* img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType);
+ data->fromImage(*img, Qt::AutoColor);
+ const QPixmap pix(data);
+ d->lock();
+ QRasterPaintEngine::drawTiledPixmap(r, pix, sp);
+ }
+ else {
+ d->unlock();
+ d->updateFlags();
+ d->drawTiledPixmap(r, pixmap);
+ }
+}
+
+
+void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::stroke(path, pen);
+}
+
+void QDirectFBPaintEngine::drawPath(const QPainterPath &path)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawPath(path);
+}
+
+void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawPoints(points, pointCount);
+}
+
+void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawPoints(points, pointCount);
+}
+
+void QDirectFBPaintEngine::drawEllipse(const QRectF &rect)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawEllipse(rect);
+}
+
+void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount,
+ PolygonDrawMode mode)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawPolygon(points, pointCount, mode);
+}
+
+void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount,
+ PolygonDrawMode mode)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawPolygon(points, pointCount, mode);
+}
+
+void QDirectFBPaintEngine::drawTextItem(const QPointF &p,
+ const QTextItem &textItem)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::drawTextItem(p, textItem);
+}
+
+void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->lock();
+ QRasterPaintEngine::fill(path, brush);
+}
+
+void QDirectFBPaintEngine::fillRect(const QRectF &r, const QBrush &brush)
+{
+ Q_D(QDirectFBPaintEngine);
+ if (brush.style() != Qt::SolidPattern) {
+ d->lock();
+ QRasterPaintEngine::fillRect(r, brush);
+ }
+ else
+ fillRect(r, brush.color());
+}
+
+void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color)
+{
+ Q_D(QDirectFBPaintEngine);
+ d->updateClip();
+ if (!d->dfbCanHandleClip() || d->matrixRotShear) {
+ d->lock();
+ QRasterPaintEngine::fillRect(rect, color);
+ } else {
+ d->unlock();
+ d->updateFlags();
+ d->setDFBColor(color);
+ d->fillRects(&rect, 1);
+ }
+}
+
+
+
+
+
+
+
+void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count,
+ uint color)
+{
+ Q_D(QDirectFBPaintEngine);
+ color = INV_PREMUL(color);
+
+ QVarLengthArray<DFBRegion> lines(count);
+ int j = 0;
+ for (int i = 0; i < count; ++i) {
+ if (spans[i].coverage == 255) {
+ lines[j].x1 = spans[i].x;
+ lines[j].y1 = spans[i].y;
+ lines[j].x2 = spans[i].x + spans[i].len - 1;
+ lines[j].y2 = spans[i].y;
+ ++j;
+ } else {
+ DFBSpan span = { spans[i].x, spans[i].len };
+ uint c = BYTE_MUL(color, spans[i].coverage);
+ d->surface->SetColor(d->surface,
+ qRed(c), qGreen(c), qBlue(c), qAlpha(c));
+ d->surface->FillSpans(d->surface, spans[i].y, &span, 1);
+ }
+ }
+ if (j > 0) {
+ d->surface->SetColor(d->surface,
+ qRed(color), qGreen(color), qBlue(color),
+ qAlpha(color));
+ d->surface->DrawLines(d->surface, lines.data(), j);
+ }
+}
+
+void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
+ int x, int y, int length,
+ uint const_alpha)
+{
+ Q_D(QDirectFBPaintEngine);
+ IDirectFBSurface *src = d->surfaceCache->getSurface(buffer, bufsize);
+ src->SetColor(src, 0, 0, 0, const_alpha);
+ const DFBRectangle rect = { 0, 0, length, 1 };
+ d->surface->Blit(d->surface, src, &rect, x, y);
+}
+
+#endif // QT_NO_DIRECTFB
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h
new file mode 100644
index 0000000..3c2cefa
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTENGINE_DIRECTFB_P_H
+#define QPAINTENGINE_DIRECTFB_P_H
+
+#include <QtGui/qpaintengine.h>
+#include <private/qpaintengine_raster_p.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+class QDirectFBPaintEnginePrivate;
+
+class QDirectFBPaintEngine : public QRasterPaintEngine
+{
+ Q_DECLARE_PRIVATE(QDirectFBPaintEngine)
+public:
+ QDirectFBPaintEngine(QPaintDevice *device);
+ ~QDirectFBPaintEngine();
+
+ bool begin(QPaintDevice *device);
+ bool end();
+
+ void drawRects(const QRect *rects, int rectCount);
+ void drawRects(const QRectF *rects, int rectCount);
+
+ void fillRect(const QRectF &r, const QBrush &brush);
+ void fillRect(const QRectF &r, const QColor &color);
+
+ void drawLines(const QLine *line, int lineCount);
+ void drawLines(const QLineF *line, int lineCount);
+
+ void drawImage(const QPointF &p, const QImage &img);
+ void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
+ Qt::ImageConversionFlags falgs = Qt::AutoColor);
+
+ void drawPixmap(const QPointF &p, const QPixmap &pm);
+ void drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &sr);
+ void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr);
+
+ void drawColorSpans(const QSpan *spans, int count, uint color);
+ void drawBufferSpan(const uint *buffer, int bufsize,
+ int x, int y, int length, uint const_alpha);
+
+
+ // The following methods simply lock the surface & call the base implementation
+ void stroke(const QVectorPath &path, const QPen &pen);
+ void drawPath(const QPainterPath &path);
+ void drawPoints(const QPointF *points, int pointCount);
+ void drawPoints(const QPoint *points, int pointCount);
+ void drawEllipse(const QRectF &rect);
+ void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
+ void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
+ void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ void fill(const QVectorPath &path, const QBrush &brush);
+
+ virtual void clipEnabledChanged();
+ virtual void penChanged();
+ virtual void brushChanged();
+ virtual void opacityChanged();
+ virtual void compositionModeChanged();
+ virtual void renderHintsChanged();
+ virtual void transformChanged();
+
+ virtual void setState(QPainterState *state);
+
+ virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
+ virtual void clip(const QRect &rect, Qt::ClipOperation op);
+
+};
+
+QT_END_HEADER
+
+#endif // QPAINTENGINE_DIRECTFB_P_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
new file mode 100644
index 0000000..6352652
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbpixmap.h"
+
+#include "qdirectfbscreen.h"
+#include "qdirectfbpaintengine.h"
+
+#include <QtGui/qbitmap.h>
+#include <directfb.h>
+
+static int global_ser_no = 0;
+
+QDirectFBPixmapData::QDirectFBPixmapData(PixelType pixelType)
+ : QPixmapData(pixelType, DirectFBClass),
+ engine(0)
+{
+ setSerialNumber(0);
+}
+
+QDirectFBPixmapData::~QDirectFBPixmapData()
+{
+ unlockDirectFB();
+ if (dfbSurface && QDirectFBScreen::instance())
+ screen->releaseDFBSurface(dfbSurface);
+ delete engine;
+}
+
+void QDirectFBPixmapData::resize(int width, int height)
+{
+ if (width <= 0 || height <= 0) {
+ setSerialNumber(0);
+ return;
+ }
+
+ DFBSurfaceDescription description;
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
+ DSDESC_HEIGHT);
+ description.width = width;
+ description.height = height;
+
+ dfbSurface = screen->createDFBSurface(&description);
+ if (!dfbSurface)
+ qCritical("QDirectFBPixmapData::resize(): Unable to allocate surface");
+
+ setSerialNumber(++global_ser_no);
+}
+
+void QDirectFBPixmapData::fromImage(const QImage &img,
+ Qt::ImageConversionFlags)
+{
+ QImage image;
+ if (QDirectFBScreen::getSurfacePixelFormat(img) == DSPF_UNKNOWN)
+ image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ else
+ image = img;
+
+ DFBSurfaceDescription description;
+ description = QDirectFBScreen::getSurfaceDescription(image);
+
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
+ IDirectFBSurface *imgSurface;
+ imgSurface = screen->createDFBSurface(&description);
+ if (!imgSurface) {
+ qWarning("QDirectFBPixmapData::fromImage()");
+ setSerialNumber(0);
+ return;
+ }
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(imgSurface, image);
+#endif
+#endif // QT_NO_DIRECTFB_PREALLOCATED
+
+ description.flags = DFBSurfaceDescriptionFlags(description.flags
+ & ~DSDESC_PREALLOCATED);
+ dfbSurface = screen->createDFBSurface(&description);
+ if (!dfbSurface) {
+ qWarning("QDirectFBPixmapData::fromImage()");
+ setSerialNumber(0);
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(dfbSurface, image);
+#endif
+
+#ifdef QT_NO_DIRECTFB_PREALLOCATED
+ char *mem;
+ surface->Lock(surface, DSLF_WRITE, (void**)&mem, &bpl);
+ const int w = image.width() * image.depth() / 8;
+ for (int i = 0; i < image.height(); ++i) {
+ memcpy(mem, image.scanLine(i), w);
+ mem += bpl;
+ }
+ surface->Unlock(surface);
+#else
+ DFBResult result;
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+ result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPixmapData::fromImage()", result);
+ dfbSurface->Flip(dfbSurface, 0, DSFLIP_NONE);
+ dfbSurface->ReleaseSource(dfbSurface);
+ screen->releaseDFBSurface(imgSurface);
+#endif // QT_NO_DIRECTFB_PREALLOCATED
+
+ setSerialNumber(++global_ser_no);
+}
+
+void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
+{
+ if (data->classId() != DirectFBClass) {
+ QPixmapData::copy(data, rect);
+ return;
+ }
+
+ IDirectFBSurface *src = static_cast<const QDirectFBPixmapData*>(data)->directFbSurface();
+
+ DFBSurfaceDescription description;
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
+ DSDESC_HEIGHT |
+ DSDESC_PIXELFORMAT);
+ description.width = rect.width();
+ description.height = rect.height();
+ src->GetPixelFormat(src, &description.pixelformat);
+
+ dfbSurface = screen->createDFBSurface(&description);
+ if (!dfbSurface) {
+ qWarning("QDirectFBPixmapData::copy()");
+ setSerialNumber(0);
+ return;
+ }
+
+ DFBResult result;
+#ifndef QT_NO_DIRECTFB_PALETTE
+ IDirectFBPalette *palette;
+ result = src->GetPalette(src, &palette);
+ if (result == DFB_OK) {
+ dfbSurface->SetPalette(dfbSurface, palette);
+ palette->Release(palette);
+ }
+#endif
+
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+ const DFBRectangle blitRect = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPixmapData::copy()", result);
+
+ setSerialNumber(++global_ser_no);
+}
+
+
+void QDirectFBPixmapData::fill(const QColor &color)
+{
+ if (!serialNumber())
+ return;
+
+ Q_ASSERT(dfbSurface);
+
+ if (color.alpha() < 255 && !hasAlphaChannel()) {
+ // convert to surface supporting alpha channel
+ DFBSurfacePixelFormat format;
+ dfbSurface->GetPixelFormat(dfbSurface, &format);
+ switch (format) {
+ case DSPF_YUY2:
+ case DSPF_UYVY:
+ format = DSPF_AYUV;
+ break;
+#if (Q_DIRECTFB_VERSION >= 0x010100)
+ case DSPF_RGB444:
+ format = DSPF_ARGB4444;
+ break;
+ case DSPF_RGB555:
+#endif
+ case DSPF_RGB18:
+ format = DSPF_ARGB6666;
+ break;
+ default:
+ format = DSPF_ARGB;
+ break;
+ }
+
+ DFBSurfaceDescription description;
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
+ DSDESC_HEIGHT |
+ DSDESC_PIXELFORMAT);
+ dfbSurface->GetSize(dfbSurface, &description.width, &description.height);
+ description.pixelformat = format;
+ screen->releaseDFBSurface(dfbSurface); // release old surface
+
+ dfbSurface = screen->createDFBSurface(&description);
+ if (!dfbSurface) {
+ qWarning("QDirectFBPixmapData::fill()");
+ setSerialNumber(0);
+ return;
+ }
+ }
+
+ dfbSurface->Clear(dfbSurface, color.red(), color.green(), color.blue(),
+ color.alpha());
+}
+
+bool QDirectFBPixmapData::hasAlphaChannel() const
+{
+ if (!serialNumber())
+ return false;
+
+ DFBSurfacePixelFormat format;
+ dfbSurface->GetPixelFormat(dfbSurface, &format);
+ switch (format) {
+ case DSPF_ARGB1555:
+ case DSPF_ARGB:
+ case DSPF_LUT8:
+ case DSPF_AiRGB:
+ case DSPF_A1:
+ case DSPF_ARGB2554:
+ case DSPF_ARGB4444:
+ case DSPF_AYUV:
+ case DSPF_A4:
+ case DSPF_ARGB1666:
+ case DSPF_ARGB6666:
+ case DSPF_LUT2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
+ Qt::TransformationMode mode) const
+{
+ if (!dfbSurface || transform.type() != QTransform::TxScale
+ || mode != Qt::FastTransformation)
+ {
+ QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
+ const QImage *image = that->buffer();
+ if (image) { // avoid deep copy
+ const QImage transformed = image->transformed(transform, mode);
+ that->unlockDirectFB();
+ QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
+ data->fromImage(transformed, Qt::AutoColor);
+ return QPixmap(data);
+ }
+ return QPixmapData::transformed(transform, mode);
+ }
+
+ int w, h;
+ dfbSurface->GetSize(dfbSurface, &w, &h);
+
+ const QSize size = transform.mapRect(QRect(0, 0, w, h)).size();
+ if (size.isEmpty())
+ return QPixmap();
+
+ QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
+ data->resize(size.width(), size.height());
+
+ IDirectFBSurface *dest = data->dfbSurface;
+ dest->SetBlittingFlags(dest, DSBLIT_NOFX);
+
+ const DFBRectangle srcRect = { 0, 0, w, h };
+ const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
+ dest->StretchBlit(dest, dfbSurface, &srcRect, &destRect);
+
+ return QPixmap(data);
+}
+
+QImage QDirectFBPixmapData::toImage() const
+{
+ if (!dfbSurface)
+ return QImage();
+
+#ifdef QT_NO_DIRECTFB_PREALLOCATED
+ QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
+ const QImage *img = that->buffer();
+ const QImage copied = img->copy();
+ that->unlockDirectFB();
+ return copied;
+#else
+
+ int w, h;
+ dfbSurface->GetSize(dfbSurface, &w, &h);
+
+ // Always convert to ARGB32:
+ QImage image(w, h, QImage::Format_ARGB32);
+
+ DFBSurfaceDescription description;
+ description = QDirectFBScreen::getSurfaceDescription(image);
+
+ IDirectFBSurface *imgSurface = screen->createDFBSurface(&description);
+ if (!imgSurface) {
+ qWarning("QDirectFBPixmapData::toImage()");
+ return QImage();
+ }
+
+ imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX);
+ DFBResult result = imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBPixmapData::toImage() blit failed", result);
+ return QImage();
+ }
+ screen->releaseDFBSurface(imgSurface);
+
+ return image;
+#endif // QT_NO_DIRECTFB_PREALLOCATED
+}
+
+QPaintEngine* QDirectFBPixmapData::paintEngine() const
+{
+ if (!engine) {
+ // QDirectFBPixmapData is also a QCustomRasterPaintDevice, so pass
+ // that to the paint engine:
+ QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
+ that->engine = new QDirectFBPaintEngine(that);
+ }
+ return engine;
+}
+
+
+QImage* QDirectFBPixmapData::buffer()
+{
+ lockDirectFB();
+ return lockedImage;
+}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
new file mode 100644
index 0000000..32676f8
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTFBPIXMAP_H
+#define QDIRECTFBPIXMAP_H
+
+#include <QtGui/private/qpixmapdata_p.h>
+#include <QtGui/private/qpaintengine_raster_p.h>
+#include "qdirectfbpaintdevice.h"
+#include <directfb.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+class QDirectFBPaintEngine;
+
+class QDirectFBPixmapData : public QPixmapData, public QDirectFBPaintDevice
+{
+public:
+ QDirectFBPixmapData(PixelType pixelType);
+ ~QDirectFBPixmapData();
+
+ // Re-implemented from QPixmapData:
+ void resize(int width, int height);
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ void copy(const QPixmapData *data, const QRect &rect);
+ void fill(const QColor &color);
+ bool hasAlphaChannel() const;
+ QPixmap transformed(const QTransform &matrix,
+ Qt::TransformationMode mode) const;
+ QImage toImage() const;
+ QPaintEngine* paintEngine() const;
+ QImage *buffer();
+
+ // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice
+ int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);}
+
+private:
+ QDirectFBPaintEngine *engine;
+};
+
+QT_END_HEADER
+
+#endif // QDIRECTFBPIXMAP_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
new file mode 100644
index 0000000..3249e65
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -0,0 +1,1064 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbscreen.h"
+#include "qdirectfbsurface.h"
+#include "qdirectfbpixmap.h"
+#include "qdirectfbmouse.h"
+#include "qdirectfbkeyboard.h"
+#include <QtGui/qwsdisplay_qws.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qwindowsystem_qws.h>
+#include <QtGui/private/qgraphicssystem_qws_p.h>
+#include <QtGui/private/qwssignalhandler_p.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qrect.h>
+
+class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem
+{
+public:
+ QDirectFBScreenPrivate(QDirectFBScreen*);
+ ~QDirectFBScreenPrivate();
+
+ void setFlipFlags(const QStringList &args);
+ QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
+
+ IDirectFB *dfb;
+ IDirectFBSurface *dfbSurface;
+ DFBSurfaceFlipFlags flipFlags;
+#ifndef QT_NO_DIRECTFB_LAYER
+ IDirectFBDisplayLayer *dfbLayer;
+#endif
+ IDirectFBScreen *dfbScreen;
+ QRegion prevExpose;
+
+ QSet<IDirectFBSurface*> allocatedSurfaces;
+
+#ifndef QT_NO_DIRECTFB_MOUSE
+ QDirectFBMouseHandler *mouse;
+#endif
+#ifndef QT_NO_DIRECTFB_KEYBOARD
+ QDirectFBKeyboardHandler *keyboard;
+#endif
+ bool videoonly;
+};
+
+QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen)
+ : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_BLIT)
+#ifndef QT_NO_DIRECTFB_LAYER
+ , dfbLayer(0)
+#endif
+#ifndef QT_NO_DIRECTFB_MOUSE
+ , mouse(0)
+#endif
+#ifndef QT_NO_DIRECTFB_KEYBOARD
+ , keyboard(0)
+#endif
+ , videoonly(false)
+{
+#ifndef QT_NO_QWS_SIGNALHANDLER
+ QWSSignalHandler::instance()->addObject(this);
+#endif
+}
+
+QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
+{
+#ifndef QT_NO_DIRECTFB_MOUSE
+ delete mouse;
+#endif
+#ifndef QT_NO_DIRECTFB_KEYBOARD
+ delete keyboard;
+#endif
+
+ foreach (IDirectFBSurface* surf, allocatedSurfaces)
+ surf->Release(surf);
+ allocatedSurfaces.clear();
+
+ if (dfbSurface)
+ dfbSurface->Release(dfbSurface);
+
+#ifndef QT_NO_DIRECTFB_LAYER
+ if (dfbLayer)
+ dfbLayer->Release(dfbLayer);
+#endif
+
+ if (dfbScreen)
+ dfbScreen->Release(dfbScreen);
+
+ if (dfb)
+ dfb->Release(dfb);
+}
+
+IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* desc, bool track)
+{
+ DFBResult result;
+ IDirectFBSurface* newSurface = 0;
+
+ if (!d_ptr->dfb) {
+ qWarning("QDirectFBScreen::createDFBSurface() - not connected");
+ return 0;
+ }
+
+ if (d_ptr->videoonly && !(desc->flags & DSDESC_PREALLOCATED)) {
+ // Add the video only capability. This means the surface will be created in video ram
+ DFBSurfaceDescription voDesc = *desc;
+ voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY);
+ voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS);
+ result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &voDesc, &newSurface);
+ }
+
+ if (!newSurface)
+ result = d_ptr->dfb->CreateSurface(d_ptr->dfb, desc, &newSurface);
+
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::createDFBSurface", result);
+ return 0;
+ }
+
+ Q_ASSERT(newSurface);
+
+ if (track) {
+ d_ptr->allocatedSurfaces.insert(newSurface);
+
+ //qDebug("Created a new DirectFB surface at %p. New count = %d",
+ // newSurface, d_ptr->allocatedSurfaces.count());
+ }
+
+ return newSurface;
+}
+
+void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface* surface)
+{
+ Q_ASSERT(surface);
+ surface->Release(surface);
+ if (!d_ptr->allocatedSurfaces.remove(surface))
+ qWarning("QDirectFBScreen::releaseDFBSurface() - %p not in list", surface);
+
+ //qDebug("Released surface at %p. New count = %d", surface, d_ptr->allocatedSurfaces.count());
+}
+
+bool QDirectFBScreen::preferVideoOnly() const
+{
+ return d_ptr->videoonly;
+}
+
+IDirectFB* QDirectFBScreen::dfb()
+{
+ return d_ptr->dfb;
+}
+
+IDirectFBSurface* QDirectFBScreen::dfbSurface()
+{
+ return d_ptr->dfbSurface;
+}
+
+#ifndef QT_NO_DIRECTFB_LAYER
+IDirectFBDisplayLayer* QDirectFBScreen::dfbDisplayLayer()
+{
+ return d_ptr->dfbLayer;
+}
+#endif
+
+DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image)
+{
+ switch (image.format()) {
+#ifndef QT_NO_DIRECTFB_PALETTE
+ case QImage::Format_Indexed8:
+ return DSPF_LUT8;
+#endif
+ case QImage::Format_RGB888:
+ return DSPF_RGB24;
+ case QImage::Format_ARGB4444_Premultiplied:
+ return DSPF_ARGB4444;
+#if (Q_DIRECTFB_VERSION >= 0x010100)
+ case QImage::Format_RGB444:
+ return DSPF_RGB444;
+ case QImage::Format_RGB555:
+ return DSPF_RGB555;
+#endif
+ case QImage::Format_RGB16:
+ return DSPF_RGB16;
+ case QImage::Format_ARGB6666_Premultiplied:
+ return DSPF_ARGB6666;
+ case QImage::Format_RGB666:
+ return DSPF_RGB18;
+ case QImage::Format_RGB32:
+ return DSPF_RGB32;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ return DSPF_ARGB;
+ default:
+ return DSPF_UNKNOWN;
+ };
+}
+
+QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format)
+{
+ switch (format) {
+ case DSPF_LUT8:
+ return QImage::Format_Indexed8;
+ case DSPF_RGB24:
+ return QImage::Format_RGB888;
+ case DSPF_ARGB4444:
+ return QImage::Format_ARGB4444_Premultiplied;
+#if (Q_DIRECTFB_VERSION >= 0x010100)
+ case DSPF_RGB444:
+ return QImage::Format_RGB444;
+ case DSPF_RGB555:
+#endif
+ case DSPF_ARGB1555:
+ return QImage::Format_RGB555;
+ case DSPF_RGB16:
+ return QImage::Format_RGB16;
+ case DSPF_ARGB6666:
+ return QImage::Format_ARGB6666_Premultiplied;
+ case DSPF_RGB18:
+ return QImage::Format_RGB666;
+ case DSPF_RGB32:
+ return QImage::Format_RGB32;
+ case DSPF_ARGB:
+ return QImage::Format_ARGB32_Premultiplied;
+ default:
+ break;
+ }
+ return QImage::Format_Invalid;
+}
+
+DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image)
+{
+ DFBSurfaceDescription description;
+ DFBSurfacePixelFormat format = getSurfacePixelFormat(image);
+
+ if (format == DSPF_UNKNOWN || image.isNull()) {
+ description.flags = DFBSurfaceDescriptionFlags(0);
+ return description;
+ }
+
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS
+ | DSDESC_WIDTH
+ | DSDESC_HEIGHT
+ | DSDESC_PIXELFORMAT
+ | DSDESC_PREALLOCATED);
+
+ description.caps = DSCAPS_NONE;
+ description.width = image.width();
+ description.height = image.height();
+ description.pixelformat = format;
+ description.preallocated[0].data = (void*)(image.bits());
+ description.preallocated[0].pitch = image.bytesPerLine();
+ description.preallocated[1].data = 0;
+ description.preallocated[1].pitch = 0;
+
+ switch (image.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ description.caps = DSCAPS_PREMULTIPLIED;
+ default:
+ break;
+ }
+
+ return description;
+}
+
+DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer,
+ int length)
+{
+ DFBSurfaceDescription description;
+
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS
+ | DSDESC_WIDTH
+ | DSDESC_HEIGHT
+ | DSDESC_PIXELFORMAT
+ | DSDESC_PREALLOCATED);
+ description.caps = DSCAPS_PREMULTIPLIED;
+ description.width = length;
+ description.height = 1;
+ description.pixelformat = DSPF_ARGB;
+ description.preallocated[0].data = (void*)buffer;
+ description.preallocated[0].pitch = length * sizeof(uint);
+ description.preallocated[1].data = 0;
+ description.preallocated[1].pitch = 0;
+
+ return description;
+}
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface,
+ const QImage &image)
+{
+ if (!surface)
+ return;
+
+ const int numColors = image.numColors();
+ if (numColors == 0)
+ return;
+
+ QVarLengthArray<DFBColor> colors(numColors);
+ for (int i = 0; i < numColors; ++i) {
+ QRgb c = image.color(i);
+ colors[i].a = qAlpha(c);
+ colors[i].r = qRed(c);
+ colors[i].g = qGreen(c);
+ colors[i].b = qBlue(c);
+ }
+
+ IDirectFBPalette *palette;
+ DFBResult result;
+ result = surface->GetPalette(surface, &palette);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::setSurfaceColorTable GetPalette",
+ result);
+ return;
+ }
+ result = palette->SetEntries(palette, colors.data(), numColors, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::setSurfaceColorTable SetEntries",
+ result);
+ }
+ palette->Release(palette);
+}
+
+void QDirectFBScreen::setImageColorTable(QImage *image, IDirectFBSurface *surface)
+{
+ if (!image || !surface || image->depth() > 8)
+ return;
+
+ IDirectFBPalette *palette = 0;
+ unsigned int numColors = 0;
+ DFBResult result;
+ do {
+ result = surface->GetPalette(surface, &palette);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result);
+ break;
+ }
+
+ result = palette->GetSize(palette, &numColors);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result);
+ break;
+ }
+
+ if (numColors == 0)
+ break;
+
+ QVarLengthArray<DFBColor> dfbColors(numColors);
+ result = palette->GetEntries(palette, dfbColors.data(), numColors, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result);
+ break;
+ }
+
+ QVector<QRgb> qtColors(numColors);
+ for (unsigned int i=0; i<numColors; ++i) {
+ const DFBColor &col = dfbColors[i];
+ qtColors[i] = qRgba(col.r, col.g, col.b, col.a);
+ }
+ image->setColorTable(qtColors);
+
+ } while (0);
+
+ if (palette)
+ palette->Release(palette);
+}
+
+#endif // QT_NO_DIRECTFB_PALETTE
+
+#if !defined(QT_NO_DIRECTFB_LAYER) && !defined(QT_NO_QWS_CURSOR)
+class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor
+{
+public:
+ QDirectFBScreenCursor();
+ ~QDirectFBScreenCursor();
+
+ void set(const QImage &image, int hotx, int hoty);
+ void move(int x, int y);
+ void show();
+ void hide();
+
+private:
+ IDirectFBDisplayLayer *layer;
+ bool implicitHide;
+};
+
+QDirectFBScreenCursor::QDirectFBScreenCursor()
+{
+ IDirectFB *fb = QDirectFBScreen::instance()->dfb();
+ if (!fb)
+ qFatal("QDirectFBScreenCursor: DirectFB not initialized");
+
+ layer = QDirectFBScreen::instance()->dfbDisplayLayer();
+
+ if (layer)
+ layer->SetCooperativeLevel(layer, DLSCL_SHARED); // XXX: hw: remove?
+ else
+ qFatal("QDirectFBScreenCursor: Unable to get primary display layer!");
+
+ enable = true;
+ hwaccel = true;
+ implicitHide = false;
+ supportsAlpha = true;
+
+ set(QImage(), 0, 0);
+}
+
+QDirectFBScreenCursor::~QDirectFBScreenCursor()
+{
+}
+
+void QDirectFBScreenCursor::show()
+{
+ DFBResult result;
+ result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::show: "
+ "Unable to set cooperative level", result);
+ }
+ result = layer->EnableCursor(layer, 1);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::show: "
+ "Unable to enable cursor", result);
+ }
+ result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::show: "
+ "Unable to reset cooperative level", result);
+ }
+ implicitHide = false;
+}
+
+void QDirectFBScreenCursor::hide()
+{
+ DFBResult result;
+ result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to set cooperative level", result);
+ }
+ result = layer->EnableCursor(layer, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to disable cursor", result);
+ }
+ result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::hide: "
+ "Unable to reset cooperative level", result);
+ }
+ implicitHide = true;
+}
+
+void QDirectFBScreenCursor::move(int x, int y)
+{
+ layer->WarpCursor(layer, x, y);
+}
+
+void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
+{
+ if (image.isNull() && isVisible()) {
+ hide();
+ implicitHide = true;
+ } else if (!image.isNull() && implicitHide) {
+ show();
+ }
+
+#ifdef QT_NO_DIRECTFB_PALETTE
+ if (image.numColors() > 0)
+ cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ else
+#endif
+ if (image.format() == QImage::Format_Indexed8) {
+ cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ } else {
+ cursor = image;
+ }
+ size = cursor.size();
+ hotspot = QPoint(hotx, hoty);
+
+ DFBSurfaceDescription description;
+ description = QDirectFBScreen::getSurfaceDescription(cursor);
+
+ IDirectFBSurface *surface;
+ surface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ if (!surface) {
+ qWarning("QDirectFBScreenCursor::set: Unable to create surface");
+ return;
+ }
+#ifndef QT_NO_DIRECTFB_PALETTE
+ QDirectFBScreen::setSurfaceColorTable(surface, cursor);
+#endif
+
+ DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: "
+ "Unable to set cooperative level", result);
+ }
+ result = layer->SetCursorShape(layer, surface, hotx, hoty);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: Unable to set cursor shape",
+ result);
+ }
+
+ result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::set: "
+ "Unable to reset cooperative level", result);
+ }
+
+ if (surface)
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+}
+#endif // QT_NO_DIRECTFB_LAYER
+
+QDirectFBScreen::QDirectFBScreen(int display_id)
+ : QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this))
+{
+}
+
+QDirectFBScreen::~QDirectFBScreen()
+{
+ delete d_ptr;
+}
+
+int QDirectFBScreen::depth(DFBSurfacePixelFormat format)
+{
+ switch (format) {
+ case DSPF_A1:
+ return 1;
+ case DSPF_A8:
+ case DSPF_RGB332:
+ case DSPF_LUT8:
+ case DSPF_ALUT44:
+ return 8;
+ case DSPF_I420:
+ case DSPF_YV12:
+ case DSPF_NV12:
+ case DSPF_NV21:
+#if (Q_DIRECTFB_VERSION >= 0x010100)
+ case DSPF_RGB444:
+#endif
+ return 12;
+#if (Q_DIRECTFB_VERSION >= 0x010100)
+ case DSPF_RGB555:
+ return 15;
+#endif
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_YUY2:
+ case DSPF_UYVY:
+ case DSPF_NV16:
+ case DSPF_ARGB2554:
+ case DSPF_ARGB4444:
+ return 16;
+ case DSPF_RGB24:
+ return 24;
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ case DSPF_AiRGB:
+ return 32;
+ case DSPF_UNKNOWN:
+ default:
+ return 0;
+ };
+ return 0;
+}
+
+void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
+{
+ QRegExp flipRegexp(QLatin1String("^flip=([\\w,]+)$"));
+ int index = args.indexOf(flipRegexp);
+ if (index >= 0) {
+ const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','),
+ QString::SkipEmptyParts);
+ flipFlags = DSFLIP_NONE;
+ foreach (QString flip, flips) {
+ if (flip == QLatin1String("wait"))
+ flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_WAIT);
+ else if (flip == QLatin1String("blit"))
+ flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_BLIT);
+ else if (flip == QLatin1String("onsync"))
+ flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_ONSYNC);
+ else if (flip == QLatin1String("pipeline"))
+ flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_PIPELINE);
+ else
+ qWarning("QDirectFBScreen: Unknown flip argument: %s",
+ qPrintable(flip));
+ }
+ }
+}
+
+QPixmapData* QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const
+{
+ if (type == QPixmapData::BitmapType)
+ return QWSGraphicsSystem::createPixmapData(type);
+
+ return new QDirectFBPixmapData(type);
+}
+
+static void printDirectFBInfo(IDirectFB *fb)
+{
+ DFBResult result;
+ DFBGraphicsDeviceDescription dev;
+
+ result = fb->GetDeviceDescription(fb, &dev);
+ if (result != DFB_OK) {
+ DirectFBError("Error reading graphics device description", result);
+ return;
+ }
+
+ qDebug("Device: %s (%s), Driver: %s v%i.%i (%s)\n"
+ " acceleration: 0x%x, blit: 0x%x, draw: 0x%0x video: %i\n",
+ dev.name, dev.vendor, dev.driver.name, dev.driver.major,
+ dev.driver.minor, dev.driver.vendor, dev.acceleration_mask,
+ dev.blitting_flags, dev.drawing_flags, dev.video_memory);
+}
+
+bool QDirectFBScreen::connect(const QString &displaySpec)
+{
+ DFBResult result = DFB_OK;
+
+ { // pass command line arguments to DirectFB
+ const QStringList args = QCoreApplication::arguments();
+ int argc = args.size();
+ char **argv = new char*[argc];
+
+ for (int i = 0; i < argc; ++i)
+ argv[i] = qstrdup(args.at(i).toLocal8Bit().constData());
+
+ result = DirectFBInit(&argc, &argv);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen: error initializing DirectFB",
+ result);
+ }
+ delete[] argv;
+ }
+
+ const QStringList displayArgs = displaySpec.split(QLatin1Char(':'),
+ QString::SkipEmptyParts);
+
+ d_ptr->setFlipFlags(displayArgs);
+
+ result = DirectFBCreate(&d_ptr->dfb);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen: error creating DirectFB interface",
+ result);
+ return false;
+ }
+
+ if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
+ printDirectFBInfo(d_ptr->dfb);
+
+ if (displayArgs.contains(QLatin1String("videoonly")))
+ d_ptr->videoonly = true;
+
+#ifndef QT_NO_DIRECTFB_WM
+ if (displayArgs.contains(QLatin1String("fullscreen")))
+#endif
+ d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN);
+
+ DFBSurfaceDescription description;
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS);
+ description.caps = DFBSurfaceCapabilities(DSCAPS_PRIMARY
+ | DSCAPS_DOUBLE
+ | DSCAPS_STATIC_ALLOC);
+ if (!(d_ptr->flipFlags & DSFLIP_BLIT)) {
+ description.caps = DFBSurfaceCapabilities(description.caps
+ | DSCAPS_DOUBLE
+ | DSCAPS_TRIPLE);
+ }
+
+
+ // We don't track the primary surface as it's released in disconnect
+ d_ptr->dfbSurface = createDFBSurface(&description, false);
+ if (!d_ptr->dfbSurface) {
+ DirectFBError("QDirectFBScreen: error creating primary surface",
+ result);
+ return false;
+ }
+ d_ptr->dfbSurface->GetSize(d_ptr->dfbSurface, &w, &h);
+
+ 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(format));
+
+ physWidth = physHeight = -1;
+ QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
+ int dimIdxW = displayArgs.indexOf(mmWidthRx);
+ if (dimIdxW >= 0) {
+ mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
+ physWidth = mmWidthRx.cap(1).toInt();
+ }
+ QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
+ int dimIdxH = displayArgs.indexOf(mmHeightRx);
+ if (dimIdxH >= 0) {
+ mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
+ physHeight = mmHeightRx.cap(1).toInt();
+ }
+ 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,
+ &d_ptr->dfbLayer);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::connect: "
+ "Unable to get primary display layer!", result);
+ return false;
+ }
+ result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen);
+#else
+ result = d_ptr->dfb->GetScreen(d_ptr->dfb, 0, &d_ptr->dfbScreen);
+#endif
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::connect: "
+ "Unable to get screen!", result);
+ return false;
+ }
+
+ setGraphicsSystem(d_ptr);
+
+ return true;
+}
+
+void QDirectFBScreen::disconnect()
+{
+ d_ptr->dfbSurface->Release(d_ptr->dfbSurface);
+ d_ptr->dfbSurface = 0;
+
+ foreach (IDirectFBSurface* surf, d_ptr->allocatedSurfaces)
+ surf->Release(surf);
+ d_ptr->allocatedSurfaces.clear();
+
+#ifndef QT_NO_DIRECTFB_LAYER
+ d_ptr->dfbLayer->Release(d_ptr->dfbLayer);
+ d_ptr->dfbLayer = 0;
+#endif
+
+ d_ptr->dfbScreen->Release(d_ptr->dfbScreen);
+ d_ptr->dfbScreen = 0;
+
+ d_ptr->dfb->Release(d_ptr->dfb);
+ d_ptr->dfb = 0;
+}
+
+bool QDirectFBScreen::initDevice()
+{
+ QWSServer *server = QWSServer::instance();
+#ifndef QT_NO_DIRECTFB_MOUSE
+ if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) {
+ server->setDefaultMouse("None");
+ d_ptr->mouse = new QDirectFBMouseHandler;
+ }
+#endif
+#ifndef QT_NO_DIRECTFB_KEYBOARD
+ if (qgetenv("QWS_KEYBOARD").isEmpty()) {
+ server->setDefaultKeyboard("None");
+ d_ptr->keyboard = new QDirectFBKeyboardHandler(QString());
+ }
+#endif
+
+#ifndef QT_NO_QWS_CURSOR
+#ifdef QT_NO_DIRECTFB_LAYER
+ QScreenCursor::initSoftwareCursor();
+#else
+ qt_screencursor = new QDirectFBScreenCursor;
+#endif
+#endif
+ return true;
+}
+
+void QDirectFBScreen::shutdownDevice()
+{
+#ifndef QT_NO_DIRECTFB_MOUSE
+ delete d_ptr->mouse;
+ d_ptr->mouse = 0;
+#endif
+#ifndef QT_NO_DIRECTFB_KEYBOARD
+ delete d_ptr->keyboard;
+ d_ptr->keyboard = 0;
+#endif
+
+#ifndef QT_NO_QWS_CURSOR
+ delete qt_screencursor;
+ qt_screencursor = 0;
+#endif
+}
+
+void QDirectFBScreen::setMode(int width, int height, int depth)
+{
+ d_ptr->dfb->SetVideoMode(d_ptr->dfb, width, height, depth);
+}
+
+void QDirectFBScreen::blank(bool on)
+{
+ d_ptr->dfbScreen->SetPowerMode(d_ptr->dfbScreen,
+ (on ? DSPM_ON : DSPM_SUSPEND));
+}
+
+QWSWindowSurface* QDirectFBScreen::createSurface(QWidget *widget) const
+{
+#ifdef QT_NO_DIRECTFB_WM
+ if (QApplication::type() == QApplication::GuiServer)
+ return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget);
+ else
+ return QScreen::createSurface(widget);
+#else
+ return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget);
+#endif
+}
+
+QWSWindowSurface* QDirectFBScreen::createSurface(const QString &key) const
+{
+ if (key == QLatin1String("directfb"))
+ return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this));
+ return QScreen::createSurface(key);
+}
+
+void QDirectFBScreen::compose(const QRegion &region)
+{
+ const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+
+ QRegion blitRegion = region;
+ QRegion blendRegion;
+
+ d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_NOFX);
+
+ // blit opaque region
+ for (int i = 0; i < windows.size(); ++i) {
+ QWSWindow *win = windows.at(i);
+ QWSWindowSurface *surface = win->windowSurface();
+ if (!surface)
+ continue;
+
+ const QRegion r = win->allocatedRegion() & blitRegion;
+ if (r.isEmpty())
+ continue;
+
+ blitRegion -= r;
+
+ if (surface->isRegionReserved()) {
+ // nothing
+ } else if (win->isOpaque()) {
+ const QPoint offset = win->requestedRegion().boundingRect().topLeft();
+
+ if (surface->key() == QLatin1String("directfb")) {
+ QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface);
+ blit(s->directFbSurface(), offset, r);
+ } else {
+ blit(surface->image(), offset, r);
+ }
+ } else {
+ blendRegion += r;
+ }
+ if (blitRegion.isEmpty())
+ break;
+ }
+
+ { // fill background
+ const QRegion fill = blitRegion + blendRegion;
+ if (!fill.isEmpty()) {
+ const QColor color = QWSServer::instance()->backgroundBrush().color();
+ solidFill(color, fill);
+ blitRegion = QRegion();
+ }
+ }
+
+ if (blendRegion.isEmpty())
+ return;
+
+ // blend non-opaque region
+ for (int i = windows.size() - 1; i >= 0; --i) {
+ QWSWindow *win = windows.at(i);
+ QWSWindowSurface *surface = win->windowSurface();
+ if (!surface)
+ continue;
+
+ const QRegion r = win->allocatedRegion() & blendRegion;
+ if (r.isEmpty())
+ continue;
+
+ DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
+ if (!win->isOpaque()) {
+ flags = DFBSurfaceBlittingFlags(flags | DSBLIT_BLEND_ALPHACHANNEL);
+ const uint opacity = win->opacity();
+ if (opacity < 255) {
+ flags = DFBSurfaceBlittingFlags(flags | DSBLIT_BLEND_COLORALPHA);
+ d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, 0xff, 0xff, 0xff, opacity);
+ }
+ }
+ d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, flags);
+
+ const QPoint offset = win->requestedRegion().boundingRect().topLeft();
+
+ if (surface->key() == QLatin1String("directfb")) {
+ QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface);
+ blit(s->directFbSurface(), offset, r);
+ } else {
+ blit(surface->image(), offset, r);
+ }
+ }
+}
+
+// Normally, when using DirectFB to compose the windows (I.e. when
+// 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.
+void QDirectFBScreen::exposeRegion(QRegion r, int changing)
+{
+ const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+ if (changing < 0 || changing >= windows.size())
+ return;
+
+#ifndef QT_NO_DIRECTFB_WM
+ QWSWindow *win = windows.at(changing);
+ QWSWindowSurface *s = win->windowSurface();
+ if (s && s->key() == QLatin1String("directfb"))
+ return;
+#endif
+
+ r &= region();
+ if (r.isEmpty())
+ return;
+
+ if (d_ptr->flipFlags & DSFLIP_BLIT) {
+ const QRect brect = r.boundingRect();
+ DFBRegion dfbRegion = { brect.left(), brect.top(),
+ brect.right(), brect.bottom() };
+ compose(r);
+ d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, &dfbRegion,
+ d_ptr->flipFlags);
+ } else {
+ compose(r + d_ptr->prevExpose);
+ d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, 0, d_ptr->flipFlags);
+ }
+ d_ptr->prevExpose = r;
+}
+
+
+void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft,
+ const QRegion &reg)
+{
+ IDirectFBSurface *src = 0;
+ DFBSurfaceDescription description = getSurfaceDescription(img);
+
+ src = createDFBSurface(&description);
+ if (!src) {
+ qWarning("QDirectFBScreen::blit(): Error creating surface");
+ return;
+ }
+#ifndef QT_NO_DIRECTFB_PALETTE
+ setSurfaceColorTable(d_ptr->dfbSurface, img);
+#endif
+
+ blit(src, topLeft, reg);
+
+ releaseDFBSurface(src);
+}
+
+void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft,
+ const QRegion &region)
+{
+ const QVector<QRect> rs = region.translated(-offset()).rects();
+ const int size = rs.size();
+ const QPoint tl = topLeft - offset();
+
+ QVarLengthArray<DFBRectangle> rects(size);
+ QVarLengthArray<DFBPoint> points(size);
+
+ int n = 0;
+ for (int i = 0; i < size; ++i) {
+ const QRect r = rs.at(i);
+ if (!r.isValid())
+ continue;
+ rects[n].x = r.x() - tl.x();
+ rects[n].y = r.y() - tl.y();
+ rects[n].w = r.width();
+ rects[n].h = r.height();
+ points[n].x = r.x();
+ points[n].y = r.y();
+ ++n;
+ }
+
+ d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, src, rects.data(),
+ points.data(), n);
+}
+
+void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ if (region.isEmpty())
+ return;
+
+ const QVector<QRect> rects = region.rects();
+ QVarLengthArray<DFBRectangle> dfbRects(rects.size());
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ dfbRects[i].x = r.x();
+ dfbRects[i].y = r.y();
+ dfbRects[i].w = r.width();
+ dfbRects[i].h = r.height();
+ }
+
+ d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface,
+ color.red(), color.green(), color.blue(),
+ color.alpha());
+ d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, dfbRects.data(),
+ dfbRects.size());
+}
+
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
new file mode 100644
index 0000000..e9a2f63
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTFBSCREEN_H
+#define QDIRECTFBSCREEN_H
+
+#include <QtGui/qscreen_qws.h>
+#include <directfb.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+#define Q_DIRECTFB_VERSION ((DIRECTFB_MAJOR_VERSION << 16) | (DIRECTFB_MINOR_VERION << 8) | DIRECTFB_MICRO_VERSION)
+
+class QDirectFBScreenPrivate;
+
+class Q_GUI_EXPORT QDirectFBScreen : public QScreen
+{
+public:
+ QDirectFBScreen(int display_id);
+ ~QDirectFBScreen();
+
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ bool initDevice();
+ void shutdownDevice();
+
+ void exposeRegion(QRegion r, int changing);
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void scroll(const QRegion &region, const QPoint &offset);
+ void solidFill(const QColor &color, const QRegion &region);
+
+ void setMode(int width, int height, int depth);
+ void blank(bool on);
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+ static inline QDirectFBScreen* instance() {
+ QScreen *inst = QScreen::instance();
+ Q_ASSERT(!inst || inst->classId() == QScreen::DirectFBClass);
+ return static_cast<QDirectFBScreen*>(inst);
+ }
+
+ IDirectFB* dfb();
+ IDirectFBSurface* dfbSurface();
+#ifndef QT_NO_DIRECTFB_LAYER
+ IDirectFBDisplayLayer* dfbDisplayLayer();
+#endif
+
+ // Track surface creation/release so we can release all on exit
+ IDirectFBSurface* createDFBSurface(const DFBSurfaceDescription* desc, bool track = true);
+ void releaseDFBSurface(IDirectFBSurface* surface);
+ bool preferVideoOnly() const;
+
+ static int depth(DFBSurfacePixelFormat format);
+
+ static DFBSurfacePixelFormat getSurfacePixelFormat(const QImage &image);
+ static DFBSurfaceDescription getSurfaceDescription(const QImage &image);
+ static DFBSurfaceDescription getSurfaceDescription(const uint *buffer,
+ int length);
+ static QImage::Format getImageFormat(DFBSurfacePixelFormat format);
+ static inline bool isPremultiplied(QImage::Format format);
+
+#ifndef QT_NO_DIRECTFB_PALETTE
+ static void setSurfaceColorTable(IDirectFBSurface *surface,
+ const QImage &image);
+ static void setImageColorTable(QImage *image, IDirectFBSurface *surface);
+#endif
+
+private:
+ void compose(const QRegion &r);
+ void blit(IDirectFBSurface *src, const QPoint &topLeft,
+ const QRegion &region);
+
+ QDirectFBScreenPrivate *d_ptr;
+};
+
+inline bool QDirectFBScreen::isPremultiplied(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+
+QT_END_HEADER
+
+#endif // QDIRECTFBSCREEN_H
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreenplugin.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreenplugin.cpp
new file mode 100644
index 0000000..ca863d2
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreenplugin.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbscreen.h"
+
+#include <QtGui/qscreendriverplugin_qws.h>
+#include <QtCore/qstringlist.h>
+
+class DirectFBScreenDriverPlugin : public QScreenDriverPlugin
+{
+public:
+ DirectFBScreenDriverPlugin();
+
+ QStringList keys() const;
+ QScreen *create(const QString&, int displayId);
+};
+
+DirectFBScreenDriverPlugin::DirectFBScreenDriverPlugin()
+ : QScreenDriverPlugin()
+{
+}
+
+QStringList DirectFBScreenDriverPlugin::keys() const
+{
+ return (QStringList() << "directfb");
+}
+
+QScreen* DirectFBScreenDriverPlugin::create(const QString& driver,
+ int displayId)
+{
+ if (driver.toLower() != "directfb")
+ return 0;
+
+ return new QDirectFBScreen(displayId);
+}
+
+Q_EXPORT_PLUGIN2(qdirectfbscreen, DirectFBScreenDriverPlugin)
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp
new file mode 100644
index 0000000..ab1d0f1
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbsurface.h"
+#include "qdirectfbscreen.h"
+#include "qdirectfbpaintengine.h"
+
+#include <qwidget.h>
+#include <qpaintdevice.h>
+#include <qvarlengtharray.h>
+
+
+//#define QT_DIRECTFB_DEBUG_SURFACES 1
+
+QDirectFBSurface::QDirectFBSurface(QDirectFBScreen* scr)
+ : QDirectFBPaintDevice(scr)
+#ifndef QT_NO_DIRECTFB_WM
+ , dfbWindow(0)
+#endif
+ , engine(0)
+{
+ setSurfaceFlags(Opaque | Buffered);
+}
+
+QDirectFBSurface::QDirectFBSurface(QDirectFBScreen* scr, QWidget *widget)
+ : QWSWindowSurface(widget), QDirectFBPaintDevice(scr)
+#ifndef QT_NO_DIRECTFB_WM
+ , dfbWindow(0)
+#endif
+ , engine(0)
+{
+ onscreen = widget->testAttribute(Qt::WA_PaintOnScreen);
+ if (onscreen)
+ setSurfaceFlags(Opaque | RegionReserved);
+ else
+ setSurfaceFlags(Opaque | Buffered);
+}
+
+QDirectFBSurface::~QDirectFBSurface()
+{
+}
+
+bool QDirectFBSurface::isValid() const
+{
+ return true;
+}
+
+#ifndef QT_NO_DIRECTFB_WM
+void QDirectFBSurface::createWindow()
+{
+ IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
+ if (!layer)
+ qFatal("QDirectFBWindowSurface: Unable to get primary display layer!");
+
+ DFBWindowDescription description;
+ description.caps = DFBWindowCapabilities(DWCAPS_NODECORATION |
+ DWCAPS_ALPHACHANNEL);
+ description.flags = DWDESC_CAPS;
+
+ DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow);
+ if (result != DFB_OK)
+ DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result);
+
+ if (dfbSurface)
+ dfbSurface->Release(dfbSurface);
+
+ dfbWindow->GetSurface(dfbWindow, &dfbSurface);
+}
+#endif // QT_NO_DIRECTFB_WM
+
+void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask)
+{
+ if (rect.isNull()) {
+#ifndef QT_NO_DIRECTFB_WM
+ if (dfbWindow) {
+ dfbWindow->Release(dfbWindow);
+ dfbWindow = 0;
+ }
+#endif
+ if (dfbSurface) {
+ dfbSurface->Release(dfbSurface);
+ dfbSurface = 0;
+ }
+ } else if (rect != geometry()) {
+ const bool isResize = rect.size() != geometry().size();
+ DFBResult result = DFB_OK;
+
+ // If we're in a resize, the surface shouldn't be locked
+ Q_ASSERT( (lockedImage == 0) || (isResize == false));
+
+ IDirectFBSurface *s = screen->dfbSurface();
+ if (onscreen && s) {
+ if (dfbSurface)
+ dfbSurface->Release(dfbSurface);
+
+ DFBRectangle r = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ result = s->GetSubSurface(s, &r, &dfbSurface);
+ } else {
+#ifdef QT_NO_DIRECTFB_WM
+ if (isResize) {
+ if (dfbSurface)
+ dfbSurface->Release(dfbSurface);
+
+ IDirectFB *dfb = screen->dfb();
+ if (!dfb) {
+ qFatal("QDirectFBWindowSurface::setGeometry(): "
+ "Unable to get DirectFB handle!");
+ }
+
+ DFBSurfaceDescription description;
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
+ DSDESC_HEIGHT |
+ DSDESC_PIXELFORMAT);
+ description.width = rect.width();
+ description.height = rect.height();
+ description.pixelformat = DSPF_ARGB;
+
+ dfbSurface = QDirectFBScreen::instance()->createDFBSurface(&description, false);
+ } else {
+ Q_ASSERT(dfbSurface);
+ }
+#else
+ const QRect oldRect = geometry();
+ const bool isMove = oldRect.isEmpty() ||
+ rect.topLeft() != oldRect.topLeft();
+
+ if (!dfbWindow)
+ createWindow();
+
+ if (isResize && isMove)
+ result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(),
+ rect.width(), rect.height());
+ else if (isResize)
+ result = dfbWindow->Resize(dfbWindow,
+ rect.width(), rect.height());
+ else if (isMove)
+ result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
+#endif
+ }
+
+ if (result != DFB_OK)
+ DirectFBErrorFatal("QDirectFBSurface::setGeometry()", result);
+ }
+
+ QWSWindowSurface::setGeometry(rect, mask);
+}
+
+QByteArray QDirectFBSurface::permanentState() const
+{
+ QByteArray array;
+#ifdef QT_NO_DIRECTFB_WM
+ array.resize(sizeof(SurfaceFlags) + sizeof(IDirectFBSurface*));
+#else
+ array.resize(sizeof(SurfaceFlags));
+#endif
+ char *ptr = array.data();
+
+ *reinterpret_cast<SurfaceFlags*>(ptr) = surfaceFlags();
+ ptr += sizeof(SurfaceFlags);
+
+#ifdef QT_NO_DIRECTFB_WM
+ *reinterpret_cast<IDirectFBSurface**>(ptr) = dfbSurface;
+#endif
+ return array;
+}
+
+void QDirectFBSurface::setPermanentState(const QByteArray &state)
+{
+ SurfaceFlags flags;
+ const char *ptr = state.constData();
+
+ flags = *reinterpret_cast<const SurfaceFlags*>(ptr);
+ setSurfaceFlags(flags);
+
+#ifdef QT_NO_DIRECTFB_WM
+ ptr += sizeof(SurfaceFlags);
+ dfbSurface = *reinterpret_cast<IDirectFBSurface* const*>(ptr);
+#endif
+}
+
+bool QDirectFBSurface::scroll(const QRegion &region, int dx, int dy)
+{
+ if (!dfbSurface)
+ return false;
+
+ const QVector<QRect> rects = region.rects();
+ const int n = rects.size();
+
+ QVarLengthArray<DFBRectangle, 8> dfbRects(n);
+ QVarLengthArray<DFBPoint, 8> dfbPoints(n);
+
+ for (int i = 0; i < n; ++i) {
+ const QRect r = rects.at(i);
+ dfbRects[i].x = r.x();
+ dfbRects[i].y = r.y();
+ dfbRects[i].w = r.width();
+ dfbRects[i].h = r.height();
+ dfbPoints[i].x = r.x() + dx;
+ dfbPoints[i].y = r.y() + dy;
+ }
+
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+ dfbSurface->BatchBlit(dfbSurface, dfbSurface,
+ dfbRects.data(), dfbPoints.data(), n);
+
+ return true;
+}
+
+bool QDirectFBSurface::move(const QPoint &offset)
+{
+ QWSWindowSurface::move(offset);
+
+#ifdef QT_NO_DIRECTFB_WM
+ return true; // buffered
+#else
+ if (!dfbWindow)
+ return false;
+
+ DFBResult status = dfbWindow->Move(dfbWindow, offset.x(), offset.y());
+ return (status == DFB_OK);
+#endif
+}
+
+QRegion QDirectFBSurface::move(const QPoint &offset, const QRegion &newClip)
+{
+#ifdef QT_NO_DIRECTFB_WM
+ return QWSWindowSurface::move(offset, newClip);
+#else
+ Q_UNUSED(offset);
+ Q_UNUSED(newClip);
+
+ // DirectFB handles the entire move, so there's no need to blit.
+ return QRegion();
+#endif
+}
+
+QPaintEngine* QDirectFBSurface::paintEngine() const
+{
+ if (!engine) {
+ QDirectFBSurface *that = const_cast<QDirectFBSurface*>(this);
+ that->engine = new QDirectFBPaintEngine(that);
+ return that->engine;
+ }
+ return engine;
+}
+
+// hw: XXX: copied from QWidgetPrivate::isOpaque()
+inline bool isWidgetOpaque(const QWidget *w)
+{
+ if (w->testAttribute(Qt::WA_OpaquePaintEvent)
+ || w->testAttribute(Qt::WA_PaintOnScreen))
+ return true;
+
+ const QPalette &pal = w->palette();
+
+ if (w->autoFillBackground()) {
+ const QBrush &autoFillBrush = pal.brush(w->backgroundRole());
+ if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque())
+ return true;
+ }
+
+ if (!w->testAttribute(Qt::WA_NoSystemBackground)) {
+ const QBrush &windowBrush = w->palette().brush(QPalette::Window);
+ if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque())
+ return true;
+ }
+
+ return false;
+}
+
+void QDirectFBSurface::flush(QWidget *widget, const QRegion &region,
+ const QPoint &offset)
+{
+ QWidget *win = window();
+
+ // hw: make sure opacity information is updated before compositing
+ const bool opaque = isWidgetOpaque(win);
+ if (opaque != isOpaque()) {
+ SurfaceFlags flags = Buffered;
+ if (opaque)
+ flags |= Opaque;
+ setSurfaceFlags(flags);
+ }
+
+#ifndef QT_NO_DIRECTFB_WM
+ const quint8 winOpacity = quint8(win->windowOpacity() * 255);
+ quint8 opacity;
+
+ if (dfbWindow) {
+ dfbWindow->GetOpacity(dfbWindow, &opacity);
+ if (winOpacity != opacity)
+ dfbWindow->SetOpacity(dfbWindow, winOpacity);
+ }
+#endif
+
+ // XXX: have to call the base function first as the decoration is
+ // currently painted there
+ QWSWindowSurface::flush(widget, region, offset);
+
+#ifndef QT_NO_DIRECTFB_WM
+ const QRect br = region.boundingRect().translated(painterOffset());
+ const DFBRegion r = { br.x(), br.y(),
+ br.x() + br.width(), br.y() + br.height() };
+
+ dfbSurface->Flip(dfbSurface, &r, DSFLIP_NONE);
+#endif
+}
+
+
+void QDirectFBSurface::beginPaint(const QRegion &)
+{
+}
+
+void QDirectFBSurface::endPaint(const QRegion &)
+{
+#ifdef QT_DIRECTFB_DEBUG_SURFACES
+ if (bufferImages.count()) {
+ qDebug("QDirectFBSurface::endPaint() this=%p", this);
+
+ foreach(QImage* bufferImg, bufferImages)
+ qDebug(" Deleting buffer image %p", bufferImg);
+ }
+#endif
+
+ qDeleteAll(bufferImages);
+ bufferImages.clear();
+ unlockDirectFB();
+}
+
+
+QImage* QDirectFBSurface::buffer(const QWidget *widget)
+{
+ if (!lockedImage)
+ return 0;
+
+ const QRect rect = QRect(offset(widget), widget->size())
+ & lockedImage->rect();
+ if (rect.isEmpty())
+ return 0;
+
+ QImage *img = new QImage(lockedImage->scanLine(rect.y())
+ + rect.x() * (lockedImage->depth() / 8),
+ rect.width(), rect.height(),
+ lockedImage->bytesPerLine(),
+ lockedImage->format());
+ bufferImages.append(img);
+
+#ifdef QT_DIRECTFB_DEBUG_SURFACES
+ qDebug("QDirectFBSurface::buffer() Created & returned %p", img);
+#endif
+
+ return img;
+}
+
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h
new file mode 100644
index 0000000..a9cdb7d
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECFBWINDOWSURFACE_H
+#define QDIRECFBWINDOWSURFACE_H
+
+#include "qdirectfbpaintengine.h"
+#include "qdirectfbpaintdevice.h"
+#include "qdirectfbscreen.h"
+
+#include <private/qpaintengine_raster_p.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <directfb.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Gui)
+
+class QDirectFBSurface: public QWSWindowSurface, public QDirectFBPaintDevice
+{
+public:
+ QDirectFBSurface(QDirectFBScreen* scr);
+ QDirectFBSurface(QDirectFBScreen* scr, QWidget *widget);
+ ~QDirectFBSurface();
+
+ bool isValid() const;
+
+ void setGeometry(const QRect &rect, const QRegion &mask);
+
+ QString key() const { return QLatin1String("directfb"); }
+ QByteArray permanentState() const;
+ void setPermanentState(const QByteArray &state);
+
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ bool move(const QPoint &offset);
+ QRegion move(const QPoint &offset, const QRegion &newClip);
+
+ QImage image() const { return QImage(); }
+ QPaintDevice* paintDevice() { return this; }
+ QPaintEngine* paintEngine() const;
+
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+
+ void beginPaint(const QRegion &);
+ void endPaint(const QRegion &);
+
+ QImage* buffer(const QWidget *widget);
+
+private:
+#ifndef QT_NO_DIRECTFB_WM
+ void createWindow();
+ IDirectFBWindow *dfbWindow;
+#endif
+ QDirectFBPaintEngine *engine;
+
+ bool onscreen;
+
+ QList<QImage*> bufferImages;
+};
+
+QT_END_HEADER
+
+#endif // QDIRECFBWINDOWSURFACE_H