Enhance msaa and blitframebuffer on ES with vendor extensions

The support already in place for ANGLE is now extended for NV.

On ES 2.0 the only way to get multisampled renderbuffers and blitframebuffer
is through vendor-specific extensions. QOpenGLFunctions is updated to resolve
the related functions for both ANGLE and NV, in addition to EXT.

Task-number: QTBUG-39187
Change-Id: I1aab805ced3d06dde3dc547221bbf833ff8e06c2
Reviewed-by: Andrew Knight <andrew.knight@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
This commit is contained in:
Laszlo Agocs 2014-06-13 11:07:42 +02:00
parent ee88ed8fab
commit 79bbef7588
2 changed files with 32 additions and 13 deletions

View File

@ -427,18 +427,21 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return;
// Fall back to using a normal non-msaa FBO if we don't have support for MSAA
if (!funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
|| !funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)) {
samples = 0;
}
#ifndef QT_OPENGL_ES_2
GLint maxSamples;
funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
samples = qBound(0, int(samples), int(maxSamples));
#endif
// On GLES 2.0 multisampled framebuffers are available through vendor-specific extensions
const bool msaaES2 = ctx->isOpenGLES() && (ctx->hasExtension("GL_ANGLE_framebuffer_multisample")
|| ctx->hasExtension("GL_NV_framebuffer_multisample"));
if (!ctx->isOpenGLES() || msaaES2) {
GLint maxSamples;
funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
samples = qBound(0, int(samples), int(maxSamples));
}
size = sz;
target = texture_target;
@ -459,11 +462,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
} else {
GLenum storageFormat = internal_format;
#ifdef GL_RGBA8_OES
// Correct the internal format used by the render buffer when using ANGLE
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && internal_format == GL_RGBA
&& strstr((const char *)funcs.glGetString(GL_RENDERER), "ANGLE") != 0) {
// Correct the internal format used by the render buffer when using ES with extensions
if (msaaES2 && internal_format == GL_RGBA)
storageFormat = GL_RGBA8_OES;
}
#endif
mipmap = false;

View File

@ -391,6 +391,10 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::FramebufferBlit;
if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample"))
extensions |= QOpenGLExtensions::FramebufferMultisample;
if (extensionMatcher.match("GL_NV_framebuffer_blit"))
extensions |= QOpenGLExtensions::FramebufferBlit;
if (extensionMatcher.match("GL_NV_framebuffer_multisample"))
extensions |= QOpenGLExtensions::FramebufferMultisample;
} else {
extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer;
@ -2031,7 +2035,9 @@ namespace {
enum ResolvePolicy
{
ResolveOES = 0x1,
ResolveEXT = 0x2
ResolveEXT = 0x2,
ResolveANGLE = 0x4,
ResolveNV = 0x8
};
template <typename Base, typename FuncType, int Policy, typename ReturnType>
@ -2152,6 +2158,12 @@ private:
\
if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "EXT"); \
\
if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \
\
if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \
\
if (!alternateFuncName.isEmpty() && !(funcs->*funcPointerName)) { \
funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName); \
@ -2164,6 +2176,12 @@ private:
\
if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "EXT"); \
\
if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \
\
if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \
}
#define RESOLVER_COMMON_NON_VOID \
@ -3160,7 +3178,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveBlitFramebuffer(GLint srcX0, GLint
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, BlitFramebuffer, BlitFramebufferANGLE)
RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, BlitFramebuffer)
(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@ -3168,7 +3186,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorageMultisample(GLen
GLenum internalFormat,
GLsizei width, GLsizei height)
{
RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, RenderbufferStorageMultisample, RenderbufferStorageMultisampleANGLE)
RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, RenderbufferStorageMultisample)
(target, samples, internalFormat, width, height);
}