diff options
Diffstat (limited to 'src/gui/opengl/qopengltexture.cpp')
-rw-r--r-- | src/gui/opengl/qopengltexture.cpp | 601 |
1 files changed, 572 insertions, 29 deletions
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index b96bc6f346..903cfb2bf8 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -64,6 +64,8 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge baseLevel(0), maxLevel(1000), depthStencilMode(QOpenGLTexture::DepthMode), + comparisonFunction(QOpenGLTexture::CompareLessEqual), + comparisonMode(QOpenGLTexture::CompareNone), minFilter(QOpenGLTexture::Nearest), magFilter(QOpenGLTexture::Nearest), maxAnisotropy(1.0f), @@ -294,16 +296,166 @@ int QOpenGLTexturePrivate::evaluateMipLevels() const } } -void QOpenGLTexturePrivate::allocateStorage() +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: + 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; +} + +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; +} + +void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType) { // Resolve the actual number of mipmap levels we can use mipLevels = evaluateMipLevels(); - // Use immutable storage whenever possible, falling back to mutable when not available - if (features.testFlag(QOpenGLTexture::ImmutableStorage)) + // 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 + const bool useImmutableStorage = isSizedTextureFormat(format) + && (isTextureTargetMultisample(target) + ? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage) + : features.testFlag(QOpenGLTexture::ImmutableStorage)); + + if (useImmutableStorage) allocateImmutableStorage(); else - allocateMutableStorage(); + allocateMutableStorage(pixelFormat, pixelType); } static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat) @@ -313,59 +465,167 @@ static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpen 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; @@ -402,6 +662,26 @@ static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpen case QOpenGLTexture::SRGB_BP_UNorm: 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::DepthFormat: return QOpenGLTexture::Depth; @@ -437,6 +717,8 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe 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: @@ -445,6 +727,8 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe case QOpenGLTexture::RG16_SNorm: case QOpenGLTexture::RGB16_SNorm: case QOpenGLTexture::RGBA16_SNorm: + return QOpenGLTexture::Int8; + case QOpenGLTexture::R8U: case QOpenGLTexture::RG8U: case QOpenGLTexture::RGB8U: @@ -457,6 +741,8 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe case QOpenGLTexture::RG32U: case QOpenGLTexture::RGB32U: case QOpenGLTexture::RGBA32U: + return QOpenGLTexture::UInt8; + case QOpenGLTexture::R8I: case QOpenGLTexture::RG8I: case QOpenGLTexture::RGB8I: @@ -469,28 +755,50 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe 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::UInt8; + return QOpenGLTexture::UInt32_RGB10A2; case QOpenGLTexture::D16: + return QOpenGLTexture::UInt16; + case QOpenGLTexture::D24: case QOpenGLTexture::D32: + return QOpenGLTexture::UInt32; + case QOpenGLTexture::D32F: - return QOpenGLTexture::UInt8; + return QOpenGLTexture::Float32; case QOpenGLTexture::D24S8: return QOpenGLTexture::UInt32_D24S8; @@ -519,6 +827,16 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe 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: return QOpenGLTexture::UInt8; case QOpenGLTexture::DepthFormat: @@ -534,11 +852,8 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe return QOpenGLTexture::NoPixelType; } -void QOpenGLTexturePrivate::allocateMutableStorage() +void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType) { - const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(format); - const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(format); - switch (target) { case QOpenGLTexture::TargetBuffer: // Buffer textures get their storage from an external OpenGL buffer @@ -747,7 +1062,7 @@ void QOpenGLTexturePrivate::allocateImmutableStorage() break; case QOpenGLTexture::Target2DMultisample: - if (features.testFlag(QOpenGLTexture::TextureMultisample)) { + if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) { texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format, dimensions[0], dimensions[1], fixedSamplePositions); @@ -758,7 +1073,7 @@ void QOpenGLTexturePrivate::allocateImmutableStorage() break; case QOpenGLTexture::Target2DMultisampleArray: - if (features.testFlag(QOpenGLTexture::TextureMultisample) + if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage) && features.testFlag(QOpenGLTexture::TextureArrays)) { texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format, dimensions[0], dimensions[1], layers, @@ -1525,6 +1840,16 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target \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 SRGB8 Equivalent to GL_SRGB8 \value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8 @@ -2050,6 +2375,16 @@ void QOpenGLTexture::setFormat(TextureFormat format) 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 RG3B2: case R5G6B5: case RGB5A1: @@ -2436,17 +2771,58 @@ bool QOpenGLTexture::isFixedSamplePositions() const 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()) { - d->allocateStorage(); + 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. @@ -2547,7 +2923,7 @@ void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace, Q_ASSERT(d->textureId); if (!isStorageAllocated()) { qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocate() before this function"); + "To do so call allocateStorage() before this function"); return; } d->setData(mipLevel, layer, cubeFace, sourceFormat, sourceType, data, options); @@ -2606,7 +2982,7 @@ void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace, Q_ASSERT(d->textureId); if (!isStorageAllocated()) { qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocate() before this function"); + "To do so call allocateStorage() before this function"); return; } d->setData(mipLevel, layer, cubeFace, sourceFormat, sourceType, data, options); @@ -2672,7 +3048,7 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps) setSize(image.width(), image.height()); setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1); - allocateStorage(); + allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); // Upload pixel data and generate mipmaps QImage glImage = image.convertToFormat(QImage::Format_RGBA8888); @@ -2699,7 +3075,7 @@ void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cube Q_ASSERT(d->textureId); if (!isStorageAllocated()) { qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocate() before this function"); + "To do so call allocateStorage() before this function"); return; } d->setCompressedData(mipLevel, layer, cubeFace, dataSize, data, options); @@ -2751,7 +3127,7 @@ void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cube Q_ASSERT(d->textureId); if (!isStorageAllocated()) { qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocate() before this function"); + "To do so call allocateStorage() before this function"); return; } d->setCompressedData(mipLevel, layer, cubeFace, dataSize, data, options); @@ -2830,7 +3206,8 @@ bool QOpenGLTexture::hasFeature(Feature feature) case ImmutableStorage: supported = f.version() >= qMakePair(4, 2) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage")); + || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage")) + || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")); break; case TextureCubeMapArrays: @@ -2875,10 +3252,17 @@ bool QOpenGLTexture::hasFeature(Feature feature) supported = f.version() >= qMakePair(1, 1); break; - case MaxFeatureFlag: + 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; - default: + case MaxFeatureFlag: break; } } @@ -2887,21 +3271,64 @@ bool QOpenGLTexture::hasFeature(Feature feature) #endif { switch (feature) { + case ImmutableStorage: + supported = f.version() >= qMakePair(3, 0) + || ctx->hasExtension(QByteArrayLiteral("EXT_texture_storage")); + 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 = ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D")); + 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); - if (!supported) { - supported = ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot")); - if (!supported) - supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two")); - } - default: + 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 MaxFeatureFlag: break; } } @@ -3167,6 +3594,16 @@ QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent compon } /*! + \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. @@ -3175,6 +3612,7 @@ QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent compon 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) @@ -3202,6 +3640,7 @@ void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode) /*! Returns the depth stencil mode for textures using a combined depth/stencil format. + \since 5.4 \sa setDepthStencilMode() */ QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const @@ -3211,6 +3650,110 @@ QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const } /*! + \enum 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 CommpareNotEqual Equivalent to GL_NOTEQUAL. + \value CompareAlways Equivalent to GL_ALWAYS. + \value CompareNever Equivalent to GL_NEVER. + +*/ + +/* + \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) +{ +#if !defined(QT_OPENGL_ES_2) + 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); +#else + Q_UNUSED(function); + qWarning("QOpenGLTexture: texture comparison functions are not supported"); +#endif +} + +/*! + \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) +{ +#if !defined(QT_OPENGL_ES_2) + 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); +#else + Q_UNUSED(mode); + qWarning("QOpenGLTexture: texture comparison modes are not supported"); +#endif +} + +/*! + \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() |