/**************************************************************************** | |
** | |
** 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 | |