summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.0.04
-rw-r--r--examples/opengl/pbuffers/main.cpp6
-rw-r--r--examples/opengl/pbuffers2/glwidget.cpp2
-rw-r--r--examples/opengl/pbuffers2/main.cpp6
-rw-r--r--src/gui/kernel/qopenglcontext.h1
-rw-r--r--src/opengl/opengl.pro3
-rw-r--r--src/opengl/qglpixelbuffer.cpp117
-rw-r--r--src/opengl/qglpixelbuffer_p.h7
-rw-r--r--src/opengl/qglpixelbuffer_stub.cpp84
9 files changed, 124 insertions, 106 deletions
diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0
index 16ba1c3453..5f2781c1b6 100644
--- a/dist/changes-5.0.0
+++ b/dist/changes-5.0.0
@@ -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
--------
diff --git a/examples/opengl/pbuffers/main.cpp b/examples/opengl/pbuffers/main.cpp
index 6ae4542ca6..58d25245a1 100644
--- a/examples/opengl/pbuffers/main.cpp
+++ b/examples/opengl/pbuffers/main.cpp
@@ -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();
}
diff --git a/examples/opengl/pbuffers2/glwidget.cpp b/examples/opengl/pbuffers2/glwidget.cpp
index 1fcfdcb533..d8dbe9854c 100644
--- a/examples/opengl/pbuffers2/glwidget.cpp
+++ b/examples/opengl/pbuffers2/glwidget.cpp
@@ -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);
diff --git a/examples/opengl/pbuffers2/main.cpp b/examples/opengl/pbuffers2/main.cpp
index eb956d472e..29ddec9bb9 100644
--- a/examples/opengl/pbuffers2/main.cpp
+++ b/examples/opengl/pbuffers2/main.cpp
@@ -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();
}
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 7dfffde4a0..9ce76a9117 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -137,6 +137,7 @@ Q_SIGNALS:
private:
friend class QGLContext;
+ friend class QGLPixelBuffer;
friend class QOpenGLContextResourceBase;
friend class QOpenGLPaintDevice;
friend class QOpenGLGlyphTexture;
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 1d4abca64e..2adb2e09ce 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -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
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index d9480c4994..135f2edd01 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -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
diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h
index 6e8d6d7301..fd20cee07a 100644
--- a/src/opengl/qglpixelbuffer_p.h
+++ b/src/opengl/qglpixelbuffer_p.h
@@ -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;
diff --git a/src/opengl/qglpixelbuffer_stub.cpp b/src/opengl/qglpixelbuffer_stub.cpp
deleted file mode 100644
index 528e48e9b6..0000000000
--- a/src/opengl/qglpixelbuffer_stub.cpp
+++ /dev/null
@@ -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