summaryrefslogtreecommitdiffstats
path: root/examples/qws/ahigl
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:34:13 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:34:13 (GMT)
commit67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch)
tree1dbf50b3dff8d5ca7e9344733968c72704eb15ff /examples/qws/ahigl
downloadQt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip
Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz
Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2
Long live Qt!
Diffstat (limited to 'examples/qws/ahigl')
-rw-r--r--examples/qws/ahigl/ahigl.pro16
-rw-r--r--examples/qws/ahigl/qscreenahigl_qws.cpp963
-rw-r--r--examples/qws/ahigl/qscreenahigl_qws.h91
-rw-r--r--examples/qws/ahigl/qscreenahiglplugin.cpp97
-rw-r--r--examples/qws/ahigl/qwindowsurface_ahigl.cpp349
-rw-r--r--examples/qws/ahigl/qwindowsurface_ahigl_p.h92
6 files changed, 1608 insertions, 0 deletions
diff --git a/examples/qws/ahigl/ahigl.pro b/examples/qws/ahigl/ahigl.pro
new file mode 100644
index 0000000..1ee8e6e
--- /dev/null
+++ b/examples/qws/ahigl/ahigl.pro
@@ -0,0 +1,16 @@
+TEMPLATE = lib
+QT += opengl
+CONFIG += plugin
+
+TARGET = qahiglscreen
+
+target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers
+INSTALLS += target
+
+HEADERS = qwindowsurface_ahigl_p.h \
+ qscreenahigl_qws.h
+
+SOURCES = qwindowsurface_ahigl.cpp \
+ qscreenahigl_qws.cpp \
+ qscreenahiglplugin.cpp
+
diff --git a/examples/qws/ahigl/qscreenahigl_qws.cpp b/examples/qws/ahigl/qscreenahigl_qws.cpp
new file mode 100644
index 0000000..b5880b3
--- /dev/null
+++ b/examples/qws/ahigl/qscreenahigl_qws.cpp
@@ -0,0 +1,963 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples 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 "qscreenahigl_qws.h"
+#include "qwindowsurface_ahigl_p.h"
+
+#include <QWSServer>
+#include <QMap>
+#include <QTimer>
+#include <QTimeLine>
+
+#include <qwindowsystem_qws.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qfixed_p.h>
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+#include <math.h>
+
+const int animationLength = 1500;
+const int frameSpan = 20;
+
+static GLuint createTexture(const QImage &img);
+
+class QAhiGLCursor : public QScreenCursor
+{
+public:
+ QAhiGLCursor() : texture(0) {}
+ ~QAhiGLCursor();
+
+ void set(const QImage &image, int hotx, int hoty);
+
+ GLuint texture;
+};
+
+QAhiGLCursor::~QAhiGLCursor()
+{
+ if (texture)
+ glDeleteTextures(1, &texture);
+}
+
+void QAhiGLCursor::set(const QImage &image, int hotx, int hoty)
+{
+ if (texture)
+ glDeleteTextures(1, &texture);
+
+ if (image.isNull())
+ texture = 0;
+ else
+ texture = createTexture(image.convertToFormat(QImage::Format_ARGB32));
+
+ QScreenCursor::set(image, hotx, hoty);
+}
+
+
+/*!
+ \class QAhiGLScreenPrivate
+ The QAhiGLScreenPrivate class contains state information for class QAhiGLScreen.
+
+ An instance of this class points to the owning instance of
+ class QAhiGLScreen. This class uses a QTimer to limit the
+ update frequency.
+ */
+//! [0]
+class QAhiGLScreenPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QAhiGLScreenPrivate(QAhiGLScreen *s);
+
+public slots:
+ void windowEvent(QWSWindow *w, QWSServer::WindowEvent e);
+ void redrawScreen();
+
+public:
+ QAhiGLScreen *screen;
+ QAhiGLCursor *cursor;
+
+ EGLContext eglContext;
+ EGLDisplay eglDisplay;
+ EGLSurface eglSurface;
+
+ QTimer updateTimer;
+ bool doEffects;
+};
+//! [0]
+
+//! [1]
+class ShowAnimation : public QTimeLine
+{
+public:
+ ShowAnimation(QAhiGLScreenPrivate *screen);
+ qreal valueForTime(int msec);
+};
+//! [1]
+
+//! [2]
+struct WindowInfo
+{
+ WindowInfo() : texture(0), animation(0) {}
+
+ GLuint texture;
+ QPointer<ShowAnimation> animation;
+};
+
+static QMap<QWSWindow*, WindowInfo*> windowMap;
+//! [2]
+
+/*!
+ Constructs the animation for the transition effect used
+ when the window associated with \a screen is displayed.
+ */
+//! [3]
+ShowAnimation::ShowAnimation(QAhiGLScreenPrivate *screen)
+ : QTimeLine(animationLength)
+{
+ setUpdateInterval(frameSpan);
+ connect(this, SIGNAL(valueChanged(qreal)), screen, SLOT(redrawScreen()));
+ connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
+ start();
+}
+//! [3]
+
+//! [4]
+qreal ShowAnimation::valueForTime(int msec)
+{
+ const qreal t = msec / qreal(duration());
+ return 3*t*t - 2*t*t*t;
+}
+//! [4]
+
+QAhiGLScreenPrivate::QAhiGLScreenPrivate(QAhiGLScreen *s)
+ : screen(s), cursor(0), doEffects(false)
+{
+ connect(&updateTimer, SIGNAL(timeout()), this, SLOT(redrawScreen()));
+}
+
+/*!
+ This slot handles the \a event when the \l {QWSServer}
+ {window server} emits a window event for the specified
+ \a window.
+
+ The \l {QWSServer::WindowEvent} {window events} handled
+ are \c Create, \c Destroy, and \c Show. The \c Create
+ event creates a new instance of \l {WindowInfo} and stores
+ it in a window map to mark the creation of a new window.
+ The \c Destroy event causes the \l {WindoInfo} instance
+ to be removed from the map and destroyed.
+
+ The \c Show event is the most interesting. If the user
+ has started the application with -display ahigl:effects,
+ then the \c Show event is handled by creating a small
+ \l {ShowAnimation} {animation} for use when the window
+ is first shown.
+ */
+//! [5]
+void QAhiGLScreenPrivate::windowEvent(QWSWindow *window,
+ QWSServer::WindowEvent event)
+{
+ switch (event) {
+ case QWSServer::Create:
+ windowMap[window] = new WindowInfo;
+ break;
+ case QWSServer::Show:
+ if (doEffects)
+ windowMap[window]->animation = new ShowAnimation(this);
+ break;
+ case QWSServer::Destroy:
+ delete windowMap[window];
+ windowMap.remove(window);
+ break;
+ default:
+ break;
+ }
+}
+//! [5]
+
+/*!
+ This function assumes the updateTimer is still counting down and stops it
+ and then calls redrawScreen() in the public screen driver class QAhiGLScreen.
+ */
+//! [6]
+void QAhiGLScreenPrivate::redrawScreen()
+{
+ updateTimer.stop();
+ screen->redrawScreen();
+}
+//! [6]
+
+/*!
+ \class QAhiGLScreen
+
+ \brief The QAhiGLScreen class is the screen driver for the ATI handheld device interface.
+
+ QAhiGLScreen is implemented with the d-pointer pattern. That is,
+ the only data member the class contains is a pointer called d_ptr,
+ which means data pointer. It points to an instance of a private
+ class called QAhiGLScreenPrivate, where all the screen driver's
+ context data members are defined. The d-pointer pattern is used
+ so that changes can be made to the screen driver's context data
+ members without destroying the binary compatibility of the public
+ screen driver class.
+
+ The pure virtual functions found in the base class QScreen are
+ listed below. All must have implementations in any screen driver
+ class derived from QScreen. All are impemented in this example,
+ except for setMode(), which has only been given a stub
+ implementation to satisfy the compiler.
+
+ bool connect(const QString & displaySpec);
+ void disconnect();
+ bool initDevice();
+ void setMode(int width, int height, int depth);
+
+ The stub implementation of setMode() is not meant to indicate
+ setMode() can be ignored in your own screen driver class. It was
+ simply decided not to provide a fully implemented screen driver
+ class for the example, which would normally be tailored to your
+ device's specific requirements.
+
+ The base class QGLScreen has only one pure virtual function,
+ hasOpenGL(), which must return true if your screen driver class
+ supports OpenGL.
+
+ QWSWindowSurface * createSurface(const QString & key) const
+ QWSWindowSurface * createSurface(QWidget * widget) const
+ void exposeRegion(QRegion region, int windowIndex)
+
+ */
+
+/*!
+ Constructs a new, ATI handheld device screen driver.
+
+ The displayId identifies the QWS server to connect to.
+ */
+QAhiGLScreen::QAhiGLScreen(int displayId) : QGLScreen(displayId)
+{
+ d_ptr = new QAhiGLScreenPrivate(this);
+ d_ptr->eglDisplay = EGL_NO_DISPLAY;
+ d_ptr->eglSurface = EGL_NO_SURFACE;
+}
+
+/*!
+ Destroys this ATI handheld device screen driver.
+ */
+QAhiGLScreen::~QAhiGLScreen()
+{
+ delete d_ptr;
+}
+
+/*!
+ \reimp
+ */
+//! [7]
+bool QAhiGLScreen::connect(const QString &displaySpec)
+{
+ // Hardcoded values for this device
+ w = 480;
+ h = 640;
+ dw = w;
+ dh = h;
+ d = 16;
+
+ const int dpi = 120;
+ physWidth = qRound(dw * 25.4 / dpi);
+ physHeight = qRound(dh * 25.4 / dpi);
+
+ if (displaySpec.section(':', 1, 1).contains("effects"))
+ d_ptr->doEffects = true;
+
+ return true;
+}
+//! [7]
+
+/*!
+ \reimp
+ */
+//! [8]
+bool QAhiGLScreen::initDevice()
+{
+ EGLint version, subversion;
+ EGLint attrs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_STENCIL_SIZE, 8, EGL_DEPTH_SIZE, 16,
+ EGL_NONE };
+ EGLint numConfig;
+ EGLConfig eglConfig;
+
+ d_ptr->eglDisplay = eglGetDisplay(0);
+ if (d_ptr->eglDisplay == EGL_NO_DISPLAY) {
+ qCritical("QAhiGLScreen::initDevice(): eglGetDisplay failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ if (!eglInitialize(d_ptr->eglDisplay, &version, &subversion)) {
+ qCritical("QAhiGLScreen::initDevice(): eglInitialize failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ if (!eglChooseConfig(d_ptr->eglDisplay, attrs, &eglConfig, 1, &numConfig)) {
+ qCritical("QAhiGLScreen::initDevice(): eglChooseConfig failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ static DummyScreen win = { w, h };
+ d_ptr->eglSurface = eglCreateWindowSurface(d_ptr->eglDisplay, eglConfig,
+ &win, 0);
+ if (d_ptr->eglSurface == EGL_NO_SURFACE) {
+ qCritical("QAhiGLScreen::initDevice(): eglCreateWindowSurface failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ d_ptr->eglContext = eglCreateContext(d_ptr->eglDisplay, eglConfig,
+ EGL_NO_CONTEXT, 0);
+ if (d_ptr->eglContext == EGL_NO_CONTEXT) {
+ qCritical("QAhiGLScreen::initDevice(): eglCreateContext failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ if (!eglMakeCurrent(d_ptr->eglDisplay, d_ptr->eglSurface, d_ptr->eglSurface, d_ptr->eglContext)) {
+ qCritical("QAhiGLScreen::initDevice(): eglMakeCurrent failed: 0x%x",
+ eglGetError());
+ return false;
+ }
+
+ d_ptr->connect(QWSServer::instance(),
+ SIGNAL(windowEvent(QWSWindow*, QWSServer::WindowEvent)),
+ SLOT(windowEvent(QWSWindow*, QWSServer::WindowEvent)));
+
+ d_ptr->cursor = new QAhiGLCursor;
+ qt_screencursor = d_ptr->cursor;
+
+ return true;
+}
+//! [8]
+
+/*!
+ \reimp
+ */
+//! [9]
+void QAhiGLScreen::shutdownDevice()
+{
+ delete d_ptr->cursor;
+ d_ptr->cursor = 0;
+ qt_screencursor = 0;
+
+ eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(d_ptr->eglDisplay, d_ptr->eglContext);
+ eglDestroySurface(d_ptr->eglDisplay, d_ptr->eglSurface);
+ eglTerminate(d_ptr->eglDisplay);
+}
+//! [9]
+
+/*!
+ \reimp
+
+ In this case, the reimplimentation does nothing. It is
+ required because the function is declared as pure virtual
+ in the base class QScreen.
+ */
+void QAhiGLScreen::disconnect()
+{
+}
+
+/*
+ This internal function rounds up to the next power of
+ two. If v is already a power of two, that same value is
+ returned.
+ */
+inline static uint nextPowerOfTwo(uint v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+/*
+ This internal function creates a texture from the image img
+ and returns its texture identifier.
+
+ The term "texture" is a graphics technology term that refers
+ to a pixmap constructed from an image by adding extra points
+ of contrast to the otherwise plain color image. The texture
+ has a, well, texture, that the original image doesn't have.
+ */
+static GLuint createTexture(const QImage &img)
+{
+ if (img.isNull())
+ return 0;
+
+ int width = img.width();
+ int height = img.height();
+ int textureWidth;
+ int textureHeight;
+ GLuint texture;
+
+ glGenTextures(1, &texture);
+ textureWidth = nextPowerOfTwo(width);
+ textureHeight = nextPowerOfTwo(height);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ switch (img.format()) {
+ case QImage::Format_RGB16:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+ textureWidth,
+ textureHeight, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, img.bits());
+ break;
+
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGB32:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ textureWidth,
+ textureHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
+ GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+ break;
+
+ default:
+ break;
+ }
+
+ return texture;
+}
+
+/*
+ A helper function used by QAhiGLScreen::drawQuad().
+ */
+static void drawQuad_helper(GLshort *coords, GLfloat *texCoords)
+{
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_SHORT, 0, coords);
+ glEnable(GL_TEXTURE_2D);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+/*
+ A helper function used by QAhiGLScreen::drawQuadWavyFlag().
+ */
+static void drawQuad_helper(GLshort *coords, GLfloat *texCoords,
+ int arraySize, int numArrays)
+{
+ glEnable(GL_TEXTURE_2D);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_SHORT, 0, coords);
+
+ for (int i = 0; i < numArrays-1; ++i)
+ glDrawArrays(GL_TRIANGLE_STRIP, i*arraySize, arraySize);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+}
+
+/*
+ A convenience function used by QAhiGLScreen::drawQuad().
+ */
+static void setRectCoords(GLshort *coords, QRect rect)
+{
+ coords[0] = GLshort(rect.left());
+ coords[1] = GLshort(rect.top());
+
+ coords[2] = GLshort(rect.right());
+ coords[3] = GLshort(rect.top());
+
+ coords[4] = GLshort(rect.right());
+ coords[5] = GLshort(rect.bottom());
+
+ coords[6] = GLshort(rect.left());
+ coords[7] = GLshort(rect.bottom());
+}
+
+/*!
+ A helper function used by QAhiGLScreen::drawWindow() and
+ QAhiGLScreen::redrawScreen().
+ */
+void QAhiGLScreen::drawQuad(const QRect &textureGeometry,
+ const QRect &subGeometry,
+ const QRect &screenGeometry)
+{
+ qreal textureWidth = qreal(nextPowerOfTwo(textureGeometry.width()));
+ qreal textureHeight = qreal(nextPowerOfTwo(textureGeometry.height()));
+
+ GLshort coords[8];
+ setRectCoords(coords, screenGeometry);
+
+ GLfloat texcoords[8];
+ texcoords[0] = (subGeometry.left() - textureGeometry.left()) / textureWidth;
+ texcoords[1] = (subGeometry.top() - textureGeometry.top()) / textureHeight;
+
+ texcoords[2] = (subGeometry.right() - textureGeometry.left()) / textureWidth;
+ texcoords[3] = (subGeometry.top() - textureGeometry.top()) / textureHeight;
+
+ texcoords[4] = (subGeometry.right() - textureGeometry.left()) / textureWidth;
+ texcoords[5] = (subGeometry.bottom() - textureGeometry.top()) / textureHeight;
+
+ texcoords[6] = (subGeometry.left() - textureGeometry.left()) / textureWidth;
+ texcoords[7] = (subGeometry.bottom() - textureGeometry.top()) / textureHeight;
+
+ drawQuad_helper(coords, texcoords);
+}
+
+/*
+ My own sine function.
+ */
+static qreal mySin(QFixed radians)
+{
+ const QFixed twoPI = QFixed::fromReal(2*M_PI);
+
+ const int tableSize = 40;
+ static int *table = 0;
+
+ if (!table) {
+ table = new int[tableSize];
+ for (int i = 0; i < tableSize; ++i) {
+ table[i] = qRound(sin(M_PI*(i*360.0/40.0)/180.0) * 16776960.0);
+ }
+ }
+
+ QFixed tableLookup = radians*tableSize/twoPI;
+ return table[tableLookup.truncate()%tableSize]/16776960.0;
+}
+
+/*
+ My own cosine function.
+ */
+static qreal myCos(QFixed radians)
+{
+ const int twoPI = qRound(2*M_PI);
+
+ const int tableSize = 40;
+ static int *table = 0;
+
+ if (!table) {
+ table = new int[tableSize];
+ for (int i = 0; i < tableSize; ++i) {
+ table[i] = int(cos(M_PI*(i*360.0/40.0)/180.0) * 16776960.0);
+ }
+ }
+
+ QFixed tableLookup = radians*tableSize/twoPI;
+ return table[tableLookup.truncate()%tableSize]/16776960.0;
+}
+
+// number of grid cells in wavy flag tesselation in x- and y-direction
+const int subdivisions = 10;
+
+/*
+ A helper function used by drawQuadWavyFlag(). It computes
+ coordinates for grid cells for a wavy flag tesselation and
+ stores them in the array called coords.
+ */
+static void setFlagCoords(GLshort *coords,
+ QRectF screenGeometry,
+ int frameNum,
+ qreal progress)
+{
+ int coordIndex = 0;
+ qreal waveHeight = 30.0*(1.0-progress);
+ for (int j = 0; j < subdivisions-1; ++j) {
+ for (int i = 0; i < subdivisions; ++i) {
+ qreal c;
+ c = screenGeometry.left()
+ + (i * screenGeometry.width() / (subdivisions - 1))
+ + waveHeight * qRound(mySin(QFixed::fromReal(M_PI * 20 * (frameNum + i) / 180.0)))
+ + waveHeight * qRound(myCos(QFixed::fromReal(M_PI * 20 * (frameNum + j) / 180.0)));
+ coords[coordIndex++] = qRound(c);
+ c = screenGeometry.top()
+ + (j * screenGeometry.height() / (subdivisions - 1))
+ + waveHeight * mySin(QFixed::fromReal(M_PI * 20 * (frameNum + i) / 180.0))
+ + waveHeight * myCos(QFixed::fromReal(M_PI * 20 * (frameNum + j) / 180.0));
+ coords[coordIndex++] = qRound(c);
+ c = screenGeometry.left() + (i * screenGeometry.width() / (subdivisions - 1))
+ + waveHeight * mySin(QFixed::fromReal(M_PI * 20 * (frameNum + i) / 180.0))
+ + waveHeight * myCos(QFixed::fromReal(M_PI * 20 * (frameNum + (j+1)) / 180.0));
+ coords[coordIndex++] = qRound(c);
+
+ c = screenGeometry.top()
+ + ((j + 1) * screenGeometry.height() / (subdivisions - 1))
+ + waveHeight * mySin(QFixed::fromReal(M_PI * 20 * (frameNum + i) / 180.0))
+ + waveHeight * myCos(QFixed::fromReal(M_PI * 20 * (frameNum + (j + 1)) / 180.0));
+ coords[coordIndex++] = qRound(c);
+ }
+ }
+}
+
+static void setFlagTexCoords(GLfloat *texcoords,
+ const QRectF &subTexGeometry,
+ const QRectF &textureGeometry,
+ int textureWidth, int textureHeight)
+{
+ qreal topLeftX = (subTexGeometry.left() - textureGeometry.left())/textureWidth;
+ qreal topLeftY = (textureGeometry.height() - (subTexGeometry.top() - textureGeometry.top()))/textureHeight;
+
+ qreal width = (subTexGeometry.right() - textureGeometry.left())/textureWidth - topLeftX;
+ qreal height = (textureGeometry.height() - (subTexGeometry.bottom() - textureGeometry.top()))/textureHeight - topLeftY;
+
+ int coordIndex = 0;
+ qreal spacing = subdivisions - 1;
+ for (int j = 0; j < subdivisions-1; ++j) {
+ for (int i = 0; i < subdivisions; ++i) {
+ texcoords[coordIndex++] = topLeftX + (i*width) / spacing;
+ texcoords[coordIndex++] = topLeftY + (j*height) / spacing;
+ texcoords[coordIndex++] = topLeftX + (i*width) / spacing;
+ texcoords[coordIndex++] = topLeftY + ((j+1)*height) / spacing;
+ }
+ }
+}
+
+void QAhiGLScreen::drawQuadWavyFlag(const QRect &textureGeometry,
+ const QRect &subTexGeometry,
+ const QRect &screenGeometry,
+ qreal progress)
+{
+ const int textureWidth = nextPowerOfTwo(textureGeometry.width());
+ const int textureHeight = nextPowerOfTwo(textureGeometry.height());
+
+ static int frameNum = 0;
+
+ GLshort coords[subdivisions*subdivisions*2*2];
+ setFlagCoords(coords, screenGeometry, frameNum++, progress);
+
+ GLfloat texcoords[subdivisions*subdivisions*2*2];
+ setFlagTexCoords(texcoords, subTexGeometry, textureGeometry,
+ textureWidth, textureHeight);
+
+ drawQuad_helper(coords, texcoords, subdivisions*2, subdivisions);
+}
+
+void QAhiGLScreen::invalidateTexture(int windowIndex)
+{
+ if (windowIndex < 0)
+ return;
+
+ QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+ if (windowIndex > windows.size() - 1)
+ return;
+
+ QWSWindow *win = windows.at(windowIndex);
+ if (!win)
+ return;
+
+ WindowInfo *info = windowMap[win];
+ if (info->texture) {
+ glDeleteTextures(1, &info->texture);
+ info->texture = 0;
+ }
+}
+
+void QAhiGLScreen::drawWindow(QWSWindow *win, qreal progress)
+{
+ const QRect screenRect = win->allocatedRegion().boundingRect();
+ QRect drawRect = screenRect;
+
+ glColor4f(1.0, 1.0, 1.0, progress);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ QWSWindowSurface *surface = win->windowSurface();
+ if (!surface)
+ return;
+
+ if (progress >= 1.0) {
+ if (surface->key() == QLatin1String("ahigl")) {
+ drawRect.setCoords(drawRect.left(), drawRect.bottom(),
+ drawRect.right(), drawRect.top());
+ }
+ drawQuad(win->requestedRegion().boundingRect(), screenRect, drawRect);
+ return;
+ }
+
+ const int dx = qRound((1 - progress) * drawRect.width() / 2);
+ const int dy = qRound((1 - progress) * drawRect.height() / 2);
+
+ drawRect.adjust(dx, dy, -dx, -dy);
+
+ if (surface->key() != QLatin1String("ahigl")) {
+ drawRect.setCoords(drawRect.left(), drawRect.bottom(),
+ drawRect.right(), drawRect.top());
+ }
+
+ drawQuadWavyFlag(win->requestedRegion().boundingRect(), screenRect,
+ drawRect, progress);
+}
+
+/*!
+ The window compositions are constructed here.
+ */
+//! [10]
+void QAhiGLScreen::redrawScreen()
+{
+ glBindFramebufferOES(GL_FRAMEBUFFER_EXT, 0);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(0, w, h, 0, -999999, 999999);
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Fill background color
+
+ QColor bgColor = QWSServer::instance()->backgroundBrush().color();
+ glClearColor(bgColor.redF(), bgColor.greenF(),
+ bgColor.blueF(), bgColor.alphaF());
+ glClear(GL_COLOR_BUFFER_BIT);
+//! [10]
+
+ // Draw all windows
+
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_ALPHA_TEST);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+//! [11]
+ QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+ for (int i = windows.size() - 1; i >= 0; --i) {
+ QWSWindow *win = windows.at(i);
+ QWSWindowSurface *surface = win->windowSurface();
+ if (!surface)
+ continue;
+
+ WindowInfo *info = windowMap[win];
+
+ if (!info->texture) {
+ if (surface->key() == QLatin1String("ahigl"))
+ info->texture = static_cast<QAhiGLWindowSurface*>(surface)->textureId();
+ else
+ info->texture = createTexture(surface->image());
+ }
+ qreal progress;
+ if (info->animation)
+ progress = info->animation->currentValue();
+ else
+ progress = 1.0;
+
+ glBindTexture(GL_TEXTURE_2D, info->texture);
+ drawWindow(win, progress);
+ } // for i
+//! [11] //! [12]
+
+ // Draw cursor
+
+ const QAhiGLCursor *cursor = d_ptr->cursor;
+ if (cursor->texture) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->cursor->texture);
+ drawQuad(cursor->boundingRect(), cursor->boundingRect(),
+ cursor->boundingRect());
+ }
+
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ eglSwapBuffers(d_ptr->eglDisplay, d_ptr->eglSurface);
+}
+//! [12]
+
+/*!
+ \reimp
+
+ */
+//! [13]
+void QAhiGLScreen::exposeRegion(QRegion r, int windowIndex)
+{
+ if ((r & region()).isEmpty())
+ return;
+
+ invalidateTexture(windowIndex);
+
+ if (!d_ptr->updateTimer.isActive())
+ d_ptr->updateTimer.start(frameSpan);
+}
+//! [13]
+
+/*!
+ \reimp
+
+ This overloading of createSurface() is called on the client side to
+ create a window surface for a new window. If the \a widget is a
+ QGLWidget, or if the widget's width and height are both less than or
+ equal to 256, it creates an instance of QAhiGLWindowSurface.
+ Otherwise, it calls QScreen::createSurface() to create a non-OpenGL
+ window surface. The pointer to the new window surface is returned.
+
+ Note that this function first asks whether this application is the
+ server, and it only creates an instance of QAhiGLWindowSurface if
+ the answer is yes. What this means is we only let the server have
+ access to the OpenGL hardware, because of an implementation
+ restyriction in the OpenGL libraries we are using. Thus only clients
+ that are in the server process get to create OpenGL window surfaces.
+ */
+//! [14]
+QWSWindowSurface* QAhiGLScreen::createSurface(QWidget *widget) const
+{
+ if (QApplication::type() == QApplication::GuiServer) {
+ if (qobject_cast<QGLWidget*>(widget)) {
+ return new QAhiGLWindowSurface(widget,
+ d_ptr->eglDisplay,
+ d_ptr->eglSurface,
+ d_ptr->eglContext);
+ }
+
+ const QRect rect = widget->frameGeometry();
+ if (rect.width() <= 256 && rect.height() <= 256) {
+ return new QAhiGLWindowSurface(widget,
+ d_ptr->eglDisplay,
+ d_ptr->eglSurface,
+ d_ptr->eglContext);
+ }
+ }
+
+ return QScreen::createSurface(widget);
+}
+//! [14]
+
+/*!
+ \reimp
+
+ This overloading of createSurface() is called on the server side
+ to manage a window surface corresponding to a window surface
+ already created on the client side.
+
+ If the \a key is "ahigl", create an instance of QAhiGLWindowSurface
+ and return it. Otherwise, call QScreen::createSurface() and return
+ the window surface it creates.
+
+ See QScreen::createSurface().
+ */
+//! [15]
+QWSWindowSurface* QAhiGLScreen::createSurface(const QString &key) const
+{
+ if (key == QLatin1String("ahigl")) {
+ return new QAhiGLWindowSurface(d_ptr->eglDisplay,
+ d_ptr->eglSurface,
+ d_ptr->eglContext);
+ }
+
+ return QScreen::createSurface(key);
+}
+//! [15]
+
+/*!
+ This function would normally reset the frame buffer resolution
+ according to \a width, \a height, and the bit \a depth. It would
+ then notify other applications that their frame buffer size had
+ changed so they could redraw. The function is a no-op in this
+ example, which means the example screen driver can't change its
+ frame buffer resolution. There is no significance to that in the
+ example. You would normally implement setMode() in an OpenGL
+ screen driver. This no-op reimplementation is required here
+ because setMode() in QScreen is a pure virtual function.
+
+ See QScreen::setMode()
+ */
+void QAhiGLScreen::setMode(int width, int height, int depth)
+{
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+}
+
+/*!
+ This function would normally be reimplemented to prevent the
+ screen driver from updating the screen if \a on is true. It is a
+ no-op in this example, which means the screen driver can always
+ update the screen.
+
+ See QScreen::blank().
+ */
+void QAhiGLScreen::blank(bool on)
+{
+ Q_UNUSED(on);
+}
+
+/*!
+ This function always returns true, since the purpose of
+ this screen driver class is to implement an OpenGL ES
+ screen driver. In some other class designed to handle both
+ OpenGL and non-OpenGL graphics, it might test the system to
+ determine whether OpenGL graphics are supported and return
+ true or false accordingly.
+ */
+bool QAhiGLScreen::hasOpenGL()
+{
+ return true;
+}
+
+#include "qscreenahigl_qws.moc"
diff --git a/examples/qws/ahigl/qscreenahigl_qws.h b/examples/qws/ahigl/qscreenahigl_qws.h
new file mode 100644
index 0000000..332d5c3
--- /dev/null
+++ b/examples/qws/ahigl/qscreenahigl_qws.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples 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 QAHIGLSCREEN_H
+#define QAHIGLSCREEN_H
+
+#include <QGLScreen>
+#include <QWSServer>
+
+QT_BEGIN_NAMESPACE
+class QAhiGLScreenPrivate;
+QT_END_NAMESPACE
+
+//! [0]
+class QAhiGLScreen : public QGLScreen
+{
+public:
+ QAhiGLScreen(int displayId);
+ virtual ~QAhiGLScreen();
+
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+
+ void setMode(int width, int height, int depth);
+ void blank(bool on);
+
+ void exposeRegion(QRegion r, int changing);
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+ bool hasOpenGL();
+
+private:
+ void invalidateTexture(int windowIndex);
+ void redrawScreen();
+ void drawWindow(QWSWindow *win, qreal progress);
+ void drawQuad(const QRect &textureGeometry,
+ const QRect &subGeometry,
+ const QRect &screenGeometry);
+ void drawQuadWavyFlag(const QRect &textureGeometry,
+ const QRect &subTexGeometry,
+ const QRect &screenGeometry,
+ float progress);
+
+ QAhiGLScreenPrivate *d_ptr;
+ friend class QAhiGLScreenPrivate;
+};
+//! [0]
+
+#endif // QAHIGLSCREEN_H
diff --git a/examples/qws/ahigl/qscreenahiglplugin.cpp b/examples/qws/ahigl/qscreenahiglplugin.cpp
new file mode 100644
index 0000000..828de82
--- /dev/null
+++ b/examples/qws/ahigl/qscreenahiglplugin.cpp
@@ -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 examples 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 "qscreenahigl_qws.h"
+
+#include <QScreenDriverPlugin>
+#include <QStringList>
+
+//! [0]
+class QAhiGLScreenPlugin : public QScreenDriverPlugin
+{
+public:
+ QAhiGLScreenPlugin();
+
+ QStringList keys() const;
+ QScreen *create(const QString&, int displayId);
+};
+//! [0]
+
+/*!
+ \class QAhiGLScreenPlugin
+ \brief The QAhiGLScreenPlugin class is the plugin for the ATI handheld device graphics driver.
+
+ QAhiGLScreenPlugin inherits QScreenDriverPlugin. See
+ \l{How to Create Qt Plugins} for details.
+ */
+
+/*!
+ This is the default constructor.
+ */
+QAhiGLScreenPlugin::QAhiGLScreenPlugin()
+ : QScreenDriverPlugin()
+{
+}
+
+/*!
+ Returns a string list containing the string "ahigl" which
+ is the only screen driver supported by this plugin.
+ */
+QStringList QAhiGLScreenPlugin::keys() const
+{
+ return (QStringList() << "ahigl");
+}
+
+/*!
+ Creates a screen driver of the kind specified by \a driver.
+ The \a displayId identifies the Qt for Embedded Linux server to connect to.
+ */
+QScreen* QAhiGLScreenPlugin::create(const QString& driver, int displayId)
+{
+ if (driver.toLower() != "ahigl")
+ return 0;
+
+ return new QAhiGLScreen(displayId);
+}
+
+//! [1]
+Q_EXPORT_PLUGIN2(qahiglscreen, QAhiGLScreenPlugin)
+//! [1]
diff --git a/examples/qws/ahigl/qwindowsurface_ahigl.cpp b/examples/qws/ahigl/qwindowsurface_ahigl.cpp
new file mode 100644
index 0000000..79924f9
--- /dev/null
+++ b/examples/qws/ahigl/qwindowsurface_ahigl.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples 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 "qwindowsurface_ahigl_p.h"
+#include "qscreenahigl_qws.h"
+
+#include <qwsdisplay_qws.h>
+#include <QtGui/QPaintDevice>
+#include <QtGui/QWidget>
+#include <QtOpenGL/private/qglpaintdevice_qws_p.h>
+#include <QtOpenGL/private/qgl_p.h>
+#include <GLES/gl.h>
+
+/*!
+ \class QAhiGLWindowSurfacePrivate
+ \internal
+
+ \brief The QAhiGLWindowSurfacePrivate class is the private implementation
+ class for class QAhiGLWindowSurface.
+
+ This class contains only state variables.
+ */
+//! [0]
+class QAhiGLWindowSurfacePrivate
+{
+public:
+ QAhiGLWindowSurfacePrivate(EGLDisplay eglDisplay,
+ EGLSurface eglSurface,
+ EGLContext eglContext);
+
+ QPaintDevice *device;
+
+ int textureWidth;
+ int textureHeight;
+
+ GLuint texture;
+ GLuint frameBufferObject;
+ GLuint depthbuf;
+
+ EGLDisplay display;
+ EGLSurface surface;
+ EGLContext context;
+};
+//! [0]
+
+/*!
+ The construct just sets statwe variables using the ones
+ provided.
+ */
+QAhiGLWindowSurfacePrivate::QAhiGLWindowSurfacePrivate(EGLDisplay eglDisplay,
+ EGLSurface eglSurface,
+ EGLContext eglContext)
+ : texture(0), frameBufferObject(0), depthbuf(0), display(eglDisplay),
+ surface(eglSurface), context(eglContext)
+{
+}
+
+inline static int nextPowerOfTwo(uint v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+/*!
+ \class QAhiGLWindowSurface
+ \preliminary
+ \internal
+
+ \brief The QAhiGLWindowSurface class provides the drawing area
+ for top-level windows using OpenGL for drawing on an ATI handheld
+ device.
+
+ In \l{Qt for Embedded Linux}, the default behavior for each client is to
+ render widgets into an area of memory. The server then displays
+ the contents of that memory on the screen. For ATI handheld
+ devices using OpenGL, QAhiGLWindowSurface is the window surface
+ class that allocates and manages the memory areas in the clients
+ and the server.
+
+ When a screen update is required, the server runs through all the
+ top-level windows that intersect with the region being updated,
+ ensuring that the clients have updated their window surfaces. Then
+ the server uses the screen driver to copy the contents of the
+ affected window surfaces into its composition and then display the
+ composition on the screen.
+
+ \tableofcontents
+
+ \section1 Pure Virtual Functions
+
+ There are two window surface instances for each top-level window.
+ One is used by the application when drawing a window, and the
+ other is used by the server application to make its copy for
+ building a window composition to send to the screen.
+
+ The key() function is implemented to uniquely identify this window
+ surface class as "ahigl", and the isValid() function is
+ implemented to determine whether the associated window is still
+ acceptable for representation by this window surface class. It
+ must either be a window using an \l {QGLWidget} {OpenGL widget},
+ or it must be a window whose frame is no bigger than 256 x 256.
+
+ The setGeometry() function is implemented to change the geometry
+ of the frame buffer whenever the geometry of the associated
+ top-level window changes. The image() function is called by the
+ window system when building window compositions to return an image
+ of the top-level window.
+
+ The paintDevice() function is implemented to return the appropriate
+ paint device.
+
+ \section1 Virtual Functions
+
+ When painting onto the surface, the window system will always call
+ the beginPaint() function before any painting operations are
+ performed. It ensures that the correct frame buffer will be used
+ by the OpenGL library for painting operations. Likewise, the
+ endPaint() function is automatically called when the painting is
+ done, but it isn't implemented for this example.
+*/
+
+/*!
+ This is the client side constructor.
+ */
+//! [1]
+QAhiGLWindowSurface::QAhiGLWindowSurface(QWidget *widget,
+ EGLDisplay eglDisplay,
+ EGLSurface eglSurface,
+ EGLContext eglContext)
+ : QWSGLWindowSurface(widget)
+{
+ d_ptr = new QAhiGLWindowSurfacePrivate(eglDisplay, eglSurface, eglContext);
+ d_ptr->device = new QWSGLPaintDevice(widget);
+
+ setSurfaceFlags(QWSWindowSurface::Buffered);
+}
+//! [1]
+
+/*!
+ This is the server side constructor.
+ */
+//! [2]
+QAhiGLWindowSurface::QAhiGLWindowSurface(EGLDisplay eglDisplay,
+ EGLSurface eglSurface,
+ EGLContext eglContext)
+{
+ d_ptr = new QAhiGLWindowSurfacePrivate(eglDisplay, eglSurface, eglContext);
+ setSurfaceFlags(QWSWindowSurface::Buffered);
+}
+//! [2]
+
+/*!
+ The destructor deletes the OpenGL structures held by the
+ private implementation class, and then it deletes the
+ private implementation class.
+ */
+QAhiGLWindowSurface::~QAhiGLWindowSurface()
+{
+ if (d_ptr->texture)
+ glDeleteTextures(1, &d_ptr->texture);
+ if (d_ptr->depthbuf)
+ glDeleteRenderbuffersOES(1, &d_ptr->depthbuf);
+ if (d_ptr->frameBufferObject)
+ glDeleteFramebuffersOES(1, &d_ptr->frameBufferObject);
+
+ delete d_ptr;
+}
+
+/*!
+ This function changes the geometry of the frame buffer
+ to the geometry in \a rect. It is called whenever the
+ geometry of the associated top-level window changes. It
+ also rebuilds the window surface's texture and binds
+ the OpenGL identifier to the texture for use by the
+ OpenGL library.
+ */
+//! [3]
+void QAhiGLWindowSurface::setGeometry(const QRect &rect)
+{
+ QSize size = rect.size();
+
+ const QWidget *w = window();
+ if (w && !w->mask().isEmpty()) {
+ const QRegion region = w->mask()
+ & rect.translated(-w->geometry().topLeft());
+ size = region.boundingRect().size();
+ }
+
+ if (geometry().size() != size) {
+
+ // Driver specific limitations:
+ // FBO maximimum size of 256x256
+ // Depth buffer required
+
+ d_ptr->textureWidth = qMin(256, nextPowerOfTwo(size.width()));
+ d_ptr->textureHeight = qMin(256, nextPowerOfTwo(size.height()));
+
+ glGenTextures(1, &d_ptr->texture);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->texture);
+
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ const int bufSize = d_ptr->textureWidth * d_ptr->textureHeight * 2;
+ GLshort buf[bufSize];
+ memset(buf, 0, sizeof(GLshort) * bufSize);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d_ptr->textureWidth,
+ d_ptr->textureHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+ glGenRenderbuffersOES(1, &d_ptr->depthbuf);
+ glBindRenderbufferOES(GL_RENDERBUFFER_EXT, d_ptr->depthbuf);
+ glRenderbufferStorageOES(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
+ d_ptr->textureWidth, d_ptr->textureHeight);
+
+ glGenFramebuffersOES(1, &d_ptr->frameBufferObject);
+ glBindFramebufferOES(GL_FRAMEBUFFER_EXT, d_ptr->frameBufferObject);
+
+ glFramebufferTexture2DOES(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, d_ptr->texture, 0);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, d_ptr->depthbuf);
+ glBindFramebufferOES(GL_FRAMEBUFFER_EXT, 0);
+ }
+
+ QWSGLWindowSurface::setGeometry(rect);
+}
+//! [3]
+
+/*!
+ Returns the window surface's texture as a QByteArray.
+ */
+QByteArray QAhiGLWindowSurface::permanentState() const
+{
+ QByteArray array;
+ array.resize(sizeof(GLuint));
+
+ char *ptr = array.data();
+ reinterpret_cast<GLuint*>(ptr)[0] = textureId();
+ return array;
+}
+
+/*!
+ Sets the window surface's texture to \a data.
+ */
+void QAhiGLWindowSurface::setPermanentState(const QByteArray &data)
+{
+ const char *ptr = data.constData();
+ d_ptr->texture = reinterpret_cast<const GLuint*>(ptr)[0];
+}
+
+/*!
+ Returns the paint device being used for this window surface.
+ */
+QPaintDevice *QAhiGLWindowSurface::paintDevice()
+{
+ return d_ptr->device;
+}
+
+/*!
+ Returns the window surface's texture.
+ */
+GLuint QAhiGLWindowSurface::textureId() const
+{
+ return d_ptr->texture;
+}
+
+/*!
+ The \l {QWSServer} {window system} always calls this function
+ before any painting operations begin for this window surface.
+ It ensures that the correct frame buffer will be used by the
+ OpenGL library for painting operations.
+ */
+//! [4]
+void QAhiGLWindowSurface::beginPaint(const QRegion &region)
+{
+ QWSGLWindowSurface::beginPaint(region);
+
+ if (d_ptr->frameBufferObject)
+ glBindFramebufferOES(GL_FRAMEBUFFER_EXT, d_ptr->frameBufferObject);
+}
+//! [4]
+
+/*!
+ This function returns true if the window associated with
+ this window surface can still rendered using this window
+ surface class. Either the window's top-level widget must
+ be an \l {QGLWidget} {OpenGL widget}, or the window's
+ frame must be no bigger than 256 x 256.
+ */
+//! [5]
+bool QAhiGLWindowSurface::isValid() const
+{
+ if (!qobject_cast<QGLWidget*>(window())) {
+ const QRect r = window()->frameGeometry();
+ if (r.width() > 256 || r.height() > 256)
+ return false;
+ }
+ return true;
+}
+//! [5]
diff --git a/examples/qws/ahigl/qwindowsurface_ahigl_p.h b/examples/qws/ahigl/qwindowsurface_ahigl_p.h
new file mode 100644
index 0000000..40a82ed
--- /dev/null
+++ b/examples/qws/ahigl/qwindowsurface_ahigl_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples 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 QWINDOWSURFACE_AHIGL_P_H
+#define QWINDOWSURFACE_AHIGL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QAhiGLWindowSurface class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtOpenGL/private/qglwindowsurface_qws_p.h>
+#include <GLES/gl.h>
+#include <GLES/egl.h>
+
+QT_BEGIN_NAMESPACE
+class QAhiGLWindowSurfacePrivate;
+QT_END_NAMESPACE
+
+//! [0]
+class QAhiGLWindowSurface : public QWSGLWindowSurface
+{
+public:
+ QAhiGLWindowSurface(QWidget *widget, EGLDisplay eglDisplay,
+ EGLSurface eglSurface, EGLContext eglContext);
+ QAhiGLWindowSurface(EGLDisplay eglDisplay, EGLSurface eglSurface,
+ EGLContext eglContext);
+ ~QAhiGLWindowSurface();
+
+ QString key() const { return QLatin1String("ahigl"); }
+ void setGeometry(const QRect &rect);
+ QPaintDevice *paintDevice();
+ void beginPaint(const QRegion &region);
+ bool isValid() const;
+
+ QByteArray permanentState() const;
+ void setPermanentState(const QByteArray &);
+
+ QImage image() const { return QImage(); }
+
+ GLuint textureId() const;
+
+private:
+ QAhiGLWindowSurfacePrivate *d_ptr;
+};
+//! [0]
+
+#endif // QWINDOWSURFACE_AHIGL_P_H