QOpenGLTexture: Set wrap mode if NPOT textures are not fully supported

The OpenGL wrap mode defaults to GL_REPEAT although it is not supported for
non-power-of-two textures on hardware that only has limited support.

I.e. the following would create a texture with an invalid wrap mode:

    auto *t = new QOpenGLTexture(QOpenGLTexture::Target2D);
    t.setSize(123, 456);

This patch adds a check in QOpenGLWindow::setSize to see if it's called with a
non-power-of-two size on hardware without full support, and if so sets wrapMode
to ClampToEdge (which should work on devices with limited support).

Task-number: QTBUG-67418
Change-Id: I56e9f4383dbf5430c2bc5e4e9e585712b3603c13
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2018-04-03 14:42:15 +02:00 committed by Johan Helsing
parent d90fb72c20
commit fbb9c0461c

View File

@ -2800,6 +2800,11 @@ QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
return d->format; return d->format;
} }
static bool isNpot(int width, int height = 1, int depth = 1)
{
return width & (width-1) || height & (height-1) || depth & (depth-1);
}
/*! /*!
Sets the dimensions of this texture object to \a width, Sets the dimensions of this texture object to \a width,
\a height, and \a depth. The default for each dimension is 1. \a height, and \a depth. The default for each dimension is 1.
@ -2807,6 +2812,10 @@ QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
implementation. Allocating storage for a texture less than the implementation. Allocating storage for a texture less than the
maximum size can still fail if your system is low on resources. maximum size can still fail if your system is low on resources.
If a non-power-of-two \a width, \a height or \a depth is provided and your
OpenGL implementation doesn't have support for repeating non-power-of-two
textures, then the wrap mode is automatically set to ClampToEdge.
\sa width(), height(), depth() \sa width(), height(), depth()
*/ */
void QOpenGLTexture::setSize(int width, int height, int depth) void QOpenGLTexture::setSize(int width, int height, int depth)
@ -2819,6 +2828,9 @@ void QOpenGLTexture::setSize(int width, int height, int depth)
return; return;
} }
if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
d->setWrapMode(WrapMode::ClampToEdge);
switch (d->target) { switch (d->target) {
case QOpenGLTexture::Target1D: case QOpenGLTexture::Target1D:
case QOpenGLTexture::Target1DArray: case QOpenGLTexture::Target1DArray: