rhi: gl: allow readbacks for all texture formats
Texture readbacks other than RGBA8 (e.g., R32UI) are often not supported on OpenGL ES but are fully supported on Desktop OpenGL 3.0+. So, do the same as the float formats: always send the correct glReadPixels command, as it should work on Desktop OpenGL. Use the toGLTextureFormat and textureFormatInfo helpers to reduce code duplication and support new texture formats automagically in the future. Use QByteArray::resizeForOverwrite to avoid unnecessary zero- initialization before glReadPixels writes data. [ChangeLog][RHI] All readback texture formats supported by the OpenGL implementation can now be used with the Qt RHI. Change-Id: I537a5fceff50c2909c16702d66596dfd2fc1119e Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
8761fa5b8b
commit
e67568706f
@ -3654,9 +3654,9 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
||||
// With GLES, GL_RGBA is the only mandated readback format, so stick with it.
|
||||
// (and that's why we return false for the ReadBackAnyTextureFormat feature)
|
||||
if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
|
||||
result->data.resize(w * h);
|
||||
result->data.resizeForOverwrite(w * h);
|
||||
QByteArray tmpBuf;
|
||||
tmpBuf.resize(w * h * 4);
|
||||
tmpBuf.resizeForOverwrite(w * h * 4);
|
||||
f->glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuf.data());
|
||||
const quint8 *srcBase = reinterpret_cast<const quint8 *>(tmpBuf.constData());
|
||||
quint8 *dstBase = reinterpret_cast<quint8 *>(result->data.data());
|
||||
@ -3671,38 +3671,20 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (result->format) {
|
||||
// For floating point formats try it because this can be
|
||||
// relevant for some use cases; if it works, then fine, if
|
||||
// not, there's nothing we can do.
|
||||
case QRhiTexture::RGBA16F:
|
||||
result->data.resize(w * h * 8);
|
||||
f->glReadPixels(x, y, w, h, GL_RGBA, GL_HALF_FLOAT, result->data.data());
|
||||
break;
|
||||
case QRhiTexture::R16F:
|
||||
result->data.resize(w * h * 2);
|
||||
f->glReadPixels(x, y, w, h, GL_RED, GL_HALF_FLOAT, result->data.data());
|
||||
break;
|
||||
case QRhiTexture::R32F:
|
||||
result->data.resize(w * h * 4);
|
||||
f->glReadPixels(x, y, w, h, GL_RED, GL_FLOAT, result->data.data());
|
||||
break;
|
||||
case QRhiTexture::RGBA32F:
|
||||
result->data.resize(w * h * 16);
|
||||
f->glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, result->data.data());
|
||||
break;
|
||||
case QRhiTexture::RGB10A2:
|
||||
result->data.resize(w * h * 4);
|
||||
f->glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, result->data.data());
|
||||
break;
|
||||
default:
|
||||
result->data.resize(w * h * 4);
|
||||
f->glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, result->data.data());
|
||||
break;
|
||||
}
|
||||
// For other formats try it because this can be relevant for some use cases;
|
||||
// if it works, then fine, if not, there's nothing we can do.
|
||||
[[maybe_unused]] GLenum glintformat;
|
||||
[[maybe_unused]] GLenum glsizedintformat;
|
||||
GLenum glformat;
|
||||
GLenum gltype;
|
||||
toGlTextureFormat(result->format, caps, &glintformat, &glsizedintformat, &glformat, &gltype);
|
||||
quint32 byteSize;
|
||||
textureFormatInfo(result->format, result->pixelSize, nullptr, &byteSize, nullptr);
|
||||
result->data.resizeForOverwrite(byteSize);
|
||||
f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
|
||||
}
|
||||
} else {
|
||||
result->data.resize(w * h * 4);
|
||||
result->data.resizeForOverwrite(w * h * 4);
|
||||
result->data.fill('\0');
|
||||
}
|
||||
if (fbo) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user