| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** 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.1, 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. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qdirectfbscreen.h" |
| #include "qdirectfbwindowsurface.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> |
| |
| #ifndef QT_NO_QWS_DIRECTFB |
| |
| QT_BEGIN_NAMESPACE |
| |
| class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem |
| { |
| Q_OBJECT |
| public: |
| QDirectFBScreenPrivate(QDirectFBScreen *qptr); |
| ~QDirectFBScreenPrivate(); |
| |
| void setFlipFlags(const QStringList &args); |
| QPixmapData *createPixmapData(QPixmapData::PixelType type) const; |
| public slots: |
| #ifdef QT_DIRECTFB_WM |
| void onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event); |
| #endif |
| public: |
| IDirectFB *dfb; |
| DFBSurfaceFlipFlags flipFlags; |
| QDirectFBScreen::DirectFBFlags directFBFlags; |
| QImage::Format alphaPixmapFormat; |
| IDirectFBScreen *dfbScreen; |
| #ifdef QT_NO_DIRECTFB_WM |
| IDirectFBSurface *primarySurface; |
| QColor backgroundColor; |
| #endif |
| #ifndef QT_NO_DIRECTFB_LAYER |
| IDirectFBDisplayLayer *dfbLayer; |
| #endif |
| QSet<IDirectFBSurface*> allocatedSurfaces; |
| |
| #ifndef QT_NO_DIRECTFB_MOUSE |
| QDirectFBMouseHandler *mouse; |
| #endif |
| #ifndef QT_NO_DIRECTFB_KEYBOARD |
| QDirectFBKeyboardHandler *keyboard; |
| #endif |
| #if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
| IDirectFBImageProvider *imageProvider; |
| #endif |
| IDirectFBSurface *cursorSurface; |
| qint64 cursorImageKey; |
| |
| QDirectFBScreen *q; |
| static QDirectFBScreen *instance; |
| }; |
| |
| QDirectFBScreen *QDirectFBScreenPrivate::instance = 0; |
| |
| QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *qptr) |
| : QWSGraphicsSystem(qptr), dfb(0), flipFlags(DSFLIP_NONE), |
| directFBFlags(QDirectFBScreen::NoFlags), alphaPixmapFormat(QImage::Format_Invalid), |
| dfbScreen(0) |
| #ifdef QT_NO_DIRECTFB_WM |
| , primarySurface(0) |
| #endif |
| #ifndef QT_NO_DIRECTFB_LAYER |
| , dfbLayer(0) |
| #endif |
| #ifndef QT_NO_DIRECTFB_MOUSE |
| , mouse(0) |
| #endif |
| #ifndef QT_NO_DIRECTFB_KEYBOARD |
| , keyboard(0) |
| #endif |
| #if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
| , imageProvider(0) |
| #endif |
| , cursorSurface(0) |
| , cursorImageKey(0) |
| , q(qptr) |
| { |
| #ifndef QT_NO_QWS_SIGNALHANDLER |
| QWSSignalHandler::instance()->addObject(this); |
| #endif |
| #ifdef QT_DIRECTFB_WM |
| connect(QWSServer::instance(), SIGNAL(windowEvent(QWSWindow*,QWSServer::WindowEvent)), |
| this, SLOT(onWindowEvent(QWSWindow*,QWSServer::WindowEvent))); |
| #endif |
| } |
| |
| QDirectFBScreenPrivate::~QDirectFBScreenPrivate() |
| { |
| #ifndef QT_NO_DIRECTFB_MOUSE |
| delete mouse; |
| #endif |
| #ifndef QT_NO_DIRECTFB_KEYBOARD |
| delete keyboard; |
| #endif |
| #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
| if (imageProvider) |
| imageProvider->Release(imageProvider); |
| #endif |
| |
| for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) { |
| (*it)->Release(*it); |
| } |
| |
| #ifdef QT_NO_DIRECTFB_WM |
| if (primarySurface) |
| primarySurface->Release(primarySurface); |
| #endif |
| |
| #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 QImage &image, QImage::Format format, SurfaceCreationOptions options, DFBResult *resultPtr) |
| { |
| if (image.isNull()) // assert? |
| return 0; |
| |
| if (QDirectFBScreen::getSurfacePixelFormat(format) == DSPF_UNKNOWN) { |
| format = QDirectFBPixmapData::hasAlphaChannel(image) ? d_ptr->alphaPixmapFormat : pixelFormat(); |
| } |
| if (image.format() != format) { |
| return createDFBSurface(image.convertToFormat(format), format, options | NoPreallocated, resultPtr); |
| } |
| |
| DFBSurfaceDescription description; |
| memset(&description, 0, sizeof(DFBSurfaceDescription)); |
| description.width = image.width(); |
| description.height = image.height(); |
| description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT; |
| initSurfaceDescriptionPixelFormat(&description, format); |
| bool doMemCopy = true; |
| #ifdef QT_DIRECTFB_PREALLOCATED |
| if (!(options & NoPreallocated)) { |
| doMemCopy = false; |
| description.flags |= DSDESC_PREALLOCATED; |
| description.preallocated[0].data = const_cast<uchar*>(image.bits()); |
| description.preallocated[0].pitch = image.bytesPerLine(); |
| description.preallocated[1].data = 0; |
| description.preallocated[1].pitch = 0; |
| } |
| #endif |
| DFBResult result; |
| IDirectFBSurface *surface = createDFBSurface(description, options, &result); |
| if (resultPtr) |
| *resultPtr = result; |
| if (!surface) { |
| DirectFBError("Couldn't create surface createDFBSurface(QImage, QImage::Format, SurfaceCreationOptions)", result); |
| return 0; |
| } |
| if (doMemCopy) { |
| int bplDFB; |
| uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bplDFB); |
| if (mem) { |
| const int height = image.height(); |
| const int bplQt = image.bytesPerLine(); |
| if (bplQt == bplDFB && bplQt == (image.width() * image.depth() / 8)) { |
| memcpy(mem, image.bits(), image.byteCount()); |
| } else { |
| for (int i=0; i<height; ++i) { |
| memcpy(mem, image.scanLine(i), bplQt); |
| mem += bplDFB; |
| } |
| } |
| surface->Unlock(surface); |
| } |
| } |
| #ifdef QT_DIRECTFB_PALETTE |
| if (image.colorCount() != 0 && surface) |
| QDirectFBScreen::setSurfaceColorTable(surface, image); |
| #endif |
| return surface; |
| } |
| |
| IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src, |
| QImage::Format format, |
| SurfaceCreationOptions options, |
| DFBResult *result) |
| { |
| Q_ASSERT(src); |
| QSize size; |
| src->GetSize(src, &size.rwidth(), &size.rheight()); |
| IDirectFBSurface *surface = createDFBSurface(size, format, options, result); |
| DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlphaChannel(surface) |
| ? DSBLIT_BLEND_ALPHACHANNEL |
| : DSBLIT_NOFX; |
| if (flags & DSBLIT_BLEND_ALPHACHANNEL) |
| surface->Clear(surface, 0, 0, 0, 0); |
| |
| surface->SetBlittingFlags(surface, flags); |
| surface->Blit(surface, src, 0, 0, 0); |
| #if (Q_DIRECTFB_VERSION >= 0x010000) |
| surface->ReleaseSource(surface); |
| #endif |
| return surface; |
| } |
| |
| IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, |
| QImage::Format format, |
| SurfaceCreationOptions options, |
| DFBResult *result) |
| { |
| DFBSurfaceDescription desc; |
| memset(&desc, 0, sizeof(DFBSurfaceDescription)); |
| desc.flags |= DSDESC_WIDTH|DSDESC_HEIGHT; |
| if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format)) |
| return 0; |
| desc.width = size.width(); |
| desc.height = size.height(); |
| return createDFBSurface(desc, options, result); |
| } |
| |
| IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options, DFBResult *resultPtr) |
| { |
| DFBResult tmp; |
| DFBResult &result = (resultPtr ? *resultPtr : tmp); |
| result = DFB_OK; |
| IDirectFBSurface *newSurface = 0; |
| |
| if (!d_ptr->dfb) { |
| qWarning("QDirectFBScreen::createDFBSurface() - not connected"); |
| return 0; |
| } |
| |
| if (d_ptr->directFBFlags & VideoOnly |
| && !(desc.flags & DSDESC_PREALLOCATED) |
| && (!(desc.flags & DSDESC_CAPS) || !(desc.caps & DSCAPS_SYSTEMONLY))) { |
| // Add the video only capability. This means the surface will be created in video ram |
| if (!(desc.flags & DSDESC_CAPS)) { |
| desc.caps = DSCAPS_VIDEOONLY; |
| desc.flags |= DSDESC_CAPS; |
| } else { |
| desc.caps |= DSCAPS_VIDEOONLY; |
| } |
| result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); |
| if (result != DFB_OK |
| #ifdef QT_NO_DEBUG |
| && (desc.flags & DSDESC_CAPS) && (desc.caps & DSCAPS_PRIMARY) |
| #endif |
| ) { |
| qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\n" |
| " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", |
| desc.flags, desc.caps, desc.width, desc.height, |
| desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat), |
| desc.preallocated[0].data, desc.preallocated[0].pitch, |
| DirectFBErrorString(result)); |
| } |
| desc.caps &= ~DSCAPS_VIDEOONLY; |
| } |
| |
| if (d_ptr->directFBFlags & SystemOnly) |
| desc.caps |= DSCAPS_SYSTEMONLY; |
| |
| if (!newSurface) |
| result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); |
| |
| if (result != DFB_OK) { |
| qWarning("QDirectFBScreen::createDFBSurface() Failed!\n" |
| " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", |
| desc.flags, desc.caps, desc.width, desc.height, |
| desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat), |
| desc.preallocated[0].data, desc.preallocated[0].pitch, |
| DirectFBErrorString(result)); |
| return 0; |
| } |
| |
| Q_ASSERT(newSurface); |
| |
| if (options & TrackSurface) { |
| d_ptr->allocatedSurfaces.insert(newSurface); |
| } |
| |
| return newSurface; |
| } |
| |
| #ifdef QT_DIRECTFB_SUBSURFACE |
| IDirectFBSurface *QDirectFBScreen::getSubSurface(IDirectFBSurface *surface, |
| const QRect &rect, |
| SurfaceCreationOptions options, |
| DFBResult *resultPtr) |
| { |
| Q_ASSERT(!(options & NoPreallocated)); |
| Q_ASSERT(surface); |
| DFBResult res; |
| DFBResult &result = (resultPtr ? *resultPtr : res); |
| IDirectFBSurface *subSurface = 0; |
| if (rect.isNull()) { |
| result = surface->GetSubSurface(surface, 0, &subSurface); |
| } else { |
| const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() }; |
| result = surface->GetSubSurface(surface, &subRect, &subSurface); |
| } |
| if (result != DFB_OK) { |
| DirectFBError("Can't get sub surface", result); |
| } else if (options & TrackSurface) { |
| d_ptr->allocatedSurfaces.insert(subSurface); |
| } |
| return subSurface; |
| } |
| #endif |
| |
| |
| void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface) |
| { |
| Q_ASSERT(QDirectFBScreen::instance()); |
| 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()); |
| } |
| |
| QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const |
| { |
| return d_ptr->directFBFlags; |
| } |
| |
| IDirectFB *QDirectFBScreen::dfb() |
| { |
| return d_ptr->dfb; |
| } |
| |
| #ifdef QT_NO_DIRECTFB_WM |
| IDirectFBSurface *QDirectFBScreen::primarySurface() |
| { |
| return d_ptr->primarySurface; |
| } |
| #endif |
| |
| #ifndef QT_NO_DIRECTFB_LAYER |
| IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer() |
| { |
| return d_ptr->dfbLayer; |
| } |
| #endif |
| |
| DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format format) |
| { |
| switch (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; |
| #if (Q_DIRECTFB_VERSION >= 0x010000) |
| case QImage::Format_ARGB6666_Premultiplied: |
| return DSPF_ARGB6666; |
| case QImage::Format_RGB666: |
| return DSPF_RGB18; |
| #endif |
| 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(IDirectFBSurface *surface) |
| { |
| DFBSurfacePixelFormat format; |
| surface->GetPixelFormat(surface, &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; |
| #if (Q_DIRECTFB_VERSION >= 0x010000) |
| case DSPF_ARGB6666: |
| return QImage::Format_ARGB6666_Premultiplied; |
| case DSPF_RGB18: |
| return QImage::Format_RGB666; |
| #endif |
| case DSPF_RGB32: |
| return QImage::Format_RGB32; |
| case DSPF_ARGB: { |
| DFBSurfaceCapabilities caps; |
| const DFBResult result = surface->GetCapabilities(surface, &caps); |
| Q_ASSERT(result == DFB_OK); |
| Q_UNUSED(result); |
| return (caps & DSCAPS_PREMULTIPLIED |
| ? QImage::Format_ARGB32_Premultiplied |
| : QImage::Format_ARGB32); } |
| default: |
| break; |
| } |
| return QImage::Format_Invalid; |
| } |
| |
| DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer, |
| int length) |
| { |
| DFBSurfaceDescription description; |
| memset(&description, 0, sizeof(DFBSurfaceDescription)); |
| |
| description.flags = 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.colorCount(); |
| if (numColors == 0) |
| return; |
| |
| QVarLengthArray<DFBColor, 256> 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); |
| } |
| |
| #endif // QT_NO_DIRECTFB_PALETTE |
| |
| #if defined QT_DIRECTFB_CURSOR |
| class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor |
| { |
| public: |
| QDirectFBScreenCursor(); |
| virtual void set(const QImage &image, int hotx, int hoty); |
| virtual void move(int x, int y); |
| virtual void show(); |
| virtual void hide(); |
| private: |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| ~QDirectFBScreenCursor(); |
| bool createWindow(); |
| IDirectFBWindow *window; |
| #endif |
| IDirectFBDisplayLayer *layer; |
| }; |
| |
| QDirectFBScreenCursor::QDirectFBScreenCursor() |
| { |
| IDirectFB *fb = QDirectFBScreen::instance()->dfb(); |
| if (!fb) |
| qFatal("QDirectFBScreenCursor: DirectFB not initialized"); |
| |
| layer = QDirectFBScreen::instance()->dfbDisplayLayer(); |
| Q_ASSERT(layer); |
| |
| enable = false; |
| hwaccel = true; |
| supportsAlpha = true; |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| window = 0; |
| DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cooperative level", result); |
| } |
| result = layer->SetCursorOpacity(layer, 0); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cursor opacity", result); |
| } |
| |
| result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cooperative level", result); |
| } |
| #endif |
| } |
| |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| QDirectFBScreenCursor::~QDirectFBScreenCursor() |
| { |
| if (window) { |
| window->Release(window); |
| window = 0; |
| } |
| } |
| |
| bool QDirectFBScreenCursor::createWindow() |
| { |
| Q_ASSERT(!window); |
| Q_ASSERT(!cursor.isNull()); |
| DFBWindowDescription description; |
| memset(&description, 0, sizeof(DFBWindowDescription)); |
| description.flags = DWDESC_POSX|DWDESC_POSY|DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|DWDESC_PIXELFORMAT|DWDESC_SURFACE_CAPS; |
| description.width = cursor.width(); |
| description.height = cursor.height(); |
| description.posx = pos.x() - hotspot.x(); |
| description.posy = pos.y() - hotspot.y(); |
| #if (Q_DIRECTFB_VERSION >= 0x010100) |
| description.flags |= DWDESC_OPTIONS; |
| description.options = DWOP_GHOST|DWOP_ALPHACHANNEL; |
| #endif |
| description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER; |
| const QImage::Format format = QDirectFBScreen::instance()->alphaPixmapFormat(); |
| description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); |
| if (QDirectFBScreen::isPremultiplied(format)) |
| description.surface_caps = DSCAPS_PREMULTIPLIED; |
| |
| DFBResult result = layer->CreateWindow(layer, &description, &window); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::createWindow: Unable to create window", result); |
| return false; |
| } |
| result = window->SetOpacity(window, 255); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set opacity ", result); |
| return false; |
| } |
| |
| result = window->SetStackingClass(window, DWSC_UPPER); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set stacking class ", result); |
| return false; |
| } |
| |
| result = window->RaiseToTop(window); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::createWindow: Unable to raise window ", result); |
| return false; |
| } |
| |
| return true; |
| } |
| #endif |
| |
| void QDirectFBScreenCursor::move(int x, int y) |
| { |
| pos = QPoint(x, y); |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| if (window) { |
| const QPoint p = pos - hotspot; |
| DFBResult result = window->MoveTo(window, p.x(), p.y()); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::move: Unable to move window", result); |
| } |
| } |
| #else |
| layer->WarpCursor(layer, x, y); |
| #endif |
| } |
| |
| void QDirectFBScreenCursor::hide() |
| { |
| if (enable) { |
| enable = false; |
| DFBResult result; |
| #ifndef QT_DIRECTFB_WINDOW_AS_CURSOR |
| result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cooperative level", result); |
| } |
| result = layer->SetCursorOpacity(layer, 0); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cursor opacity", result); |
| } |
| result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set cooperative level", result); |
| } |
| #else |
| if (window) { |
| result = window->SetOpacity(window, 0); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::hide: " |
| "Unable to set window opacity", result); |
| } |
| } |
| #endif |
| } |
| } |
| |
| void QDirectFBScreenCursor::show() |
| { |
| if (!enable) { |
| enable = true; |
| DFBResult result; |
| result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cooperative level", result); |
| } |
| result = layer->SetCursorOpacity(layer, |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| 0 |
| #else |
| 255 |
| #endif |
| ); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cursor shape", result); |
| } |
| result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cooperative level", result); |
| } |
| #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR |
| if (window) { |
| DFBResult result = window->SetOpacity(window, 255); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set window opacity", result); |
| } |
| } |
| #endif |
| } |
| } |
| |
| void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty) |
| { |
| QDirectFBScreen *screen = QDirectFBScreen::instance(); |
| if (!screen) |
| return; |
| |
| if (image.isNull()) { |
| cursor = QImage(); |
| hide(); |
| } else { |
| cursor = image.convertToFormat(screen->alphaPixmapFormat()); |
| size = cursor.size(); |
| hotspot = QPoint(hotx, hoty); |
| DFBResult result = DFB_OK; |
| IDirectFBSurface *surface = screen->createDFBSurface(cursor, screen->alphaPixmapFormat(), |
| QDirectFBScreen::DontTrackSurface, &result); |
| if (!surface) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to create surface", result); |
| return; |
| } |
| #ifndef QT_DIRECTFB_WINDOW_AS_CURSOR |
| result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cooperative level", result); |
| } |
| result = layer->SetCursorShape(layer, surface, hotx, hoty); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cursor shape", result); |
| } |
| result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::show: " |
| "Unable to set cooperative level", result); |
| } |
| #else |
| if (window || createWindow()) { |
| QSize windowSize; |
| result = window->GetSize(window, &windowSize.rwidth(), &windowSize.rheight()); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: " |
| "Unable to get window size", result); |
| } |
| result = window->Resize(window, size.width(), size.height()); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to resize window", result); |
| } |
| |
| IDirectFBSurface *windowSurface; |
| result = window->GetSurface(window, &windowSurface); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to get window surface", result); |
| } else { |
| result = windowSurface->Clear(windowSurface, 0, 0, 0, 0); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to clear surface", result); |
| } |
| |
| result = windowSurface->Blit(windowSurface, surface, 0, 0, 0); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to blit to surface", result); |
| } |
| } |
| result = windowSurface->Flip(windowSurface, 0, DSFLIP_NONE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::set: Unable to flip window", result); |
| } |
| |
| windowSurface->Release(windowSurface); |
| } |
| #endif |
| surface->Release(surface); |
| show(); |
| } |
| |
| } |
| #endif // QT_DIRECTFB_CURSOR |
| |
| QDirectFBScreen::QDirectFBScreen(int display_id) |
| : QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this)) |
| { |
| QDirectFBScreenPrivate::instance = this; |
| } |
| |
| QDirectFBScreen::~QDirectFBScreen() |
| { |
| if (QDirectFBScreenPrivate::instance == this) |
| QDirectFBScreenPrivate::instance = 0; |
| delete d_ptr; |
| } |
| |
| QDirectFBScreen *QDirectFBScreen::instance() |
| { |
| return QDirectFBScreenPrivate::instance; |
| } |
| |
| 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; |
| } |
| |
| int QDirectFBScreen::depth(QImage::Format format) |
| { |
| int depth = 0; |
| switch(format) { |
| case QImage::Format_Invalid: |
| case QImage::NImageFormats: |
| Q_ASSERT(false); |
| case QImage::Format_Mono: |
| case QImage::Format_MonoLSB: |
| depth = 1; |
| break; |
| case QImage::Format_Indexed8: |
| depth = 8; |
| break; |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| depth = 32; |
| break; |
| case QImage::Format_RGB555: |
| case QImage::Format_RGB16: |
| case QImage::Format_RGB444: |
| case QImage::Format_ARGB4444_Premultiplied: |
| depth = 16; |
| break; |
| case QImage::Format_RGB666: |
| case QImage::Format_ARGB6666_Premultiplied: |
| case QImage::Format_ARGB8565_Premultiplied: |
| case QImage::Format_ARGB8555_Premultiplied: |
| case QImage::Format_RGB888: |
| depth = 24; |
| break; |
| } |
| return depth; |
| } |
| |
| void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) |
| { |
| QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$")); |
| int index = args.indexOf(flipRegexp); |
| if (index >= 0) { |
| const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','), |
| QString::SkipEmptyParts); |
| flipFlags = DSFLIP_NONE; |
| foreach(const QString &flip, flips) { |
| if (flip == QLatin1String("wait")) |
| flipFlags |= DSFLIP_WAIT; |
| else if (flip == QLatin1String("blit")) |
| flipFlags |= DSFLIP_BLIT; |
| else if (flip == QLatin1String("onsync")) |
| flipFlags |= DSFLIP_ONSYNC; |
| else if (flip == QLatin1String("pipeline")) |
| flipFlags |= DSFLIP_PIPELINE; |
| else |
| qWarning("QDirectFBScreen: Unknown flip argument: %s", |
| qPrintable(flip)); |
| } |
| } else { |
| flipFlags = DSFLIP_BLIT|DSFLIP_ONSYNC; |
| } |
| } |
| |
| #ifdef QT_DIRECTFB_WM |
| void QDirectFBScreenPrivate::onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event) |
| { |
| if (event == QWSServer::Raise) { |
| QWSWindowSurface *windowSurface = window->windowSurface(); |
| if (windowSurface && windowSurface->key() == QLatin1String("directfb")) { |
| static_cast<QDirectFBWindowSurface*>(windowSurface)->raise(); |
| } |
| } |
| } |
| #endif |
| |
| QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const |
| { |
| if (type == QPixmapData::BitmapType) |
| return QWSGraphicsSystem::createPixmapData(type); |
| |
| return new QDirectFBPixmapData(q, type); |
| } |
| |
| #if (Q_DIRECTFB_VERSION >= 0x000923) |
| #ifdef QT_NO_DEBUG |
| struct FlagDescription; |
| static const FlagDescription *accelerationDescriptions = 0; |
| static const FlagDescription *blitDescriptions = 0; |
| static const FlagDescription *drawDescriptions = 0; |
| #else |
| struct FlagDescription { |
| const char *name; |
| uint flag; |
| }; |
| |
| static const FlagDescription accelerationDescriptions[] = { |
| { "DFXL_NONE", DFXL_NONE }, |
| { "DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE }, |
| { "DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE }, |
| { "DFXL_DRAWLINE", DFXL_DRAWLINE }, |
| { "DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE }, |
| { "DFXL_BLIT", DFXL_BLIT }, |
| { "DFXL_STRETCHBLIT", DFXL_STRETCHBLIT }, |
| { "DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES }, |
| { "DFXL_DRAWSTRING", DFXL_DRAWSTRING }, |
| { 0, 0 } |
| }; |
| |
| static const FlagDescription blitDescriptions[] = { |
| { "DSBLIT_NOFX", DSBLIT_NOFX }, |
| { "DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL }, |
| { "DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA }, |
| { "DSBLIT_COLORIZE", DSBLIT_COLORIZE }, |
| { "DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY }, |
| { "DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY }, |
| { "DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY }, |
| { "DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY }, |
| { "DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY }, |
| { "DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE }, |
| #if (Q_DIRECTFB_VERSION >= 0x000923) |
| { "DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR }, |
| { "DSBLIT_XOR", DSBLIT_XOR }, |
| #endif |
| #if (Q_DIRECTFB_VERSION >= 0x010000) |
| { "DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION }, |
| #endif |
| { 0, 0 } |
| }; |
| |
| static const FlagDescription drawDescriptions[] = { |
| { "DSDRAW_NOFX", DSDRAW_NOFX }, |
| { "DSDRAW_BLEND", DSDRAW_BLEND }, |
| { "DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY }, |
| { "DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY }, |
| { "DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY }, |
| { "DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY }, |
| { "DSDRAW_XOR", DSDRAW_XOR }, |
| { 0, 0 } |
| }; |
| #endif |
| |
| static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags) |
| { |
| #ifdef QT_NO_DEBUG |
| Q_UNUSED(mask); |
| Q_UNUSED(flags); |
| return QByteArray(""); |
| #else |
| if (!mask) |
| return flags[0].name; |
| |
| QStringList list; |
| for (int i=1; flags[i].name; ++i) { |
| if (mask & flags[i].flag) { |
| list.append(QString::fromLatin1(flags[i].name)); |
| } |
| } |
| Q_ASSERT(!list.isEmpty()); |
| return (QLatin1Char(' ') + list.join(QLatin1String("|"))).toLatin1(); |
| #endif |
| } |
| static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface) |
| { |
| DFBResult result; |
| DFBGraphicsDeviceDescription dev; |
| |
| result = fb->GetDeviceDescription(fb, &dev); |
| if (result != DFB_OK) { |
| DirectFBError("Error reading graphics device description", result); |
| return; |
| } |
| |
| DFBSurfacePixelFormat pixelFormat; |
| primarySurface->GetPixelFormat(primarySurface, &pixelFormat); |
| |
| qDebug("Device: %s (%s), Driver: %s v%i.%i (%s) Pixelformat: %d (%d)\n" |
| "acceleration: 0x%x%s\nblit: 0x%x%s\ndraw: 0x%0x%s\nvideo: %iKB\n", |
| dev.name, dev.vendor, dev.driver.name, dev.driver.major, |
| dev.driver.minor, dev.driver.vendor, DFB_PIXELFORMAT_INDEX(pixelFormat), |
| QDirectFBScreen::getImageFormat(primarySurface), dev.acceleration_mask, |
| flagDescriptions(dev.acceleration_mask, accelerationDescriptions).constData(), |
| dev.blitting_flags, flagDescriptions(dev.blitting_flags, blitDescriptions).constData(), |
| dev.drawing_flags, flagDescriptions(dev.drawing_flags, drawDescriptions).constData(), |
| (dev.video_memory >> 10)); |
| } |
| #endif |
| |
| static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value) |
| { |
| Q_ASSERT(value); |
| QRegExp rx(QString::fromLatin1("%1=?(\\d+)").arg(variable)); |
| rx.setCaseSensitivity(Qt::CaseInsensitive); |
| if (arguments.indexOf(rx) != -1) { |
| *value = rx.cap(1).toInt(); |
| return true; |
| } |
| return false; |
| } |
| |
| static inline QColor colorFromName(const QString &name) |
| { |
| QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")); |
| rx.setCaseSensitivity(Qt::CaseInsensitive); |
| if (rx.exactMatch(name)) { |
| Q_ASSERT(rx.captureCount() == 4); |
| int ints[4]; |
| int i; |
| for (i=0; i<4; ++i) { |
| bool ok; |
| ints[i] = rx.cap(i + 1).toUInt(&ok, 16); |
| if (!ok || ints[i] > 255) |
| break; |
| } |
| if (i == 4) |
| return QColor(ints[0], ints[1], ints[2], ints[3]); |
| } |
| return QColor(name); |
| } |
| |
| 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("videoonly"), Qt::CaseInsensitive)) |
| d_ptr->directFBFlags |= VideoOnly; |
| |
| if (displayArgs.contains(QLatin1String("systemonly"), Qt::CaseInsensitive)) { |
| if (d_ptr->directFBFlags & VideoOnly) { |
| qWarning("QDirectFBScreen: error. videoonly and systemonly are mutually exclusive"); |
| } else { |
| d_ptr->directFBFlags |= SystemOnly; |
| } |
| } |
| |
| if (displayArgs.contains(QLatin1String("boundingrectflip"), Qt::CaseInsensitive)) { |
| d_ptr->directFBFlags |= BoundingRectFlip; |
| } else if (displayArgs.contains(QLatin1String("nopartialflip"), Qt::CaseInsensitive)) { |
| d_ptr->directFBFlags |= NoPartialFlip; |
| } |
| |
| #ifdef QT_DIRECTFB_IMAGECACHE |
| int imageCacheSize = 4 * 1024 * 1024; // 4 MB |
| setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize); |
| QDirectFBPaintEngine::initImageCache(imageCacheSize); |
| #endif |
| |
| #ifndef QT_NO_DIRECTFB_WM |
| if (displayArgs.contains(QLatin1String("fullscreen"))) |
| #endif |
| d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN); |
| |
| const bool forcePremultiplied = displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive); |
| |
| DFBSurfaceDescription description; |
| memset(&description, 0, sizeof(DFBSurfaceDescription)); |
| IDirectFBSurface *surface; |
| |
| #ifdef QT_NO_DIRECTFB_WM |
| description.flags = DSDESC_CAPS; |
| if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) |
| description.flags |= DSDESC_WIDTH; |
| if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) |
| description.flags |= DSDESC_HEIGHT; |
| |
| description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; |
| struct { |
| const char *name; |
| const DFBSurfaceCapabilities cap; |
| } const capabilities[] = { |
| { "static_alloc", DSCAPS_STATIC_ALLOC }, |
| { "triplebuffer", DSCAPS_TRIPLE }, |
| { "interlaced", DSCAPS_INTERLACED }, |
| { "separated", DSCAPS_SEPARATED }, |
| // { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported |
| { 0, DSCAPS_NONE } |
| }; |
| for (int i=0; capabilities[i].name; ++i) { |
| if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive)) |
| description.caps |= capabilities[i].cap; |
| } |
| |
| if (forcePremultiplied) { |
| description.caps |= DSCAPS_PREMULTIPLIED; |
| } |
| |
| // We don't track the primary surface as it's released in disconnect |
| d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result); |
| if (!d_ptr->primarySurface) { |
| DirectFBError("QDirectFBScreen: error creating primary surface", |
| result); |
| return false; |
| } |
| |
| surface = d_ptr->primarySurface; |
| #else |
| description.flags = DSDESC_WIDTH|DSDESC_HEIGHT; |
| description.width = description.height = 1; |
| surface = createDFBSurface(description, DontTrackSurface, &result); |
| if (!surface) { |
| DirectFBError("QDirectFBScreen: error creating surface", result); |
| return false; |
| } |
| #endif |
| // Work out what format we're going to use for surfaces with an alpha channel |
| QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface); |
| d_ptr->alphaPixmapFormat = pixelFormat; |
| |
| switch (pixelFormat) { |
| case QImage::Format_RGB666: |
| d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied; |
| break; |
| case QImage::Format_RGB444: |
| d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied; |
| break; |
| case QImage::Format_RGB32: |
| pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; |
| // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps |
| break; |
| case QImage::Format_Indexed8: |
| qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8 pixelformat."); |
| return false; |
| case QImage::NImageFormats: |
| case QImage::Format_Invalid: |
| case QImage::Format_Mono: |
| case QImage::Format_MonoLSB: |
| case QImage::Format_RGB888: |
| case QImage::Format_RGB16: |
| case QImage::Format_RGB555: |
| d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; |
| break; |
| case QImage::Format_ARGB32: |
| if (forcePremultiplied) |
| d_ptr->alphaPixmapFormat = pixelFormat = QImage::Format_ARGB32_Premultiplied; |
| case QImage::Format_ARGB32_Premultiplied: |
| case QImage::Format_ARGB4444_Premultiplied: |
| case QImage::Format_ARGB8555_Premultiplied: |
| case QImage::Format_ARGB8565_Premultiplied: |
| case QImage::Format_ARGB6666_Premultiplied: |
| // works already |
| break; |
| } |
| setPixelFormat(pixelFormat); |
| QScreen::d = QDirectFBScreen::depth(pixelFormat); |
| data = 0; |
| lstep = 0; |
| size = 0; |
| |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::connect: " |
| "Unable to get screen!", result); |
| return false; |
| } |
| const QString qws_size = QString::fromLatin1(qgetenv("QWS_SIZE")); |
| if (!qws_size.isEmpty()) { |
| QRegExp rx(QLatin1String("(\\d+)x(\\d+)")); |
| if (!rx.exactMatch(qws_size)) { |
| qWarning("QDirectFBScreen::connect: Can't parse QWS_SIZE=\"%s\"", qPrintable(qws_size)); |
| } else { |
| int *ints[2] = { &w, &h }; |
| for (int i=0; i<2; ++i) { |
| *ints[i] = rx.cap(i + 1).toInt(); |
| if (*ints[i] <= 0) { |
| qWarning("QDirectFBScreen::connect: %s is not a positive integer", |
| qPrintable(rx.cap(i + 1))); |
| w = h = 0; |
| break; |
| } |
| } |
| } |
| } |
| |
| setIntOption(displayArgs, QLatin1String("width"), &w); |
| setIntOption(displayArgs, QLatin1String("height"), &h); |
| |
| #ifndef QT_NO_DIRECTFB_LAYER |
| int layerId = DLID_PRIMARY; |
| setIntOption(displayArgs, QLatin1String("layerid"), &layerId); |
| |
| result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, static_cast<DFBDisplayLayerID>(layerId), |
| &d_ptr->dfbLayer); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::connect: " |
| "Unable to get 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 (w <= 0 || h <= 0) { |
| #ifdef QT_NO_DIRECTFB_WM |
| result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); |
| #elif (Q_DIRECTFB_VERSION >= 0x010000) |
| IDirectFBSurface *layerSurface; |
| if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) == DFB_OK) { |
| result = layerSurface->GetSize(layerSurface, &w, &h); |
| layerSurface->Release(layerSurface); |
| } |
| if (w <= 0 || h <= 0) { |
| result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); |
| } |
| #else |
| qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n" |
| "query the size of the primary surface in windowed mode. You have to specify\n" |
| "the size of the display using QWS_SIZE=[0-9]x[0-9] or\n" |
| "QWS_DISPLAY=directfb:width=[0-9]:height=[0-9]"); |
| return false; |
| #endif |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::connect: " |
| "Unable to get screen size!", result); |
| return false; |
| } |
| } |
| |
| |
| dw = w; |
| dh = h; |
| |
| Q_ASSERT(dw != 0 && dh != 0); |
| |
| physWidth = physHeight = -1; |
| setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth); |
| setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight); |
| const int dpi = 72; |
| if (physWidth < 0) |
| physWidth = qRound(dw * 25.4 / dpi); |
| if (physHeight < 0) |
| physHeight = qRound(dh * 25.4 / dpi); |
| |
| setGraphicsSystem(d_ptr); |
| |
| #if (Q_DIRECTFB_VERSION >= 0x000923) |
| if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive)) |
| printDirectFBInfo(d_ptr->dfb, surface); |
| #endif |
| #ifdef QT_DIRECTFB_WM |
| surface->Release(surface); |
| QColor backgroundColor; |
| #else |
| QColor &backgroundColor = d_ptr->backgroundColor; |
| #endif |
| |
| QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)")); |
| backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive); |
| if (displayArgs.indexOf(backgroundColorRegExp) != -1) { |
| backgroundColor = colorFromName(backgroundColorRegExp.cap(1)); |
| } |
| #ifdef QT_NO_DIRECTFB_WM |
| if (!backgroundColor.isValid()) |
| backgroundColor = Qt::green; |
| d_ptr->primarySurface->Clear(d_ptr->primarySurface, backgroundColor.red(), |
| backgroundColor.green(), backgroundColor.blue(), |
| backgroundColor.alpha()); |
| d_ptr->primarySurface->Flip(d_ptr->primarySurface, 0, d_ptr->flipFlags); |
| #else |
| if (backgroundColor.isValid()) { |
| DFBResult result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_ADMINISTRATIVE); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::connect " |
| "Unable to set cooperative level", result); |
| } |
| result = d_ptr->dfbLayer->SetBackgroundColor(d_ptr->dfbLayer, backgroundColor.red(), backgroundColor.green(), |
| backgroundColor.blue(), backgroundColor.alpha()); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::connect: " |
| "Unable to set background color", result); |
| } |
| |
| result = d_ptr->dfbLayer->SetBackgroundMode(d_ptr->dfbLayer, DLBM_COLOR); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreenCursor::connect: " |
| "Unable to set background mode", result); |
| } |
| |
| result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_SHARED); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::connect " |
| "Unable to set cooperative level", result); |
| } |
| |
| } |
| #endif |
| |
| return true; |
| } |
| |
| void QDirectFBScreen::disconnect() |
| { |
| #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
| if (d_ptr->imageProvider) |
| d_ptr->imageProvider->Release(d_ptr->imageProvider); |
| #endif |
| #ifdef QT_NO_DIRECTFB_WM |
| d_ptr->primarySurface->Release(d_ptr->primarySurface); |
| d_ptr->primarySurface = 0; |
| #endif |
| |
| foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces) |
| surf->Release(surf); |
| 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() |
| { |
| #ifndef QT_NO_DIRECTFB_MOUSE |
| if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) { |
| QWSServer::instance()->setDefaultMouse("None"); |
| d_ptr->mouse = new QDirectFBMouseHandler; |
| } |
| #endif |
| #ifndef QT_NO_DIRECTFB_KEYBOARD |
| if (qgetenv("QWS_KEYBOARD").isEmpty()) { |
| QWSServer::instance()->setDefaultKeyboard("None"); |
| d_ptr->keyboard = new QDirectFBKeyboardHandler(QString()); |
| } |
| #endif |
| |
| #ifdef QT_DIRECTFB_CURSOR |
| qt_screencursor = new QDirectFBScreenCursor; |
| #elif !defined QT_NO_QWS_CURSOR |
| QScreenCursor::initSoftwareCursor(); |
| #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 QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); |
| } else { |
| return QScreen::createSurface(widget); |
| } |
| #else |
| return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); |
| #endif |
| } |
| |
| QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const |
| { |
| if (key == QLatin1String("directfb")) { |
| return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); |
| } |
| return QScreen::createSurface(key); |
| } |
| |
| #if defined QT_NO_DIRECTFB_WM |
| struct PaintCommand { |
| PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {} |
| IDirectFBSurface *dfbSurface; |
| QImage image; |
| QPoint windowPosition; |
| QRegion source; |
| quint8 windowOpacity; |
| DFBSurfaceBlittingFlags blittingFlags; |
| }; |
| |
| static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos) |
| { |
| source.x = sourceGlobal.x() - pos.x(); |
| source.y = sourceGlobal.y() - pos.y(); |
| source.w = sourceGlobal.width(); |
| source.h = sourceGlobal.height(); |
| } |
| #endif |
| |
| void QDirectFBScreen::exposeRegion(QRegion r, int) |
| { |
| Q_UNUSED(r); |
| #if defined QT_NO_DIRECTFB_WM |
| |
| r &= region(); |
| if (r.isEmpty()) { |
| return; |
| } |
| r = r.boundingRect(); |
| |
| IDirectFBSurface *primary = d_ptr->primarySurface; |
| const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows(); |
| QVarLengthArray<PaintCommand, 4> commands(windows.size()); |
| QRegion region = r; |
| int idx = 0; |
| for (int i=0; i<windows.size(); ++i) { |
| QWSWindowSurface *surface = windows.at(i)->windowSurface(); |
| if (!surface) |
| continue; |
| |
| const QRect windowGeometry = surface->geometry(); |
| const QRegion intersection = region & windowGeometry; |
| if (intersection.isEmpty()) { |
| continue; |
| } |
| |
| PaintCommand &cmd = commands[idx]; |
| |
| if (surface->key() == QLatin1String("directfb")) { |
| const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface); |
| cmd.dfbSurface = ws->directFBSurface(); |
| |
| if (!cmd.dfbSurface) { |
| continue; |
| } |
| } else { |
| cmd.image = surface->image(); |
| if (cmd.image.isNull()) { |
| continue; |
| } |
| } |
| ++idx; |
| |
| cmd.windowPosition = windowGeometry.topLeft(); |
| cmd.source = intersection; |
| if (windows.at(i)->isOpaque()) { |
| region -= intersection; |
| if (region.isEmpty()) |
| break; |
| } else { |
| cmd.windowOpacity = windows.at(i)->opacity(); |
| cmd.blittingFlags = cmd.windowOpacity == 255 |
| ? DSBLIT_BLEND_ALPHACHANNEL |
| : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA); |
| } |
| } |
| |
| solidFill(d_ptr->backgroundColor, region); |
| |
| while (idx > 0) { |
| const PaintCommand &cmd = commands[--idx]; |
| Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull()); |
| IDirectFBSurface *surface; |
| if (cmd.dfbSurface) { |
| surface = cmd.dfbSurface; |
| } else { |
| Q_ASSERT(!cmd.image.isNull()); |
| DFBResult result; |
| surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result); |
| Q_ASSERT((result != DFB_OK) == !surface); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result); |
| continue; |
| } |
| } |
| |
| primary->SetBlittingFlags(primary, cmd.blittingFlags); |
| if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) { |
| primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity); |
| } |
| const QRegion ®ion = cmd.source; |
| const int rectCount = region.rectCount(); |
| DFBRectangle source; |
| if (rectCount == 1) { |
| ::initParameters(source, region.boundingRect(), cmd.windowPosition); |
| primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y); |
| } else { |
| const QVector<QRect> rects = region.rects(); |
| for (int i=0; i<rectCount; ++i) { |
| ::initParameters(source, rects.at(i), cmd.windowPosition); |
| primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y); |
| } |
| } |
| if (surface != cmd.dfbSurface) { |
| surface->Release(surface); |
| } |
| } |
| |
| primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff); |
| |
| #if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR |
| if (QScreenCursor *cursor = QScreenCursor::instance()) { |
| const QRect cursorRectangle = cursor->boundingRect(); |
| if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) { |
| const QImage image = cursor->image(); |
| if (image.cacheKey() != d_ptr->cursorImageKey) { |
| if (d_ptr->cursorSurface) { |
| releaseDFBSurface(d_ptr->cursorSurface); |
| } |
| d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface); |
| d_ptr->cursorImageKey = image.cacheKey(); |
| } |
| |
| Q_ASSERT(d_ptr->cursorSurface); |
| primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL); |
| primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y()); |
| } |
| } |
| #endif |
| flipSurface(primary, d_ptr->flipFlags, r, QPoint()); |
| primary->SetBlittingFlags(primary, DSBLIT_NOFX); |
| #endif |
| } |
| |
| void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) |
| { |
| #ifdef QT_DIRECTFB_WM |
| Q_UNUSED(color); |
| Q_UNUSED(region); |
| #else |
| QDirectFBScreen::solidFill(d_ptr->primarySurface, color, region); |
| #endif |
| } |
| |
| static inline void clearRect(IDirectFBSurface *surface, const QColor &color, const QRect &rect) |
| { |
| Q_ASSERT(surface); |
| const DFBRegion region = { rect.left(), rect.top(), rect.right(), rect.bottom() }; |
| // could just reinterpret_cast this to a DFBRegion |
| surface->SetClip(surface, ®ion); |
| surface->Clear(surface, color.red(), color.green(), color.blue(), color.alpha()); |
| } |
| |
| void QDirectFBScreen::solidFill(IDirectFBSurface *surface, const QColor &color, const QRegion ®ion) |
| { |
| if (region.isEmpty()) |
| return; |
| |
| const int n = region.rectCount(); |
| if (n == 1) { |
| clearRect(surface, color, region.boundingRect()); |
| } else { |
| const QVector<QRect> rects = region.rects(); |
| for (int i=0; i<n; ++i) { |
| clearRect(surface, color, rects.at(i)); |
| } |
| } |
| surface->SetClip(surface, 0); |
| } |
| |
| QImage::Format QDirectFBScreen::alphaPixmapFormat() const |
| { |
| return d_ptr->alphaPixmapFormat; |
| } |
| |
| bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, |
| QImage::Format format) |
| { |
| const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); |
| if (pixelformat == DSPF_UNKNOWN) |
| return false; |
| description->flags |= DSDESC_PIXELFORMAT; |
| description->pixelformat = pixelformat; |
| if (QDirectFBScreen::isPremultiplied(format)) { |
| if (!(description->flags & DSDESC_CAPS)) { |
| description->caps = DSCAPS_PREMULTIPLIED; |
| description->flags |= DSDESC_CAPS; |
| } else { |
| description->caps |= DSCAPS_PREMULTIPLIED; |
| } |
| } |
| return true; |
| } |
| |
| uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) |
| { |
| void *mem = 0; |
| const DFBResult result = surface->Lock(surface, flags, &mem, bpl); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::lockSurface()", result); |
| } |
| |
| return reinterpret_cast<uchar*>(mem); |
| } |
| |
| static inline bool isFullUpdate(IDirectFBSurface *surface, const QRegion ®ion, const QPoint &offset) |
| { |
| if (offset == QPoint(0, 0) && region.rectCount() == 1) { |
| QSize size; |
| surface->GetSize(surface, &size.rwidth(), &size.rheight()); |
| if (region.boundingRect().size() == size) |
| return true; |
| } |
| return false; |
| } |
| |
| void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, |
| const QRegion ®ion, const QPoint &offset) |
| { |
| if (d_ptr->directFBFlags & NoPartialFlip |
| || (!(flipFlags & DSFLIP_BLIT) && QT_PREPEND_NAMESPACE(isFullUpdate(surface, region, offset)))) { |
| surface->Flip(surface, 0, flipFlags); |
| } else { |
| if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.rectCount() > 1) { |
| const QVector<QRect> rects = region.rects(); |
| const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; |
| for (int i=0; i<rects.size(); ++i) { |
| const QRect &r = rects.at(i); |
| const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), |
| r.right() + offset.x(), |
| r.bottom() + offset.y() }; |
| surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); |
| } |
| } else { |
| const QRect r = region.boundingRect(); |
| const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), |
| r.right() + offset.x(), |
| r.bottom() + offset.y() }; |
| surface->Flip(surface, &dfbReg, flipFlags); |
| } |
| } |
| } |
| |
| #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE |
| void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider) |
| { |
| Q_ASSERT(provider); |
| if (d_ptr->imageProvider) |
| d_ptr->imageProvider->Release(d_ptr->imageProvider); |
| d_ptr->imageProvider = provider; |
| } |
| #endif |
| |
| void QDirectFBScreen::waitIdle() |
| { |
| d_ptr->dfb->WaitIdle(d_ptr->dfb); |
| } |
| |
| #ifdef QT_DIRECTFB_WM |
| IDirectFBWindow *QDirectFBScreen::windowForWidget(const QWidget *widget) const |
| { |
| if (widget) { |
| const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface()); |
| if (surface && surface->key() == QLatin1String("directfb")) { |
| return static_cast<const QDirectFBWindowSurface*>(surface)->directFBWindow(); |
| } |
| } |
| return 0; |
| } |
| #endif |
| |
| IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const |
| { |
| Q_ASSERT(widget); |
| if (!widget->isVisible() || widget->size().isNull()) |
| return 0; |
| |
| const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface()); |
| if (surface && surface->key() == QLatin1String("directfb")) { |
| return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect); |
| } |
| return 0; |
| } |
| |
| #ifdef QT_DIRECTFB_SUBSURFACE |
| IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const |
| { |
| Q_ASSERT(widget); |
| QRect rect; |
| IDirectFBSurface *surface = surfaceForWidget(widget, &rect); |
| IDirectFBSurface *subSurface = 0; |
| if (surface) { |
| if (!area.isNull()) |
| rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0))); |
| if (!rect.isNull()) { |
| const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() }; |
| const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface); |
| if (result != DFB_OK) { |
| DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result); |
| } |
| } |
| } |
| return subSurface; |
| } |
| #endif |
| |
| Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_widget(const QWidget *widget, QRect *rect) |
| { |
| return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->surfaceForWidget(widget, rect) : 0; |
| } |
| #ifdef QT_DIRECTFB_SUBSURFACE |
| Q_GUI_EXPORT IDirectFBSurface *qt_directfb_subsurface_for_widget(const QWidget *widget, const QRect &area) |
| { |
| return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->subSurfaceForWidget(widget, area) : 0; |
| } |
| #endif |
| #ifdef QT_DIRECTFB_WM |
| Q_GUI_EXPORT IDirectFBWindow *qt_directfb_window_for_widget(const QWidget *widget) |
| { |
| return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->windowForWidget(widget) : 0; |
| } |
| |
| #endif |
| |
| QT_END_NAMESPACE |
| |
| #include "qdirectfbscreen.moc" |
| #endif // QT_NO_QWS_DIRECTFB |
| |