NPOT texture support in QOpenGLTextureCache

Enable non power of two texture support for non compatible NPOT GPU.
If the context does not handle NPOTTexture feature, the image to bind is scaled to POT size. It works with OpenGL ES and Desktop version.
It is actually almost the same code as the one in QGLContextPrivate::bindTexture.

Change-Id: I6f0f511165c9e171a14f4ba6ba0b7a902e590cf6
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
This commit is contained in:
Cedric Chedaleux 2014-02-03 12:53:26 +01:00 committed by The Qt Project
parent fdef360bad
commit 96b7ac569c

View File

@ -40,6 +40,7 @@
****************************************************************************/ ****************************************************************************/
#include "qopengltexturecache_p.h" #include "qopengltexturecache_p.h"
#include <qopenglfunctions.h>
#include <private/qopenglcontext_p.h> #include <private/qopenglcontext_p.h>
#include <private/qimagepixmapcleanuphooks_p.h> #include <private/qimagepixmapcleanuphooks_p.h>
#include <qpa/qplatformpixmap.h> #include <qpa/qplatformpixmap.h>
@ -128,6 +129,20 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &
return id; return id;
} }
// returns the highest number closest to v, which is a power of 2
// NB! assumes 32 bit ints
static int qt_next_power_of_two(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
++v;
return v;
}
GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image) GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image)
{ {
if (image.isNull()) if (image.isNull())
@ -144,7 +159,19 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
} }
} }
GLuint id = bindTexture(context, key, image); QImage img = image;
if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)) {
// Scale the pixmap if needed. GL textures needs to have the
// dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
// 2.0 or use the GL_TEXTURE_RECTANGLE texture target
int tx_w = qt_next_power_of_two(image.width());
int tx_h = qt_next_power_of_two(image.height());
if (tx_w != image.width() || tx_h != image.height()) {
img = img.scaled(tx_w, tx_h);
}
}
GLuint id = bindTexture(context, key, img);
if (id > 0) if (id > 0)
QImagePixmapCleanupHooks::enableCleanupHooks(image); QImagePixmapCleanupHooks::enableCleanupHooks(image);