4875 lines
169 KiB
C++
4875 lines
169 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
|
|
** Copyright (C) 2020 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtGui 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$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qopengltexture.h"
|
|
#include "qopengltexture_p.h"
|
|
#include "qopengltexturehelper_p.h"
|
|
#include "qopenglfunctions.h"
|
|
#include <QtGui/qcolor.h>
|
|
#include <QtGui/qopenglcontext.h>
|
|
#include <QtCore/qdebug.h>
|
|
#include <private/qobject_p.h>
|
|
#include <private/qopenglcontext_p.h>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
//this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value
|
|
#if !defined(GL_TEXTURE_WRAP_R)
|
|
#define GL_TEXTURE_WRAP_R 0x8072
|
|
#endif
|
|
|
|
QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,
|
|
QOpenGLTexture *qq)
|
|
: q_ptr(qq),
|
|
context(nullptr),
|
|
target(textureTarget),
|
|
textureId(0),
|
|
format(QOpenGLTexture::NoFormat),
|
|
formatClass(QOpenGLTexture::NoFormatClass),
|
|
requestedMipLevels(1),
|
|
mipLevels(-1),
|
|
layers(1),
|
|
faces(1),
|
|
samples(0),
|
|
fixedSamplePositions(true),
|
|
baseLevel(0),
|
|
maxLevel(1000),
|
|
depthStencilMode(QOpenGLTexture::DepthMode),
|
|
comparisonFunction(QOpenGLTexture::CompareLessEqual),
|
|
comparisonMode(QOpenGLTexture::CompareNone),
|
|
minFilter(QOpenGLTexture::Nearest),
|
|
magFilter(QOpenGLTexture::Nearest),
|
|
maxAnisotropy(1.0f),
|
|
minLevelOfDetail(-1000.0f),
|
|
maxLevelOfDetail(1000.0f),
|
|
levelOfDetailBias(0.0f),
|
|
textureView(false),
|
|
autoGenerateMipMaps(true),
|
|
storageAllocated(false),
|
|
texFuncs(nullptr),
|
|
functions(nullptr)
|
|
{
|
|
dimensions[0] = dimensions[1] = dimensions[2] = 1;
|
|
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
bindingTarget = QOpenGLTexture::BindingTarget1D;
|
|
break;
|
|
case QOpenGLTexture::Target1DArray:
|
|
bindingTarget = QOpenGLTexture::BindingTarget1DArray;
|
|
break;
|
|
case QOpenGLTexture::Target2D:
|
|
bindingTarget = QOpenGLTexture::BindingTarget2D;
|
|
break;
|
|
case QOpenGLTexture::Target2DArray:
|
|
bindingTarget = QOpenGLTexture::BindingTarget2DArray;
|
|
break;
|
|
case QOpenGLTexture::Target3D:
|
|
bindingTarget = QOpenGLTexture::BindingTarget3D;
|
|
break;
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
|
|
faces = 6;
|
|
break;
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
|
|
faces = 6;
|
|
break;
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
|
|
break;
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
bindingTarget = QOpenGLTexture::BindingTarget2DMultisampleArray;
|
|
break;
|
|
case QOpenGLTexture::TargetRectangle:
|
|
bindingTarget = QOpenGLTexture::BindingTargetRectangle;
|
|
break;
|
|
case QOpenGLTexture::TargetBuffer:
|
|
bindingTarget = QOpenGLTexture::BindingTargetBuffer;
|
|
break;
|
|
}
|
|
|
|
swizzleMask[0] = QOpenGLTexture::RedValue;
|
|
swizzleMask[1] = QOpenGLTexture::GreenValue;
|
|
swizzleMask[2] = QOpenGLTexture::BlueValue;
|
|
swizzleMask[3] = QOpenGLTexture::AlphaValue;
|
|
|
|
wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
|
|
? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
|
|
}
|
|
|
|
QOpenGLTexturePrivate::~QOpenGLTexturePrivate()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::initializeOpenGLFunctions()
|
|
{
|
|
// If we already have a functions object, there is nothing to do
|
|
if (texFuncs)
|
|
return;
|
|
|
|
// See if the context already has a suitable resource we can use.
|
|
// If not create a functions object and add it to the context in case
|
|
// others wish to use it too
|
|
texFuncs = context->textureFunctions();
|
|
if (!texFuncs) {
|
|
texFuncs = new QOpenGLTextureHelper(context);
|
|
auto *funcs = texFuncs; // lets us capture by pointer value below
|
|
context->setTextureFunctions(funcs, [funcs] { delete funcs; });
|
|
}
|
|
}
|
|
|
|
bool QOpenGLTexturePrivate::create()
|
|
{
|
|
if (textureId != 0)
|
|
return true;
|
|
|
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
|
if (!ctx) {
|
|
qWarning("Requires a valid current OpenGL context.\n"
|
|
"Texture has not been created");
|
|
return false;
|
|
}
|
|
context = ctx;
|
|
functions = ctx->functions();
|
|
|
|
// Resolve any functions we will need based upon context version and create the texture
|
|
initializeOpenGLFunctions();
|
|
|
|
// What features do we have?
|
|
QOpenGLTexture::Feature feature = QOpenGLTexture::ImmutableStorage;
|
|
while (feature != QOpenGLTexture::MaxFeatureFlag) {
|
|
if (QOpenGLTexture::hasFeature(feature))
|
|
features |= feature;
|
|
feature = static_cast<QOpenGLTexture::Feature>(feature << 1);
|
|
}
|
|
|
|
functions->glGenTextures(1, &textureId);
|
|
return textureId != 0;
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::destroy()
|
|
{
|
|
if (!textureId) {
|
|
// not created or already destroyed
|
|
return;
|
|
}
|
|
QOpenGLContext *currentContext = QOpenGLContext::currentContext();
|
|
if (!currentContext) {
|
|
qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n"
|
|
"Texture has not been destroyed");
|
|
return;
|
|
}
|
|
if (!QOpenGLContext::areSharing(currentContext, context)) {
|
|
|
|
qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p"
|
|
" is not shared with current context %p.\n"
|
|
"Texture has not been destroyed",
|
|
static_cast<const void *>(context),
|
|
static_cast<const void *>(currentContext));
|
|
return;
|
|
}
|
|
|
|
functions->glDeleteTextures(1, &textureId);
|
|
|
|
context = nullptr;
|
|
functions = nullptr;
|
|
textureId = 0;
|
|
format = QOpenGLTexture::NoFormat;
|
|
formatClass = QOpenGLTexture::NoFormatClass;
|
|
requestedMipLevels = 1;
|
|
mipLevels = -1;
|
|
layers = 1;
|
|
faces = 1;
|
|
samples = 0;
|
|
fixedSamplePositions = true,
|
|
baseLevel = 0;
|
|
maxLevel = 1000;
|
|
depthStencilMode = QOpenGLTexture::DepthMode;
|
|
minFilter = QOpenGLTexture::Nearest;
|
|
magFilter = QOpenGLTexture::Nearest;
|
|
maxAnisotropy = 1.0f;
|
|
minLevelOfDetail = -1000.0f;
|
|
maxLevelOfDetail = 1000.0f;
|
|
levelOfDetailBias = 0.0f;
|
|
textureView = false;
|
|
autoGenerateMipMaps = true;
|
|
storageAllocated = false;
|
|
texFuncs = nullptr;
|
|
|
|
swizzleMask[0] = QOpenGLTexture::RedValue;
|
|
swizzleMask[1] = QOpenGLTexture::GreenValue;
|
|
swizzleMask[2] = QOpenGLTexture::BlueValue;
|
|
swizzleMask[3] = QOpenGLTexture::AlphaValue;
|
|
|
|
wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
|
|
? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::bind()
|
|
{
|
|
functions->glBindTexture(target, textureId);
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::bind(uint unit, QOpenGLTexture::TextureUnitReset reset)
|
|
{
|
|
GLint oldTextureUnit = 0;
|
|
if (reset == QOpenGLTexture::ResetTextureUnit)
|
|
functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
|
|
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
|
|
functions->glBindTexture(target, textureId);
|
|
|
|
if (reset == QOpenGLTexture::ResetTextureUnit)
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::release()
|
|
{
|
|
functions->glBindTexture(target, 0);
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::release(uint unit, QOpenGLTexture::TextureUnitReset reset)
|
|
{
|
|
GLint oldTextureUnit = 0;
|
|
if (reset == QOpenGLTexture::ResetTextureUnit)
|
|
functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
|
|
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
|
|
functions->glBindTexture(target, 0);
|
|
|
|
if (reset == QOpenGLTexture::ResetTextureUnit)
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
|
|
}
|
|
|
|
bool QOpenGLTexturePrivate::isBound() const
|
|
{
|
|
GLint boundTextureId = 0;
|
|
functions->glGetIntegerv(bindingTarget, &boundTextureId);
|
|
return (static_cast<GLuint>(boundTextureId) == textureId);
|
|
}
|
|
|
|
bool QOpenGLTexturePrivate::isBound(uint unit) const
|
|
{
|
|
GLint oldTextureUnit = 0;
|
|
functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
|
|
|
|
GLint boundTextureId = 0;
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
|
|
functions->glGetIntegerv(bindingTarget, &boundTextureId);
|
|
bool result = (static_cast<GLuint>(boundTextureId) == textureId);
|
|
|
|
texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
|
|
return result;
|
|
}
|
|
|
|
int QOpenGLTexturePrivate::evaluateMipLevels() const
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::Target3D:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
return qMin(maximumMipLevelCount(), qMax(1, requestedMipLevels));
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)
|
|
{
|
|
switch (internalFormat) {
|
|
case QOpenGLTexture::NoFormat:
|
|
return false;
|
|
|
|
case QOpenGLTexture::R8_UNorm:
|
|
case QOpenGLTexture::RG8_UNorm:
|
|
case QOpenGLTexture::RGB8_UNorm:
|
|
case QOpenGLTexture::RGBA8_UNorm:
|
|
case QOpenGLTexture::R16_UNorm:
|
|
case QOpenGLTexture::RG16_UNorm:
|
|
case QOpenGLTexture::RGB16_UNorm:
|
|
case QOpenGLTexture::RGBA16_UNorm:
|
|
case QOpenGLTexture::R8_SNorm:
|
|
case QOpenGLTexture::RG8_SNorm:
|
|
case QOpenGLTexture::RGB8_SNorm:
|
|
case QOpenGLTexture::RGBA8_SNorm:
|
|
case QOpenGLTexture::R16_SNorm:
|
|
case QOpenGLTexture::RG16_SNorm:
|
|
case QOpenGLTexture::RGB16_SNorm:
|
|
case QOpenGLTexture::RGBA16_SNorm:
|
|
case QOpenGLTexture::R8U:
|
|
case QOpenGLTexture::RG8U:
|
|
case QOpenGLTexture::RGB8U:
|
|
case QOpenGLTexture::RGBA8U:
|
|
case QOpenGLTexture::R16U:
|
|
case QOpenGLTexture::RG16U:
|
|
case QOpenGLTexture::RGB16U:
|
|
case QOpenGLTexture::RGBA16U:
|
|
case QOpenGLTexture::R32U:
|
|
case QOpenGLTexture::RG32U:
|
|
case QOpenGLTexture::RGB32U:
|
|
case QOpenGLTexture::RGBA32U:
|
|
case QOpenGLTexture::R8I:
|
|
case QOpenGLTexture::RG8I:
|
|
case QOpenGLTexture::RGB8I:
|
|
case QOpenGLTexture::RGBA8I:
|
|
case QOpenGLTexture::R16I:
|
|
case QOpenGLTexture::RG16I:
|
|
case QOpenGLTexture::RGB16I:
|
|
case QOpenGLTexture::RGBA16I:
|
|
case QOpenGLTexture::R32I:
|
|
case QOpenGLTexture::RG32I:
|
|
case QOpenGLTexture::RGB32I:
|
|
case QOpenGLTexture::RGBA32I:
|
|
case QOpenGLTexture::R16F:
|
|
case QOpenGLTexture::RG16F:
|
|
case QOpenGLTexture::RGB16F:
|
|
case QOpenGLTexture::RGBA16F:
|
|
case QOpenGLTexture::R32F:
|
|
case QOpenGLTexture::RG32F:
|
|
case QOpenGLTexture::RGB32F:
|
|
case QOpenGLTexture::RGBA32F:
|
|
case QOpenGLTexture::RGB9E5:
|
|
case QOpenGLTexture::RG11B10F:
|
|
case QOpenGLTexture::RG3B2:
|
|
case QOpenGLTexture::R5G6B5:
|
|
case QOpenGLTexture::RGB5A1:
|
|
case QOpenGLTexture::RGBA4:
|
|
case QOpenGLTexture::RGB10A2:
|
|
|
|
case QOpenGLTexture::D16:
|
|
case QOpenGLTexture::D24:
|
|
case QOpenGLTexture::D32:
|
|
case QOpenGLTexture::D32F:
|
|
|
|
case QOpenGLTexture::D24S8:
|
|
case QOpenGLTexture::D32FS8X24:
|
|
|
|
case QOpenGLTexture::S8:
|
|
|
|
case QOpenGLTexture::RGB_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT3:
|
|
case QOpenGLTexture::RGBA_DXT5:
|
|
case QOpenGLTexture::R_ATI1N_UNorm:
|
|
case QOpenGLTexture::R_ATI1N_SNorm:
|
|
case QOpenGLTexture::RG_ATI2N_UNorm:
|
|
case QOpenGLTexture::RG_ATI2N_SNorm:
|
|
case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_UNorm:
|
|
case QOpenGLTexture::SRGB8:
|
|
case QOpenGLTexture::SRGB8_Alpha8:
|
|
case QOpenGLTexture::SRGB_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT3:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT5:
|
|
case QOpenGLTexture::SRGB_BP_UNorm:
|
|
case QOpenGLTexture::R11_EAC_UNorm:
|
|
case QOpenGLTexture::R11_EAC_SNorm:
|
|
case QOpenGLTexture::RG11_EAC_UNorm:
|
|
case QOpenGLTexture::RG11_EAC_SNorm:
|
|
case QOpenGLTexture::RGB8_ETC2:
|
|
case QOpenGLTexture::SRGB8_ETC2:
|
|
case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::RGBA8_ETC2_EAC:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
|
|
case QOpenGLTexture::RGBA_ASTC_4x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x5:
|
|
case QOpenGLTexture::RGBA_ASTC_8x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x5:
|
|
case QOpenGLTexture::RGBA_ASTC_10x6:
|
|
case QOpenGLTexture::RGBA_ASTC_10x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x12:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
|
|
return true;
|
|
|
|
case QOpenGLTexture::RGB8_ETC1:
|
|
return false;
|
|
|
|
case QOpenGLTexture::DepthFormat:
|
|
case QOpenGLTexture::AlphaFormat:
|
|
|
|
case QOpenGLTexture::RGBFormat:
|
|
case QOpenGLTexture::RGBAFormat:
|
|
|
|
case QOpenGLTexture::LuminanceFormat:
|
|
|
|
case QOpenGLTexture::LuminanceAlphaFormat:
|
|
return false;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
return false;
|
|
}
|
|
|
|
static bool isTextureTargetMultisample(QOpenGLTexture::Target target)
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::Target3D:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
return false;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
return true;
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
return false;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
return false;
|
|
}
|
|
|
|
bool QOpenGLTexturePrivate::isUsingImmutableStorage() const
|
|
{
|
|
// Use immutable storage whenever possible, falling back to mutable
|
|
// Note that if multisample textures are not supported at all, we'll still fail into
|
|
// the mutable storage allocation
|
|
return isSizedTextureFormat(format)
|
|
&& (isTextureTargetMultisample(target)
|
|
? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
|
|
: features.testFlag(QOpenGLTexture::ImmutableStorage));
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
|
|
{
|
|
// Resolve the actual number of mipmap levels we can use
|
|
mipLevels = evaluateMipLevels();
|
|
|
|
if (isUsingImmutableStorage())
|
|
allocateImmutableStorage();
|
|
else
|
|
allocateMutableStorage(pixelFormat, pixelType);
|
|
}
|
|
|
|
static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
|
|
{
|
|
switch (internalFormat) {
|
|
case QOpenGLTexture::NoFormat:
|
|
return QOpenGLTexture::NoSourceFormat;
|
|
|
|
case QOpenGLTexture::R8_UNorm:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG8_UNorm:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB8_UNorm:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA8_UNorm:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R16_UNorm:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG16_UNorm:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB16_UNorm:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA16_UNorm:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R8_SNorm:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG8_SNorm:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB8_SNorm:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA8_SNorm:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R16_SNorm:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG16_SNorm:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB16_SNorm:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA16_SNorm:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R8U:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG8U:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB8U:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA8U:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R16U:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG16U:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB16U:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA16U:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R32U:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG32U:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB32U:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA32U:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R8I:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG8I:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB8I:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA8I:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R16I:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG16I:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB16I:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA16I:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R32I:
|
|
return QOpenGLTexture::Red_Integer;
|
|
|
|
case QOpenGLTexture::RG32I:
|
|
return QOpenGLTexture::RG_Integer;
|
|
|
|
case QOpenGLTexture::RGB32I:
|
|
return QOpenGLTexture::RGB_Integer;
|
|
|
|
case QOpenGLTexture::RGBA32I:
|
|
return QOpenGLTexture::RGBA_Integer;
|
|
|
|
case QOpenGLTexture::R16F:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG16F:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB16F:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA16F:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R32F:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG32F:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB32F:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBA32F:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::RGB9E5:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RG11B10F:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RG3B2:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::R5G6B5:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGB5A1:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::RGBA4:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::RGB10A2:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::D16:
|
|
case QOpenGLTexture::D24:
|
|
case QOpenGLTexture::D32:
|
|
case QOpenGLTexture::D32F:
|
|
return QOpenGLTexture::Depth;
|
|
|
|
case QOpenGLTexture::D24S8:
|
|
case QOpenGLTexture::D32FS8X24:
|
|
return QOpenGLTexture::DepthStencil;
|
|
|
|
case QOpenGLTexture::S8:
|
|
return QOpenGLTexture::Stencil;
|
|
|
|
case QOpenGLTexture::RGB_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT3:
|
|
case QOpenGLTexture::RGBA_DXT5:
|
|
case QOpenGLTexture::R_ATI1N_UNorm:
|
|
case QOpenGLTexture::R_ATI1N_SNorm:
|
|
case QOpenGLTexture::RG_ATI2N_UNorm:
|
|
case QOpenGLTexture::RG_ATI2N_SNorm:
|
|
case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_UNorm:
|
|
case QOpenGLTexture::SRGB8:
|
|
case QOpenGLTexture::SRGB8_Alpha8:
|
|
case QOpenGLTexture::SRGB_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT3:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT5:
|
|
case QOpenGLTexture::SRGB_BP_UNorm:
|
|
case QOpenGLTexture::RGB8_ETC1:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::R11_EAC_UNorm:
|
|
case QOpenGLTexture::R11_EAC_SNorm:
|
|
return QOpenGLTexture::Red;
|
|
|
|
case QOpenGLTexture::RG11_EAC_UNorm:
|
|
case QOpenGLTexture::RG11_EAC_SNorm:
|
|
return QOpenGLTexture::RG;
|
|
|
|
case QOpenGLTexture::RGB8_ETC2:
|
|
case QOpenGLTexture::SRGB8_ETC2:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::RGBA8_ETC2_EAC:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::RGBA_ASTC_4x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x5:
|
|
case QOpenGLTexture::RGBA_ASTC_8x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x5:
|
|
case QOpenGLTexture::RGBA_ASTC_10x6:
|
|
case QOpenGLTexture::RGBA_ASTC_10x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x12:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::DepthFormat:
|
|
return QOpenGLTexture::Depth;
|
|
|
|
case QOpenGLTexture::AlphaFormat:
|
|
return QOpenGLTexture::Alpha;
|
|
|
|
case QOpenGLTexture::RGBFormat:
|
|
return QOpenGLTexture::RGB;
|
|
|
|
case QOpenGLTexture::RGBAFormat:
|
|
return QOpenGLTexture::RGBA;
|
|
|
|
case QOpenGLTexture::LuminanceFormat:
|
|
return QOpenGLTexture::Luminance;
|
|
|
|
case QOpenGLTexture::LuminanceAlphaFormat:
|
|
return QOpenGLTexture::LuminanceAlpha;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
return QOpenGLTexture::NoSourceFormat;
|
|
}
|
|
|
|
static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
|
|
{
|
|
switch (internalFormat) {
|
|
case QOpenGLTexture::NoFormat:
|
|
return QOpenGLTexture::NoPixelType;
|
|
|
|
case QOpenGLTexture::R8_UNorm:
|
|
case QOpenGLTexture::RG8_UNorm:
|
|
case QOpenGLTexture::RGB8_UNorm:
|
|
case QOpenGLTexture::RGBA8_UNorm:
|
|
case QOpenGLTexture::R16_UNorm:
|
|
case QOpenGLTexture::RG16_UNorm:
|
|
case QOpenGLTexture::RGB16_UNorm:
|
|
case QOpenGLTexture::RGBA16_UNorm:
|
|
return QOpenGLTexture::UInt8;
|
|
|
|
case QOpenGLTexture::R8_SNorm:
|
|
case QOpenGLTexture::RG8_SNorm:
|
|
case QOpenGLTexture::RGB8_SNorm:
|
|
case QOpenGLTexture::RGBA8_SNorm:
|
|
case QOpenGLTexture::R16_SNorm:
|
|
case QOpenGLTexture::RG16_SNorm:
|
|
case QOpenGLTexture::RGB16_SNorm:
|
|
case QOpenGLTexture::RGBA16_SNorm:
|
|
return QOpenGLTexture::Int8;
|
|
|
|
case QOpenGLTexture::R8U:
|
|
case QOpenGLTexture::RG8U:
|
|
case QOpenGLTexture::RGB8U:
|
|
case QOpenGLTexture::RGBA8U:
|
|
case QOpenGLTexture::R16U:
|
|
case QOpenGLTexture::RG16U:
|
|
case QOpenGLTexture::RGB16U:
|
|
case QOpenGLTexture::RGBA16U:
|
|
case QOpenGLTexture::R32U:
|
|
case QOpenGLTexture::RG32U:
|
|
case QOpenGLTexture::RGB32U:
|
|
case QOpenGLTexture::RGBA32U:
|
|
return QOpenGLTexture::UInt8;
|
|
|
|
case QOpenGLTexture::R8I:
|
|
case QOpenGLTexture::RG8I:
|
|
case QOpenGLTexture::RGB8I:
|
|
case QOpenGLTexture::RGBA8I:
|
|
case QOpenGLTexture::R16I:
|
|
case QOpenGLTexture::RG16I:
|
|
case QOpenGLTexture::RGB16I:
|
|
case QOpenGLTexture::RGBA16I:
|
|
case QOpenGLTexture::R32I:
|
|
case QOpenGLTexture::RG32I:
|
|
case QOpenGLTexture::RGB32I:
|
|
case QOpenGLTexture::RGBA32I:
|
|
return QOpenGLTexture::Int8;
|
|
|
|
case QOpenGLTexture::R16F:
|
|
case QOpenGLTexture::RG16F:
|
|
case QOpenGLTexture::RGB16F:
|
|
case QOpenGLTexture::RGBA16F:
|
|
return QOpenGLTexture::Float16;
|
|
|
|
case QOpenGLTexture::R32F:
|
|
case QOpenGLTexture::RG32F:
|
|
case QOpenGLTexture::RGB32F:
|
|
case QOpenGLTexture::RGBA32F:
|
|
return QOpenGLTexture::Float32;
|
|
|
|
case QOpenGLTexture::RGB9E5:
|
|
return QOpenGLTexture::UInt16_RGB5A1_Rev;
|
|
|
|
case QOpenGLTexture::RG11B10F:
|
|
return QOpenGLTexture::UInt32_RG11B10F;
|
|
|
|
case QOpenGLTexture::RG3B2:
|
|
return QOpenGLTexture::UInt8_RG3B2;
|
|
|
|
case QOpenGLTexture::R5G6B5:
|
|
return QOpenGLTexture::UInt16_R5G6B5;
|
|
|
|
case QOpenGLTexture::RGB5A1:
|
|
return QOpenGLTexture::UInt16_RGB5A1;
|
|
|
|
case QOpenGLTexture::RGBA4:
|
|
return QOpenGLTexture::UInt16_RGBA4;
|
|
|
|
case QOpenGLTexture::RGB10A2:
|
|
return QOpenGLTexture::UInt32_RGB10A2;
|
|
|
|
case QOpenGLTexture::D16:
|
|
return QOpenGLTexture::UInt16;
|
|
|
|
case QOpenGLTexture::D24:
|
|
case QOpenGLTexture::D32:
|
|
return QOpenGLTexture::UInt32;
|
|
|
|
case QOpenGLTexture::D32F:
|
|
return QOpenGLTexture::Float32;
|
|
|
|
case QOpenGLTexture::D24S8:
|
|
return QOpenGLTexture::UInt32_D24S8;
|
|
|
|
case QOpenGLTexture::D32FS8X24:
|
|
return QOpenGLTexture::Float32_D32_UInt32_S8_X24;
|
|
|
|
case QOpenGLTexture::S8:
|
|
return QOpenGLTexture::UInt8;
|
|
|
|
case QOpenGLTexture::RGB_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT3:
|
|
case QOpenGLTexture::RGBA_DXT5:
|
|
case QOpenGLTexture::R_ATI1N_UNorm:
|
|
case QOpenGLTexture::R_ATI1N_SNorm:
|
|
case QOpenGLTexture::RG_ATI2N_UNorm:
|
|
case QOpenGLTexture::RG_ATI2N_SNorm:
|
|
case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_UNorm:
|
|
case QOpenGLTexture::SRGB8:
|
|
case QOpenGLTexture::SRGB8_Alpha8:
|
|
case QOpenGLTexture::SRGB_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT3:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT5:
|
|
case QOpenGLTexture::SRGB_BP_UNorm:
|
|
case QOpenGLTexture::R11_EAC_UNorm:
|
|
case QOpenGLTexture::R11_EAC_SNorm:
|
|
case QOpenGLTexture::RG11_EAC_UNorm:
|
|
case QOpenGLTexture::RG11_EAC_SNorm:
|
|
case QOpenGLTexture::RGB8_ETC2:
|
|
case QOpenGLTexture::SRGB8_ETC2:
|
|
case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::RGBA8_ETC2_EAC:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
|
|
case QOpenGLTexture::RGB8_ETC1:
|
|
case QOpenGLTexture::RGBA_ASTC_4x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x5:
|
|
case QOpenGLTexture::RGBA_ASTC_8x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x5:
|
|
case QOpenGLTexture::RGBA_ASTC_10x6:
|
|
case QOpenGLTexture::RGBA_ASTC_10x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x12:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
|
|
return QOpenGLTexture::UInt8;
|
|
|
|
case QOpenGLTexture::DepthFormat:
|
|
return QOpenGLTexture::UInt32;
|
|
|
|
case QOpenGLTexture::AlphaFormat:
|
|
case QOpenGLTexture::RGBFormat:
|
|
case QOpenGLTexture::RGBAFormat:
|
|
case QOpenGLTexture::LuminanceFormat:
|
|
case QOpenGLTexture::LuminanceAlphaFormat:
|
|
return QOpenGLTexture::UInt8;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
return QOpenGLTexture::NoPixelType;
|
|
}
|
|
|
|
static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
|
|
{
|
|
switch (internalFormat) {
|
|
case QOpenGLTexture::NoFormat:
|
|
|
|
case QOpenGLTexture::R8_UNorm:
|
|
case QOpenGLTexture::RG8_UNorm:
|
|
case QOpenGLTexture::RGB8_UNorm:
|
|
case QOpenGLTexture::RGBA8_UNorm:
|
|
case QOpenGLTexture::R16_UNorm:
|
|
case QOpenGLTexture::RG16_UNorm:
|
|
case QOpenGLTexture::RGB16_UNorm:
|
|
case QOpenGLTexture::RGBA16_UNorm:
|
|
case QOpenGLTexture::R8_SNorm:
|
|
case QOpenGLTexture::RG8_SNorm:
|
|
case QOpenGLTexture::RGB8_SNorm:
|
|
case QOpenGLTexture::RGBA8_SNorm:
|
|
case QOpenGLTexture::R16_SNorm:
|
|
case QOpenGLTexture::RG16_SNorm:
|
|
case QOpenGLTexture::RGB16_SNorm:
|
|
case QOpenGLTexture::RGBA16_SNorm:
|
|
case QOpenGLTexture::R8U:
|
|
case QOpenGLTexture::RG8U:
|
|
case QOpenGLTexture::RGB8U:
|
|
case QOpenGLTexture::RGBA8U:
|
|
case QOpenGLTexture::R16U:
|
|
case QOpenGLTexture::RG16U:
|
|
case QOpenGLTexture::RGB16U:
|
|
case QOpenGLTexture::RGBA16U:
|
|
case QOpenGLTexture::R32U:
|
|
case QOpenGLTexture::RG32U:
|
|
case QOpenGLTexture::RGB32U:
|
|
case QOpenGLTexture::RGBA32U:
|
|
case QOpenGLTexture::R8I:
|
|
case QOpenGLTexture::RG8I:
|
|
case QOpenGLTexture::RGB8I:
|
|
case QOpenGLTexture::RGBA8I:
|
|
case QOpenGLTexture::R16I:
|
|
case QOpenGLTexture::RG16I:
|
|
case QOpenGLTexture::RGB16I:
|
|
case QOpenGLTexture::RGBA16I:
|
|
case QOpenGLTexture::R32I:
|
|
case QOpenGLTexture::RG32I:
|
|
case QOpenGLTexture::RGB32I:
|
|
case QOpenGLTexture::RGBA32I:
|
|
case QOpenGLTexture::R16F:
|
|
case QOpenGLTexture::RG16F:
|
|
case QOpenGLTexture::RGB16F:
|
|
case QOpenGLTexture::RGBA16F:
|
|
case QOpenGLTexture::R32F:
|
|
case QOpenGLTexture::RG32F:
|
|
case QOpenGLTexture::RGB32F:
|
|
case QOpenGLTexture::RGBA32F:
|
|
case QOpenGLTexture::RGB9E5:
|
|
case QOpenGLTexture::RG11B10F:
|
|
case QOpenGLTexture::RG3B2:
|
|
case QOpenGLTexture::R5G6B5:
|
|
case QOpenGLTexture::RGB5A1:
|
|
case QOpenGLTexture::RGBA4:
|
|
case QOpenGLTexture::RGB10A2:
|
|
|
|
case QOpenGLTexture::D16:
|
|
case QOpenGLTexture::D24:
|
|
case QOpenGLTexture::D32:
|
|
case QOpenGLTexture::D32F:
|
|
|
|
case QOpenGLTexture::D24S8:
|
|
case QOpenGLTexture::D32FS8X24:
|
|
|
|
case QOpenGLTexture::S8:
|
|
return false;
|
|
|
|
case QOpenGLTexture::RGB_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT1:
|
|
case QOpenGLTexture::RGBA_DXT3:
|
|
case QOpenGLTexture::RGBA_DXT5:
|
|
case QOpenGLTexture::R_ATI1N_UNorm:
|
|
case QOpenGLTexture::R_ATI1N_SNorm:
|
|
case QOpenGLTexture::RG_ATI2N_UNorm:
|
|
case QOpenGLTexture::RG_ATI2N_SNorm:
|
|
case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
|
|
case QOpenGLTexture::RGB_BP_UNorm:
|
|
case QOpenGLTexture::SRGB8:
|
|
case QOpenGLTexture::SRGB8_Alpha8:
|
|
case QOpenGLTexture::SRGB_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT1:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT3:
|
|
case QOpenGLTexture::SRGB_Alpha_DXT5:
|
|
case QOpenGLTexture::SRGB_BP_UNorm:
|
|
case QOpenGLTexture::R11_EAC_UNorm:
|
|
case QOpenGLTexture::R11_EAC_SNorm:
|
|
case QOpenGLTexture::RG11_EAC_UNorm:
|
|
case QOpenGLTexture::RG11_EAC_SNorm:
|
|
case QOpenGLTexture::RGB8_ETC2:
|
|
case QOpenGLTexture::SRGB8_ETC2:
|
|
case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::RGBA8_ETC2_EAC:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
|
|
case QOpenGLTexture::RGB8_ETC1:
|
|
case QOpenGLTexture::RGBA_ASTC_4x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x5:
|
|
case QOpenGLTexture::RGBA_ASTC_8x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x5:
|
|
case QOpenGLTexture::RGBA_ASTC_10x6:
|
|
case QOpenGLTexture::RGBA_ASTC_10x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x12:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
|
|
return true;
|
|
|
|
case QOpenGLTexture::DepthFormat:
|
|
case QOpenGLTexture::AlphaFormat:
|
|
case QOpenGLTexture::RGBFormat:
|
|
case QOpenGLTexture::RGBAFormat:
|
|
case QOpenGLTexture::LuminanceFormat:
|
|
case QOpenGLTexture::LuminanceAlphaFormat:
|
|
return false;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
return false;
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
|
|
{
|
|
// There is no way to allocate mutable storage for compressed textures in in
|
|
// versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs
|
|
// do not mandate accepting null data pointers for glCompressedTexImage*D,
|
|
// unlike glTexImage*D (which in turn does not accept compressed formats).
|
|
if (isCompressedFormat(format)) {
|
|
storageAllocated = true;
|
|
return;
|
|
}
|
|
|
|
switch (target) {
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// Buffer textures get their storage from an external OpenGL buffer
|
|
qWarning("Buffer textures do not allocate storage");
|
|
return;
|
|
|
|
case QOpenGLTexture::Target1D:
|
|
if (features.testFlag(QOpenGLTexture::Texture1D)) {
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
} else {
|
|
qWarning("1D textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1DArray:
|
|
if (features.testFlag(QOpenGLTexture::Texture1D)
|
|
&& features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
layers,
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
} else {
|
|
qWarning("1D array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
mipLevelSize(level, dimensions[1]),
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap: {
|
|
// Cubemaps are the odd one out. We have to allocate storage for each
|
|
// face and miplevel using the special cubemap face targets rather than
|
|
// GL_TARGET_CUBEMAP.
|
|
const QOpenGLTexture::CubeMapFace faceTargets[] = {
|
|
QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX,
|
|
QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY,
|
|
QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ
|
|
};
|
|
|
|
for (int faceTarget = 0; faceTarget < 6; ++faceTarget) {
|
|
for (int level = 0; level < mipLevels; ++level) {
|
|
texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget,
|
|
level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
mipLevelSize(level, dimensions[1]),
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case QOpenGLTexture::Target2DArray:
|
|
if (features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
mipLevelSize(level, dimensions[1]),
|
|
layers,
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
} else {
|
|
qWarning("Array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
// Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
|
|
if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
mipLevelSize(level, dimensions[1]),
|
|
6 * layers,
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
} else {
|
|
qWarning("Cubemap Array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
if (features.testFlag(QOpenGLTexture::Texture3D)) {
|
|
for (int level = 0; level < mipLevels; ++level)
|
|
texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
|
|
mipLevelSize(level, dimensions[0]),
|
|
mipLevelSize(level, dimensions[1]),
|
|
mipLevelSize(level, dimensions[2]),
|
|
0,
|
|
pixelFormat, pixelType, nullptr);
|
|
} else {
|
|
qWarning("3D textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
if (features.testFlag(QOpenGLTexture::TextureMultisample)) {
|
|
texFuncs->glTextureImage2DMultisample(textureId, target, bindingTarget, samples, format,
|
|
dimensions[0], dimensions[1],
|
|
fixedSamplePositions);
|
|
} else {
|
|
qWarning("Multisample textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
if (features.testFlag(QOpenGLTexture::TextureMultisample)
|
|
&& features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
texFuncs->glTextureImage3DMultisample(textureId, target, bindingTarget, samples, format,
|
|
dimensions[0], dimensions[1], layers,
|
|
fixedSamplePositions);
|
|
} else {
|
|
qWarning("Multisample array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
|
|
storageAllocated = true;
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::allocateImmutableStorage()
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// Buffer textures get their storage from an external OpenGL buffer
|
|
qWarning("Buffer textures do not allocate storage");
|
|
return;
|
|
|
|
case QOpenGLTexture::Target1D:
|
|
if (features.testFlag(QOpenGLTexture::Texture1D)) {
|
|
texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0]);
|
|
} else {
|
|
qWarning("1D textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1DArray:
|
|
if (features.testFlag(QOpenGLTexture::Texture1D)
|
|
&& features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0], layers);
|
|
} else {
|
|
qWarning("1D array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0], dimensions[1]);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DArray:
|
|
if (features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0], dimensions[1], layers);
|
|
} else {
|
|
qWarning("Array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
// Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
|
|
if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
|
|
texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0], dimensions[1], 6 * layers);
|
|
} else {
|
|
qWarning("Cubemap Array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
if (features.testFlag(QOpenGLTexture::Texture3D)) {
|
|
texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
|
|
dimensions[0], dimensions[1], dimensions[2]);
|
|
} else {
|
|
qWarning("3D textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) {
|
|
texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format,
|
|
dimensions[0], dimensions[1],
|
|
fixedSamplePositions);
|
|
} else {
|
|
qWarning("Multisample textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
|
|
&& features.testFlag(QOpenGLTexture::TextureArrays)) {
|
|
texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format,
|
|
dimensions[0], dimensions[1], layers,
|
|
fixedSamplePositions);
|
|
} else {
|
|
qWarning("Multisample array textures are not supported");
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
|
|
storageAllocated = true;
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
|
|
QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
|
|
0, mipLevelSize( mipLevel, dimensions[0] ),
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1DArray:
|
|
Q_UNUSED(cubeFace);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DArray:
|
|
Q_UNUSED(cubeFace);
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
mipLevelSize(mipLevel, dimensions[2]),
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
|
|
0, 0,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMapArray: {
|
|
int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
|
|
int layerFace = 6 * layer + faceIndex;
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layerFace,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
}
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
Q_UNUSED(mipLevel);
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
|
|
0, 0,
|
|
dimensions[0],
|
|
dimensions[1],
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// We don't upload pixel data for these targets
|
|
qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
|
|
break;
|
|
}
|
|
|
|
// If requested perform automatic mip map generation
|
|
if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
|
|
Q_Q(QOpenGLTexture);
|
|
q->generateMipMaps();
|
|
}
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
|
|
int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
|
|
QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
Q_UNUSED(yOffset);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(height);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, width,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1DArray:
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(yOffset);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(height);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, layer,
|
|
width,
|
|
layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, yOffset,
|
|
width, height,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DArray:
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, yOffset, layer,
|
|
width, height, layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(layerCount);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
|
|
xOffset, yOffset,
|
|
width, height,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMapArray: {
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(depth);
|
|
int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
|
|
int layerFace = 6 * layer + faceIndex;
|
|
texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
xOffset, yOffset, layerFace,
|
|
width, height,
|
|
layerCount,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
}
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
Q_UNUSED(mipLevel);
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
Q_UNUSED(zOffset);
|
|
Q_UNUSED(depth);
|
|
texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
|
|
xOffset, yOffset,
|
|
width, height,
|
|
sourceFormat, sourceType, data, options);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// We don't upload pixel data for these targets
|
|
qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
|
|
break;
|
|
}
|
|
|
|
// If requested perform automatic mip map generation
|
|
if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
|
|
Q_Q(QOpenGLTexture);
|
|
q->generateMipMaps();
|
|
}
|
|
}
|
|
|
|
|
|
void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount,
|
|
QOpenGLTexture::CubeMapFace cubeFace,
|
|
int dataSize, const void *data,
|
|
const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
if (!isCompressedFormat(format)) {
|
|
qWarning("Cannot set compressed data for non-compressed format 0x%x", format);
|
|
return;
|
|
}
|
|
|
|
const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op?
|
|
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
if (needsFullSpec) {
|
|
texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel,
|
|
format,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
0, dataSize, data, options);
|
|
} else {
|
|
texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
|
|
0, mipLevelSize( mipLevel, dimensions[0] ),
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1DArray:
|
|
Q_UNUSED(cubeFace);
|
|
if (!needsFullSpec) {
|
|
texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
layerCount,
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
if (needsFullSpec) {
|
|
texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel,
|
|
format,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
0, dataSize, data, options);
|
|
} else {
|
|
texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DArray:
|
|
Q_UNUSED(cubeFace);
|
|
if (!needsFullSpec) {
|
|
texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
layerCount,
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
Q_UNUSED(cubeFace);
|
|
Q_UNUSED(layerCount);
|
|
if (needsFullSpec) {
|
|
texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel,
|
|
format,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
mipLevelSize(mipLevel, dimensions[2]),
|
|
0, dataSize, data, options);
|
|
} else {
|
|
texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layer,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
mipLevelSize(mipLevel, dimensions[2]),
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
Q_UNUSED(layer);
|
|
Q_UNUSED(layerCount);
|
|
if (needsFullSpec) {
|
|
texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel,
|
|
format,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
0, dataSize, data, options);
|
|
} else {
|
|
texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
|
|
0, 0,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMapArray: {
|
|
int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
|
|
int layerFace = 6 * layer + faceIndex;
|
|
if (!needsFullSpec) {
|
|
texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
|
|
0, 0, layerFace,
|
|
mipLevelSize(mipLevel, dimensions[0]),
|
|
mipLevelSize(mipLevel, dimensions[1]),
|
|
layerCount,
|
|
format, dataSize, data, options);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// We don't upload pixel data for these targets
|
|
qWarning("QOpenGLTexture::setCompressedData(): Texture target does not support pixel data upload");
|
|
break;
|
|
}
|
|
|
|
// If requested perform automatic mip map generation
|
|
if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
|
|
Q_Q(QOpenGLTexture);
|
|
q->generateMipMaps();
|
|
}
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::WrapMode mode)
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
wrapModes[0] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
wrapModes[0] = wrapModes[1] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
wrapModes[0] = wrapModes[1] = wrapModes[2] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_R, mode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
wrapModes[0] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
case QOpenGLTexture::DirectionR:
|
|
qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
wrapModes[0] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
wrapModes[1] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::DirectionR:
|
|
qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
wrapModes[0] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
wrapModes[1] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
|
|
break;
|
|
|
|
case QOpenGLTexture::DirectionR:
|
|
wrapModes[2] = mode;
|
|
texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
|
|
{
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
return wrapModes[0];
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
case QOpenGLTexture::DirectionR:
|
|
qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
|
|
return QOpenGLTexture::Repeat;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
return wrapModes[0];
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
return wrapModes[1];
|
|
|
|
case QOpenGLTexture::DirectionR:
|
|
qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
|
|
return QOpenGLTexture::Repeat;
|
|
}
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
switch (direction) {
|
|
case QOpenGLTexture::DirectionS:
|
|
return wrapModes[0];
|
|
|
|
case QOpenGLTexture::DirectionT:
|
|
return wrapModes[1];
|
|
|
|
case QOpenGLTexture::DirectionR:
|
|
return wrapModes[2];
|
|
}
|
|
break;
|
|
}
|
|
// Should never get here
|
|
Q_ASSERT(false);
|
|
return QOpenGLTexture::Repeat;
|
|
}
|
|
|
|
QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target viewTarget,
|
|
QOpenGLTexture::TextureFormat viewFormat,
|
|
int minimumMipmapLevel, int maximumMipmapLevel,
|
|
int minimumLayer, int maximumLayer) const
|
|
{
|
|
// Do sanity checks - see http://www.opengl.org/wiki/GLAPI/glTextureView
|
|
|
|
// Check the targets are compatible
|
|
bool viewTargetCompatible = false;
|
|
switch (target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::Target1D
|
|
|| viewTarget == QOpenGLTexture::Target1DArray);
|
|
break;
|
|
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2D
|
|
|| viewTarget == QOpenGLTexture::Target2DArray);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::Target3D);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetCubeMap
|
|
|| viewTarget == QOpenGLTexture::Target2D
|
|
|| viewTarget == QOpenGLTexture::Target2DArray
|
|
|| viewTarget == QOpenGLTexture::TargetCubeMapArray);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2DMultisample
|
|
|| viewTarget == QOpenGLTexture::Target2DMultisampleArray);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetRectangle:
|
|
viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetRectangle);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetBuffer:
|
|
// Cannot be used with texture views
|
|
break;
|
|
}
|
|
|
|
if (!viewTargetCompatible) {
|
|
qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view targets");
|
|
return nullptr;
|
|
}
|
|
|
|
// Check the formats are compatible
|
|
bool viewFormatCompatible = false;
|
|
switch (formatClass) {
|
|
case QOpenGLTexture::NoFormatClass:
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_128Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA32F
|
|
|| viewFormat == QOpenGLTexture::RGBA32U
|
|
|| viewFormat == QOpenGLTexture::RGBA32I);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_96Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB32F
|
|
|| viewFormat == QOpenGLTexture::RGB32U
|
|
|| viewFormat == QOpenGLTexture::RGB32I);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_64Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA16F
|
|
|| viewFormat == QOpenGLTexture::RG32F
|
|
|| viewFormat == QOpenGLTexture::RGBA16U
|
|
|| viewFormat == QOpenGLTexture::RG32U
|
|
|| viewFormat == QOpenGLTexture::RGBA16I
|
|
|| viewFormat == QOpenGLTexture::RG32I
|
|
|| viewFormat == QOpenGLTexture::RGBA16_UNorm
|
|
|| viewFormat == QOpenGLTexture::RGBA16_SNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_48Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB16_UNorm
|
|
|| viewFormat == QOpenGLTexture::RGB16_SNorm
|
|
|| viewFormat == QOpenGLTexture::RGB16F
|
|
|| viewFormat == QOpenGLTexture::RGB16U
|
|
|| viewFormat == QOpenGLTexture::RGB16I);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_32Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RG16F
|
|
|| viewFormat == QOpenGLTexture::RG11B10F
|
|
|| viewFormat == QOpenGLTexture::R32F
|
|
|| viewFormat == QOpenGLTexture::RGB10A2
|
|
|| viewFormat == QOpenGLTexture::RGBA8U
|
|
|| viewFormat == QOpenGLTexture::RG16U
|
|
|| viewFormat == QOpenGLTexture::R32U
|
|
|| viewFormat == QOpenGLTexture::RGBA8I
|
|
|| viewFormat == QOpenGLTexture::RG16I
|
|
|| viewFormat == QOpenGLTexture::R32I
|
|
|| viewFormat == QOpenGLTexture::RGBA8_UNorm
|
|
|| viewFormat == QOpenGLTexture::RG16_UNorm
|
|
|| viewFormat == QOpenGLTexture::RGBA8_SNorm
|
|
|| viewFormat == QOpenGLTexture::RG16_SNorm
|
|
|| viewFormat == QOpenGLTexture::SRGB8_Alpha8
|
|
|| viewFormat == QOpenGLTexture::RGB9E5);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_24Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB8_UNorm
|
|
|| viewFormat == QOpenGLTexture::RGB8_SNorm
|
|
|| viewFormat == QOpenGLTexture::SRGB8
|
|
|| viewFormat == QOpenGLTexture::RGB8U
|
|
|| viewFormat == QOpenGLTexture::RGB8I);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_16Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::R16F
|
|
|| viewFormat == QOpenGLTexture::RG8U
|
|
|| viewFormat == QOpenGLTexture::R16U
|
|
|| viewFormat == QOpenGLTexture::RG8I
|
|
|| viewFormat == QOpenGLTexture::R16I
|
|
|| viewFormat == QOpenGLTexture::RG8_UNorm
|
|
|| viewFormat == QOpenGLTexture::R16_UNorm
|
|
|| viewFormat == QOpenGLTexture::RG8_SNorm
|
|
|| viewFormat == QOpenGLTexture::R16_SNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_8Bit:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::R8U
|
|
|| viewFormat == QOpenGLTexture::R8I
|
|
|| viewFormat == QOpenGLTexture::R8_UNorm
|
|
|| viewFormat == QOpenGLTexture::R8_SNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_RGTC1_R:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::R_ATI1N_UNorm
|
|
|| viewFormat == QOpenGLTexture::R_ATI1N_SNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_RGTC2_RG:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RG_ATI2N_UNorm
|
|
|| viewFormat == QOpenGLTexture::RG_ATI2N_SNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_BPTC_Unorm:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNorm
|
|
|| viewFormat == QOpenGLTexture::SRGB_BP_UNorm);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_BPTC_Float:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT
|
|
|| viewFormat == QOpenGLTexture::RGB_BP_SIGNED_FLOAT);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_S3TC_DXT1_RGB:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_DXT1
|
|
|| viewFormat == QOpenGLTexture::SRGB_DXT1);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_S3TC_DXT1_RGBA:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT1
|
|
|| viewFormat == QOpenGLTexture::SRGB_Alpha_DXT1);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_S3TC_DXT3_RGBA:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT3
|
|
|| viewFormat == QOpenGLTexture::SRGB_Alpha_DXT3);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_S3TC_DXT5_RGBA:
|
|
viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT5
|
|
|| viewFormat == QOpenGLTexture::SRGB_Alpha_DXT5);
|
|
break;
|
|
|
|
case QOpenGLTexture::FormatClass_Unique:
|
|
viewFormatCompatible = (viewFormat == format);
|
|
break;
|
|
}
|
|
|
|
if (!viewFormatCompatible) {
|
|
qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view formats");
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
// Create a view
|
|
QOpenGLTexture *view = new QOpenGLTexture(viewTarget);
|
|
view->setFormat(viewFormat);
|
|
view->create();
|
|
view->d_ptr->textureView = true;
|
|
texFuncs->glTextureView(view->textureId(), viewTarget, textureId, viewFormat,
|
|
minimumMipmapLevel, maximumMipmapLevel - minimumMipmapLevel + 1,
|
|
minimumLayer, maximumLayer - minimumLayer + 1);
|
|
return view;
|
|
}
|
|
|
|
|
|
/*!
|
|
\class QOpenGLTexture
|
|
\inmodule QtGui
|
|
\since 5.2
|
|
\wrapper
|
|
\brief The QOpenGLTexture class encapsulates an OpenGL texture object.
|
|
|
|
QOpenGLTexture makes it easy to work with OpenGL textures and the myriad features
|
|
and targets that they offer depending upon the capabilities of your OpenGL implementation.
|
|
|
|
The typical usage pattern for QOpenGLTexture is
|
|
\list
|
|
\li Instantiate the object specifying the texture target type
|
|
\li Set properties that affect the storage requirements e.g. storage format, dimensions
|
|
\li Allocate the server-side storage
|
|
\li Optionally upload pixel data
|
|
\li Optionally set any additional properties e.g. filtering and border options
|
|
\li Render with texture or render to texture
|
|
\endlist
|
|
|
|
In the common case of simply using a QImage as the source of texture pixel data
|
|
most of the above steps are performed automatically.
|
|
|
|
\code
|
|
// Prepare texture
|
|
QOpenGLTexture *texture = new QOpenGLTexture(QImage(fileName).mirrored());
|
|
texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
|
|
texture->setMagnificationFilter(QOpenGLTexture::Linear);
|
|
...
|
|
// Render with texture
|
|
texture->bind();
|
|
glDrawArrays(...);
|
|
\endcode
|
|
|
|
Note that the QImage is mirrored vertically to account for the fact that
|
|
OpenGL and QImage use opposite directions for the y axis. Another option
|
|
would be to transform your texture coordinates.
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::Filter
|
|
This enum defines the filtering parameters for a QOpenGLTexture object.
|
|
\value Nearest Equivalent to GL_NEAREST
|
|
\value Linear Equivalent to GL_LINEAR
|
|
\value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST
|
|
\value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR
|
|
\value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST
|
|
\value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::Target
|
|
This enum defines the texture target of a QOpenGLTexture object.
|
|
For more information on creating array textures, see \l{Array Texture}.
|
|
|
|
\value Target1D A 1-dimensional texture.
|
|
Equivalent to GL_TEXTURE_1D.
|
|
\value Target1DArray An array of 1-dimensional textures.
|
|
Equivalent to GL_TEXTURE_1D_ARRAY
|
|
\value Target2D A 2-dimensional texture.
|
|
Equivalent to GL_TEXTURE_2D
|
|
\value Target2DArray An array of 2-dimensional textures.
|
|
Equivalent to GL_TEXTURE_2D_ARRAY
|
|
\value Target3D A 3-dimensional texture.
|
|
Equivalent to GL_TEXTURE_3D
|
|
\value TargetCubeMap A cubemap texture.
|
|
Equivalent to GL_TEXTURE_CUBE_MAP
|
|
\value TargetCubeMapArray An array of cubemap textures.
|
|
Equivalent to GL_TEXTURE_CUBE_MAP_ARRAY
|
|
\value Target2DMultisample A 2-dimensional texture with multisample support.
|
|
Equivalent to GL_TEXTURE_2D_MULTISAMPLE
|
|
\value Target2DMultisampleArray An array of 2-dimensional textures with multisample support.
|
|
Equivalent to GL_TEXTURE_2D_MULTISAMPLE_ARRAY
|
|
\value TargetRectangle A rectangular 2-dimensional texture.
|
|
Equivalent to GL_TEXTURE_RECTANGLE
|
|
\value TargetBuffer A texture with data from an OpenGL buffer object.
|
|
Equivalent to GL_TEXTURE_BUFFER
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::BindingTarget
|
|
This enum defines the possible binding targets of texture units.
|
|
|
|
\value BindingTarget1D Equivalent to GL_TEXTURE_BINDING_1D
|
|
\value BindingTarget1DArray Equivalent to GL_TEXTURE_BINDING_1D_ARRAY
|
|
\value BindingTarget2D Equivalent to GL_TEXTURE_BINDING_2D
|
|
\value BindingTarget2DArray Equivalent to GL_TEXTURE_BINDING_2D_ARRAY
|
|
\value BindingTarget3D Equivalent to GL_TEXTURE_BINDING_3D
|
|
\value BindingTargetCubeMap Equivalent to GL_TEXTURE_BINDING_CUBE_MAP
|
|
\value BindingTargetCubeMapArray Equivalent to GL_TEXTURE_BINDING_CUBE_MAP_ARRAY
|
|
\value BindingTarget2DMultisample Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE
|
|
\value BindingTarget2DMultisampleArray Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
|
|
\value BindingTargetRectangle Equivalent to GL_TEXTURE_BINDING_RECTANGLE
|
|
\value BindingTargetBuffer Equivalent to GL_TEXTURE_BINDING_BUFFER
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::MipMapGeneration
|
|
This enum defines the options to control mipmap generation.
|
|
|
|
\value GenerateMipMaps Mipmaps should be generated
|
|
\value DontGenerateMipMaps Mipmaps should not be generated
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::TextureUnitReset
|
|
This enum defines options ot control texture unit activation.
|
|
|
|
\value ResetTextureUnit The previous active texture unit will be reset
|
|
\value DontResetTextureUnit The previous active texture unit will not be rest
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::TextureFormat
|
|
This enum defines the possible texture formats. Depending upon your OpenGL
|
|
implementation only a subset of these may be supported.
|
|
|
|
\value NoFormat Equivalent to GL_NONE
|
|
|
|
\value R8_UNorm Equivalent to GL_R8
|
|
\value RG8_UNorm Equivalent to GL_RG8
|
|
\value RGB8_UNorm Equivalent to GL_RGB8
|
|
\value RGBA8_UNorm Equivalent to GL_RGBA8
|
|
|
|
\value R16_UNorm Equivalent to GL_R16
|
|
\value RG16_UNorm Equivalent to GL_RG16
|
|
\value RGB16_UNorm Equivalent to GL_RGB16
|
|
\value RGBA16_UNorm Equivalent to GL_RGBA16
|
|
|
|
\value R8_SNorm Equivalent to GL_R8_SNORM
|
|
\value RG8_SNorm Equivalent to GL_RG8_SNORM
|
|
\value RGB8_SNorm Equivalent to GL_RGB8_SNORM
|
|
\value RGBA8_SNorm Equivalent to GL_RGBA8_SNORM
|
|
|
|
\value R16_SNorm Equivalent to GL_R16_SNORM
|
|
\value RG16_SNorm Equivalent to GL_RG16_SNORM
|
|
\value RGB16_SNorm Equivalent to GL_RGB16_SNORM
|
|
\value RGBA16_SNorm Equivalent to GL_RGBA16_SNORM
|
|
|
|
\value R8U Equivalent to GL_R8UI
|
|
\value RG8U Equivalent to GL_RG8UI
|
|
\value RGB8U Equivalent to GL_RGB8UI
|
|
\value RGBA8U Equivalent to GL_RGBA8UI
|
|
|
|
\value R16U Equivalent to GL_R16UI
|
|
\value RG16U Equivalent to GL_RG16UI
|
|
\value RGB16U Equivalent to GL_RGB16UI
|
|
\value RGBA16U Equivalent to GL_RGBA16UI
|
|
|
|
\value R32U Equivalent to GL_R32UI
|
|
\value RG32U Equivalent to GL_RG32UI
|
|
\value RGB32U Equivalent to GL_RGB32UI
|
|
\value RGBA32U Equivalent to GL_RGBA32UI
|
|
|
|
\value R8I Equivalent to GL_R8I
|
|
\value RG8I Equivalent to GL_RG8I
|
|
\value RGB8I Equivalent to GL_RGB8I
|
|
\value RGBA8I Equivalent to GL_RGBA8I
|
|
|
|
\value R16I Equivalent to GL_R16I
|
|
\value RG16I Equivalent to GL_RG16I
|
|
\value RGB16I Equivalent to GL_RGB16I
|
|
\value RGBA16I Equivalent to GL_RGBA16I
|
|
|
|
\value R32I Equivalent to GL_R32I
|
|
\value RG32I Equivalent to GL_RG32I
|
|
\value RGB32I Equivalent to GL_RGB32I
|
|
\value RGBA32I Equivalent to GL_RGBA32I
|
|
|
|
\value R16F Equivalent to GL_R16F
|
|
\value RG16F Equivalent to GL_RG16F
|
|
\value RGB16F Equivalent to GL_RGB16F
|
|
\value RGBA16F Equivalent to GL_RGBA16F
|
|
|
|
\value R32F Equivalent to GL_R32F
|
|
\value RG32F Equivalent to GL_RG32F
|
|
\value RGB32F Equivalent to GL_RGB32F
|
|
\value RGBA32F Equivalent to GL_RGBA32F
|
|
|
|
\value RGB9E5 Equivalent to GL_RGB9_E5
|
|
\value RG11B10F Equivalent to GL_R11F_G11F_B10F
|
|
\value RG3B2 Equivalent to GL_R3_G3_B2
|
|
\value R5G6B5 Equivalent to GL_RGB565
|
|
\value RGB5A1 Equivalent to GL_RGB5_A1
|
|
\value RGBA4 Equivalent to GL_RGBA4
|
|
\value RGB10A2 Equivalent to GL_RGB10_A2UI
|
|
|
|
\value D16 Equivalent to GL_DEPTH_COMPONENT16
|
|
\value D24 Equivalent to GL_DEPTH_COMPONENT24
|
|
\value D24S8 Equivalent to GL_DEPTH24_STENCIL8
|
|
\value D32 Equivalent to GL_DEPTH_COMPONENT32
|
|
\value D32F Equivalent to GL_DEPTH_COMPONENT32F
|
|
\value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8
|
|
\value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4
|
|
|
|
\value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT
|
|
\value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
|
\value RGBA_DXT3 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
|
|
\value RGBA_DXT5 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
|
|
\value R_ATI1N_UNorm Equivalent to GL_COMPRESSED_RED_RGTC1
|
|
\value R_ATI1N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RED_RGTC1
|
|
\value RG_ATI2N_UNorm Equivalent to GL_COMPRESSED_RG_RGTC2
|
|
\value RG_ATI2N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG_RGTC2
|
|
\value RGB_BP_UNSIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
|
|
\value RGB_BP_SIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
|
|
\value RGB_BP_UNorm Equivalent to GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
|
|
\value R11_EAC_UNorm Equivalent to GL_COMPRESSED_R11_EAC
|
|
\value R11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_R11_EAC
|
|
\value RG11_EAC_UNorm Equivalent to GL_COMPRESSED_RG11_EAC
|
|
\value RG11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG11_EAC
|
|
\value RGB8_ETC2 Equivalent to GL_COMPRESSED_RGB8_ETC2
|
|
\value SRGB8_ETC2 Equivalent to GL_COMPRESSED_SRGB8_ETC2
|
|
\value RGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
|
|
\value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
|
|
\value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC
|
|
\value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
|
|
\value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES
|
|
\value RGBA_ASTC_4x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_4x4_KHR
|
|
\value RGBA_ASTC_5x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x4_KHR
|
|
\value RGBA_ASTC_5x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x5_KHR
|
|
\value RGBA_ASTC_6x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x5_KHR
|
|
\value RGBA_ASTC_6x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x6_KHR
|
|
\value RGBA_ASTC_8x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x5_KHR
|
|
\value RGBA_ASTC_8x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x6_KHR
|
|
\value RGBA_ASTC_8x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x8_KHR
|
|
\value RGBA_ASTC_10x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x5_KHR
|
|
\value RGBA_ASTC_10x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x6_KHR
|
|
\value RGBA_ASTC_10x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x8_KHR
|
|
\value RGBA_ASTC_10x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x10_KHR
|
|
\value RGBA_ASTC_12x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x10_KHR
|
|
\value RGBA_ASTC_12x12 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x12_KHR
|
|
\value SRGB8_Alpha8_ASTC_4x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
|
|
\value SRGB8_Alpha8_ASTC_5x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
|
|
\value SRGB8_Alpha8_ASTC_5x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
|
|
\value SRGB8_Alpha8_ASTC_6x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
|
|
\value SRGB8_Alpha8_ASTC_6x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
|
|
\value SRGB8_Alpha8_ASTC_8x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
|
|
\value SRGB8_Alpha8_ASTC_8x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
|
|
\value SRGB8_Alpha8_ASTC_8x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
|
|
\value SRGB8_Alpha8_ASTC_10x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
|
|
\value SRGB8_Alpha8_ASTC_10x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
|
|
\value SRGB8_Alpha8_ASTC_10x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
|
|
\value SRGB8_Alpha8_ASTC_10x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
|
|
\value SRGB8_Alpha8_ASTC_12x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
|
|
\value SRGB8_Alpha8_ASTC_12x12 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
|
|
|
|
\value SRGB8 Equivalent to GL_SRGB8
|
|
\value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8
|
|
\value SRGB_DXT1 Equivalent to GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
|
|
\value SRGB_Alpha_DXT1 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
|
|
\value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
|
|
\value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
|
|
\value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
|
|
|
|
\value DepthFormat Equivalent to GL_DEPTH_COMPONENT (only OpenGL ES 3 or ES 2 with OES_depth_texture)
|
|
\value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only)
|
|
\value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only)
|
|
\value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only)
|
|
\value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
|
|
\value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::CubeMapFace
|
|
This enum defines the possible CubeMap faces.
|
|
|
|
\value CubeMapPositiveX Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
|
\value CubeMapNegativeX Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_X
|
|
\value CubeMapPositiveY Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
|
|
\value CubeMapNegativeY Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
|
|
\value CubeMapPositiveZ Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Z
|
|
\value CubeMapNegativeZ Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::PixelFormat
|
|
This enum defines the possible client-side pixel formats for a pixel
|
|
transfer operation.
|
|
|
|
\value NoSourceFormat Equivalent to GL_NONE
|
|
\value Red Equivalent to GL_RED
|
|
\value RG Equivalent to GL_RG
|
|
\value RGB Equivalent to GL_RGB
|
|
\value BGR Equivalent to GL_BGR
|
|
\value RGBA Equivalent to GL_RGBA
|
|
\value BGRA Equivalent to GL_BGRA
|
|
\value Red_Integer Equivalent to GL_RED_INTEGER
|
|
\value RG_Integer Equivalent to GL_RG_INTEGER
|
|
\value RGB_Integer Equivalent to GL_RGB_INTEGER
|
|
\value BGR_Integer Equivalent to GL_BGR_INTEGER
|
|
\value RGBA_Integer Equivalent to GL_RGBA_INTEGER
|
|
\value BGRA_Integer Equivalent to GL_BGRA_INTEGER
|
|
\value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4
|
|
\value Depth Equivalent to GL_DEPTH_COMPONENT
|
|
\value DepthStencil Equivalent to GL_DEPTH_STENCIL
|
|
\value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only)
|
|
\value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
|
|
\value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
|
|
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::PixelType
|
|
This enum defines the possible pixel data types for a pixel transfer operation
|
|
|
|
\value NoPixelType Equivalent to GL_NONE
|
|
\value Int8 Equivalent to GL_BYTE
|
|
\value UInt8 Equivalent to GL_UNSIGNED_BYTE
|
|
\value Int16 Equivalent to GL_SHORT
|
|
\value UInt16 Equivalent to GL_UNSIGNED_SHORT
|
|
\value Int32 Equivalent to GL_INT
|
|
\value UInt32 Equivalent to GL_UNSIGNED_INT
|
|
\value Float16 Equivalent to GL_HALF_FLOAT
|
|
\value Float16OES Equivalent to GL_HALF_FLOAT_OES
|
|
\value Float32 Equivalent to GL_FLOAT
|
|
\value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV
|
|
\value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV
|
|
\value UInt8_RG3B2 Equivalent to GL_UNSIGNED_BYTE_3_3_2
|
|
\value UInt8_RG3B2_Rev Equivalent to GL_UNSIGNED_BYTE_2_3_3_REV
|
|
\value UInt16_RGB5A1 Equivalent to GL_UNSIGNED_SHORT_5_5_5_1
|
|
\value UInt16_RGB5A1_Rev Equivalent to GL_UNSIGNED_SHORT_1_5_5_5_REV
|
|
\value UInt16_R5G6B5 Equivalent to GL_UNSIGNED_SHORT_5_6_5
|
|
\value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV
|
|
\value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4
|
|
\value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV
|
|
\value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8
|
|
\value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV
|
|
\value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2
|
|
\value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV
|
|
\value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4
|
|
\value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::Feature
|
|
This enum defines the OpenGL texture-related features that can be tested for.
|
|
|
|
\value ImmutableStorage Support for immutable texture storage
|
|
\value ImmutableMultisampleStorage Support for immutable texture storage with
|
|
multisample targets
|
|
\value TextureRectangle Support for the GL_TEXTURE_RECTANGLE target
|
|
\value TextureArrays Support for texture targets with array layers
|
|
\value Texture3D Support for the 3 dimensional texture target
|
|
\value TextureMultisample Support for texture targets that have multisample capabilities
|
|
\value TextureBuffer Support for textures that use OpenGL buffer objects
|
|
as their data source
|
|
\value TextureCubeMapArrays Support for cubemap array texture target
|
|
\value Swizzle Support for texture component swizzle masks
|
|
\value StencilTexturing Support for stencil texturing (i.e. looking up depth or stencil
|
|
components of a combined depth/stencil format texture in GLSL shaders).
|
|
\value AnisotropicFiltering Support for anisotropic texture filtering
|
|
\value NPOTTextures Basic support for non-power-of-two textures
|
|
\value NPOTTextureRepeat Full support for non-power-of-two textures including texture
|
|
repeat modes
|
|
\value Texture1D Support for the 1 dimensional texture target
|
|
\value TextureComparisonOperators Support for texture comparison operators
|
|
\value TextureMipMapLevel Support for setting the base and maximum mipmap levels
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::SwizzleComponent
|
|
This enum defines the texture color components that can be assigned a swizzle mask.
|
|
|
|
\value SwizzleRed The red component. Equivalent to GL_TEXTURE_SWIZZLE_R
|
|
\value SwizzleGreen The green component. Equivalent to GL_TEXTURE_SWIZZLE_G
|
|
\value SwizzleBlue The blue component. Equivalent to GL_TEXTURE_SWIZZLE_B
|
|
\value SwizzleAlpha The alpha component. Equivalent to GL_TEXTURE_SWIZZLE_A
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::SwizzleValue
|
|
This enum defines the possible mask values for texture swizzling.
|
|
|
|
\value RedValue Maps the component to the red channel. Equivalent to GL_RED
|
|
\value GreenValue Maps the component to the green channel. Equivalent to GL_GREEN
|
|
\value BlueValue Maps the component to the blue channel. Equivalent to GL_BLUE
|
|
\value AlphaValue Maps the component to the alpha channel. Equivalent to GL_ALPHA
|
|
\value ZeroValue Maps the component to a fixed value of 0. Equivalent to GL_ZERO
|
|
\value OneValue Maps the component to a fixed value of 1. Equivalent to GL_ONE
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::WrapMode
|
|
This enum defines the possible texture coordinate wrapping modes.
|
|
|
|
\value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT
|
|
\value MirroredRepeat Texture coordinate is reflected about 0 and 1. Equivalent to GL_MIRRORED_REPEAT
|
|
\value ClampToEdge Clamps the texture coordinates to [0,1]. Equivalent to GL_CLAMP_TO_EDGE
|
|
\value ClampToBorder As for ClampToEdge but also blends samples at 0 and 1 with a
|
|
fixed border color. Equivalent to GL_CLAMP_TO_BORDER
|
|
*/
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::CoordinateDirection
|
|
This enum defines the possible texture coordinate directions
|
|
|
|
\value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S
|
|
\value DirectionT The vertical direction. Equivalent to GL_TEXTURE_WRAP_T
|
|
\value DirectionR The depth direction. Equivalent to GL_TEXTURE_WRAP_R
|
|
*/
|
|
|
|
/*!
|
|
Creates a QOpenGLTexture object that can later be bound to \a target.
|
|
|
|
This does not create the underlying OpenGL texture object. Therefore,
|
|
construction using this constructor does not require a valid current
|
|
OpenGL context.
|
|
*/
|
|
QOpenGLTexture::QOpenGLTexture(Target target)
|
|
: d_ptr(new QOpenGLTexturePrivate(target, this))
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Creates a QOpenGLTexture object that can later be bound to the 2D texture
|
|
target and contains the pixel data contained in \a image. If you wish
|
|
to have a chain of mipmaps generated then set \a genMipMaps to \c true (this
|
|
is the default).
|
|
|
|
This does create the underlying OpenGL texture object. Therefore,
|
|
construction using this constructor does require a valid current
|
|
OpenGL context.
|
|
*/
|
|
QOpenGLTexture::QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps)
|
|
: QOpenGLTexture(QOpenGLTexture::Target2D)
|
|
{
|
|
setData(image, genMipMaps);
|
|
}
|
|
|
|
QOpenGLTexture::~QOpenGLTexture()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Returns the binding target of this texture.
|
|
|
|
\since 5.4
|
|
*/
|
|
QOpenGLTexture::Target QOpenGLTexture::target() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->target;
|
|
}
|
|
|
|
/*!
|
|
Creates the underlying OpenGL texture object. This requires a current valid
|
|
OpenGL context. If the texture object already exists, this function does
|
|
nothing.
|
|
|
|
Once the texture object is created you can obtain the object
|
|
name from the textureId() function. This may be useful if you wish to make
|
|
some raw OpenGL calls related to this texture.
|
|
|
|
Normally it should not be necessary to call this function directly as all
|
|
functions that set properties of the texture object implicitly call create()
|
|
on your behalf.
|
|
|
|
Returns \c true if the creation succeeded, otherwise returns \c false.
|
|
|
|
\sa destroy(), isCreated(), textureId()
|
|
*/
|
|
bool QOpenGLTexture::create()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
return d->create();
|
|
}
|
|
|
|
/*!
|
|
Destroys the underlying OpenGL texture object. This requires a current valid
|
|
OpenGL context.
|
|
|
|
\sa create(), isCreated(), textureId()
|
|
*/
|
|
void QOpenGLTexture::destroy()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
return d->destroy();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if the underlying OpenGL texture object has been created.
|
|
|
|
\sa create(), destroy(), textureId()
|
|
*/
|
|
bool QOpenGLTexture::isCreated() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->textureId != 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the name of the underlying OpenGL texture object or 0 if it has
|
|
not yet been created.
|
|
|
|
\sa create(), destroy(), isCreated()
|
|
*/
|
|
GLuint QOpenGLTexture::textureId() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->textureId;
|
|
}
|
|
|
|
/*!
|
|
Binds this texture to the currently active texture unit ready for
|
|
rendering. Note that you do not need to bind QOpenGLTexture objects
|
|
in order to modify them as the implementation makes use of the
|
|
EXT_direct_state_access extension where available and simulates it
|
|
where it is not.
|
|
|
|
\sa release()
|
|
*/
|
|
void QOpenGLTexture::bind()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->bind();
|
|
}
|
|
|
|
/*!
|
|
Binds this texture to texture unit \a unit ready for
|
|
rendering. Note that you do not need to bind QOpenGLTexture objects
|
|
in order to modify them as the implementation makes use of the
|
|
EXT_direct_state_access extension where available and simulates it
|
|
where it is not.
|
|
|
|
If parameter \a reset is \c true then this function will restore
|
|
the active unit to the texture unit that was active upon entry.
|
|
|
|
\sa release()
|
|
*/
|
|
void QOpenGLTexture::bind(uint unit, TextureUnitReset reset)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->bind(unit, reset);
|
|
}
|
|
|
|
/*!
|
|
Unbinds this texture from the currently active texture unit.
|
|
|
|
\sa bind()
|
|
*/
|
|
void QOpenGLTexture::release()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->release();
|
|
}
|
|
|
|
/*!
|
|
Unbinds this texture from texture unit \a unit.
|
|
|
|
If parameter \a reset is \c true then this function
|
|
will restore the active unit to the texture unit that was active
|
|
upon entry.
|
|
*/
|
|
void QOpenGLTexture::release(uint unit, TextureUnitReset reset)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->release(unit, reset);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this texture is bound to the corresponding target
|
|
of the currently active texture unit.
|
|
|
|
\sa bind(), release()
|
|
*/
|
|
bool QOpenGLTexture::isBound() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
return d->isBound();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this texture is bound to the corresponding target
|
|
of texture unit \a unit.
|
|
|
|
\sa bind(), release()
|
|
*/
|
|
bool QOpenGLTexture::isBound(uint unit)
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
return d->isBound(unit);
|
|
}
|
|
|
|
/*!
|
|
Returns the textureId of the texture that is bound to the \a target
|
|
of the currently active texture unit.
|
|
*/
|
|
GLuint QOpenGLTexture::boundTextureId(BindingTarget target)
|
|
{
|
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
|
if (!ctx) {
|
|
qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
|
|
return 0;
|
|
}
|
|
|
|
GLint textureId = 0;
|
|
ctx->functions()->glGetIntegerv(target, &textureId);
|
|
return static_cast<GLuint>(textureId);
|
|
}
|
|
|
|
/*!
|
|
Returns the textureId of the texture that is bound to the \a target
|
|
of the texture unit \a unit.
|
|
*/
|
|
GLuint QOpenGLTexture::boundTextureId(uint unit, BindingTarget target)
|
|
{
|
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
|
if (!ctx) {
|
|
qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
|
|
return 0;
|
|
}
|
|
|
|
QOpenGLFunctions *funcs = ctx->functions();
|
|
funcs->initializeOpenGLFunctions();
|
|
|
|
GLint oldTextureUnit = 0;
|
|
funcs->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
|
|
|
|
funcs->glActiveTexture(unit);
|
|
GLint textureId = 0;
|
|
funcs->glGetIntegerv(target, &textureId);
|
|
funcs->glActiveTexture(oldTextureUnit);
|
|
|
|
return static_cast<GLuint>(textureId);
|
|
}
|
|
|
|
/*!
|
|
Sets the format of this texture object to \a format. This function
|
|
must be called before texture storage is allocated.
|
|
|
|
Note that all formats may not be supported. The exact set of supported
|
|
formats is dependent upon your OpenGL implementation and version.
|
|
|
|
\sa format(), allocateStorage()
|
|
*/
|
|
void QOpenGLTexture::setFormat(TextureFormat format)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("QOpenGLTexture::setFormat(): Cannot change format once storage has been allocated");
|
|
return;
|
|
}
|
|
|
|
d->format = format;
|
|
|
|
switch (format) {
|
|
case NoFormat:
|
|
d->formatClass = NoFormatClass;
|
|
break;
|
|
|
|
case RGBA32F:
|
|
case RGBA32U:
|
|
case RGBA32I:
|
|
d->formatClass = FormatClass_128Bit;
|
|
break;
|
|
|
|
case RGB32F:
|
|
case RGB32U:
|
|
case RGB32I:
|
|
d->formatClass = FormatClass_96Bit;
|
|
break;
|
|
|
|
case RGBA16F:
|
|
case RG32F:
|
|
case RGBA16U:
|
|
case RG32U:
|
|
case RGBA16I:
|
|
case RG32I:
|
|
case RGBA16_UNorm:
|
|
case RGBA16_SNorm:
|
|
d->formatClass = FormatClass_64Bit;
|
|
break;
|
|
|
|
case RGB16_UNorm:
|
|
case RGB16_SNorm:
|
|
case RGB16F:
|
|
case RGB16U:
|
|
case RGB16I:
|
|
d->formatClass = FormatClass_48Bit;
|
|
break;
|
|
|
|
case RG16F:
|
|
case RG11B10F:
|
|
case R32F:
|
|
case RGB10A2:
|
|
case RGBA8U:
|
|
case RG16U:
|
|
case R32U:
|
|
case RGBA8I:
|
|
case RG16I:
|
|
case R32I:
|
|
case RGBA8_UNorm:
|
|
case RG16_UNorm:
|
|
case RGBA8_SNorm:
|
|
case RG16_SNorm:
|
|
case SRGB8_Alpha8:
|
|
case RGB9E5:
|
|
d->formatClass = FormatClass_32Bit;
|
|
break;
|
|
|
|
case RGB8_UNorm:
|
|
case RGB8_SNorm:
|
|
case SRGB8:
|
|
case RGB8U:
|
|
case RGB8I:
|
|
d->formatClass = FormatClass_24Bit;
|
|
break;
|
|
|
|
case R16F:
|
|
case RG8U:
|
|
case R16U:
|
|
case RG8I:
|
|
case R16I:
|
|
case RG8_UNorm:
|
|
case R16_UNorm:
|
|
case RG8_SNorm:
|
|
case R16_SNorm:
|
|
d->formatClass = FormatClass_16Bit;
|
|
break;
|
|
|
|
case R8U:
|
|
case R8I:
|
|
case R8_UNorm:
|
|
case R8_SNorm:
|
|
d->formatClass = FormatClass_8Bit;
|
|
break;
|
|
|
|
case R_ATI1N_UNorm:
|
|
case R_ATI1N_SNorm:
|
|
d->formatClass = FormatClass_RGTC1_R;
|
|
break;
|
|
|
|
case RG_ATI2N_UNorm:
|
|
case RG_ATI2N_SNorm:
|
|
d->formatClass = FormatClass_RGTC2_RG;
|
|
break;
|
|
|
|
case RGB_BP_UNorm:
|
|
case SRGB_BP_UNorm:
|
|
d->formatClass = FormatClass_BPTC_Unorm;
|
|
break;
|
|
|
|
case RGB_BP_UNSIGNED_FLOAT:
|
|
case RGB_BP_SIGNED_FLOAT:
|
|
d->formatClass = FormatClass_BPTC_Float;
|
|
break;
|
|
|
|
case RGB_DXT1:
|
|
case SRGB_DXT1:
|
|
d->formatClass = FormatClass_S3TC_DXT1_RGB;
|
|
break;
|
|
|
|
case RGBA_DXT1:
|
|
case SRGB_Alpha_DXT1:
|
|
d->formatClass = FormatClass_S3TC_DXT1_RGBA;
|
|
break;
|
|
|
|
case RGBA_DXT3:
|
|
case SRGB_Alpha_DXT3:
|
|
d->formatClass = FormatClass_S3TC_DXT3_RGBA;
|
|
break;
|
|
|
|
case RGBA_DXT5:
|
|
case SRGB_Alpha_DXT5:
|
|
d->formatClass = FormatClass_S3TC_DXT5_RGBA;
|
|
break;
|
|
|
|
case QOpenGLTexture::R11_EAC_UNorm:
|
|
case QOpenGLTexture::R11_EAC_SNorm:
|
|
case QOpenGLTexture::RG11_EAC_UNorm:
|
|
case QOpenGLTexture::RG11_EAC_SNorm:
|
|
case QOpenGLTexture::RGB8_ETC2:
|
|
case QOpenGLTexture::SRGB8_ETC2:
|
|
case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
|
|
case QOpenGLTexture::RGBA8_ETC2_EAC:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
|
|
case QOpenGLTexture::RGB8_ETC1:
|
|
case RG3B2:
|
|
case R5G6B5:
|
|
case RGB5A1:
|
|
case RGBA4:
|
|
case D16:
|
|
case D24:
|
|
case D24S8:
|
|
case D32:
|
|
case D32F:
|
|
case D32FS8X24:
|
|
case S8:
|
|
case DepthFormat:
|
|
case AlphaFormat:
|
|
case RGBFormat:
|
|
case RGBAFormat:
|
|
case LuminanceFormat:
|
|
case LuminanceAlphaFormat:
|
|
case QOpenGLTexture::RGBA_ASTC_4x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x4:
|
|
case QOpenGLTexture::RGBA_ASTC_5x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x5:
|
|
case QOpenGLTexture::RGBA_ASTC_6x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x5:
|
|
case QOpenGLTexture::RGBA_ASTC_8x6:
|
|
case QOpenGLTexture::RGBA_ASTC_8x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x5:
|
|
case QOpenGLTexture::RGBA_ASTC_10x6:
|
|
case QOpenGLTexture::RGBA_ASTC_10x8:
|
|
case QOpenGLTexture::RGBA_ASTC_10x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x10:
|
|
case QOpenGLTexture::RGBA_ASTC_12x12:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
|
|
case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
|
|
d->formatClass = FormatClass_Unique;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the format of this texture object.
|
|
|
|
\sa setFormat()
|
|
*/
|
|
QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->format;
|
|
}
|
|
|
|
static bool isNpot(int width, int height = 1, int depth = 1)
|
|
{
|
|
return width & (width-1) || height & (height-1) || depth & (depth-1);
|
|
}
|
|
|
|
/*!
|
|
Sets the dimensions of this texture object to \a width,
|
|
\a height, and \a depth. The default for each dimension is 1.
|
|
The maximum allowable texture size is dependent upon your OpenGL
|
|
implementation. Allocating storage for a texture less than the
|
|
maximum size can still fail if your system is low on resources.
|
|
|
|
If a non-power-of-two \a width, \a height or \a depth is provided and your
|
|
OpenGL implementation doesn't have support for repeating non-power-of-two
|
|
textures, then the wrap mode is automatically set to ClampToEdge.
|
|
|
|
\sa width(), height(), depth()
|
|
*/
|
|
void QOpenGLTexture::setSize(int width, int height, int depth)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("Cannot resize a texture that already has storage allocated.\n"
|
|
"To do so, destroy() the texture and then create() and setSize()");
|
|
return;
|
|
}
|
|
|
|
if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
|
|
d->setWrapMode(WrapMode::ClampToEdge);
|
|
|
|
switch (d->target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
d->dimensions[0] = width;
|
|
Q_UNUSED(height);
|
|
Q_UNUSED(depth);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
d->dimensions[0] = width;
|
|
d->dimensions[1] = height;
|
|
Q_UNUSED(depth);
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
if (width != height)
|
|
qWarning("QAbstractOpenGLTexture::setSize(): Cube map textures must be square");
|
|
d->dimensions[0] = d->dimensions[1] = width;
|
|
Q_UNUSED(depth);
|
|
break;
|
|
|
|
case QOpenGLTexture::Target3D:
|
|
d->dimensions[0] = width;
|
|
d->dimensions[1] = height;
|
|
d->dimensions[2] = depth;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the width of a 1D, 2D or 3D texture.
|
|
|
|
\sa height(), depth(), setSize()
|
|
*/
|
|
int QOpenGLTexture::width() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->dimensions[0];
|
|
}
|
|
|
|
/*!
|
|
Returns the height of a 2D or 3D texture.
|
|
|
|
\sa width(), depth(), setSize()
|
|
*/
|
|
int QOpenGLTexture::height() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->dimensions[1];
|
|
}
|
|
|
|
/*!
|
|
Returns the depth of a 3D texture.
|
|
|
|
\sa width(), height(), setSize()
|
|
*/
|
|
int QOpenGLTexture::depth() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->dimensions[2];
|
|
}
|
|
|
|
/*!
|
|
For texture targets that support mipmaps, this function
|
|
sets the requested number of mipmap \a levels to allocate storage
|
|
for. This function should be called before storage is allocated
|
|
for the texture.
|
|
|
|
If the texture target does not support mipmaps this function
|
|
has no effect.
|
|
|
|
\sa mipLevels(), maximumMipLevels(), isStorageAllocated()
|
|
*/
|
|
void QOpenGLTexture::setMipLevels(int levels)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("Cannot set mip levels on a texture that already has storage allocated.\n"
|
|
"To do so, destroy() the texture and then create() and setMipLevels()");
|
|
return;
|
|
}
|
|
|
|
switch (d->target) {
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::Target3D:
|
|
d->requestedMipLevels = levels;
|
|
break;
|
|
|
|
case QOpenGLTexture::TargetBuffer:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
qWarning("QAbstractOpenGLTexture::setMipLevels(): This texture target does not support mipmaps");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the number of mipmap levels for this texture. If storage
|
|
has not yet been allocated for this texture it returns the
|
|
requested number of mipmap levels.
|
|
|
|
\sa setMipLevels(), maximumMipLevels(), isStorageAllocated()
|
|
*/
|
|
int QOpenGLTexture::mipLevels() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return isStorageAllocated() ? d->mipLevels : d->requestedMipLevels;
|
|
}
|
|
|
|
/*!
|
|
Returns the maximum number of mipmap levels that this texture
|
|
can have given the current dimensions.
|
|
|
|
\sa setMipLevels(), mipLevels(), setSize()
|
|
*/
|
|
int QOpenGLTexture::maximumMipLevels() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->maximumMipLevelCount();
|
|
}
|
|
|
|
/*!
|
|
Sets the number of array \a layers to allocate storage for. This
|
|
function should be called before storage is allocated for the texture.
|
|
|
|
For targets that do not support array layers this function has
|
|
no effect.
|
|
|
|
\sa layers(), isStorageAllocated()
|
|
*/
|
|
void QOpenGLTexture::setLayers(int layers)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("Cannot set layers on a texture that already has storage allocated.\n"
|
|
"To do so, destroy() the texture and then create() and setLayers()");
|
|
return;
|
|
}
|
|
|
|
switch (d->target) {
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
d->layers = layers;
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target3D:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
qWarning("Texture target does not support array layers");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the number of array layers for this texture. If
|
|
storage has not yet been allocated for this texture then
|
|
this function returns the requested number of array layers.
|
|
|
|
For texture targets that do not support array layers this
|
|
will return 1.
|
|
|
|
\sa setLayers(), isStorageAllocated()
|
|
*/
|
|
int QOpenGLTexture::layers() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->layers;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of faces for this texture. For cubemap
|
|
and cubemap array type targets this will be 6.
|
|
|
|
For non-cubemap type targets this will return 1.
|
|
*/
|
|
int QOpenGLTexture::faces() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->faces;
|
|
}
|
|
|
|
/*!
|
|
Sets the number of \a samples to allocate storage for when rendering to
|
|
a multisample capable texture target. This function should
|
|
be called before storage is allocated for the texture.
|
|
|
|
For targets that do not support multisampling this function has
|
|
no effect.
|
|
|
|
\sa samples(), isStorageAllocated()
|
|
*/
|
|
void QOpenGLTexture::setSamples(int samples)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("Cannot set sample count on a texture that already has storage allocated.\n"
|
|
"To do so, destroy() the texture and then create() and setSamples()");
|
|
return;
|
|
}
|
|
|
|
switch (d->target) {
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
d->samples = samples;
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target3D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
|
|
qWarning("Texture target does not support multisampling");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the number of multisample sample points for this texture.
|
|
If storage has not yet been allocated for this texture then
|
|
this function returns the requested number of samples.
|
|
|
|
For texture targets that do not support multisampling this
|
|
will return 0.
|
|
|
|
\sa setSamples(), isStorageAllocated()
|
|
*/
|
|
int QOpenGLTexture::samples() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->samples;
|
|
}
|
|
|
|
/*!
|
|
Sets whether the sample positions and number of samples used with
|
|
a multisample capable texture target to \a fixed. If set to \c true
|
|
the sample positions and number of samples used are the same for
|
|
all texels in the image and will not depend upon the image size or
|
|
internal format. This function should be called before storage is allocated
|
|
for the texture.
|
|
|
|
For targets that do not support multisampling this function has
|
|
no effect.
|
|
|
|
The default value is \c true.
|
|
|
|
\sa isFixedSamplePositions(), isStorageAllocated()
|
|
*/
|
|
void QOpenGLTexture::setFixedSamplePositions(bool fixed)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (isStorageAllocated()) {
|
|
qWarning("Cannot set sample positions on a texture that already has storage allocated.\n"
|
|
"To do so, destroy() the texture and then create() and setFixedSamplePositions()");
|
|
return;
|
|
}
|
|
|
|
switch (d->target) {
|
|
case QOpenGLTexture::Target2DMultisample:
|
|
case QOpenGLTexture::Target2DMultisampleArray:
|
|
d->fixedSamplePositions = fixed;
|
|
break;
|
|
|
|
case QOpenGLTexture::Target1D:
|
|
case QOpenGLTexture::Target2D:
|
|
case QOpenGLTexture::Target3D:
|
|
case QOpenGLTexture::Target1DArray:
|
|
case QOpenGLTexture::Target2DArray:
|
|
case QOpenGLTexture::TargetCubeMap:
|
|
case QOpenGLTexture::TargetCubeMapArray:
|
|
case QOpenGLTexture::TargetBuffer:
|
|
case QOpenGLTexture::TargetRectangle:
|
|
|
|
qWarning("Texture target does not support multisampling");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns whether this texture uses a fixed pattern of multisample
|
|
samples. If storage has not yet been allocated for this texture then
|
|
this function returns the requested fixed sample position setting.
|
|
|
|
For texture targets that do not support multisampling this
|
|
will return \c true.
|
|
|
|
\sa setFixedSamplePositions(), isStorageAllocated()
|
|
*/
|
|
bool QOpenGLTexture::isFixedSamplePositions() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->fixedSamplePositions;
|
|
}
|
|
|
|
/*!
|
|
Allocates server-side storage for this texture object taking
|
|
into account, the format, dimensions, mipmap levels, array
|
|
layers and cubemap faces.
|
|
|
|
Once storage has been allocated it is no longer possible to change
|
|
these properties.
|
|
|
|
If supported QOpenGLTexture makes use of immutable texture
|
|
storage.
|
|
|
|
Once storage has been allocated for the texture then pixel data
|
|
can be uploaded via one of the setData() overloads.
|
|
|
|
\note If immutable texture storage is not available,
|
|
then a default pixel format and pixel type will be used to
|
|
create the mutable storage. You can use the other
|
|
allocateStorage() overload to specify exactly the pixel format
|
|
and the pixel type to use when allocating mutable storage;
|
|
this is particulary useful under certain OpenGL ES implementations
|
|
(notably, OpenGL ES 2), where the pixel format and the pixel type
|
|
used at allocation time must perfectly match the format
|
|
and the type passed to any subsequent setData() call.
|
|
|
|
\sa isStorageAllocated(), setData()
|
|
*/
|
|
void QOpenGLTexture::allocateStorage()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
if (d->create()) {
|
|
const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(d->format);
|
|
const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(d->format);
|
|
d->allocateStorage(pixelFormat, pixelType);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\since 5.5
|
|
|
|
Allocates server-side storage for this texture object taking
|
|
into account, the format, dimensions, mipmap levels, array
|
|
layers and cubemap faces.
|
|
|
|
Once storage has been allocated it is no longer possible to change
|
|
these properties.
|
|
|
|
If supported QOpenGLTexture makes use of immutable texture
|
|
storage. However, if immutable texture storage is not available,
|
|
then the specified \a pixelFormat and \a pixelType will be used
|
|
to allocate mutable storage; note that in certain OpenGL implementations
|
|
(notably, OpenGL ES 2) they must perfectly match the format
|
|
and the type passed to any subsequent setData() call.
|
|
|
|
Once storage has been allocated for the texture then pixel data
|
|
can be uploaded via one of the setData() overloads.
|
|
|
|
\sa isStorageAllocated(), setData()
|
|
*/
|
|
void QOpenGLTexture::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
if (d->create())
|
|
d->allocateStorage(pixelFormat, pixelType);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if server-side storage for this texture as been
|
|
allocated.
|
|
|
|
The texture format, dimensions, mipmap levels and array layers
|
|
cannot be altered once storage ihas been allocated.
|
|
|
|
\sa allocateStorage(), setSize(), setMipLevels(), setLayers(), setFormat()
|
|
*/
|
|
bool QOpenGLTexture::isStorageAllocated() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->storageAllocated;
|
|
}
|
|
|
|
/*!
|
|
Attempts to create a texture view onto this texture. A texture
|
|
view is somewhat analogous to a view in SQL in that it presents
|
|
a restricted or reinterpreted view of the original data. Texture
|
|
views do not allocate any more server-side storage, insted relying
|
|
on the storage buffer of the source texture.
|
|
|
|
Texture views are only available when using immutable storage. For
|
|
more information on texture views see
|
|
http://www.opengl.org/wiki/Texture_Storage#Texture_views.
|
|
|
|
The \a target argument specifies the target to use for the view.
|
|
Only some targets can be used depending upon the target of the original
|
|
target. For e.g. a view onto a Target1DArray texture can specify
|
|
either Target1DArray or Target1D but for the latter the number of
|
|
array layers specified with \a minimumLayer and \a maximumLayer must
|
|
be exactly 1.
|
|
|
|
Simpliar constraints apply for the \a viewFormat. See the above link
|
|
and the specification for more details.
|
|
|
|
The \a minimumMipmapLevel, \a maximumMipmapLevel, \a minimumLayer,
|
|
and \a maximumLayer arguments serve to restrict the parts of the
|
|
texture accessible by the texture view.
|
|
|
|
If creation of the texture view fails this function will return
|
|
0. If the function succeeds it will return a pointer to a new
|
|
QOpenGLTexture object that will return \c true from its isTextureView()
|
|
function.
|
|
|
|
\sa isTextureView()
|
|
*/
|
|
QOpenGLTexture *QOpenGLTexture::createTextureView(Target target,
|
|
TextureFormat viewFormat,
|
|
int minimumMipmapLevel, int maximumMipmapLevel,
|
|
int minimumLayer, int maximumLayer) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
if (!isStorageAllocated()) {
|
|
qWarning("Cannot set create a texture view of a texture that does not have storage allocated.");
|
|
return nullptr;
|
|
}
|
|
Q_ASSERT(maximumMipmapLevel >= minimumMipmapLevel);
|
|
Q_ASSERT(maximumLayer >= minimumLayer);
|
|
return d->createTextureView(target, viewFormat,
|
|
minimumMipmapLevel, maximumMipmapLevel,
|
|
minimumLayer, maximumLayer);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this texture object is actually a view onto another
|
|
texture object.
|
|
|
|
\sa createTextureView()
|
|
*/
|
|
bool QOpenGLTexture::isTextureView() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
return d->textureView;
|
|
}
|
|
|
|
/*!
|
|
Uploads pixel \a data for this texture object \a mipLevel, array \a layer, and \a cubeFace.
|
|
Storage must have been allocated before uploading pixel data. Some overloads of setData()
|
|
will set appropriate dimensions, mipmap levels, and array layers and then allocate storage
|
|
for you if they have enough information to do so. This will be noted in the function
|
|
documentation.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a sourceFormat
|
|
and \a sourceType. The pixel data upload can optionally be controlled by \a options.
|
|
|
|
If using a compressed format() then you should use setCompressedData() instead of this
|
|
function.
|
|
|
|
\since 5.3
|
|
\sa setCompressedData()
|
|
*/
|
|
void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
if (!isStorageAllocated()) {
|
|
qWarning("Cannot set data on a texture that does not have storage allocated.\n"
|
|
"To do so call allocateStorage() before this function");
|
|
return;
|
|
}
|
|
d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.9
|
|
\overload
|
|
|
|
Parameter \a layerCount is the number of layers in a texture array
|
|
that are being uploaded/populated by this call.
|
|
*/
|
|
void QOpenGLTexture::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
if (!isStorageAllocated()) {
|
|
qWarning("Cannot set data on a texture that does not have storage allocated.\n"
|
|
"To do so call allocateStorage() before this function");
|
|
return;
|
|
}
|
|
d->setData(mipLevel, layer, layerCount, cubeFace, sourceFormat, sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.3
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setData(int mipLevel, int layer,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.3
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setData(int mipLevel,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.3
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
\overload
|
|
|
|
This overload is to be used to update a part of the texture. Parameters \a
|
|
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
|
|
texture. Parameters \a width, \a height and \a depth specify the dimensions
|
|
of the sub image.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a
|
|
sourceFormat and \a sourceType. The pixel data upload can optionally be
|
|
controlled by \a options.
|
|
*/
|
|
void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
|
|
int width, int height, int depth,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
0, 0, 1,
|
|
QOpenGLTexture::CubeMapPositiveX, sourceFormat,
|
|
sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
\overload
|
|
|
|
This overload is to be used to update a part of the texture. Parameters \a
|
|
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
|
|
texture. Parameters \a width, \a height and \a depth specify the dimensions
|
|
of the sub image. The mip map level the sub image we want to
|
|
update is specified with \a mipLevel.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a
|
|
sourceFormat and \a sourceType. The pixel data upload can optionally be
|
|
controlled by \a options.
|
|
*/
|
|
void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
|
|
int width, int height, int depth,
|
|
int mipLevel,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
mipLevel, 0, 1,
|
|
QOpenGLTexture::CubeMapPositiveX, sourceFormat,
|
|
sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
\overload
|
|
|
|
This overload is to be used to update a part of the texture. Parameters \a
|
|
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
|
|
texture. Parameters \a width, \a height and \a depth specify the dimensions
|
|
of the sub image. The mip map level and layerof the sub image we want to
|
|
update are specified with \a mipLevel and \a layer.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a
|
|
sourceFormat and \a sourceType. The pixel data upload can optionally be
|
|
controlled by \a options.
|
|
*/
|
|
void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
|
|
int width, int height, int depth,
|
|
int mipLevel, int layer,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
mipLevel, layer, 1,
|
|
QOpenGLTexture::CubeMapPositiveX, sourceFormat,
|
|
sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
\overload
|
|
|
|
This overload is to be used to update a part of the texture. Parameters \a
|
|
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
|
|
texture. Parameters \a width, \a height and \a depth specify the dimensions
|
|
of the sub image.The mip map level, layer and cube map face of the sub
|
|
image we want to update are specified with \a mipLevel, \a layer and \a
|
|
face.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a
|
|
sourceFormat and \a sourceType. The pixel data upload can optionally be
|
|
controlled by \a options.
|
|
*/
|
|
void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
|
|
int width, int height, int depth,
|
|
int mipLevel, int layer,
|
|
CubeMapFace face,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
mipLevel, layer, 1,
|
|
face, sourceFormat,
|
|
sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
\overload
|
|
|
|
This overload is to be used to update a part of the texture. Parameters \a
|
|
xOffset, \a yOffset, \a zOffset specify the texel offsets within the
|
|
texture. Parameters \a width, \a height and \a depth specify the dimensions
|
|
of the sub image.The mip map level, starting layer, cube map face and
|
|
number of layers of the sub image we want to update are specified with \a
|
|
mipLevel, \a layer, \a face and \a layerCount.
|
|
|
|
The structure of the pixel data pointed to by \a data is specified by \a
|
|
sourceFormat and \a sourceType. The pixel data upload can optionally be
|
|
controlled by \a options.
|
|
*/
|
|
void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
|
|
int width, int height, int depth,
|
|
int mipLevel, int layer,
|
|
CubeMapFace face, int layerCount,
|
|
PixelFormat sourceFormat, PixelType sourceType,
|
|
const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setData(xOffset, yOffset, zOffset,
|
|
width, height, depth,
|
|
mipLevel, layer, layerCount,
|
|
face, sourceFormat,
|
|
sourceType, data, options);
|
|
}
|
|
|
|
/*!
|
|
This overload of setData() will allocate storage for you.
|
|
The pixel data is contained in \a image. Mipmaps are generated by default.
|
|
Set \a genMipMaps to \l DontGenerateMipMaps to turn off mipmap generation.
|
|
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
|
|
{
|
|
QOpenGLContext *context = QOpenGLContext::currentContext();
|
|
if (!context) {
|
|
qWarning("QOpenGLTexture::setData() requires a valid current context");
|
|
return;
|
|
}
|
|
|
|
if (image.isNull()) {
|
|
qWarning("QOpenGLTexture::setData() tried to set a null image");
|
|
return;
|
|
}
|
|
|
|
if (context->isOpenGLES() && context->format().majorVersion() < 3)
|
|
setFormat(QOpenGLTexture::RGBAFormat);
|
|
else
|
|
setFormat(QOpenGLTexture::RGBA8_UNorm);
|
|
|
|
setSize(image.width(), image.height());
|
|
setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1);
|
|
allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
|
|
|
|
// Upload pixel data and generate mipmaps
|
|
QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
|
|
QOpenGLPixelTransferOptions uploadOptions;
|
|
uploadOptions.setAlignment(1);
|
|
setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions);
|
|
}
|
|
|
|
/*!
|
|
Uploads compressed pixel \a data to \a mipLevel, array \a layer, and \a cubeFace.
|
|
The pixel transfer can optionally be controlled with \a options. The \a dataSize
|
|
argument should specify the size of the data pointed to by \a data.
|
|
|
|
If not using a compressed format() then you should use setData() instead of this
|
|
function.
|
|
|
|
\since 5.3
|
|
*/
|
|
void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
|
|
int dataSize, const void *data,
|
|
const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
if (!isStorageAllocated()) {
|
|
qWarning("Cannot set data on a texture that does not have storage allocated.\n"
|
|
"To do so call allocateStorage() before this function");
|
|
return;
|
|
}
|
|
d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options);
|
|
}
|
|
|
|
/*!
|
|
\since 5.9
|
|
\overload
|
|
|
|
Parameter \a layerCount is the number of layers in a texture array
|
|
that are being uploaded/populated by this call.
|
|
*/
|
|
void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, int dataSize, const void *data, const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
if (!isStorageAllocated()) {
|
|
qWarning("Cannot set data on a texture that does not have storage allocated.\n"
|
|
"To do so call allocateStorage() before this function");
|
|
return;
|
|
}
|
|
d->setCompressedData(mipLevel, layer, layerCount, cubeFace, dataSize, data, options);
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, const void *data,
|
|
const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, const void *data,
|
|
const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setCompressedData(int dataSize, const void *data,
|
|
const QOpenGLPixelTransferOptions * const options)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->textureId);
|
|
d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if your OpenGL implementation and version supports the texture
|
|
feature \a feature.
|
|
*/
|
|
bool QOpenGLTexture::hasFeature(Feature feature)
|
|
{
|
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
|
if (!ctx) {
|
|
qWarning("QOpenGLTexture::hasFeature() requires a valid current context");
|
|
return false;
|
|
}
|
|
|
|
QSurfaceFormat f = ctx->format();
|
|
|
|
bool supported = false;
|
|
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!ctx->isOpenGLES()) {
|
|
switch (feature) {
|
|
case ImmutableMultisampleStorage:
|
|
supported = f.version() >= qMakePair(4, 3)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage_multisample"));
|
|
break;
|
|
|
|
case TextureBuffer:
|
|
supported = f.version() >= qMakePair(3, 0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_buffer_object"));
|
|
break;
|
|
|
|
case StencilTexturing:
|
|
supported = f.version() >= qMakePair(4, 3)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_stencil_texturing"));
|
|
break;
|
|
|
|
case ImmutableStorage:
|
|
supported = f.version() >= qMakePair(4, 2)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage"))
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage"));
|
|
break;
|
|
|
|
case TextureCubeMapArrays:
|
|
supported = f.version() >= qMakePair(4, 0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("ARB_texture_cube_map_array"));
|
|
break;
|
|
|
|
case Swizzle:
|
|
supported = f.version() >= qMakePair(3, 3)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_swizzle"));
|
|
break;
|
|
|
|
case TextureMultisample:
|
|
supported = f.version() >= qMakePair(3, 2)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_multisample"));
|
|
break;
|
|
|
|
case TextureArrays:
|
|
supported = f.version() >= qMakePair(3, 0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_array"));
|
|
break;
|
|
|
|
case TextureRectangle:
|
|
supported = f.version() >= qMakePair(2, 1)
|
|
|| ctx->hasExtension(QByteArrayLiteral("ARB_texture_rectangle"));
|
|
break;
|
|
|
|
case Texture3D:
|
|
supported = f.version() >= qMakePair(1, 3);
|
|
break;
|
|
|
|
case AnisotropicFiltering:
|
|
supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
|
|
break;
|
|
|
|
case NPOTTextures:
|
|
case NPOTTextureRepeat:
|
|
supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
|
|
break;
|
|
|
|
case Texture1D:
|
|
supported = f.version() >= qMakePair(1, 1);
|
|
break;
|
|
|
|
case TextureComparisonOperators:
|
|
// GL 1.4 and GL_ARB_shadow alone support only LEQUAL and GEQUAL;
|
|
// since we're talking about history anyhow avoid to be extra pedantic
|
|
// in the feature set, and simply claim supported if we have the full set of operators
|
|
// (which has been added into 1.5 / GL_EXT_shadow_funcs).
|
|
supported = f.version() >= qMakePair(1, 5)
|
|
|| (ctx->hasExtension(QByteArrayLiteral("GL_ARB_shadow"))
|
|
&& ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_funcs")));
|
|
break;
|
|
|
|
case TextureMipMapLevel:
|
|
supported = f.version() >= qMakePair(1, 2);
|
|
break;
|
|
|
|
case MaxFeatureFlag:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ctx->isOpenGLES())
|
|
#endif
|
|
{
|
|
const char *renderer = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_RENDERER));
|
|
switch (feature) {
|
|
case ImmutableStorage:
|
|
supported = (f.version() >= qMakePair(3, 0) || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")))
|
|
&& !(renderer && strstr(renderer, "Mali")); // do not use on Mali: QTBUG-45106
|
|
break;
|
|
|
|
case ImmutableMultisampleStorage:
|
|
supported = f.version() >= qMakePair(3, 1);
|
|
break;
|
|
|
|
case TextureRectangle:
|
|
break;
|
|
|
|
case TextureArrays:
|
|
supported = f.version() >= qMakePair(3, 0);
|
|
break;
|
|
|
|
case Texture3D:
|
|
supported = f.version() >= qMakePair(3, 0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"));
|
|
break;
|
|
|
|
case TextureMultisample:
|
|
supported = f.version() >= qMakePair(3, 1);
|
|
break;
|
|
|
|
case TextureBuffer:
|
|
break;
|
|
|
|
case TextureCubeMapArrays:
|
|
break;
|
|
|
|
case Swizzle:
|
|
supported = f.version() >= qMakePair(3, 0);
|
|
break;
|
|
|
|
case StencilTexturing:
|
|
break;
|
|
|
|
case AnisotropicFiltering:
|
|
supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
|
|
break;
|
|
|
|
case NPOTTextures:
|
|
case NPOTTextureRepeat:
|
|
supported = f.version() >= qMakePair(3,0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot"))
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
|
|
break;
|
|
|
|
case Texture1D:
|
|
break;
|
|
|
|
case TextureComparisonOperators:
|
|
supported = f.version() >= qMakePair(3, 0)
|
|
|| ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_samplers"));
|
|
break;
|
|
|
|
case TextureMipMapLevel:
|
|
supported = f.version() >= qMakePair(3, 0);
|
|
break;
|
|
|
|
case MaxFeatureFlag:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return supported;
|
|
}
|
|
|
|
/*!
|
|
Sets the base mipmap level used for all texture lookups with this texture to \a baseLevel.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa mipBaseLevel(), setMipMaxLevel(), setMipLevelRange()
|
|
*/
|
|
void QOpenGLTexture::setMipBaseLevel(int baseLevel)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (!d->features.testFlag(TextureMipMapLevel)) {
|
|
qWarning("QOpenGLTexture::setMipBaseLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
|
|
return;
|
|
}
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(baseLevel <= d->maxLevel);
|
|
d->baseLevel = baseLevel;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
|
|
}
|
|
|
|
/*!
|
|
Returns the mipmap base level used for all texture lookups with this texture.
|
|
The default is 0.
|
|
|
|
\sa setMipBaseLevel(), mipMaxLevel(), mipLevelRange()
|
|
*/
|
|
int QOpenGLTexture::mipBaseLevel() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->baseLevel;
|
|
}
|
|
|
|
/*!
|
|
Sets the maximum mipmap level used for all texture lookups with this texture to \a maxLevel.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa mipMaxLevel(), setMipBaseLevel(), setMipLevelRange()
|
|
*/
|
|
void QOpenGLTexture::setMipMaxLevel(int maxLevel)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (!d->features.testFlag(TextureMipMapLevel)) {
|
|
qWarning("QOpenGLTexture::setMipMaxLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
|
|
return;
|
|
}
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->baseLevel <= maxLevel);
|
|
d->maxLevel = maxLevel;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
|
|
}
|
|
|
|
/*!
|
|
Returns the mipmap maximum level used for all texture lookups with this texture.
|
|
|
|
\sa setMipMaxLevel(), mipBaseLevel(), mipLevelRange()
|
|
*/
|
|
int QOpenGLTexture::mipMaxLevel() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->maxLevel;
|
|
}
|
|
|
|
/*!
|
|
Sets the range of mipmap levels that can be used for texture lookups with this texture
|
|
to range from \a baseLevel to \a maxLevel.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa setMipBaseLevel(), setMipMaxLevel(), mipLevelRange()
|
|
*/
|
|
void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (!d->features.testFlag(TextureMipMapLevel)) {
|
|
qWarning("QOpenGLTexture::setMipLevelRange: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
|
|
return;
|
|
}
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(baseLevel <= maxLevel);
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
|
|
}
|
|
|
|
/*!
|
|
Returns the range of mipmap levels that can be used for texture lookups with this texture.
|
|
|
|
\sa mipBaseLevel(), mipMaxLevel()
|
|
*/
|
|
QPair<int, int> QOpenGLTexture::mipLevelRange() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return qMakePair(d->baseLevel, d->maxLevel);
|
|
}
|
|
|
|
/*!
|
|
If \a enabled is \c true, enables automatic mipmap generation for this texture object
|
|
to occur whenever the level 0 mipmap data is set via setData().
|
|
|
|
The automatic mipmap generation is enabled by default.
|
|
|
|
\note Mipmap generation is not supported for compressed textures with OpenGL ES 2.0.
|
|
|
|
\sa isAutoMipMapGenerationEnabled(), generateMipMaps()
|
|
*/
|
|
void QOpenGLTexture::setAutoMipMapGenerationEnabled(bool enabled)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->autoGenerateMipMaps = enabled;
|
|
}
|
|
|
|
/*!
|
|
Returns whether auto mipmap generation is enabled for this texture object.
|
|
|
|
\sa setAutoMipMapGenerationEnabled(), generateMipMaps()
|
|
*/
|
|
bool QOpenGLTexture::isAutoMipMapGenerationEnabled() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->autoGenerateMipMaps;
|
|
}
|
|
|
|
/*!
|
|
Generates mipmaps for this texture object from mipmap level 0. If you are
|
|
using a texture target and filtering option that requires mipmaps and you
|
|
have disabled automatic mipmap generation then you need to call this function
|
|
or the overload to create the mipmap chain.
|
|
|
|
\note Mipmap generation is not supported for compressed textures with OpenGL ES.
|
|
|
|
\sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
|
|
*/
|
|
void QOpenGLTexture::generateMipMaps()
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (isCompressedFormat(d->format)) {
|
|
if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
|
|
if (ctx->isOpenGLES())
|
|
return;
|
|
}
|
|
d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
|
|
}
|
|
|
|
/*!
|
|
Generates mipmaps for this texture object from mipmap level \a baseLevel. If you are
|
|
using a texture target and filtering option that requires mipmaps and you
|
|
have disabled automatic mipmap generation then you need to call this function
|
|
or the overload to create the mipmap chain.
|
|
|
|
The generation of mipmaps to above \a baseLevel is achieved by setting the mipmap
|
|
base level to \a baseLevel and then generating the mipmap chain. If \a resetBaseLevel
|
|
is \c true, then the baseLevel of the texture will be reset to its previous value.
|
|
|
|
\sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
|
|
*/
|
|
void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (isCompressedFormat(d->format)) {
|
|
if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
|
|
if (ctx->isOpenGLES())
|
|
return;
|
|
}
|
|
int oldBaseLevel;
|
|
if (resetBaseLevel)
|
|
oldBaseLevel = mipBaseLevel();
|
|
setMipBaseLevel(baseLevel);
|
|
d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
|
|
if (resetBaseLevel)
|
|
setMipBaseLevel(oldBaseLevel);
|
|
}
|
|
|
|
/*!
|
|
GLSL shaders are able to reorder the components of the vec4 returned by texture
|
|
functions. It is also desirable to be able to control this reordering from CPU
|
|
side code. This is made possible by swizzle masks since OpenGL 3.3.
|
|
|
|
Each component of the texture can be mapped to one of the SwizzleValue options.
|
|
|
|
This function maps \a component to the output \a value.
|
|
|
|
\note This function has no effect on Mac and Qt built for OpenGL ES 2.
|
|
\sa swizzleMask()
|
|
*/
|
|
void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue value)
|
|
{
|
|
#if !defined(Q_OS_MAC) && !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (!d->features.testFlag(Swizzle)) {
|
|
qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
|
|
return;
|
|
}
|
|
d->swizzleMask[component - SwizzleRed] = value;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, component, value);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(component);
|
|
Q_UNUSED(value);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Texture swizzling is not supported");
|
|
}
|
|
|
|
/*!
|
|
Parameters \a {r}, \a {g}, \a {b}, and \a {a} are values used for setting
|
|
the colors red, green, blue, and the alpha value.
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g,
|
|
SwizzleValue b, SwizzleValue a)
|
|
{
|
|
#if !defined(Q_OS_MAC) && !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (!d->features.testFlag(Swizzle)) {
|
|
qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
|
|
return;
|
|
}
|
|
GLint swizzleMask[] = {GLint(r), GLint(g), GLint(b), GLint(a)};
|
|
d->swizzleMask[0] = r;
|
|
d->swizzleMask[1] = g;
|
|
d->swizzleMask[2] = b;
|
|
d->swizzleMask[3] = a;
|
|
d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(r);
|
|
Q_UNUSED(g);
|
|
Q_UNUSED(b);
|
|
Q_UNUSED(a);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Texture swizzling is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the swizzle mask for texture \a component.
|
|
*/
|
|
QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent component) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->swizzleMask[component - SwizzleRed];
|
|
}
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::DepthStencilMode
|
|
\since 5.4
|
|
This enum specifies which component of a depth/stencil texture is
|
|
accessed when the texture is sampled.
|
|
|
|
\value DepthMode Equivalent to GL_DEPTH_COMPONENT.
|
|
\value StencilMode Equivalent to GL_STENCIL_INDEX.
|
|
*/
|
|
|
|
/*!
|
|
If using a texture that has a combined depth/stencil format this function sets
|
|
which component of the texture is accessed to \a mode.
|
|
|
|
When the parameter is set to DepthMode, then accessing it from the
|
|
shader will access the depth component as a single float, as normal. But when
|
|
the parameter is set to StencilMode, the shader will access the stencil component.
|
|
|
|
\note This function has no effect on Mac and Qt built for OpenGL ES 2.
|
|
\since 5.4
|
|
\sa depthStencilMode()
|
|
*/
|
|
void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode)
|
|
{
|
|
#if !defined(Q_OS_MAC) && !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (!d->features.testFlag(StencilTexturing)) {
|
|
qWarning("QOpenGLTexture::setDepthStencilMode() requires OpenGL >= 4.3 or GL_ARB_stencil_texturing");
|
|
return;
|
|
}
|
|
d->depthStencilMode = mode;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_DEPTH_STENCIL_TEXTURE_MODE, mode);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(mode);
|
|
#endif
|
|
qWarning("QOpenGLTexture: DepthStencil Mode is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the depth stencil mode for textures using a combined depth/stencil format.
|
|
|
|
\since 5.4
|
|
\sa setDepthStencilMode()
|
|
*/
|
|
QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->depthStencilMode;
|
|
}
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::ComparisonFunction
|
|
\since 5.5
|
|
This enum specifies which comparison operator is used when texture comparison
|
|
is enabled on this texture.
|
|
|
|
\value CompareLessEqual Equivalent to GL_LEQUAL.
|
|
\value CompareGreaterEqual Equivalent to GL_GEQUAL.
|
|
\value CompareLess Equivalent to GL_LESS.
|
|
\value CompareGreater Equivalent to GL_GREATER.
|
|
\value CompareEqual Equivalent to GL_EQUAL.
|
|
\value CompareNotEqual Equivalent to GL_NOTEQUAL.
|
|
\value CompareAlways Equivalent to GL_ALWAYS.
|
|
\value CompareNever Equivalent to GL_NEVER.
|
|
|
|
\omitvalue CommpareNotEqual
|
|
*/
|
|
|
|
/*!
|
|
\since 5.5
|
|
|
|
Sets the texture comparison function on this texture to \a function. The texture
|
|
comparison function is used by shadow samplers when sampling a depth texture.
|
|
|
|
\sa comparisonFunction()
|
|
*/
|
|
void QOpenGLTexture::setComparisonFunction(QOpenGLTexture::ComparisonFunction function)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (!d->features.testFlag(TextureComparisonOperators)) {
|
|
qWarning("QOpenGLTexture::setComparisonFunction: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
|
|
return;
|
|
}
|
|
d->comparisonFunction = function;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_FUNC, function);
|
|
}
|
|
|
|
/*!
|
|
\since 5.5
|
|
|
|
Returns the texture comparison operator set on this texture. By default, a
|
|
texture has a CompareLessEqual comparison function.
|
|
|
|
\sa setComparisonFunction()
|
|
*/
|
|
QOpenGLTexture::ComparisonFunction QOpenGLTexture::comparisonFunction() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->comparisonFunction;
|
|
}
|
|
|
|
/*!
|
|
\enum QOpenGLTexture::ComparisonMode
|
|
\since 5.5
|
|
This enum specifies which comparison mode is used when sampling this texture.
|
|
|
|
\value CompareRefToTexture Equivalent to GL_COMPARE_REF_TO_TEXTURE.
|
|
\value CompareNone Equivalent to GL_NONE.
|
|
*/
|
|
|
|
/*!
|
|
\since 5.5
|
|
|
|
Sets the texture comparison mode on this texture to \a mode. The texture
|
|
comparison mode is used by shadow samplers when sampling a depth texture.
|
|
|
|
\sa comparisonMode()
|
|
*/
|
|
void QOpenGLTexture::setComparisonMode(QOpenGLTexture::ComparisonMode mode)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
if (!d->features.testFlag(TextureComparisonOperators)) {
|
|
qWarning("QOpenGLTexture::setComparisonMode: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
|
|
return;
|
|
}
|
|
d->comparisonMode = mode;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_MODE, mode);
|
|
}
|
|
|
|
/*!
|
|
\since 5.5
|
|
|
|
Returns the texture comparison mode set on this texture. By default, a
|
|
texture has a CompareNone comparison mode (i.e. comparisons are disabled).
|
|
|
|
\sa setComparisonMode()
|
|
*/
|
|
QOpenGLTexture::ComparisonMode QOpenGLTexture::comparisonMode() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->comparisonMode;
|
|
}
|
|
|
|
/*!
|
|
Sets the filter used for minification to \a filter.
|
|
|
|
\sa minificationFilter(), setMagnificationFilter(), setMinMagFilters()
|
|
*/
|
|
void QOpenGLTexture::setMinificationFilter(QOpenGLTexture::Filter filter)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->minFilter = filter;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
}
|
|
|
|
/*!
|
|
Returns the minification filter.
|
|
|
|
\sa setMinificationFilter()
|
|
*/
|
|
QOpenGLTexture::Filter QOpenGLTexture::minificationFilter() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->minFilter;
|
|
}
|
|
|
|
/*!
|
|
Sets the magnification filter to \a filter.
|
|
|
|
\sa magnificationFilter(), setMinificationFilter(), setMinMagFilters()
|
|
*/
|
|
void QOpenGLTexture::setMagnificationFilter(QOpenGLTexture::Filter filter)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->magFilter = filter;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
}
|
|
|
|
/*!
|
|
Returns the magnification filter.
|
|
|
|
\sa setMagnificationFilter()
|
|
*/
|
|
QOpenGLTexture::Filter QOpenGLTexture::magnificationFilter() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->magFilter;
|
|
}
|
|
|
|
/*!
|
|
Sets the minification filter to \a minificationFilter and the magnification filter
|
|
to \a magnificationFilter.
|
|
|
|
\sa minMagFilters(), setMinificationFilter(), setMagnificationFilter()
|
|
*/
|
|
void QOpenGLTexture::setMinMagFilters(QOpenGLTexture::Filter minificationFilter,
|
|
QOpenGLTexture::Filter magnificationFilter)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->minFilter = minificationFilter;
|
|
d->magFilter = magnificationFilter;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, minificationFilter);
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, magnificationFilter);
|
|
}
|
|
|
|
/*!
|
|
Returns the current minification and magnification filters.
|
|
|
|
\sa setMinMagFilters()
|
|
*/
|
|
QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter> QOpenGLTexture::minMagFilters() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter>(d->minFilter, d->magFilter);
|
|
}
|
|
|
|
/*!
|
|
If your OpenGL implementation supports the GL_EXT_texture_filter_anisotropic extension
|
|
this function sets the maximum anisotropy level to \a anisotropy.
|
|
|
|
\sa maximumAnisotropy()
|
|
*/
|
|
void QOpenGLTexture::setMaximumAnisotropy(float anisotropy)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
if (!d->features.testFlag(AnisotropicFiltering)) {
|
|
qWarning("QOpenGLTexture::setMaximumAnisotropy() requires GL_EXT_texture_filter_anisotropic");
|
|
return;
|
|
}
|
|
d->maxAnisotropy = anisotropy;
|
|
d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
|
|
}
|
|
|
|
/*!
|
|
Returns the maximum level of anisotropy to be accounted for when performing texture lookups.
|
|
This requires the GL_EXT_texture_filter_anisotropic extension.
|
|
|
|
\sa setMaximumAnisotropy()
|
|
*/
|
|
float QOpenGLTexture::maximumAnisotropy() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->maxAnisotropy;
|
|
}
|
|
|
|
/*!
|
|
Sets the wrap (or repeat mode) for all texture dimentions to \a mode.
|
|
|
|
\sa wrapMode()
|
|
*/
|
|
void QOpenGLTexture::setWrapMode(QOpenGLTexture::WrapMode mode)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->setWrapMode(mode);
|
|
}
|
|
|
|
/*!
|
|
Holds the texture dimension \a direction.
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
|
|
{
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->setWrapMode(direction, mode);
|
|
}
|
|
|
|
/*!
|
|
Returns the wrap mode for the texture dimension \a direction.
|
|
|
|
\sa setWrapMode()
|
|
*/
|
|
QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->wrapMode(direction);
|
|
}
|
|
|
|
/*!
|
|
Sets the border color of the texture to \a color.
|
|
|
|
\note This function has no effect on Mac and Qt built for OpenGL ES 2.
|
|
\sa borderColor()
|
|
*/
|
|
void QOpenGLTexture::setBorderColor(const QColor &color)
|
|
{
|
|
setBorderColor(static_cast<float>(color.redF()), static_cast<float>(color.greenF()),
|
|
static_cast<float>(color.blueF()), static_cast<float>(color.alphaF()));
|
|
}
|
|
|
|
/*!
|
|
Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and \a {a} to the
|
|
alpha value.
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setBorderColor(float r, float g, float b, float a)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
float values[4];
|
|
values[0] = r;
|
|
values[1] = g;
|
|
values[2] = b;
|
|
values[3] = a;
|
|
d->borderColor.clear();
|
|
for (int i = 0; i < 4; ++i)
|
|
d->borderColor.append(QVariant(values[i]));
|
|
d->texFuncs->glTextureParameterfv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(r);
|
|
Q_UNUSED(g);
|
|
Q_UNUSED(b);
|
|
Q_UNUSED(a);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Border color is not supported");
|
|
}
|
|
|
|
/*!
|
|
Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
|
|
value to \a {a}.
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setBorderColor(int r, int g, int b, int a)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
int values[4];
|
|
values[0] = r;
|
|
values[1] = g;
|
|
values[2] = b;
|
|
values[3] = a;
|
|
d->borderColor.clear();
|
|
for (int i = 0; i < 4; ++i)
|
|
d->borderColor.append(QVariant(values[i]));
|
|
d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(r);
|
|
Q_UNUSED(g);
|
|
Q_UNUSED(b);
|
|
Q_UNUSED(a);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Border color is not supported");
|
|
|
|
// TODO Handle case of using glTextureParameterIiv() based on format
|
|
}
|
|
|
|
/*!
|
|
Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
|
|
value to \a {a}.
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
int values[4];
|
|
values[0] = int(r);
|
|
values[1] = int(g);
|
|
values[2] = int(b);
|
|
values[3] = int(a);
|
|
d->borderColor.clear();
|
|
for (int i = 0; i < 4; ++i)
|
|
d->borderColor.append(QVariant(values[i]));
|
|
d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(r);
|
|
Q_UNUSED(g);
|
|
Q_UNUSED(b);
|
|
Q_UNUSED(a);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Border color is not supported");
|
|
|
|
// TODO Handle case of using glTextureParameterIuiv() based on format
|
|
}
|
|
|
|
/*!
|
|
Returns the borderColor of this texture.
|
|
|
|
\sa setBorderColor()
|
|
*/
|
|
QColor QOpenGLTexture::borderColor() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
QColor c(0.0f, 0.0f, 0.0f, 0.0f);
|
|
if (!d->borderColor.isEmpty()) {
|
|
c.setRedF(d->borderColor.at(0).toFloat());
|
|
c.setGreenF(d->borderColor.at(1).toFloat());
|
|
c.setBlueF(d->borderColor.at(2).toFloat());
|
|
c.setAlphaF(d->borderColor.at(3).toFloat());
|
|
}
|
|
return c;
|
|
}
|
|
|
|
/*!
|
|
Writes the texture border color into the first four elements
|
|
of the array pointed to by \a border.
|
|
|
|
\sa setBorderColor()
|
|
*/
|
|
void QOpenGLTexture::borderColor(float *border) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(border);
|
|
if (d->borderColor.isEmpty()) {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = 0.0f;
|
|
} else {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = d->borderColor.at(i).toFloat();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Writes the texture border color into the first four elements
|
|
of the array pointed to by \a border.
|
|
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::borderColor(int *border) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(border);
|
|
if (d->borderColor.isEmpty()) {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = 0;
|
|
} else {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = d->borderColor.at(i).toInt();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Writes the texture border color into the first four elements
|
|
of the array pointed to by \a border.
|
|
|
|
\overload
|
|
*/
|
|
void QOpenGLTexture::borderColor(unsigned int *border) const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
Q_ASSERT(border);
|
|
if (d->borderColor.isEmpty()) {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = 0;
|
|
} else {
|
|
for (int i = 0; i < 4; ++i)
|
|
border[i] = d->borderColor.at(i).toUInt();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Sets the minimum level of detail to \a value. This limits the selection of highest
|
|
resolution mipmap (lowest mipmap level). The default value is -1000.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa minimumLevelOfDetail(), setMaximumLevelOfDetail(), setLevelOfDetailRange()
|
|
*/
|
|
void QOpenGLTexture::setMinimumLevelOfDetail(float value)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(value < d->maxLevelOfDetail);
|
|
d->minLevelOfDetail = value;
|
|
d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, value);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(value);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Detail level is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the minimum level of detail parameter.
|
|
|
|
\sa setMinimumLevelOfDetail(), maximumLevelOfDetail(), levelOfDetailRange()
|
|
*/
|
|
float QOpenGLTexture::minimumLevelOfDetail() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->minLevelOfDetail;
|
|
}
|
|
|
|
/*!
|
|
Sets the maximum level of detail to \a value. This limits the selection of lowest
|
|
resolution mipmap (highest mipmap level). The default value is 1000.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa maximumLevelOfDetail(), setMinimumLevelOfDetail(), setLevelOfDetailRange()
|
|
*/
|
|
void QOpenGLTexture::setMaximumLevelOfDetail(float value)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(value > d->minLevelOfDetail);
|
|
d->maxLevelOfDetail = value;
|
|
d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, value);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(value);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Detail level is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the maximum level of detail parameter.
|
|
|
|
\sa setMaximumLevelOfDetail(), minimumLevelOfDetail(), levelOfDetailRange()
|
|
*/
|
|
float QOpenGLTexture::maximumLevelOfDetail() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->maxLevelOfDetail;
|
|
}
|
|
|
|
/*!
|
|
Sets the minimum level of detail parameters to \a min and the maximum level
|
|
to \a max.
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa levelOfDetailRange(), setMinimumLevelOfDetail(), setMaximumLevelOfDetail()
|
|
*/
|
|
void QOpenGLTexture::setLevelOfDetailRange(float min, float max)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
Q_ASSERT(min < max);
|
|
d->minLevelOfDetail = min;
|
|
d->maxLevelOfDetail = max;
|
|
d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, min);
|
|
d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, max);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(min);
|
|
Q_UNUSED(max);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Detail level is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the minimum and maximum level of detail parameters.
|
|
|
|
\sa setLevelOfDetailRange(), minimumLevelOfDetail(), maximumLevelOfDetail()
|
|
*/
|
|
QPair<float, float> QOpenGLTexture::levelOfDetailRange() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return qMakePair(d->minLevelOfDetail, d->maxLevelOfDetail);
|
|
}
|
|
|
|
/*!
|
|
Sets the level of detail bias to \a bias.
|
|
Level of detail bias affects the point at which mipmapping levels change.
|
|
Increasing values for level of detail bias makes the overall images blurrier
|
|
or smoother. Decreasing values make the overall images sharper.
|
|
|
|
\note This function has no effect on Qt built for OpenGL ES 2.
|
|
\sa levelofDetailBias()
|
|
*/
|
|
void QOpenGLTexture::setLevelofDetailBias(float bias)
|
|
{
|
|
#if !QT_CONFIG(opengles2)
|
|
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
|
Q_D(QOpenGLTexture);
|
|
d->create();
|
|
Q_ASSERT(d->texFuncs);
|
|
Q_ASSERT(d->textureId);
|
|
d->levelOfDetailBias = bias;
|
|
d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_LOD_BIAS, bias);
|
|
return;
|
|
}
|
|
#else
|
|
Q_UNUSED(bias);
|
|
#endif
|
|
qWarning("QOpenGLTexture: Detail level is not supported");
|
|
}
|
|
|
|
/*!
|
|
Returns the level of detail bias parameter.
|
|
|
|
\sa setLevelofDetailBias()
|
|
*/
|
|
float QOpenGLTexture::levelofDetailBias() const
|
|
{
|
|
Q_D(const QOpenGLTexture);
|
|
return d->levelOfDetailBias;
|
|
}
|
|
|
|
#ifndef QT_NO_DEBUG_STREAM
|
|
QDebug operator<<(QDebug debug, const QOpenGLTexture *t)
|
|
{
|
|
QDebugStateSaver saver(debug);
|
|
debug.nospace();
|
|
debug << "QOpenGLTexture(";
|
|
if (t) {
|
|
const QOpenGLTexturePrivate *d = t->d_ptr.data();
|
|
debug << d->target << ", bindingTarget=" << d->bindingTarget
|
|
<< ", size=[" << d->dimensions[0]
|
|
<< ", " << d->dimensions[1];
|
|
if (d->target == QOpenGLTexture::Target3D)
|
|
debug << ", " << d->dimensions[2];
|
|
debug << "], format=" << d->format << ", formatClass=" << d->formatClass;
|
|
if (t->isCreated())
|
|
debug << ", textureId=" << d->textureId;
|
|
if (t->isBound())
|
|
debug << ", [bound]";
|
|
if (t->isTextureView())
|
|
debug << ", [view]";
|
|
if (d->fixedSamplePositions)
|
|
debug << ", [fixedSamplePositions]";
|
|
debug << ", mipLevels=" << d->requestedMipLevels << ", layers=" << d->layers
|
|
<< ", faces=" << d->faces << ", samples=" << d->samples
|
|
<< ", depthStencilMode=" << d->depthStencilMode << ", comparisonFunction="
|
|
<< d->comparisonFunction << ", comparisonMode=" << d->comparisonMode
|
|
<< ", features=" << d->features << ", minificationFilter=" << d->minFilter
|
|
<< ", magnificationFilter=" << d->magFilter << ", wrapMode=" << d->wrapModes[0];
|
|
} else {
|
|
debug << '0';
|
|
}
|
|
debug << ')';
|
|
return debug;
|
|
}
|
|
#endif // QT_NO_DEBUG_STREAM
|
|
|
|
QT_END_NAMESPACE
|