diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-10-05 16:05:06 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-10-09 17:15:05 +0200 |
commit | 9baf69c765c446b7c8f069ebdd50910877a7d0f8 (patch) | |
tree | c996af48af33b51b35273f66674d61beccf43de5 /src/gui | |
parent | 32924110ce69498ab5b05d00728f77affd6817d9 (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/gui')
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 8 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 31 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 4 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 2 |
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; |