Switch to RGB(A|X)8888[_Premultiplied] for QOpenGLFBO readbacks on GLES

Instead of the never-ending blacklisting of "broken" drivers, simply switch
to always choosing a byte ordered QImage format with OpenGL ES, and keep
on using the (one and only) spec-mandated GL_RGBA/GL_UNSIGNED_BYTE combo.

There is nothing broken with not supporting BGRA for glReadPixels even when
GL_EXT_read_format_bgra (an out of date, pre-2.0 extension that got folded
into the spec to begin with) is present. We do not have a good way to tell
if BGRA_EXT is supported for glReadPixels or not, so just skip the whole
problem altogether.

Task-number: QTBUG-59283
Task-number: QTBUG-59303
Change-Id: I9f0605380923bd3b3ffdeb80f5c172d3e4cc7927
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
Laszlo Agocs 2017-03-17 15:23:37 +01:00
parent bae0c4c11a
commit dd38574160
2 changed files with 12 additions and 35 deletions

View File

@ -1282,35 +1282,11 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ
return img;
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
// Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian.
const bool has_bgra_ext = context->isOpenGLES()
? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
: context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
// For OpenGL ES stick with the byte ordered format / RGBA readback format
// since that is the only spec mandated way. (also, skip the
// GL_IMPLEMENTATION_COLOR_READ_FORMAT mess since there is nothing saying a
// BGRA capable impl would return BGRA from there)
#ifndef Q_OS_IOS
const char *renderer = reinterpret_cast<const char *>(funcs->glGetString(GL_RENDERER));
const char *ver = reinterpret_cast<const char *>(funcs->glGetString(GL_VERSION));
// Blacklist GPU chipsets that have problems with their BGRA support.
const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0
&& ::strstr(ver, "1.3") != 0) ||
(qstrcmp(renderer, "Mali-T760") == 0
&& ::strstr(ver, "3.1") != 0) ||
(qstrcmp(renderer, "Mali-T720") == 0
&& ::strstr(ver, "3.1") != 0) ||
qstrcmp(renderer, "PowerVR SGX 554") == 0;
#else
const bool blackListed = true;
#endif
const bool supports_bgra = has_bgra_ext && !blackListed;
if (supports_bgra) {
QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
return img;
}
#endif
QImage rgbaImage(size, include_alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888);
funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits());
return rgbaImage;
@ -1362,8 +1338,11 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value
of QOpenGLPaintDevice::paintFlipped().
The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
only when internalTextureFormat() is set to \c GL_RGB.
The returned image has a format of premultiplied ARGB32 or RGB32. The latter
is used only when internalTextureFormat() is set to \c GL_RGB. Since Qt 5.2
the function will fall back to premultiplied RGBA8888 or RGBx8888 when
reading to (A)RGB32 is not supported, and this includes OpenGL ES. Since Qt
5.4 an A2BGR30 image is returned if the internal format is RGB10_A2.
If the rendering in the framebuffer was not done with premultiplied alpha in mind,
create a wrapper QImage with a non-premultiplied format. This is necessary before
@ -1376,10 +1355,6 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
\endcode
Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when
reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the
internal format is RGB10_A2.
For multisampled framebuffer objects the samples are resolved using the
\c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents
of the returned image is undefined.

View File

@ -1195,7 +1195,9 @@ void tst_QGL::currentFboSync()
QGLFramebufferObject::bindDefault();
QCOMPARE(fbo1.toImage(), fbo2Image);
// Convert the QGLFBO's result since QOpenGLFBO uses a wider
// variety of possible return formats.
QCOMPARE(fbo1.toImage().convertToFormat(fbo2Image.format()), fbo2Image);
}
{