diff options
-rw-r--r-- | dist/changes-5.0.0 | 4 | ||||
-rw-r--r-- | examples/opengl/pbuffers/main.cpp | 6 | ||||
-rw-r--r-- | examples/opengl/pbuffers2/glwidget.cpp | 2 | ||||
-rw-r--r-- | examples/opengl/pbuffers2/main.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qopenglcontext.h | 1 | ||||
-rw-r--r-- | src/opengl/opengl.pro | 3 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 117 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer_p.h | 7 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer_stub.cpp | 84 |
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 |