📄 qscreenahigl_qws.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the example classes of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#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/qtextengine_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. */class QAhiGLScreenPrivate : public QObject{ Q_OBJECTpublic: 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;};class ShowAnimation : public QTimeLine{public: ShowAnimation(QAhiGLScreenPrivate *screen); qreal valueForTime(int msec);};struct WindowInfo{ WindowInfo() : texture(0), animation(0) {} GLuint texture; QPointer<ShowAnimation> animation;};static QMap<QWSWindow*, WindowInfo*> windowMap;/*! Constructs the animation for the transition effect used when the window associated with \a screen is displayed. */ShowAnimation::ShowAnimation(QAhiGLScreenPrivate *screen) : QTimeLine(animationLength){ setUpdateInterval(frameSpan); connect(this, SIGNAL(valueChanged(qreal)), screen, SLOT(redrawScreen())); connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); start();}qreal ShowAnimation::valueForTime(int msec){ const qreal t = msec / qreal(duration()); return 3*t*t - 2*t*t*t;}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. */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; }}/*! This function assumes the updateTimer is still counting down and stops it and then calls redrawScreen() in the public screen driver class QAhiGLScreen. */void QAhiGLScreenPrivate::redrawScreen(){ updateTimer.stop(); screen->redrawScreen();}/*! \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 Qtopia Core 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 */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;}/*! \reimp */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;}/*! \reimp */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);}/*! \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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -