diff options
Diffstat (limited to 'src/opengl/qopenglframebufferobject.cpp')
-rw-r--r-- | src/opengl/qopenglframebufferobject.cpp | 151 |
1 files changed, 94 insertions, 57 deletions
diff --git a/src/opengl/qopenglframebufferobject.cpp b/src/opengl/qopenglframebufferobject.cpp index 78b192b630..5c8f769d39 100644 --- a/src/opengl/qopenglframebufferobject.cpp +++ b/src/opengl/qopenglframebufferobject.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qopenglframebufferobject.h" #include "qopenglframebufferobject_p.h" @@ -54,6 +18,15 @@ QT_BEGIN_NAMESPACE +Q_TRACE_PREFIX(qtopengl, + "#include <private/qopengl2pexvertexarray_p.h>" \ + "#include <private/qopengltextureuploader_p.h>" \ + "#include <qopenglframebufferobject.h>" +); +Q_TRACE_PARAM_REPLACE(GLenum, int); +Q_TRACE_PARAM_REPLACE(GLint, int); +Q_TRACE_METADATA(qtopengl, "ENUM { } QOpenGLFramebufferObject::Attachment; "); + #ifndef QT_NO_DEBUG #define QT_RESET_GLERROR() \ { \ @@ -152,6 +125,25 @@ QT_BEGIN_NAMESPACE #define GL_DEPTH_STENCIL 0x84F9 #endif +#ifndef GL_HALF_FLOAT +#define GL_HALF_FLOAT 0x140B +#endif + +#ifndef GL_RGBA32F +#define GL_RGBA32F 0x8814 +#endif + +#ifndef GL_RGB32F +#define GL_RGB32F 0x8815 +#endif + +#ifndef GL_RGBA16F +#define GL_RGBA16F 0x881A +#endif + +#ifndef GL_RGB16F +#define GL_RGB16F 0x881B +#endif /*! @@ -469,10 +461,11 @@ namespace } } -void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *qfbo, const QSize &size, - QOpenGLFramebufferObject::Attachment attachment, - GLenum texture_target, GLenum internal_format, - GLint samples, bool mipmap) +void Q_TRACE_INSTRUMENT(qtopengl) QOpenGLFramebufferObjectPrivate::init( + QOpenGLFramebufferObject *qfbo, const QSize &size, + QOpenGLFramebufferObject::Attachment attachment, + GLenum texture_target, GLenum internal_format, + GLint samples, bool mipmap) { Q_TRACE_SCOPE(QOpenGLFramebufferObjectPrivate_init, qfbo, size, attachment, texture_target, internal_format, samples, mipmap); Q_UNUSED(qfbo); @@ -554,9 +547,25 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx) pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; else if (color.internalFormat == GL_RGB16 || color.internalFormat == GL_RGBA16) pixelType = GL_UNSIGNED_SHORT; + else if (color.internalFormat == GL_RGB16F || color.internalFormat == GL_RGBA16F) + pixelType = GL_HALF_FLOAT; + + bool isOpaque = false; + switch (color.internalFormat) { + case GL_RGB8: + case GL_RGB16: + case GL_RGB16F: + case GL_RGB32F: + isOpaque = true; + break; + case GL_RGB10: + // opaque but the pixel type (INT_2_10_10_10) has alpha and so requires RGBA texture format + break; + } + const GLuint textureFormat = isOpaque ? GL_RGB : GL_RGBA; funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0, - GL_RGBA, pixelType, nullptr); + textureFormat, pixelType, nullptr); if (format.mipmap()) { int width = color.size.width(); int height = color.size.height(); @@ -565,8 +574,8 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx) width = qMax(1, width >> 1); height = qMax(1, height >> 1); ++level; - funcs.glTexImage2D(target, level, color.internalFormat, width, height, 0, - GL_RGBA, pixelType, nullptr); + funcs.glTexImage2D(target, level, color.internalFormat, width, height, 0, textureFormat, + pixelType, nullptr); } } funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + idx, @@ -1008,7 +1017,7 @@ QOpenGLFramebufferObject::~QOpenGLFramebufferObject() if (isBound()) release(); - for (const auto &color : qAsConst(d->colorAttachments)) { + for (const auto &color : std::as_const(d->colorAttachments)) { if (color.guard) color.guard->free(); } @@ -1068,7 +1077,7 @@ void QOpenGLFramebufferObject::addColorAttachment(const QSize &size, GLenum inte QOpenGLFramebufferObjectPrivate::ColorAttachment color(size, effectiveInternalFormat(internalFormat)); d->colorAttachments.append(color); - const int idx = d->colorAttachments.count() - 1; + const int idx = d->colorAttachments.size() - 1; if (d->requestedSamples == 0) { d->initTexture(idx); @@ -1149,7 +1158,7 @@ bool QOpenGLFramebufferObject::bind() if (d->format.samples() == 0) { // Create new textures to replace the ones stolen via takeTexture(). - for (int i = 0; i < d->colorAttachments.count(); ++i) { + for (int i = 0; i < d->colorAttachments.size(); ++i) { if (!d->colorAttachments.at(i).guard) d->initTexture(i); } @@ -1229,7 +1238,7 @@ QList<GLuint> QOpenGLFramebufferObject::textures() const QList<GLuint> ids; if (d->format.samples() != 0) return ids; - ids.reserve(d->colorAttachments.count()); + ids.reserve(d->colorAttachments.size()); for (const auto &color : d->colorAttachments) ids.append(color.guard ? color.guard->id() : 0); return ids; @@ -1281,7 +1290,7 @@ GLuint QOpenGLFramebufferObject::takeTexture(int colorAttachmentIndex) { Q_D(QOpenGLFramebufferObject); GLuint id = 0; - if (isValid() && d->format.samples() == 0 && d->colorAttachments.count() > colorAttachmentIndex) { + if (isValid() && d->format.samples() == 0 && d->colorAttachments.size() > colorAttachmentIndex) { QOpenGLContext *current = QOpenGLContext::currentContext(); if (current && current->shareGroup() == d->fbo_guard->group() && isBound()) release(); @@ -1349,7 +1358,8 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2); if (isOpenGL12orBetter) { QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); - funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, img.bits()); + if (!img.isNull()) + funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, img.bits()); return img; } @@ -1359,7 +1369,8 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ // BGRA capable impl would return BGRA from there) QImage rgbaImage(size, include_alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888); - funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits()); + if (!rgbaImage.isNull()) + funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits()); return rgbaImage; } @@ -1367,7 +1378,8 @@ static inline QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool incl { // We assume OpenGL 1.2+ or ES 3.0+ here. QImage img(size, include_alpha ? QImage::Format_A2BGR30_Premultiplied : QImage::Format_BGR30); - context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, img.bits()); + if (!img.isNull()) + context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, img.bits()); return img; } @@ -1375,7 +1387,25 @@ static inline QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool inclu { // We assume OpenGL 1.2+ or ES 3.0+ here. QImage img(size, include_alpha ? QImage::Format_RGBA64_Premultiplied : QImage::Format_RGBX64); - context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_SHORT, img.bits()); + if (!img.isNull()) + context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_SHORT, img.bits()); + return img; +} + +static inline QImage qt_gl_read_framebuffer_rgba16f(const QSize &size, bool include_alpha, QOpenGLContext *context) +{ + // We assume OpenGL (ES) 3.0+ here. + QImage img(size, include_alpha ? QImage::Format_RGBA16FPx4_Premultiplied : QImage::Format_RGBX16FPx4); + if (!img.isNull()) + context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_HALF_FLOAT, img.bits()); + return img; +} + +static inline QImage qt_gl_read_framebuffer_rgba32f(const QSize &size, bool include_alpha, QOpenGLContext *context) +{ + QImage img(size, include_alpha ? QImage::Format_RGBA32FPx4_Premultiplied : QImage::Format_RGBX32FPx4); + if (!img.isNull()) + context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_FLOAT, img.bits()); return img; } @@ -1400,14 +1430,21 @@ static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, return qt_gl_read_framebuffer_rgba16(size, false, ctx).mirrored(false, flip); case GL_RGBA16: return qt_gl_read_framebuffer_rgba16(size, include_alpha, ctx).mirrored(false, flip); + case GL_RGB16F: + return qt_gl_read_framebuffer_rgba16f(size, false, ctx).mirrored(false, flip); + case GL_RGBA16F: + return qt_gl_read_framebuffer_rgba16f(size, include_alpha, ctx).mirrored(false, flip); + case GL_RGB32F: + return qt_gl_read_framebuffer_rgba32f(size, false, ctx).mirrored(false, flip); + case GL_RGBA32F: + return qt_gl_read_framebuffer_rgba32f(size, include_alpha, ctx).mirrored(false, flip); case GL_RGBA: case GL_RGBA8: default: return qt_gl_read_framebuffer_rgba8(size, include_alpha, ctx).mirrored(false, flip); } - Q_UNREACHABLE(); - return QImage(); + Q_UNREACHABLE_RETURN(QImage()); } Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) @@ -1483,7 +1520,7 @@ QImage QOpenGLFramebufferObject::toImage(bool flipped, int colorAttachmentIndex) return QImage(); } - if (d->colorAttachments.count() <= colorAttachmentIndex) { + if (d->colorAttachments.size() <= colorAttachmentIndex) { qWarning("QOpenGLFramebufferObject::toImage() called for missing color attachment"); return QImage(); } |