summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/powervr/pvreglscreen
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/powervr/pvreglscreen')
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp351
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h99
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro27
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp74
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp273
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h85
6 files changed, 909 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
new file mode 100644
index 0000000000..c981e0d300
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** 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$
+** 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 "pvreglscreen.h"
+#include "pvreglwindowsurface.h"
+#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;
+ 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);
+}
+
+bool PvrEglScreen::initDevice()
+{
+ openTty();
+ return true;
+}
+
+bool PvrEglScreen::connect(const QString &displaySpec)
+{
+ if (!pvrQwsDisplayOpen())
+ return false;
+
+ // Initialize the QScreen properties.
+ data = (uchar *)(pvrQwsDisplay.screens[0].mapped);
+ w = pvrQwsDisplay.screens[0].screenRect.width;
+ h = pvrQwsDisplay.screens[0].screenRect.height;
+ lstep = pvrQwsDisplay.screens[0].screenStride;
+ dw = w;
+ dh = h;
+ size = h * lstep;
+ mapsize = size;
+ switch (pvrQwsDisplay.screens[0].pixelFormat) {
+ case PVR2D_RGB565:
+ d = 16;
+ setPixelFormat(QImage::Format_RGB16);
+ break;
+ case PVR2D_ARGB4444:
+ d = 16;
+ setPixelFormat(QImage::Format_ARGB4444_Premultiplied);
+ break;
+ case PVR2D_ARGB8888:
+ d = 32;
+ setPixelFormat(QImage::Format_ARGB32_Premultiplied);
+ break;
+ default:
+ pvrQwsDisplayClose();
+ qWarning("PvrEglScreen::connect: unsupported pixel format %d", (int)(pvrQwsDisplay.screens[0].pixelFormat));
+ return false;
+ }
+
+ // Handle display physical size spec.
+ QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
+ QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
+ int dimIdxW = displayArgs.indexOf(mmWidthRx);
+ QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
+ int dimIdxH = displayArgs.indexOf(mmHeightRx);
+ if (dimIdxW >= 0) {
+ mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
+ physWidth = mmWidthRx.cap(1).toInt();
+ if (dimIdxH < 0)
+ physHeight = dh*physWidth/dw;
+ }
+ if (dimIdxH >= 0) {
+ mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
+ physHeight = mmHeightRx.cap(1).toInt();
+ if (dimIdxW < 0)
+ physWidth = dw*physHeight/dh;
+ }
+ if (dimIdxW < 0 && dimIdxH < 0) {
+ const int dpi = 72;
+ physWidth = qRound(dw * 25.4 / dpi);
+ physHeight = qRound(dh * 25.4 / dpi);
+ }
+
+ // Find the name of the tty device to use.
+ QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
+ if (displayArgs.indexOf(ttyRegExp) != -1)
+ ttyDevice = ttyRegExp.cap(1);
+ if (displayArgs.contains(QLatin1String("nographicsmodeswitch")))
+ doGraphicsMode = false;
+
+ // The screen is ready.
+ return true;
+}
+
+void PvrEglScreen::disconnect()
+{
+ pvrQwsDisplayClose();
+}
+
+void PvrEglScreen::shutdownDevice()
+{
+ closeTty();
+}
+
+void PvrEglScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &region)
+{
+ QGLScreen::blit(img, topLeft, region);
+ sync();
+}
+
+void PvrEglScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ QGLScreen::solidFill(color, region);
+ sync();
+}
+
+bool PvrEglScreen::chooseContext
+ (QGLContext *context, const QGLContext *shareContext)
+{
+ // We use PvrEglScreenSurfaceFunctions instead.
+ Q_UNUSED(context);
+ Q_UNUSED(shareContext);
+ return false;
+}
+
+bool PvrEglScreen::hasOpenGL()
+{
+ return true;
+}
+
+//![1]
+QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const
+{
+ if (qobject_cast<QGLWidget*>(widget))
+ return new PvrEglWindowSurface(widget, (PvrEglScreen *)this, displayId);
+
+ return QScreen::createSurface(widget);
+}
+
+QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const
+{
+ if (key == QLatin1String("PvrEgl"))
+ 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)
+ ->transformOrientation();
+}
+
+#else
+
+int PvrEglScreen::transformation() const
+{
+ return 0;
+}
+
+#endif
+
+void PvrEglScreen::sync()
+{
+ // Put code here to synchronize 2D and 3D operations if necessary.
+}
+
+void PvrEglScreen::openTty()
+{
+ const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
+
+ if (ttyDevice.isEmpty()) {
+ for (const char * const *dev = devs; *dev; ++dev) {
+ ttyfd = ::open(*dev, O_RDWR);
+ if (ttyfd != -1)
+ break;
+ }
+ } else {
+ ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR);
+ }
+
+ if (ttyfd == -1)
+ return;
+
+ ::fcntl(ttyfd, F_SETFD, FD_CLOEXEC);
+
+ if (doGraphicsMode) {
+ ioctl(ttyfd, KDGETMODE, &oldKdMode);
+ if (oldKdMode != KD_GRAPHICS) {
+ int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
+ if (ret == -1)
+ doGraphicsMode = false;
+ }
+ }
+
+ // No blankin' screen, no blinkin' cursor!, no cursor!
+ const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
+ ::write(ttyfd, termctl, sizeof(termctl));
+}
+
+void PvrEglScreen::closeTty()
+{
+ if (ttyfd == -1)
+ return;
+
+ if (doGraphicsMode)
+ ioctl(ttyfd, KDSETMODE, oldKdMode);
+
+ // Blankin' screen, blinkin' cursor!
+ const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
+ ::write(ttyfd, termctl, sizeof(termctl));
+
+ ::close(ttyfd);
+ ttyfd = -1;
+}
+
+//![2]
+bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native)
+{
+//![2]
+ QWSWindowSurface *surface =
+ static_cast<QWSWindowSurface *>(widget->windowSurface());
+ if (!surface) {
+ // The widget does not have a surface yet, so give it one.
+ surface = new PvrEglWindowSurface(widget, screen, displayId);
+ widget->setWindowSurface(surface);
+ } else if (surface->key() != QLatin1String("PvrEgl")) {
+ // The application has attached a QGLContext to an ordinary QWidget.
+ // Replace the widget's window surface with a new one that can do GL.
+ QRect geometry = widget->frameGeometry();
+ geometry.moveTo(widget->mapToGlobal(QPoint(0, 0)));
+ surface = new PvrEglWindowSurface(widget, screen, displayId);
+ surface->setGeometry(geometry);
+ widget->setWindowSurface(surface);
+ widget->setAttribute(Qt::WA_NoSystemBackground, true);
+ }
+ PvrEglWindowSurface *nsurface = static_cast<PvrEglWindowSurface*>(surface);
+ *native = (EGLNativeWindowType)(nsurface->nativeDrawable());
+ return true;
+}
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
new file mode 100644
index 0000000000..efb2406771
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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$
+** 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 PVREGLSCREEN_H
+#define PVREGLSCREEN_H
+
+#include <QScreen>
+#include <QGLScreen>
+#include "pvrqwsdrawable.h"
+
+class PvrEglScreen;
+
+class PvrEglScreenSurfaceFunctions : public QGLScreenSurfaceFunctions
+{
+public:
+ PvrEglScreenSurfaceFunctions(PvrEglScreen *s, int screenNum)
+ : screen(s), displayId(screenNum) {}
+
+ bool createNativeWindow(QWidget *widget, EGLNativeWindowType *native);
+
+private:
+ PvrEglScreen *screen;
+ int displayId;
+};
+
+class PvrEglScreen : public QGLScreen
+{
+public:
+ PvrEglScreen(int displayId);
+ ~PvrEglScreen();
+
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+ void setMode(int, int, int) {}
+
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void solidFill(const QColor &color, const QRegion &region);
+
+ bool chooseContext(QGLContext *context, const QGLContext *shareContext);
+ bool hasOpenGL();
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+ int transformation() const;
+
+private:
+ void sync();
+ void openTty();
+ void closeTty();
+
+ int fd;
+ int ttyfd, oldKdMode;
+ QString ttyDevice;
+ bool doGraphicsMode;
+ mutable const QScreen *parent;
+};
+
+#endif
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro
new file mode 100644
index 0000000000..675be85460
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro
@@ -0,0 +1,27 @@
+TEMPLATE = lib
+TARGET = qgfxpvregl
+CONFIG += qt plugin warn_on
+QT += opengl
+
+LIBS += -lpvrQWSWSEGL
+
+DEFINES += QT_QWS_CLIENTBLIT
+
+INCLUDEPATH += ../QWSWSEGL
+
+
+HEADERS = \
+ pvreglscreen.h \
+ pvreglwindowsurface.h
+
+SOURCES = \
+ pvreglscreenplugin.cpp \
+ pvreglscreen.cpp \
+ pvreglwindowsurface.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers
+
+target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers
+INSTALLS += target
+
+include(../powervr.pri) \ No newline at end of file
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp
new file mode 100644
index 0000000000..872285e818
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreenplugin.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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$
+** 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 "pvreglscreen.h"
+
+#include <QScreenDriverPlugin>
+#include <QStringList>
+
+class PvrEglScreenPlugin : public QScreenDriverPlugin
+{
+public:
+ PvrEglScreenPlugin();
+
+ QStringList keys() const;
+ QScreen *create(const QString&, int displayId);
+};
+
+PvrEglScreenPlugin::PvrEglScreenPlugin()
+ : QScreenDriverPlugin()
+{
+}
+
+QStringList PvrEglScreenPlugin::keys() const
+{
+ return (QStringList() << "powervr");
+}
+
+QScreen* PvrEglScreenPlugin::create(const QString& driver, int displayId)
+{
+ if (driver.toLower() != "powervr")
+ return 0;
+
+ return new PvrEglScreen(displayId);
+}
+
+Q_EXPORT_PLUGIN2(qgfxpvregl, PvrEglScreenPlugin)
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
new file mode 100644
index 0000000000..43648159c8
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** 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$
+** 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 "pvreglwindowsurface.h"
+#include "pvreglscreen.h"
+#include <QScreen>
+#include <QDebug>
+#include <QWSDisplay>
+
+PvrEglWindowSurface::PvrEglWindowSurface
+ (QWidget *widget, PvrEglScreen *screen, int screenNum)
+ : QWSGLWindowSurface(widget)
+{
+ setSurfaceFlags(QWSWindowSurface::Opaque);
+
+ this->widget = widget;
+ this->screen = screen;
+ this->pdevice = 0;
+
+ QPoint pos = offset(widget);
+ QSize size = widget->size();
+
+ PvrQwsRect pvrRect;
+ pvrRect.x = pos.x();
+ 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
+ // is created for a widget, bound to a EGLSurface, and then destroyed.
+ // When a new PvrEglWindowSurface is created for the widget, it will
+ // pick up the previous PvrQwsDrawable if the EGLSurface has not been
+ // destroyed in the meantime.
+ drawable = pvrQwsFetchWindow((long)widget);
+ if (drawable)
+ pvrQwsSetGeometry(drawable, &pvrRect);
+ else
+ drawable = pvrQwsCreateWindow(screenNum, (long)widget, &pvrRect);
+ pvrQwsSetRotation(drawable, screen->transformation());
+}
+
+PvrEglWindowSurface::PvrEglWindowSurface()
+ : QWSGLWindowSurface()
+{
+ setSurfaceFlags(QWSWindowSurface::Opaque);
+ drawable = 0;
+ widget = 0;
+ screen = 0;
+ pdevice = 0;
+}
+
+PvrEglWindowSurface::~PvrEglWindowSurface()
+{
+ // Release the PvrQwsDrawable. If it is bound to an EGLSurface,
+ // then it will stay around until a new PvrEglWindowSurface is
+ // created for the widget. If it is not bound to an EGLSurface,
+ // it will be destroyed immediately.
+ if (drawable && pvrQwsReleaseWindow(drawable))
+ pvrQwsDestroyDrawable(drawable);
+
+ delete pdevice;
+}
+
+bool PvrEglWindowSurface::isValid() const
+{
+ return (widget != 0);
+}
+
+void PvrEglWindowSurface::setGeometry(const QRect &rect)
+{
+ if (drawable) {
+ // XXX: adjust for the screen offset.
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ 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);
+}
+
+bool PvrEglWindowSurface::move(const QPoint &offset)
+{
+ QRect rect = geometry().translated(offset);
+ if (drawable) {
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ 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);
+}
+
+QByteArray PvrEglWindowSurface::permanentState() const
+{
+ // Nothing interesting to pass to the server just yet.
+ return QByteArray();
+}
+
+void PvrEglWindowSurface::setPermanentState(const QByteArray &state)
+{
+ Q_UNUSED(state);
+}
+
+void PvrEglWindowSurface::flush
+ (QWidget *widget, const QRegion &region, const QPoint &offset)
+{
+ // The GL paint engine is responsible for the swapBuffers() call.
+ // If we were to call the base class's implementation of flush()
+ // then it would fetch the image() and manually blit it to the
+ // screeen instead of using the fast PVR2D blit.
+ Q_UNUSED(widget);
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+}
+
+QImage PvrEglWindowSurface::image() const
+{
+ if (drawable) {
+ PvrQwsRect pvrRect;
+ pvrQwsGetGeometry(drawable, &pvrRect);
+ void *data = pvrQwsGetRenderBuffer(drawable);
+ if (data) {
+ return QImage((uchar *)data, pvrRect.width, pvrRect.height,
+ pvrQwsGetStride(drawable), screen->pixelFormat());
+ }
+ }
+ return QImage(16, 16, screen->pixelFormat());
+}
+
+QPaintDevice *PvrEglWindowSurface::paintDevice()
+{
+ return widget;
+}
+
+void PvrEglWindowSurface::setDirectRegion(const QRegion &r, int id)
+{
+ QWSGLWindowSurface::setDirectRegion(r, id);
+
+ if (!drawable)
+ return;
+
+ // Clip the region to the window boundaries in case the child
+ // is partially outside the geometry of the parent.
+ QWidget *window = widget->window();
+ QRegion region = r;
+ if (widget != window) {
+ QRect rect = window->geometry();
+ rect.moveTo(window->mapToGlobal(QPoint(0, 0)));
+ region = region.intersect(rect);
+ }
+
+ if (region.isEmpty()) {
+ pvrQwsClearVisibleRegion(drawable);
+ } else if (region.rectCount() == 1) {
+ QRect rect = region.boundingRect();
+ PvrQwsRect pvrRect;
+ pvrRect.x = rect.x();
+ 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 {
+ QVector<QRect> rects = region.rects();
+ PvrQwsRect *pvrRects = new PvrQwsRect [rects.size()];
+ for (int index = 0; index < rects.size(); ++index) {
+ QRect rect = rects[index];
+ pvrRects[index].x = rect.x();
+ pvrRects[index].y = rect.y();
+ 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
new file mode 100644
index 0000000000..9f5600c136
--- /dev/null
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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$
+** 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 PVREGLWINDOWSURFACE_H
+#define PVREGLWINDOWSURFACE_H
+
+#include <private/qglwindowsurface_qws_p.h>
+#include "pvrqwsdrawable.h"
+
+class PvrEglScreen;
+
+class PvrEglWindowSurface : public QWSGLWindowSurface
+{
+public:
+ PvrEglWindowSurface(QWidget *widget, PvrEglScreen *screen, int screenNum);
+ PvrEglWindowSurface();
+ ~PvrEglWindowSurface();
+
+ QString key() const { return QLatin1String("PvrEgl"); }
+
+ bool isValid() const;
+
+ void setGeometry(const QRect &rect);
+ bool move(const QPoint &offset);
+
+ QByteArray permanentState() const;
+ void setPermanentState(const QByteArray &state);
+
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+
+ QImage image() const;
+ QPaintDevice *paintDevice();
+
+ void setDirectRegion(const QRegion &region, int id);
+
+ long nativeDrawable() const { return (long)widget; }
+
+private:
+ QWidget *widget;
+ PvrQwsDrawable *drawable;
+ PvrEglScreen *screen;
+ QPaintDevice *pdevice;
+
+ void transformRects(PvrQwsRect *rects, int count) const;
+};
+
+#endif