blob: 28d296febbf268af7367b49ba503c0f7bbd14b09 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D 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 "qtextureimagedata_p.h"
#include <QDebug>
#include <QFileInfo>
#include <QFile>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
QTextureImageDataPrivate::QTextureImageDataPrivate()
: m_width(-1)
, m_height(-1)
, m_depth(-1)
, m_layers(-1)
, m_faces(-1)
, m_mipLevels(-1)
, m_blockSize(-1)
, m_target(QOpenGLTexture::Target2D)
, m_format(QOpenGLTexture::NoFormat)
, m_pixelFormat(QOpenGLTexture::RGBA)
, m_pixelType(QOpenGLTexture::UInt8)
, m_isCompressed(false)
, m_isKtx(false)
{
}
QByteArray QTextureImageDataPrivate::ktxData(int layer, int face, int mipmapLevel) const
{
Q_ASSERT(layer >= 0 && layer < m_layers &&
face >= 0 && face < m_faces &&
mipmapLevel >= 0 && mipmapLevel < m_mipLevels);
int offset = 0;
for (int i = 0; i < mipmapLevel; i++)
offset += (mipmapLevelSize(i) * m_faces * m_layers) + 4;
const int selectedMipmapLevelSize = mipmapLevelSize(mipmapLevel);
offset += (selectedMipmapLevelSize * m_faces * layer) + (selectedMipmapLevelSize * face) + 4;
return QByteArray::fromRawData(m_data.constData() + offset, selectedMipmapLevelSize);
}
QByteArray QTextureImageDataPrivate::data(int layer, int face, int mipmapLevel) const
{
if (layer < 0 || layer >= m_layers ||
face < 0 || face >= m_faces ||
mipmapLevel < 0 || mipmapLevel >= m_mipLevels) {
qWarning() << Q_FUNC_INFO << "Requesting texture data for invalid layer, face or mipMapLevel";
return QByteArray();
}
if (m_isKtx)
return ktxData(layer, face, mipmapLevel);
int offset = layer * ddsLayerSize() + face * ddsFaceSize();
for (int i = 0; i < mipmapLevel; i++)
offset += mipmapLevelSize(i);
return QByteArray::fromRawData(m_data.constData() + offset, mipmapLevelSize(mipmapLevel));
}
QTextureImageDataPrivate *QTextureImageDataPrivate::get(QTextureImageData *imageData)
{
return imageData->d_func();
}
void QTextureImageDataPrivate::setData(const QByteArray &data,
int blockSize,
bool isCompressed)
{
m_isCompressed = isCompressed;
m_data = data;
m_blockSize = blockSize;
}
int QTextureImageDataPrivate::ddsLayerSize() const
{
return m_faces * ddsFaceSize();
}
int QTextureImageDataPrivate::ddsFaceSize() const
{
int size = 0;
for (int i = 0; i < m_mipLevels; i++)
size += mipmapLevelSize(i);
return size;
}
// XXX check if this works for ETC1 compression
int QTextureImageDataPrivate::mipmapLevelSize(int level) const
{
int w = qMax(m_width >> level, 1);
int h = qMax(m_height >> level, 1);
int d = qMax(m_depth >> level, 1);
if (m_isCompressed)
return ((w + 3) / 4) * ((h + 3) / 4) * m_blockSize * d;
else
return w * h * m_blockSize * d;
}
/*!
\class Qt3DRender::QTextureImageData
\inmodule Qt3DRender
\since 5.5
\brief QTextureImageData stores data representing a texture.
*/
/*!
Constructs a new Qt3DRender::QTextureImageData.
*/
QTextureImageData::QTextureImageData()
: d_ptr(new QTextureImageDataPrivate())
{
}
/*! \internal */
QTextureImageData::QTextureImageData(QTextureImageDataPrivate &dd)
: d_ptr(&dd)
{
}
/*! \internal */
QTextureImageData::~QTextureImageData()
{
cleanup();
delete d_ptr;
}
QTextureImageData &QTextureImageData::operator=(const QTextureImageData &other)
{
Q_D(QTextureImageData);
*d = *other.d_ptr;
return *this;
}
/*!
Remove stored texture data and return the object to its initial state
*/
void QTextureImageData::cleanup() Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_width = -1;
d->m_height = -1;
d->m_depth = -1;
d->m_layers = -1;
d->m_faces = -1;
d->m_mipLevels = -1;
d->m_blockSize = 0;
d->m_isCompressed = false;
d->m_data.clear();
}
/*!
\return true if the stored texture is in a compressed format
*/
bool QTextureImageData::isCompressed() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_isCompressed;
}
/*!
\return the width of the stored texture
*/
int QTextureImageData::width() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_width;
}
/*!
\return the height of the stored texture
*/
int QTextureImageData::height() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_height;
}
/*!
\return the depth of the stored texture
*/
int QTextureImageData::depth() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_depth;
}
/*!
\return the number of layers in the stored texture
*/
int QTextureImageData::layers() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_layers;
}
/*!
\return the number of mip levels in the stored texture
*/
int QTextureImageData::mipLevels() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_mipLevels;
}
/*!
\return the number of faces in the stored texture
*/
int QTextureImageData::faces() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_faces;;
}
/*!
* Sets the width to \a width.
* \param setWidth
*/
void QTextureImageData::setWidth(int width) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_width = width;
}
/*!
* Sets the height to \a height.
* \param setHeight
*/
void QTextureImageData::setHeight(int height) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_height = height;
}
/*!
* Sets the depth to \a depth.
* \param setDepth
*/
void QTextureImageData::setDepth(int depth) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_depth = depth;
}
/*!
* Sets the layers to \a layers.
* \param setLayers
*/
void QTextureImageData::setLayers(int layers) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_layers = layers;
}
/*!
* Sets the mip levels to \a mipLevels.
* \param setMipLevels
*/
void QTextureImageData::setMipLevels(int mipLevels) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_mipLevels = mipLevels;
}
/*!
* Sets the faces to \a faces.
* \param setFaces
*/
void QTextureImageData::setFaces(int faces) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_faces = faces;
}
/*!
\return the target for the stored texture
*/
QOpenGLTexture::Target QTextureImageData::target() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_target;
}
/*!
\return the format of the stored texture
*/
QOpenGLTexture::TextureFormat QTextureImageData::format() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_format;
}
/*!
* Sets the target to \a target.
* \param target
*/
void QTextureImageData::setTarget(QOpenGLTexture::Target target) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_target = target;
}
/*!
* Sets the format to \a format.
* \param
*/
void QTextureImageData::setFormat(QOpenGLTexture::TextureFormat format) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_format = format;
}
/*!
* Sets the pixel format to \a pixelFormat.
* \param setPixelFormat
*/
void QTextureImageData::setPixelFormat(QOpenGLTexture::PixelFormat pixelFormat) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_pixelFormat = pixelFormat;
}
/*!
* Sets the pixel type to \a pixelType
* \param setPixelType
*/
void QTextureImageData::setPixelType(QOpenGLTexture::PixelType pixelType) Q_DECL_NOTHROW
{
Q_D(QTextureImageData);
d->m_pixelType = pixelType;
}
/*!
Copies the image \a image as raw data within this object
*/
void QTextureImageData::setImage(const QImage &image)
{
Q_D(QTextureImageData);
d->m_width = image.width();
d->m_height = image.height();
d->m_depth = 1;
d->m_faces = 1;
d->m_layers = 1;
d->m_mipLevels = 1;
QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
Q_ASSERT_X(glImage.bytesPerLine() == (glImage.width() * glImage.depth() + 7) / 8,
"QTextureImageData::setImage", "glImage is not packed"); // QTBUG-48330
d->m_blockSize = 4;
QByteArray imageBytes((const char*) glImage.constBits(), glImage.sizeInBytes());
setData(imageBytes, d->m_blockSize, false);
d->m_format = QOpenGLTexture::RGBA8_UNorm;
d->m_pixelFormat = QOpenGLTexture::RGBA;
d->m_pixelType = QOpenGLTexture::UInt8;
d->m_target = QOpenGLTexture::Target2D;
}
/*!
Store the data \a data with blocksize \a blockSize and if the data to be stored is compressed \a isCompressed
*/
void QTextureImageData::setData(const QByteArray &data, int blockSize, bool isCompressed)
{
Q_D(QTextureImageData);
d->setData(data, blockSize, isCompressed);
}
/*!
\return the raw image data for the texture at layer \a layer, face \a face and mipmapLevel \a mipmapLevel
*/
QByteArray QTextureImageData::data(int layer, int face, int mipmapLevel) const
{
Q_D(const QTextureImageData);
return d->data(layer, face, mipmapLevel);
}
/*!
\return the pixel format of the stored texture
*/
QOpenGLTexture::PixelFormat QTextureImageData::pixelFormat() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_pixelFormat;
}
/*!
\return the pixel type of the stored texture
*/
QOpenGLTexture::PixelType QTextureImageData::pixelType() const Q_DECL_NOTHROW
{
Q_D(const QTextureImageData);
return d->m_pixelType;
}
} // namespace Qt3DRender
QT_END_NAMESPACE