diff options
Diffstat (limited to 'src/plugins/gfxdrivers')
20 files changed, 260 insertions, 1135 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index 8662df6..57b1950 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -207,7 +207,7 @@ void QDirectFBMouseHandlerPrivate::readMouseData() int wheel = 0; if (input.type == DIET_AXISMOTION) { -#ifdef QT_NO_DIRECTFB_LAYER +#if defined(QT_NO_DIRECTFB_LAYER) || defined(QT_DIRECTFB_WINDOW_AS_CURSOR) if (input.flags & DIEF_AXISABS) { switch (input.axis) { case DIAI_X: x = input.axisabs; break; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 0f7a6de..449bc0d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -99,8 +99,11 @@ public: 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), @@ -802,13 +805,21 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty) 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) { @@ -1050,6 +1061,26 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var return false; } +static inline QColor colorFromName(const QString &name) +{ + QRegExp rx("#([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.numCaptures() == 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; @@ -1282,18 +1313,50 @@ bool QDirectFBScreen::connect(const QString &displaySpec) #endif #ifdef QT_DIRECTFB_WM surface->Release(surface); + QColor backgroundColor; #else - QRegExp backgroundColorRegExp(QLatin1String("bgcolor=?(.+)")); + QColor &backgroundColor = d_ptr->backgroundColor; +#endif + + QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)")); backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive); if (displayArgs.indexOf(backgroundColorRegExp) != -1) { - d_ptr->backgroundColor.setNamedColor(backgroundColorRegExp.cap(1)); + backgroundColor = colorFromName(backgroundColorRegExp.cap(1)); } - if (!d_ptr->backgroundColor.isValid()) - d_ptr->backgroundColor = Qt::green; - d_ptr->primarySurface->Clear(d_ptr->primarySurface, d_ptr->backgroundColor.red(), - d_ptr->backgroundColor.green(), d_ptr->backgroundColor.blue(), - d_ptr->backgroundColor.alpha()); +#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; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 5e8c5c6..0520cdc 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) -#if !defined QT_NO_DIRECTFB_SUBSURFACE && !defined QT_DIRECTFB_SUBSURFACE -#define QT_DIRECTFB_SUBSURFACE +#if !defined QT_DIRECTFB_SUBSURFACE && !defined QT_NO_DIRECTFB_SUBSURFACE +#define QT_NO_DIRECTFB_SUBSURFACE #endif #if !defined QT_NO_DIRECTFB_LAYER && !defined QT_DIRECTFB_LAYER #define QT_DIRECTFB_LAYER @@ -163,12 +163,7 @@ public: QWSWindowSurface *createSurface(QWidget *widget) const; QWSWindowSurface *createSurface(const QString &key) const; - static inline QDirectFBScreen *instance() { - QScreen *inst = QScreen::instance(); - Q_ASSERT(!inst || inst->classId() == QScreen::DirectFBClass); - return static_cast<QDirectFBScreen*>(inst); - } - + static QDirectFBScreen *instance(); void waitIdle(); IDirectFBSurface *surfaceForWidget(const QWidget *widget, QRect *rect) const; #ifdef QT_DIRECTFB_SUBSURFACE diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index f33e820..27ec668 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -262,7 +262,11 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) if (oldSurface != dfbSurface) updateFormat(); - QWSWindowSurface::setGeometry(rect); + if (oldRect.size() != rect.size()) { + QWSWindowSurface::setGeometry(rect); + } else { + QWindowSurface::setGeometry(rect); + } } QByteArray QDirectFBWindowSurface::permanentState() const @@ -276,6 +280,8 @@ void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { if (state.size() == sizeof(this)) { sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData()); + Q_ASSERT(sibling); + sibling->setSurfaceFlags(surfaceFlags()); } } diff --git a/src/plugins/gfxdrivers/gfxdrivers.pro b/src/plugins/gfxdrivers/gfxdrivers.pro index 21aaf0f..d1ee3f2 100644 --- a/src/plugins/gfxdrivers/gfxdrivers.pro +++ b/src/plugins/gfxdrivers/gfxdrivers.pro @@ -5,6 +5,5 @@ contains(gfx-plugins, linuxfb) :SUBDIRS += linuxfb contains(gfx-plugins, qvfb) :SUBDIRS += qvfb contains(gfx-plugins, vnc) :SUBDIRS += vnc contains(gfx-plugins, transformed) :SUBDIRS += transformed -contains(gfx-plugins, hybrid) :SUBDIRS += hybrid contains(gfx-plugins, svgalib) :SUBDIRS += svgalib contains(gfx-plugins, powervr) :SUBDIRS += powervr diff --git a/src/plugins/gfxdrivers/hybrid/hybrid.pro b/src/plugins/gfxdrivers/hybrid/hybrid.pro deleted file mode 100644 index 8b8e9ef..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybrid.pro +++ /dev/null @@ -1,16 +0,0 @@ -TEMPLATE = lib -CONFIG += plugin -QT += opengl - -QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers - -TARGET = hybridscreen -target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers -INSTALLS += target - -HEADERS = hybridscreen.h \ - hybridsurface.h -SOURCES = hybridscreen.cpp \ - hybridsurface.cpp \ - hybridplugin.cpp - diff --git a/src/plugins/gfxdrivers/hybrid/hybridplugin.cpp b/src/plugins/gfxdrivers/hybrid/hybridplugin.cpp deleted file mode 100644 index 17be760..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybridplugin.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "hybridscreen.h" - -#include <QScreenDriverPlugin> -#include <QStringList> - -class HybridPlugin : public QScreenDriverPlugin -{ -public: - HybridPlugin(); - - QStringList keys() const; - QScreen *create(const QString&, int displayId); -}; - -HybridPlugin::HybridPlugin() - : QScreenDriverPlugin() -{ -} - -QStringList HybridPlugin::keys() const -{ - return (QStringList() << "hybrid"); -} - -QScreen* HybridPlugin::create(const QString &driver, int displayId) -{ - if (driver.toLower() != "hybrid") - return 0; - - return new HybridScreen(displayId); -} - -Q_EXPORT_STATIC_PLUGIN(Hybrid) -Q_EXPORT_PLUGIN2(hybridscreendriver, HybridPlugin) diff --git a/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp b/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp deleted file mode 100644 index 4062551..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "hybridscreen.h" -#include "hybridsurface.h" - -#include <QVector> -#include <QVarLengthArray> -#include <QApplication> -#include <QColor> -#include <QWidget> - -#include <GLES/egl.h> - -class HybridScreenPrivate -{ -public: - HybridScreenPrivate(HybridScreen *owner); - - bool verbose; - EGLDisplay display; - EGLint majorEGLVersion; - EGLint minorEGLVersion; - - QScreen *screen; - -private: - HybridScreen *q_ptr; -}; - -HybridScreenPrivate::HybridScreenPrivate(HybridScreen *owner) - : display(EGL_NO_DISPLAY), majorEGLVersion(0), minorEGLVersion(0), - screen(0), q_ptr(owner) -{ -} - -HybridScreen::HybridScreen(int displayId) - : QGLScreen(displayId) -{ - d_ptr = new HybridScreenPrivate(this); -} - -HybridScreen::~HybridScreen() -{ - delete d_ptr; -} - -static void error(const char *message) -{ - const EGLint error = eglGetError(); - qWarning("HybridScreen error: %s: 0x%x", message, error); -} - -static int getDisplayId(const QString &spec) -{ - QRegExp regexp(QLatin1String(":(\\d+)\\b")); - if (regexp.lastIndexIn(spec) != -1) { - const QString capture = regexp.cap(1); - return capture.toInt(); - } - return 0; -} - -bool HybridScreen::connect(const QString &displaySpec) -{ - QString dspec = displaySpec; - if (dspec.startsWith(QLatin1String("hybrid:"), Qt::CaseInsensitive)) - dspec = dspec.mid(QString::fromLatin1("hybrid:").size()); - else if (dspec.compare(QLatin1String("hybrid"), Qt::CaseInsensitive) == 0) - dspec = QString(); - - const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId); - if (dspec.endsWith(displayIdSpec)) - dspec = dspec.left(dspec.size() - displayIdSpec.size()); - - const QStringList args = dspec.split(QLatin1Char(':'), - QString::SkipEmptyParts); - const int id = getDisplayId(dspec); - d_ptr->screen = qt_get_screen(id, dspec.toLatin1().constData()); - - const QScreen *screen = d_ptr->screen; - d = screen->depth(); - w = screen->width(); - h = screen->height(); - dw = screen->deviceWidth(); - dh = screen->deviceHeight(); - lstep = screen->linestep(); - data = screen->base(); - physWidth = screen->physicalWidth(); - physHeight = screen->physicalHeight(); - setPixelFormat(screen->pixelFormat()); - setOffset(screen->offset()); - - d_ptr->verbose = args.contains(QLatin1String("verbose")); - - d_ptr->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (d_ptr->display == EGL_NO_DISPLAY) { - error("getting display"); - return false; - } - - EGLBoolean status; - status = eglInitialize(d_ptr->display, - &d_ptr->majorEGLVersion, &d_ptr->minorEGLVersion); - if (!status) { - error("eglInitialize"); - return false; - } - if (d_ptr->verbose) { - qDebug("Detected EGL version %d.%d", - d_ptr->majorEGLVersion, d_ptr->minorEGLVersion); - - EGLint numConfigs = 0; - eglGetConfigs(d_ptr->display, 0, 0, &numConfigs); - qDebug("%d available configurations", numConfigs); - } - - // XXX: hw: use eglQueryString to find supported APIs - - qt_screen = this; // XXX - - return true; -} - -bool HybridScreen::initDevice() -{ - if (d_ptr->screen) - return d_ptr->screen->initDevice(); - return false; -} - -void HybridScreen::shutdownDevice() -{ - if (d_ptr->screen) - d_ptr->screen->shutdownDevice(); -} - -void HybridScreen::disconnect() -{ - if (!eglTerminate(d_ptr->display)) - error("disconnecting"); - if (d_ptr->screen) { - d_ptr->screen->disconnect(); - delete d_ptr->screen; - d_ptr->screen = 0; - } - -} - -bool HybridScreen::hasOpenGLOverlays() const -{ - return true; -} - -bool HybridScreen::chooseContext(QGLContext *context, - const QGLContext *shareContext) -{ -#if 0 - // hw: update the glFormat variable. Probably needs a setter in the - // QGLWindowSurface class which can be a friend of whatever it wants. - - GLint res; - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_LEVEL, &res); - d_ptr->glFormat.setPlane(res); - QT_EGL_ERR("eglGetConfigAttrib"); - - /* - if(deviceIsPixmap()) - res = 0; - else - eglDescribePixelFormat(fmt, EGL_DOUBLEBUFFER, &res); - d_ptr->glFormat.setDoubleBuffer(res); - */ - - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_DEPTH_SIZE, &res); - d_ptr->glFormat.setDepth(res); - if (d_ptr->glFormat.depth()) - d_ptr->glFormat.setDepthBufferSize(res); - - //eglGetConfigAttrib(d_ptr->display,d_ptr->config, EGL_RGBA, &res); - //d_ptr->glFormat.setRgba(res); - - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_ALPHA_SIZE, &res); - d_ptr->glFormat.setAlpha(res); - if (d_ptr->glFormat.alpha()) - d_ptr->glFormat.setAlphaBufferSize(res); - - //eglGetConfigAttrib(d_ptr->display,d_ptr->config, EGL_ACCUM_RED_SIZE, &res); - //d_ptr->glFormat.setAccum(res); - //if (d_ptr->glFormat.accum()) - // d_ptr->glFormat.setAccumBufferSize(res); - - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_STENCIL_SIZE, &res); - d_ptr->glFormat.setStencil(res); - if (d_ptr->glFormat.stencil()) - d_ptr->glFormat.setStencilBufferSize(res); - - //eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_STEREO, &res); - //d_ptr->glFormat.setStereo(res); - - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_SAMPLE_BUFFERS, &res); - d_ptr->glFormat.setSampleBuffers(res); - - if (d_ptr->glFormat.sampleBuffers()) { - eglGetConfigAttrib(d_ptr->display, d_ptr->config, EGL_SAMPLES, &res); - d_ptr->glFormat.setSamples(res); - } -#endif - - // hw: TODO: implement sharing of contexts - -#if 0 - if(shareContext && - (!shareContext->isValid() || !shareContext->d_func()->cx)) { - qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); - shareContext = 0; - } -#endif - -#if 0 - d_ptr->cx = ctx; - if (shareContext && shareContext->d_func()->cx) { - QGLContext *share = const_cast<QGLContext *>(shareContext); - d_ptr->sharing = true; - share->d_func()->sharing = true; - } -#endif - -#if 0 - // vblank syncing - GLint interval = d_ptr->reqFormat.swapInterval(); - if (interval != -1) { - if (interval != 0) - eglSwapInterval(d_ptr->display, interval); - } -#endif - - return QGLScreen::chooseContext(context, shareContext); -} - -void HybridScreen::setDirty(const QRect& rect) -{ - d_ptr->screen->setDirty(rect); -} - -void HybridScreen::setMode(int w, int h, int d) -{ - d_ptr->screen->setMode(w, h, d); - setDirty(region().boundingRect()); -} - -bool HybridScreen::supportsDepth(int depth) const -{ - return d_ptr->screen->supportsDepth(depth); -} - -void HybridScreen::save() -{ - d_ptr->screen->save(); -} - -void HybridScreen::restore() -{ - d_ptr->screen->restore(); -} - -void HybridScreen::blank(bool on) -{ - d_ptr->screen->blank(on); -} - -bool HybridScreen::onCard(const unsigned char *ptr) const -{ - return d_ptr->screen->onCard(ptr); -} - -bool HybridScreen::onCard(const unsigned char *ptr, ulong &offset) const -{ - return d_ptr->screen->onCard(ptr, offset); -} - -bool HybridScreen::isInterlaced() const -{ - return d_ptr->screen->isInterlaced(); -} - -int HybridScreen::memoryNeeded(const QString &str) -{ - return d_ptr->screen->memoryNeeded(str); -} - -int HybridScreen::sharedRamSize(void *ptr) -{ - return d_ptr->screen->sharedRamSize(ptr); -} - -void HybridScreen::haltUpdates() -{ - d_ptr->screen->haltUpdates(); -} - -void HybridScreen::resumeUpdates() -{ - d_ptr->screen->resumeUpdates(); -} - -void HybridScreen::exposeRegion(QRegion r, int changing) -{ - d_ptr->screen->exposeRegion(r, changing); -} - -void HybridScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion) -{ - d_ptr->screen->blit(img, topLeft, region); -} - -void HybridScreen::solidFill(const QColor &color, const QRegion ®ion) -{ - d_ptr->screen->solidFill(color, region); -} - -QWSWindowSurface* HybridScreen::createSurface(QWidget *widget) const -{ - if (qobject_cast<QGLWidget*>(widget)) - return new HybridSurface(widget, d_ptr->display); - return d_ptr->screen->createSurface(widget); -} - -QWSWindowSurface* HybridScreen::createSurface(const QString &key) const -{ - if (key == QLatin1String("hybrid")) - return new HybridSurface; - return d_ptr->screen->createSurface(key); -} - -QList<QScreen*> HybridScreen::subScreens() const -{ - return d_ptr->screen->subScreens(); -} - -QRegion HybridScreen::region() const -{ - return d_ptr->screen->region(); -} diff --git a/src/plugins/gfxdrivers/hybrid/hybridscreen.h b/src/plugins/gfxdrivers/hybrid/hybridscreen.h deleted file mode 100644 index b7888d5..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybridscreen.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HYBRIDSCREEN_H -#define HYBRIDSCREEN_H - -#include <QtOpenGL/QGLScreen> - -class HybridScreenPrivate; - -class HybridScreen : public QGLScreen -{ -public: - HybridScreen(int displayId); - ~HybridScreen(); - - bool hasOpenGLOverlays() const; - - bool chooseContext(QGLContext *context, const QGLContext *shareContext); - bool hasOpenGL() { return true; } - - bool initDevice(); - bool connect(const QString &displaySpec); - void disconnect(); - void shutdownDevice(); - void setMode(int,int,int); - bool supportsDepth(int) const; - - void save(); - void restore(); - void blank(bool on); - - bool onCard(const unsigned char *) const; - bool onCard(const unsigned char *, ulong& out_offset) const; - - bool isInterlaced() const; - - int memoryNeeded(const QString&); - int sharedRamSize(void *); - - void haltUpdates(); - void resumeUpdates(); - - void exposeRegion(QRegion r, int changing); - - void blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion); - void solidFill(const QColor &color, const QRegion ®ion); - void setDirty(const QRect&); - - QWSWindowSurface* createSurface(QWidget *widget) const; - QWSWindowSurface* createSurface(const QString &key) const; - - QList<QScreen*> subScreens() const; - QRegion region() const; -private: - HybridScreenPrivate *d_ptr; -}; - -#endif // HYBRIDSCREEN_H diff --git a/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp b/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp deleted file mode 100644 index df183e2..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "hybridsurface.h" - -#include <private/qwindowsurface_qws_p.h> -#include <private/qwslock_p.h> -#include <qscreen_qws.h> -#include <qvarlengtharray.h> - -static void error(const char *message) -{ - const EGLint error = eglGetError(); - qWarning("HybridSurface error: %s: 0x%x", message, error); -} - -static void imgToVanilla(const QImage *img, VanillaPixmap *pix) -{ - pix->width = img->width(); - pix->height = img->height(); - pix->stride = img->bytesPerLine(); - - if (img->depth() == 32) { - pix->rSize = pix->gSize = pix->bSize = pix->aSize = 8; - pix->lSize = 0; - pix->rOffset = 16; - pix->gOffset = 8; - pix->bOffset = 0; - pix->aOffset = 24; - } else if (img->format() == QImage::Format_RGB16) { - pix->rSize = 5; - pix->gSize = 6; - pix->bSize = 5; - pix->aSize = 0; - pix->lSize = 0; - pix->rOffset = 11; - pix->gOffset = 5; - pix->bOffset = 0; - pix->aOffset = 0; - } - - pix->padding = pix->padding2 = 0; - pix->pixels = const_cast<uchar*>(img->bits()); -} - -HybridSurface::HybridSurface() - : QWSGLWindowSurface(), memlock(0) -{ - setSurfaceFlags(Buffered | Opaque); -} - -HybridSurface::HybridSurface(QWidget *w, EGLDisplay disp) - : QWSGLWindowSurface(w), memlock(0), display(disp), config(0), - surface(EGL_NO_SURFACE), context(EGL_NO_CONTEXT), - pdevice(new QWSGLPaintDevice(w)) -{ - setSurfaceFlags(Buffered | Opaque); - - EGLint configAttribs[] = { - EGL_RED_SIZE, 0, - EGL_GREEN_SIZE, 0, - EGL_BLUE_SIZE, 0, - EGL_ALPHA_SIZE, 0, - EGL_DEPTH_SIZE, 0, - EGL_STENCIL_SIZE, EGL_DONT_CARE, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE, EGL_NONE - }; - - - EGLBoolean status; - EGLint numConfigs; - status = eglChooseConfig(display, configAttribs, 0, 0, &numConfigs); - if (!status) { - error("chooseConfig"); - return; - } - - //If there isn't any configuration good enough - if (numConfigs < 1) { - error("chooseConfig, no matching configurations found"); - return; - } - - QVarLengthArray<EGLConfig> configs(numConfigs); - - status = eglChooseConfig(display, configAttribs, configs.data(), - numConfigs, &numConfigs); - if (!status) { - error("chooseConfig"); - return; - } - - // hw: if used on an image buffer we need to check whether the resulting - // configuration matches our requirements exactly! - config = configs[0]; - - context = eglCreateContext(display, config, 0, 0); - //(shareContext ? shareContext->d_func()->cx : 0), - //configAttribs); - if (context == EGL_NO_CONTEXT) - error("eglCreateContext"); - -} - -HybridSurface::~HybridSurface() -{ -} - -bool HybridSurface::isValid() const -{ - return true; -} - -void HybridSurface::setGeometry(const QRect &rect, const QRegion &mask) -{ - const QSize size = rect.size(); - if (img.size() != size) { -// QWidget *win = window(); - QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied; - const int bytesPerPixel = 4; - - const int bpl = (size.width() * bytesPerPixel + 3) & ~3; - const int imagesize = bpl * size.height(); - - if (imagesize == 0) { - eglDestroySurface(display, surface); - mem.detach(); - img = QImage(); - } else { - mem.detach(); - if (!mem.create(imagesize)) { - perror("HybridSurface::setGeometry allocating shared memory"); - qFatal("Error creating shared memory of size %d", imagesize); - } - uchar *base = static_cast<uchar*>(mem.address()); - img = QImage(base, size.width(), size.height(), imageFormat); -// setImageMetrics(img, win); - - imgToVanilla(&img, &vanillaPix); - surface = eglCreatePixmapSurface(display, config, &vanillaPix, 0); - if (surface == EGL_NO_SURFACE) - error("setGeometry:eglCreatePixmapSurface"); - - } - } - QWSWindowSurface::setGeometry(rect, mask); -} - -QByteArray HybridSurface::permanentState() const -{ - QByteArray array; - array.resize(4 * sizeof(int) + sizeof(QImage::Format) + - sizeof(SurfaceFlags)); - - char *ptr = array.data(); - - reinterpret_cast<int*>(ptr)[0] = mem.id(); - reinterpret_cast<int*>(ptr)[1] = img.width(); - reinterpret_cast<int*>(ptr)[2] = img.height(); - reinterpret_cast<int*>(ptr)[3] = (memlock ? memlock->id() : -1); - ptr += 4 * sizeof(int); - - *reinterpret_cast<QImage::Format*>(ptr) = img.format(); - ptr += sizeof(QImage::Format); - - *reinterpret_cast<SurfaceFlags*>(ptr) = surfaceFlags(); - - return array; -} - -void HybridSurface::setPermanentState(const QByteArray &data) -{ - int memId; - int width; - int height; - int lockId; - QImage::Format format; - SurfaceFlags flags; - - const char *ptr = data.constData(); - - memId = reinterpret_cast<const int*>(ptr)[0]; - width = reinterpret_cast<const int*>(ptr)[1]; - height = reinterpret_cast<const int*>(ptr)[2]; - lockId = reinterpret_cast<const int*>(ptr)[3]; - ptr += 4 * sizeof(int); - - format = *reinterpret_cast<const QImage::Format*>(ptr); - ptr += sizeof(QImage::Format); - flags = *reinterpret_cast<const SurfaceFlags*>(ptr); - - setSurfaceFlags(flags); - -// setMemory(memId); - if (mem.id() != memId) { - mem.detach(); - if (!mem.attach(memId)) { - perror("QWSSharedMemSurface: attaching to shared memory"); - qCritical("QWSSharedMemSurface: Error attaching to" - " shared memory 0x%x", memId); - } - } - -// setLock(lockId); - if (!memlock || memlock->id() == lockId) { - delete memlock; - memlock = (lockId == -1 ? 0 : new QWSLock(lockId)); - } - - uchar *base = static_cast<uchar*>(mem.address()); - img = QImage(base, width, height, format); -} - -QImage HybridSurface::image() const -{ - return img; -} - -QPaintDevice* HybridSurface::paintDevice() -{ - return pdevice; -} - -void HybridSurface::beginPaint(const QRegion ®ion) -{ - QWSGLWindowSurface::beginPaint(region); - eglBindAPI(EGL_OPENGL_ES_API); - - EGLBoolean ok = eglMakeCurrent(display, surface, surface, context); - if (!ok) - error("qglMakeCurrent"); -} - -bool HybridSurface::lock(int timeout) -{ - Q_UNUSED(timeout); - if (!memlock) - return true; - return memlock->lock(QWSLock::BackingStore); -} - -void HybridSurface::unlock() -{ - if (memlock) - memlock->unlock(QWSLock::BackingStore); -} - -QPoint HybridSurface::painterOffset() const -{ - const QWidget *w = window(); - if (!w) - return QPoint(); - - if (w->mask().isEmpty()) - return QWSWindowSurface::painterOffset(); - - const QRegion region = w->mask() - & w->frameGeometry().translated(-w->geometry().topLeft()); - return -region.boundingRect().topLeft(); -} - diff --git a/src/plugins/gfxdrivers/hybrid/hybridsurface.h b/src/plugins/gfxdrivers/hybrid/hybridsurface.h deleted file mode 100644 index 1fba95b..0000000 --- a/src/plugins/gfxdrivers/hybrid/hybridsurface.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HYBRIDSURFACE_H -#define HYBRIDSURFACE_H - -#include <private/qglwindowsurface_qws_p.h> -#include <private/qglpaintdevice_qws_p.h> -#include <GLES/egl.h> -#include <vanilla/eglVanilla.h> -#include <private/qwssharedmemory_p.h> - -class HybridPaintDevice; -class HybridSurfacePrivate; -class QWSLock; - -class HybridSurface : public QWSGLWindowSurface -{ -public: - HybridSurface(); - HybridSurface(QWidget *w, EGLDisplay display); - ~HybridSurface(); - - void beginPaint(const QRegion ®ion); - bool lock(int timeout); - void unlock(); - - bool isValid() const; - void setGeometry(const QRect &rect, const QRegion &mask); - QString key() const { return QLatin1String("hybrid"); } - - QByteArray permanentState() const; - void setPermanentState(const QByteArray &state); - - QImage image() const; - QPaintDevice *paintDevice(); - QPoint painterOffset() const; - -private: - QWSSharedMemory mem; - QImage img; - QWSLock *memlock; - EGLDisplay display; - EGLConfig config; - EGLSurface surface; - EGLContext context; - QWSGLPaintDevice *pdevice; - - VanillaPixmap vanillaPix; -}; - -#endif // HYBRIDSURFACE_H diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c index ac9dc8d..c1b655a 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c @@ -617,6 +617,16 @@ void pvrQwsGetGeometry(PvrQwsDrawable *drawable, PvrQwsRect *rect) *rect = drawable->rect; } +void pvrQwsSetRotation(PvrQwsDrawable *drawable, int angle) +{ + if (drawable->rotationAngle != angle) { + drawable->rotationAngle = angle; + + /* Force the buffers to be recreated if the rotation angle changes */ + pvrQwsInvalidateBuffers(drawable); + } +} + int pvrQwsGetStride(PvrQwsDrawable *drawable) { if (drawable->backBuffersValid) diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h index 952ff6f..b9e035f 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h @@ -126,6 +126,9 @@ void pvrQwsSetGeometry(PvrQwsDrawable *drawable, const PvrQwsRect *rect); /* Get the current geometry for a drawable */ void pvrQwsGetGeometry(PvrQwsDrawable *drawable, PvrQwsRect *rect); +/* Set the rotation angle in degrees */ +void pvrQwsSetRotation(PvrQwsDrawable *drawable, int angle); + /* Get the line stride for a drawable. Returns zero if the buffers are not allocated or have been invalidated */ int pvrQwsGetStride(PvrQwsDrawable *drawable); diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h index cf80a90..dcd4e4f 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h @@ -114,6 +114,7 @@ struct _PvrQwsDrawable int isFullScreen; int strideBytes; int stridePixels; + int rotationAngle; PvrQwsSwapFunction swapFunction; void *userData; PvrQwsDrawable *nextWinId; diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c index 253f39f..28b2251 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c @@ -132,6 +132,16 @@ static WSEGLError wseglCloseDisplay(WSEGLDisplayHandle display) return WSEGL_SUCCESS; } +static WSEGLRotationAngle wseglRotationValue(int degrees) +{ + switch (degrees) { + case 90: return WSEGL_ROTATE_90; + case 180: return WSEGL_ROTATE_180; + case 270: return WSEGL_ROTATE_270; + default: return WSEGL_ROTATE_0; + } +} + /* Create the WSEGL drawable version of a native window */ static WSEGLError wseglCreateWindowDrawable (WSEGLDisplayHandle display, WSEGLConfig *config, @@ -152,7 +162,7 @@ static WSEGLError wseglCreateWindowDrawable *drawable = (WSEGLDrawableHandle)screen; if (!pvrQwsAllocBuffers(screen)) return WSEGL_OUT_OF_MEMORY; - *rotationAngle = WSEGL_ROTATE_0; + *rotationAngle = wseglRotationValue(screen->rotationAngle); return WSEGL_SUCCESS; } @@ -163,7 +173,7 @@ static WSEGLError wseglCreateWindowDrawable /* The drawable is ready to go */ *drawable = (WSEGLDrawableHandle)draw; - *rotationAngle = WSEGL_ROTATE_0; + *rotationAngle = wseglRotationValue(draw->rotationAngle); if (!pvrQwsAllocBuffers(draw)) return WSEGL_OUT_OF_MEMORY; return WSEGL_SUCCESS; diff --git a/src/plugins/gfxdrivers/powervr/README b/src/plugins/gfxdrivers/powervr/README index 4dce87f..322a6b2 100644 --- a/src/plugins/gfxdrivers/powervr/README +++ b/src/plugins/gfxdrivers/powervr/README @@ -51,6 +51,11 @@ on the device with: hellogl_es -qws +The driver also supports screen rotation if Qt is configured with the +-qt-gfx-transformed option and the QWS_DISPLAY variable is wrapped in a +"Transformed" declaration: + + Transformed:powervr:mmWidth40:mmHeight54:Rot90:0 Know Issues: * A QGLWidget may not have window decorations if it is a top-level window. diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp index cb453d7..1dec9ea 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp @@ -44,33 +44,42 @@ #include "pvrqwsdrawable_p.h" #include <QRegExp> #include <qwindowsystem_qws.h> +#ifndef QT_NO_QWS_TRANSFORMED +#include <qscreentransformed_qws.h> +#endif #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/kd.h> #include <fcntl.h> #include <unistd.h> +//![0] PvrEglScreen::PvrEglScreen(int displayId) : QGLScreen(displayId) { setOptions(NativeWindows); setSupportsBlitInClients(true); setSurfaceFunctions(new PvrEglScreenSurfaceFunctions(this, displayId)); +//![0] fd = -1; ttyfd = -1; doGraphicsMode = true; oldKdMode = KD_TEXT; - if (QWSServer::instance()) - holder = new PvrEglSurfaceHolder(); - else - holder = 0; + parent = 0; + + // Make sure that the EGL layer is initialized and the drivers loaded. + EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); + if (!eglInitialize(dpy, 0, 0)) + qWarning("Could not initialize EGL display - are the drivers loaded?"); + + // Make sure that screen 0 is initialized. + pvrQwsScreenWindow(0); } PvrEglScreen::~PvrEglScreen() { if (fd >= 0) ::close(fd); - delete holder; } bool PvrEglScreen::initDevice() @@ -183,10 +192,11 @@ bool PvrEglScreen::hasOpenGL() return true; } +//![1] QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const { if (qobject_cast<QGLWidget*>(widget)) - return new PvrEglWindowSurface(widget, (QScreen *)this, displayId); + return new PvrEglWindowSurface(widget, (PvrEglScreen *)this, displayId); return QScreen::createSurface(widget); } @@ -194,10 +204,72 @@ QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const { if (key == QLatin1String("PvrEgl")) - return new PvrEglWindowSurface(holder); + return new PvrEglWindowSurface(); return QScreen::createSurface(key); } +//![1] + +#ifndef QT_NO_QWS_TRANSFORMED + +static const QScreen *parentScreen + (const QScreen *current, const QScreen *lookingFor) +{ + if (!current) + return 0; + switch (current->classId()) { + case QScreen::ProxyClass: + case QScreen::TransformedClass: { + const QScreen *child = + static_cast<const QProxyScreen *>(current)->screen(); + if (child == lookingFor) + return current; + else + return parentScreen(child, lookingFor); + } + // Not reached. + + case QScreen::MultiClass: { + QList<QScreen *> screens = current->subScreens(); + foreach (QScreen *screen, screens) { + if (screen == lookingFor) + return current; + const QScreen *parent = parentScreen(screen, lookingFor); + if (parent) + return parent; + } + } + break; + + default: break; + } + return 0; +} + +int PvrEglScreen::transformation() const +{ + // We need to search for our parent screen, which is assumed to be + // "Transformed". If it isn't, then there is no transformation. + // There is no direct method to get the parent screen so we need + // to search every screen until we find ourselves. + if (!parent && qt_screen != this) + parent = parentScreen(qt_screen, this); + if (!parent) + return 0; + if (parent->classId() != QScreen::TransformedClass) + return 0; + return 90 * static_cast<const QTransformedScreen *>(parent) + ->transformation(); +} + +#else + +int PvrEglScreen::transformation() const +{ + return 0; +} + +#endif void PvrEglScreen::sync() { @@ -253,8 +325,10 @@ void PvrEglScreen::closeTty() ttyfd = -1; } +//![2] bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native) { +//![2] QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(widget->windowSurface()); if (!surface) { @@ -275,116 +349,3 @@ bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNative *native = (EGLNativeWindowType)(nsurface->nativeDrawable()); return true; } - -// The PowerVR engine on the device needs to allocate about 2Mb of -// contiguous physical memory to manage drawing into a surface. -// -// The problem is that once Qtopia begins its startup sequence, -// it allocates enough memory to severely fragment the physical -// address space on the device. This leaves the PowerVR engine -// unable to allocate the necessary contiguous physical memory -// when an EGL surface is created. -// -// A solution to this is to pre-allocate a dummy surface early -// in the startup sequence before memory becomes fragmented, -// reserving it for any future EGL applications to use. -// -// However, the PowerVR engine has problems managing multiple -// surfaces concurrently, and so real EGL applications end up -// with unacceptably slow frame rates unless the dummy surface -// is destroyed while the real EGL applications are running. -// -// In summary, we need to try to ensure that there is always at -// least one EGL surface active at any given time to reserve the -// memory but destroy the temporary surface when a real surface -// is using the device. That is the purpose of PvrEglSurfaceHolder. - -PvrEglSurfaceHolder::PvrEglSurfaceHolder(QObject *parent) - : QObject(parent) -{ - numRealSurfaces = 0; - - PvrQwsRect rect; - rect.x = 0; - rect.y = 0; - rect.width = 16; - rect.height = 16; - tempSurface = pvrQwsCreateWindow(0, -1, &rect); - - dpy = EGL_NO_DISPLAY; - config = 0; - surface = EGL_NO_SURFACE; - - dpy = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); - if (!eglInitialize(dpy, 0, 0)) { - qWarning("Could not initialize EGL display - are the drivers loaded?"); - dpy = EGL_NO_DISPLAY; - return; - } - - EGLint attribList[16]; - int temp = 0; - attribList[temp++] = EGL_LEVEL; // Framebuffer level 0 - attribList[temp++] = 0; - attribList[temp++] = EGL_SURFACE_TYPE; - attribList[temp++] = EGL_WINDOW_BIT; - attribList[temp++] = EGL_NONE; - - EGLint numConfigs = 0; - if (!eglChooseConfig(dpy, attribList, &config, 1, &numConfigs) || numConfigs != 1) { - qWarning("Could not find a matching a EGL configuration"); - eglTerminate(dpy); - dpy = EGL_NO_DISPLAY; - return; - } - - surface = eglCreateWindowSurface - (dpy, config, (EGLNativeWindowType)(-1), NULL); - if (surface == EGL_NO_SURFACE) - qWarning("Could not create the temporary EGL surface"); -} - -PvrEglSurfaceHolder::~PvrEglSurfaceHolder() -{ - if (surface != EGL_NO_SURFACE) - eglDestroySurface(dpy, surface); - if (dpy != EGL_NO_DISPLAY) - eglTerminate(dpy); - if (tempSurface) - pvrQwsDestroyDrawable(tempSurface); -} - -// Add a real EGL surface to the system. -void PvrEglSurfaceHolder::addSurface() -{ - ++numRealSurfaces; - if (numRealSurfaces == 1) { - // Destroy the temporary surface while some other application - // is making use of the EGL sub-system for 3D rendering. - if (surface != EGL_NO_SURFACE) { - eglDestroySurface(dpy, surface); - surface = EGL_NO_SURFACE; - } - } -} - -// Remove an actual EGL surface from the system. -void PvrEglSurfaceHolder::removeSurface() -{ - if (numRealSurfaces > 0) { - --numRealSurfaces; - if (numRealSurfaces == 0) { - // The last real EGL surface has been destroyed, so re-create - // the temporary surface. There is a race condition here in - // that Qtopia could allocate a lot of memory just after - // the real EGL surface is destroyed but before we could - // create the temporary surface again. - if (surface == EGL_NO_SURFACE && dpy != EGL_NO_DISPLAY) { - surface = eglCreateWindowSurface - (dpy, config, (EGLNativeWindowType)(-1), NULL); - if (surface == EGL_NO_SURFACE) - qWarning("Could not re-create the temporary EGL surface"); - } - } - } -} diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h index 1c79f8e..5769e70 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h @@ -46,37 +46,21 @@ #include <QGLScreen> #include "pvrqwsdrawable.h" +class PvrEglScreen; + class PvrEglScreenSurfaceFunctions : public QGLScreenSurfaceFunctions { public: - PvrEglScreenSurfaceFunctions(QScreen *s, int screenNum) + PvrEglScreenSurfaceFunctions(PvrEglScreen *s, int screenNum) : screen(s), displayId(screenNum) {} bool createNativeWindow(QWidget *widget, EGLNativeWindowType *native); private: - QScreen *screen; + PvrEglScreen *screen; int displayId; }; -class PvrEglSurfaceHolder : public QObject -{ - Q_OBJECT -public: - PvrEglSurfaceHolder(QObject *parent=0); - ~PvrEglSurfaceHolder(); - - void addSurface(); - void removeSurface(); - -private: - int numRealSurfaces; - PvrQwsDrawable *tempSurface; - EGLDisplay dpy; - EGLConfig config; - EGLSurface surface; -}; - class PvrEglScreen : public QGLScreen { public: @@ -98,6 +82,8 @@ public: QWSWindowSurface* createSurface(QWidget *widget) const; QWSWindowSurface* createSurface(const QString &key) const; + int transformation() const; + private: void sync(); void openTty(); @@ -105,9 +91,9 @@ private: int fd; int ttyfd, oldKdMode; - PvrEglSurfaceHolder *holder; QString ttyDevice; bool doGraphicsMode; + mutable const QScreen *parent; }; #endif diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp index 09c0ace..4a3787f 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp @@ -46,14 +46,13 @@ #include <QWSDisplay> PvrEglWindowSurface::PvrEglWindowSurface - (QWidget *widget, QScreen *screen, int screenNum) + (QWidget *widget, PvrEglScreen *screen, int screenNum) : QWSGLWindowSurface(widget) { setSurfaceFlags(QWSWindowSurface::Opaque); this->widget = widget; this->screen = screen; - this->holder = 0; this->pdevice = 0; QPoint pos = offset(widget); @@ -64,6 +63,7 @@ PvrEglWindowSurface::PvrEglWindowSurface pvrRect.y = pos.y(); pvrRect.width = size.width(); pvrRect.height = size.height(); + transformRects(&pvrRect, 1); // Try to recover a previous PvrQwsDrawable object for the widget // if there is one. This can happen when a PvrEglWindowSurface @@ -76,9 +76,10 @@ PvrEglWindowSurface::PvrEglWindowSurface pvrQwsSetGeometry(drawable, &pvrRect); else drawable = pvrQwsCreateWindow(screenNum, (long)widget, &pvrRect); + pvrQwsSetRotation(drawable, screen->transformation()); } -PvrEglWindowSurface::PvrEglWindowSurface(PvrEglSurfaceHolder *holder) +PvrEglWindowSurface::PvrEglWindowSurface() : QWSGLWindowSurface() { setSurfaceFlags(QWSWindowSurface::Opaque); @@ -86,9 +87,6 @@ PvrEglWindowSurface::PvrEglWindowSurface(PvrEglSurfaceHolder *holder) widget = 0; screen = 0; pdevice = 0; - - this->holder = holder; - holder->addSurface(); } PvrEglWindowSurface::~PvrEglWindowSurface() @@ -100,8 +98,6 @@ PvrEglWindowSurface::~PvrEglWindowSurface() if (drawable && pvrQwsReleaseWindow(drawable)) pvrQwsDestroyDrawable(drawable); - if (holder) - holder->removeSurface(); delete pdevice; } @@ -119,7 +115,9 @@ void PvrEglWindowSurface::setGeometry(const QRect &rect) pvrRect.y = rect.y(); pvrRect.width = rect.width(); pvrRect.height = rect.height(); + transformRects(&pvrRect, 1); pvrQwsSetGeometry(drawable, &pvrRect); + pvrQwsSetRotation(drawable, screen->transformation()); } QWSGLWindowSurface::setGeometry(rect); } @@ -133,7 +131,9 @@ bool PvrEglWindowSurface::move(const QPoint &offset) pvrRect.y = rect.y(); pvrRect.width = rect.width(); pvrRect.height = rect.height(); + transformRects(&pvrRect, 1); pvrQwsSetGeometry(drawable, &pvrRect); + pvrQwsSetRotation(drawable, screen->transformation()); } return QWSGLWindowSurface::move(offset); } @@ -206,7 +206,9 @@ void PvrEglWindowSurface::setDirectRegion(const QRegion &r, int id) pvrRect.y = rect.y(); pvrRect.width = rect.width(); pvrRect.height = rect.height(); + transformRects(&pvrRect, 1); pvrQwsSetVisibleRegion(drawable, &pvrRect, 1); + pvrQwsSetRotation(drawable, screen->transformation()); if (!pvrQwsSwapBuffers(drawable, 1)) screen->solidFill(QColor(0, 0, 0), region); } else { @@ -219,9 +221,53 @@ void PvrEglWindowSurface::setDirectRegion(const QRegion &r, int id) pvrRects[index].width = rect.width(); pvrRects[index].height = rect.height(); } + transformRects(pvrRects, rects.size()); pvrQwsSetVisibleRegion(drawable, pvrRects, rects.size()); + pvrQwsSetRotation(drawable, screen->transformation()); if (!pvrQwsSwapBuffers(drawable, 1)) screen->solidFill(QColor(0, 0, 0), region); delete [] pvrRects; } } + +void PvrEglWindowSurface::transformRects(PvrQwsRect *rects, int count) const +{ + switch (screen->transformation()) { + case 0: break; + + case 90: + { + for (int index = 0; index < count; ++index) { + int x = rects[index].y; + int y = screen->height() - (rects[index].x + rects[index].width); + rects[index].x = x; + rects[index].y = y; + qSwap(rects[index].width, rects[index].height); + } + } + break; + + case 180: + { + for (int index = 0; index < count; ++index) { + int x = screen->width() - (rects[index].x + rects[index].width); + int y = screen->height() - (rects[index].y + rects[index].height); + rects[index].x = x; + rects[index].y = y; + } + } + break; + + case 270: + { + for (int index = 0; index < count; ++index) { + int x = screen->width() - (rects[index].y + rects[index].height); + int y = rects[index].x; + rects[index].x = x; + rects[index].y = y; + qSwap(rects[index].width, rects[index].height); + } + } + break; + } +} diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h index 0da3653..b0a161c 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h @@ -45,14 +45,13 @@ #include <private/qglwindowsurface_qws_p.h> #include "pvrqwsdrawable.h" -class QScreen; -class PvrEglSurfaceHolder; +class PvrEglScreen; class PvrEglWindowSurface : public QWSGLWindowSurface { public: - PvrEglWindowSurface(QWidget *widget, QScreen *screen, int screenNum); - PvrEglWindowSurface(PvrEglSurfaceHolder *holder); + PvrEglWindowSurface(QWidget *widget, PvrEglScreen *screen, int screenNum); + PvrEglWindowSurface(); ~PvrEglWindowSurface(); QString key() const { return QLatin1String("PvrEgl"); } @@ -77,9 +76,10 @@ public: private: QWidget *widget; PvrQwsDrawable *drawable; - QScreen *screen; - PvrEglSurfaceHolder *holder; + PvrEglScreen *screen; QPaintDevice *pdevice; + + void transformRects(PvrQwsRect *rects, int count) const; }; #endif |