diff options
Diffstat (limited to 'src/plugins/gfxdrivers/hybrid')
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybrid.pro | 16 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybridplugin.cpp | 75 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybridscreen.cpp | 382 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybridscreen.h | 97 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybridsurface.cpp | 300 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/hybrid/hybridsurface.h | 90 |
6 files changed, 960 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/hybrid/hybrid.pro b/src/plugins/gfxdrivers/hybrid/hybrid.pro new file mode 100644 index 0000000..8b8e9ef --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybrid.pro @@ -0,0 +1,16 @@ +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 new file mode 100644 index 0000000..803c4fc --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybridplugin.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "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 new file mode 100644 index 0000000..3a40b4c --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp @@ -0,0 +1,382 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "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(QLatin1String("hybrid:")).size()); + else if (dspec.compare(QLatin1String("hybrid"), Qt::CaseInsensitive) == 0) + dspec = QString(); + + const QString displayIdSpec = QString(QLatin1String(" :%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 new file mode 100644 index 0000000..d463e12 --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybridscreen.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef 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 new file mode 100644 index 0000000..7281328 --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybridsurface.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "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 new file mode 100644 index 0000000..d9be3b6 --- /dev/null +++ b/src/plugins/gfxdrivers/hybrid/hybridsurface.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef 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 |