Added QGLPixelBuffer implementation using framebuffer objects.
Instead of having QGLPixelBuffer be a unusable stub implementation we deprecate it and implement it in terms of QOpenGLFramebufferObject. Framebuffer objects are anyway the recommended replacement for pixelbuffers in modern OpenGL, as the context switching overhead is avoided. Change-Id: Ia220c358ee92813e87981d297c51d84525010322 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
This commit is contained in:
parent
2d70dde68a
commit
ccf0669da9
4
dist/changes-5.0.0
vendored
4
dist/changes-5.0.0
vendored
@ -570,6 +570,10 @@ QtOpenGL
|
||||
now have equivalents in QtGui, along with the naming change QGL -> QOpenGL.
|
||||
The classes in QtOpenGL that have equivalents in QtGui can now be considered
|
||||
deprecated.
|
||||
* QGLPixelBuffer is now deprecated and implemented in terms of a hidden
|
||||
QGLWidget and a QOpenGLFramebufferObject. It is recommended that applications
|
||||
using QGLPixelBuffer for offscreen rendering to a texture switch to using
|
||||
QOpenGLFramebufferObject directly instead, for improved performance.
|
||||
|
||||
QtScript
|
||||
--------
|
||||
|
@ -49,14 +49,16 @@ int main(int argc, char **argv)
|
||||
Q_INIT_RESOURCE(pbuffers);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
GLWidget widget(0);
|
||||
widget.resize(640, 480);
|
||||
widget.makeCurrent();
|
||||
|
||||
if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
|
||||
QMessageBox::information(0, "OpenGL pbuffers",
|
||||
"This system does not support OpenGL/pbuffers.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
GLWidget widget(0);
|
||||
widget.resize(640, 480);
|
||||
widget.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
@ -144,8 +144,6 @@ void GLWidget::draw()
|
||||
pbuffer_painter.end();
|
||||
glFlush();
|
||||
|
||||
// rendering directly to a texture is not supported on X11 and
|
||||
// some Windows implementations, unfortunately
|
||||
if (!hasDynamicTextureUpdate)
|
||||
pbuffer->updateDynamicTexture(dynamicTexture);
|
||||
|
||||
|
@ -47,14 +47,14 @@ int main(int argc, char **argv)
|
||||
Q_INIT_RESOURCE(pbuffers2);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
GLWidget widget(0);
|
||||
widget.resize(640, 480);
|
||||
widget.makeCurrent();
|
||||
if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
|
||||
QMessageBox::information(0, "OpenGL pbuffers 2",
|
||||
"This system does not support OpenGL/pbuffers.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
GLWidget widget(0);
|
||||
widget.resize(640, 480);
|
||||
widget.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ Q_SIGNALS:
|
||||
|
||||
private:
|
||||
friend class QGLContext;
|
||||
friend class QGLPixelBuffer;
|
||||
friend class QOpenGLContextResourceBase;
|
||||
friend class QOpenGLPaintDevice;
|
||||
friend class QOpenGLGlyphTexture;
|
||||
|
@ -61,7 +61,6 @@ SOURCES += qglshaderprogram.cpp \
|
||||
gl2paintengineex/qglcustomshaderstage.cpp \
|
||||
gl2paintengineex/qtextureglyphcache_gl.cpp
|
||||
|
||||
SOURCES += qgl_qpa.cpp \
|
||||
qglpixelbuffer_stub.cpp
|
||||
SOURCES += qgl_qpa.cpp
|
||||
|
||||
INCLUDEPATH += ../3rdparty/harfbuzz/src
|
||||
|
@ -92,7 +92,10 @@
|
||||
\sa {opengl/pbuffers}{Pbuffers Example}
|
||||
*/
|
||||
|
||||
#include <private/qopenglextensions_p.h>
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtGui/qopenglframebufferobject.h>
|
||||
|
||||
#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
|
||||
|
||||
@ -129,16 +132,7 @@ void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &form
|
||||
req_format = format;
|
||||
req_shareWidget = shareWidget;
|
||||
invalid = false;
|
||||
qctx = new QGLContext(format);
|
||||
qctx->d_func()->sharing = (shareWidget != 0);
|
||||
if (shareWidget != 0 && shareWidget->d_func()->glcx) {
|
||||
QGLContextGroup::addShare(qctx, shareWidget->d_func()->glcx);
|
||||
shareWidget->d_func()->glcx->d_func()->sharing = true;
|
||||
}
|
||||
|
||||
glDevice.setPBuffer(q);
|
||||
qctx->d_func()->paintDevice = q;
|
||||
qctx->d_func()->valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +192,6 @@ QGLPixelBuffer::~QGLPixelBuffer()
|
||||
if (current != d->qctx)
|
||||
makeCurrent();
|
||||
d->cleanup();
|
||||
delete d->qctx;
|
||||
if (current && current != d->qctx)
|
||||
current->makeCurrent();
|
||||
}
|
||||
@ -217,6 +210,17 @@ bool QGLPixelBuffer::makeCurrent()
|
||||
if (d->invalid)
|
||||
return false;
|
||||
d->qctx->makeCurrent();
|
||||
if (!d->fbo) {
|
||||
QOpenGLFramebufferObjectFormat format;
|
||||
if (d->req_format.stencil())
|
||||
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||
else if (d->req_format.depth())
|
||||
format.setAttachment(QOpenGLFramebufferObject::Depth);
|
||||
if (d->req_format.sampleBuffers())
|
||||
format.setSamples(d->req_format.samples());
|
||||
d->fbo = new QOpenGLFramebufferObject(d->req_size, format);
|
||||
d->fbo->bind();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -306,14 +310,39 @@ bool QGLPixelBuffer::doneCurrent()
|
||||
void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
|
||||
{
|
||||
Q_D(const QGLPixelBuffer);
|
||||
if (d->invalid)
|
||||
if (d->invalid || !d->fbo)
|
||||
return;
|
||||
|
||||
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#undef glBindFramebuffer
|
||||
|
||||
#ifndef GL_READ_FRAMEBUFFER
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#endif
|
||||
|
||||
#ifndef GL_DRAW_FRAMEBUFFER
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
#endif
|
||||
|
||||
QOpenGLExtensions extensions(ctx);
|
||||
|
||||
if (d->blit_fbo) {
|
||||
QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
|
||||
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
#ifndef QT_OPENGL_ES
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0);
|
||||
#else
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
|
||||
#endif
|
||||
|
||||
if (d->blit_fbo)
|
||||
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->d_func()->current_fbo);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -521,4 +550,70 @@ QGLFormat QGLPixelBuffer::format() const
|
||||
\internal
|
||||
*/
|
||||
|
||||
bool QGLPixelBufferPrivate::init(const QSize &, const QGLFormat &f, QGLWidget *shareWidget)
|
||||
{
|
||||
widget = new QGLWidget(f, 0, shareWidget);
|
||||
widget->resize(1, 1);
|
||||
qctx = const_cast<QGLContext *>(widget->context());
|
||||
return widget->isValid();
|
||||
}
|
||||
|
||||
bool QGLPixelBufferPrivate::cleanup()
|
||||
{
|
||||
delete fbo;
|
||||
fbo = 0;
|
||||
delete blit_fbo;
|
||||
blit_fbo = 0;
|
||||
delete widget;
|
||||
widget = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
|
||||
{
|
||||
Q_UNUSED(texture_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
void QGLPixelBuffer::releaseFromDynamicTexture()
|
||||
{
|
||||
}
|
||||
|
||||
GLuint QGLPixelBuffer::generateDynamicTexture() const
|
||||
{
|
||||
Q_D(const QGLPixelBuffer);
|
||||
if (!d->fbo)
|
||||
return 0;
|
||||
|
||||
if (d->fbo->format().samples() > 0
|
||||
&& QOpenGLExtensions(QOpenGLContext::currentContext())
|
||||
.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
|
||||
{
|
||||
if (!d->blit_fbo)
|
||||
const_cast<QOpenGLFramebufferObject *&>(d->blit_fbo) = new QOpenGLFramebufferObject(d->req_size);
|
||||
} else {
|
||||
return d->fbo->texture();
|
||||
}
|
||||
|
||||
GLuint texture;
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
bool QGLPixelBuffer::hasOpenGLPbuffers()
|
||||
{
|
||||
return QOpenGLFramebufferObject::hasOpenGLFramebufferObjects();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -60,7 +60,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglContext;
|
||||
|
||||
class QOpenGLFramebufferObject;
|
||||
|
||||
class QGLPBufferGLPaintDevice : public QGLPaintDevice
|
||||
{
|
||||
@ -77,7 +77,7 @@ private:
|
||||
class QGLPixelBufferPrivate {
|
||||
Q_DECLARE_PUBLIC(QGLPixelBuffer)
|
||||
public:
|
||||
QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), pbuf(0), ctx(0)
|
||||
QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), widget(0), fbo(0), blit_fbo(0), pbuf(0), ctx(0)
|
||||
{
|
||||
}
|
||||
bool init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget);
|
||||
@ -88,6 +88,9 @@ public:
|
||||
bool invalid;
|
||||
QGLContext *qctx;
|
||||
QGLPBufferGLPaintDevice glDevice;
|
||||
QGLWidget *widget;
|
||||
QOpenGLFramebufferObject *fbo;
|
||||
QOpenGLFramebufferObject *blit_fbo;
|
||||
QGLFormat format;
|
||||
|
||||
QGLFormat req_format;
|
||||
|
@ -1,84 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtOpenGL module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qdebug.h>
|
||||
#include "qglpixelbuffer.h"
|
||||
#include "qglpixelbuffer_p.h"
|
||||
|
||||
#include <qimage.h>
|
||||
#include <private/qgl_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
Q_UNUSED(f);
|
||||
Q_UNUSED(shareWidget);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QGLPixelBufferPrivate::cleanup()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
|
||||
{
|
||||
Q_UNUSED(texture_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
void QGLPixelBuffer::releaseFromDynamicTexture()
|
||||
{
|
||||
}
|
||||
|
||||
GLuint QGLPixelBuffer::generateDynamicTexture() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QGLPixelBuffer::hasOpenGLPbuffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
Loading…
x
Reference in New Issue
Block a user