summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-10-05 16:05:06 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-10-09 17:15:05 +0200
commit9baf69c765c446b7c8f069ebdd50910877a7d0f8 (patch)
treec996af48af33b51b35273f66674d61beccf43de5 /src
parent32924110ce69498ab5b05d00728f77affd6817d9 (diff)
rhi: gl: Add a feature flag for reading back non-zero mip levels
The joys of "level - Specifies the mipmap level of the texture image to be attached, which must be 0." for glFramebufferTexture2D in OpenGL ES 2.0. Change-Id: Iaf19502f48d7ba73b26abb72535bfa6696a1e182 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/gui/rhi/qrhi.cpp8
-rw-r--r--src/gui/rhi/qrhi_p.h3
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp31
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h4
-rw-r--r--src/gui/rhi/qrhimetal.mm2
-rw-r--r--src/gui/rhi/qrhivulkan.cpp2
7 files changed, 41 insertions, 11 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index bea8890234..57c466678e 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -572,7 +572,13 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
supported for QRhiBuffer instances with a usage different than
UniformBuffer. While this is supported in the majority of cases, it will be
unsupported with OpenGL ES older than 3.0.
-*/
+
+ \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
+ than 0 is supported when reading back texture contents. When not supported,
+ specifying a non-zero level in QRhiReadbackDescription leads to returning
+ an all-zero image. In practice this feature will be unsupported with OpenGL
+ ES 2.0, while it will likely be supported everywhere else.
+ */
/*!
\enum QRhi::BeginFrameFlag
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 993fc44b58..bfcc1d39f5 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -1436,7 +1436,8 @@ public:
BaseVertex,
BaseInstance,
TriangleFanTopology,
- ReadBackNonUniformBuffer
+ ReadBackNonUniformBuffer,
+ ReadBackNonBaseMipLevel
};
enum BeginFrameFlag {
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 7c39fe0b11..096a8c2756 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -473,6 +473,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return false;
case QRhi::ReadBackNonUniformBuffer:
return true;
+ case QRhi::ReadBackNonBaseMipLevel:
+ return true;
default:
Q_UNREACHABLE();
return false;
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index fa99ee5e25..ca1c91499d 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -500,6 +500,11 @@ bool QRhiGles2::create(QRhi::Flags flags)
// extension(s) (which is not in ES 3.0...messy)
caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
+ if (caps.gles)
+ caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3; // ES 3.0
+ else
+ caps.nonBaseLevelFramebufferTexture = true;
+
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
f->glEnable(GL_POINT_SPRITE);
@@ -744,6 +749,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ReadBackNonUniformBuffer:
return !caps.gles || caps.properMapBuffer;
+ case QRhi::ReadBackNonBaseMipLevel:
+ return caps.nonBaseLevelFramebufferTexture;
default:
Q_UNREACHABLE();
return false;
@@ -2156,23 +2163,31 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
QRhiReadbackResult *result = cmd.args.readPixels.result;
GLuint tex = cmd.args.readPixels.texture;
GLuint fbo = 0;
+ int mipLevel = 0;
if (tex) {
result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
result->format = cmd.args.readPixels.format;
- f->glGenFramebuffers(1, &fbo);
- f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- cmd.args.readPixels.readTarget, cmd.args.readPixels.texture, cmd.args.readPixels.level);
+ mipLevel = cmd.args.readPixels.level;
+ if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
+ f->glGenFramebuffers(1, &fbo);
+ f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.readPixels.readTarget, cmd.args.readPixels.texture, mipLevel);
+ }
} else {
result->pixelSize = currentSwapChain->pixelSize;
result->format = QRhiTexture::RGBA8;
// readPixels handles multisample resolving implicitly
}
result->data.resize(result->pixelSize.width() * result->pixelSize.height() * 4);
- // With GLES (2.0?) GL_RGBA is the only mandated readback format, so stick with it.
- f->glReadPixels(0, 0, result->pixelSize.width(), result->pixelSize.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- result->data.data());
+ if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
+ // With GLES (2.0?) GL_RGBA is the only mandated readback format, so stick with it.
+ f->glReadPixels(0, 0, result->pixelSize.width(), result->pixelSize.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ result->data.data());
+ } else {
+ result->data.fill('\0');
+ }
if (fbo) {
f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
f->glDeleteFramebuffers(1, &fbo);
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 29cccb0c9c..8814d9c19d 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -753,7 +753,8 @@ public:
baseVertex(false),
compute(false),
textureCompareMode(false),
- properMapBuffer(false)
+ properMapBuffer(false),
+ nonBaseLevelFramebufferTexture(false)
{ }
int ctxMajor;
int ctxMinor;
@@ -785,6 +786,7 @@ public:
uint compute : 1;
uint textureCompareMode : 1;
uint properMapBuffer : 1;
+ uint nonBaseLevelFramebufferTexture : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QVector<GLint> supportedCompressedFormats;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 9c579ebfe1..694882ab93 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -559,6 +559,8 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return false;
case QRhi::ReadBackNonUniformBuffer:
return true;
+ case QRhi::ReadBackNonBaseMipLevel:
+ return true;
default:
Q_UNREACHABLE();
return false;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 154908b333..0d364dd9fc 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -3823,6 +3823,8 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ReadBackNonUniformBuffer:
return true;
+ case QRhi::ReadBackNonBaseMipLevel:
+ return true;
default:
Q_UNREACHABLE();
return false;