diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2024-02-05 15:27:25 +0100 |
---|---|---|
committer | Artem Dyomin <artem.dyomin@qt.io> | 2024-02-08 23:41:11 +0100 |
commit | 1d6bb23f6285252f7fa6cac87003cbe0f33f51af (patch) | |
tree | 07394fe5aeead85ae56f23f60b2d74ce2b9bf5b8 /src/gui/rhi/qrhigles2.cpp | |
parent | 1d799e91082092821a04885bd9d069febefc37da (diff) |
Fix loading QRhiTexture from image on gles
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>
Diffstat (limited to 'src/gui/rhi/qrhigles2.cpp')
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 67 |
1 files changed, 30 insertions, 37 deletions
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index e41ac6d353..2f0659909f 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -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; @@ -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); @@ -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); } |