summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2009-11-02 09:09:06 +1000
committerRhys Weatherley <rhys.weatherley@nokia.com>2009-11-02 09:09:06 +1000
commitacde9118f87ebd5aba5904072e40997a2a155d13 (patch)
tree26084564ab77d0779ff85726de9f973061186cd7 /src
parent4204fdcc04e20eabd19704f2235ba06afa84605e (diff)
Make screen rotation work properly with the PowerVR screen driver
Task-number: QT-2261 Reviewed-by: Tom Back port of 75719e4e06882825fe056935d782b4153bf0ac5b
Diffstat (limited to 'src')
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c10
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.h3
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h1
-rw-r--r--src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwswsegl.c14
-rw-r--r--src/plugins/gfxdrivers/powervr/README5
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp67
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h9
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp54
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h8
9 files changed, 162 insertions, 9 deletions
diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c
index ac9dc8d834..c1b655a5b1 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 952ff6ff52..b9e035f084 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 cf80a90b1c..dcd4e4fbc8 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 253f39f11e..28b22518ab 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 4dce87f830..322a6b2e01 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 66966720b3..2e4c6d10db 100644
--- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
@@ -44,6 +44,9 @@
#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>
@@ -60,6 +63,7 @@ PvrEglScreen::PvrEglScreen(int displayId)
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);
@@ -189,7 +193,7 @@ bool PvrEglScreen::hasOpenGL()
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);
}
@@ -202,6 +206,67 @@ QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const
return QScreen::createSurface(key);
}
+#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()
{
// Put code here to synchronize 2D and 3D operations if necessary.
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
index 8bf42c7fc6..5769e7025c 100644
--- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.h
@@ -46,16 +46,18 @@
#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;
};
@@ -80,6 +82,8 @@ public:
QWSWindowSurface* createSurface(QWidget *widget) const;
QWSWindowSurface* createSurface(const QString &key) const;
+ int transformation() const;
+
private:
void sync();
void openTty();
@@ -89,6 +93,7 @@ private:
int ttyfd, oldKdMode;
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 2c5ac21711..4a3787f537 100644
--- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.cpp
@@ -46,7 +46,7 @@
#include <QWSDisplay>
PvrEglWindowSurface::PvrEglWindowSurface
- (QWidget *widget, QScreen *screen, int screenNum)
+ (QWidget *widget, PvrEglScreen *screen, int screenNum)
: QWSGLWindowSurface(widget)
{
setSurfaceFlags(QWSWindowSurface::Opaque);
@@ -63,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
@@ -75,6 +76,7 @@ PvrEglWindowSurface::PvrEglWindowSurface
pvrQwsSetGeometry(drawable, &pvrRect);
else
drawable = pvrQwsCreateWindow(screenNum, (long)widget, &pvrRect);
+ pvrQwsSetRotation(drawable, screen->transformation());
}
PvrEglWindowSurface::PvrEglWindowSurface()
@@ -113,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);
}
@@ -127,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);
}
@@ -200,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 {
@@ -213,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 58a5fb2361..b0a161c235 100644
--- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglwindowsurface.h
@@ -45,12 +45,12 @@
#include <private/qglwindowsurface_qws_p.h>
#include "pvrqwsdrawable.h"
-class QScreen;
+class PvrEglScreen;
class PvrEglWindowSurface : public QWSGLWindowSurface
{
public:
- PvrEglWindowSurface(QWidget *widget, QScreen *screen, int screenNum);
+ PvrEglWindowSurface(QWidget *widget, PvrEglScreen *screen, int screenNum);
PvrEglWindowSurface();
~PvrEglWindowSurface();
@@ -76,8 +76,10 @@ public:
private:
QWidget *widget;
PvrQwsDrawable *drawable;
- QScreen *screen;
+ PvrEglScreen *screen;
QPaintDevice *pdevice;
+
+ void transformRects(PvrQwsRect *rects, int count) const;
};
#endif