Skip to content

Commit

Permalink
Fix loading QRhiTexture from image on gles
Browse files Browse the repository at this point in the history
The code should consider that image may be created by
a pointer to user data, with original alignments.
It means that we the way of setting parameters from
raw data and QImage should be the same.

In Qt Multimedia we want to pass a zero-copy image
to rhi creation to get rid of an extra copy:
codereview.qt-project.org/c/qt/qtmultimedia/+/537062

Aslo, data align has been fixed.
Due to the documentation, GL_UNPACK_ALIGNMENT can
be 8, 4, 2, 1. Let's find the biggest possible align.

Task-number: QTBUG-121934
Pick-to: 6.7 6.6 6.5
Change-Id: Ic0f1617d4699217a7549c13e916be96108183d03
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
  • Loading branch information
Artemiy-d committed Feb 8, 2024
1 parent 1d799e9 commit 1d6bb23
Showing 1 changed file with 30 additions and 37 deletions.
67 changes: 30 additions & 37 deletions src/gui/rhi/qrhigles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2287,17 +2287,15 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
const QPoint dp = subresDesc.destinationTopLeft();
const QByteArray rawData = subresDesc.data();
if (!subresDesc.image().isNull()) {
QImage img = subresDesc.image();
QSize size = img.size();

auto setCmdByNotCompressedData = [&](const void* data, QSize size, quint32 dataStride)
{
quint32 bytesPerLine = 0;
quint32 bytesPerPixel = 0;
textureFormatInfo(texD->m_format, size, &bytesPerLine, nullptr, &bytesPerPixel);

QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::SubImage;
if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
const QPoint sp = subresDesc.sourceTopLeft();
if (!subresDesc.sourceSize().isEmpty())
size = subresDesc.sourceSize();
img = img.copy(sp.x(), sp.y(), size.width(), size.height());
}
cmd.args.subImage.target = texD->target;
cmd.args.subImage.texture = texD->texture;
cmd.args.subImage.faceTarget = effectiveTarget;
Expand All @@ -2309,9 +2307,27 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.subImage.h = size.height();
cmd.args.subImage.glformat = texD->glformat;
cmd.args.subImage.gltype = texD->gltype;
cmd.args.subImage.rowStartAlign = 4;
cmd.args.subImage.rowLength = 0;
cmd.args.subImage.data = cbD->retainImage(img);

if (dataStride == 0)
dataStride = bytesPerLine;

cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
cmd.args.subImage.rowLength = bytesPerPixel ? dataStride / bytesPerPixel : 0;

cmd.args.subImage.data = data;
};

if (!subresDesc.image().isNull()) {
QImage img = subresDesc.image();
QSize size = img.size();
if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
const QPoint sp = subresDesc.sourceTopLeft();
if (!subresDesc.sourceSize().isEmpty())
size = subresDesc.sourceSize();
img = img.copy(sp.x(), sp.y(), size.width(), size.height());
}

setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
} else if (!rawData.isEmpty() && isCompressed) {
const int depth = qMax(1, texD->m_depth);
const int arraySize = qMax(0, texD->m_arraySize);
Expand Down Expand Up @@ -2379,31 +2395,8 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
} else if (!rawData.isEmpty()) {
const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
: subresDesc.sourceSize();
quint32 bytesPerLine = 0;
quint32 bytesPerPixel = 0;
textureFormatInfo(texD->m_format, size, &bytesPerLine, nullptr, &bytesPerPixel);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::SubImage;
cmd.args.subImage.target = texD->target;
cmd.args.subImage.texture = texD->texture;
cmd.args.subImage.faceTarget = effectiveTarget;
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
cmd.args.subImage.dz = is3D || isArray ? layer : 0;
cmd.args.subImage.w = size.width();
cmd.args.subImage.h = size.height();
cmd.args.subImage.glformat = texD->glformat;
cmd.args.subImage.gltype = texD->gltype;
// Default unpack alignment (row start alignment
// requirement) is 4. QImage guarantees 4 byte aligned
// row starts, but our raw data here does not.
cmd.args.subImage.rowStartAlign = (bytesPerLine & 3) ? 1 : 4;
if (subresDesc.dataStride() && bytesPerPixel)
cmd.args.subImage.rowLength = subresDesc.dataStride() / bytesPerPixel;
else
cmd.args.subImage.rowLength = 0;
cmd.args.subImage.data = cbD->retainData(rawData);

setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
} else {
qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
}
Expand Down

0 comments on commit 1d6bb23

Please sign in to comment.