📄 11.18 实例:在嵌入式系统中使用opengl.txt
字号:
QAhiGLScreenPlugin 类 :
class QAhiGLScreenPlugin : public QScreenDriverPlugin
{
public:
QAhiGLScreenPlugin();
QStringList keys() const;
QScreen *create(const QString&, int displayId);
};
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;
};
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;
};
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 ®ion);
bool isValid() const;
QByteArray permanentState() const;
void setPermanentState(const QByteArray &);
QImage image() const { return QImage(); }
GLuint textureId() const;
private:
QAhiGLWindowSurfacePrivate *d_ptr;
};
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;
};
struct WindowInfo
{
WindowInfo() : texture(0), animation(0) {}
GLuint texture;
QPointer<ShowAnimation> animation;
};
static QMap<QWSWindow*, WindowInfo*> windowMap;
class ShowAnimation : public QTimeLine
{
public:
ShowAnimation(QAhiGLScreenPrivate *screen);
qreal valueForTime(int msec);
};
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;
}
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;
}
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;
}
}
ShowAnimation::ShowAnimation(QAhiGLScreenPrivate *screen)
: QTimeLine(animationLength)
{
setUpdateInterval(frameSpan);
connect(this, SIGNAL(valueChanged(qreal)), screen, SLOT(redrawScreen()));
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
start();
}
void QAhiGLScreen::exposeRegion(QRegion r, int windowIndex)
{
if ((r & region()).isEmpty())
return;
invalidateTexture(windowIndex);
if (!d_ptr->updateTimer.isActive())
d_ptr->updateTimer.start(frameSpan);
}
void QAhiGLScreenPrivate::redrawScreen()
{
updateTimer.stop();
screen->redrawScreen();
}
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);
}
QAhiGLWindowSurface::QAhiGLWindowSurface(EGLDisplay eglDisplay,
EGLSurface eglSurface,
EGLContext eglContext)
{
d_ptr = new QAhiGLWindowSurfacePrivate(eglDisplay, eglSurface, eglContext);
setSurfaceFlags(QWSWindowSurface::Buffered);
}
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) {
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);
}
void QAhiGLWindowSurface::beginPaint(const QRegion ®ion)
{
QWSGLWindowSurface::beginPaint(region);
if (d_ptr->frameBufferObject)
glBindFramebufferOES(GL_FRAMEBUFFER_EXT, d_ptr->frameBufferObject);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -