Fix tiling of NPOT textures on GL/ES
The emulation was not working since the vertices are clamped before getting to the fragment shader. So instead just resize the brush if not supported. Change-Id: I856e47890cd3021874b77d869a6ff7162cadde10 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
e65371caf9
commit
0bb760260e
@ -167,7 +167,7 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
|
||||
code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended
|
||||
code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core;
|
||||
|
||||
code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_desktop_core;
|
||||
code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_core;
|
||||
code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core;
|
||||
code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core;
|
||||
code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core;
|
||||
@ -212,10 +212,7 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
|
||||
code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader;
|
||||
code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
|
||||
code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader;
|
||||
if (context->isOpenGLES())
|
||||
code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_ES;
|
||||
else
|
||||
code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_desktop;
|
||||
code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader;
|
||||
code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader;
|
||||
code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader;
|
||||
code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader;
|
||||
|
@ -303,17 +303,7 @@ static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\
|
||||
static const char* const qopenglslAffinePositionWithTextureBrushVertexShader
|
||||
= qopenglslPositionWithTextureBrushVertexShader;
|
||||
|
||||
// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
|
||||
// we emulate GL_REPEAT by only taking the fractional part of the texture coords.
|
||||
// TODO: Special case POT textures which don't need this emulation
|
||||
static const char* const qopenglslTextureBrushSrcFragmentShader_ES = "\n\
|
||||
varying highp vec2 brushTextureCoords; \n\
|
||||
uniform sampler2D brushTexture; \n\
|
||||
lowp vec4 srcPixel() { \n\
|
||||
return texture2D(brushTexture, fract(brushTextureCoords)); \n\
|
||||
}\n";
|
||||
|
||||
static const char* const qopenglslTextureBrushSrcFragmentShader_desktop = "\n\
|
||||
static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\
|
||||
varying highp vec2 brushTextureCoords; \n\
|
||||
uniform sampler2D brushTexture; \n\
|
||||
lowp vec4 srcPixel() \n\
|
||||
@ -795,7 +785,7 @@ static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\
|
||||
static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core
|
||||
= qopenglslPositionWithTextureBrushVertexShader_core;
|
||||
|
||||
static const char* const qopenglslTextureBrushSrcFragmentShader_desktop_core = "\n\
|
||||
static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\
|
||||
in vec2 brushTextureCoords; \n\
|
||||
uniform sampler2D brushTexture; \n\
|
||||
vec4 srcPixel() \n\
|
||||
|
@ -272,6 +272,12 @@ GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const ImageWithBindOptions &ima
|
||||
return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, imageWithOptions.image, imageWithOptions.options);
|
||||
}
|
||||
|
||||
inline static bool isPowerOfTwo(int x)
|
||||
{
|
||||
// Assumption: x >= 1
|
||||
return x == (x & -x);
|
||||
}
|
||||
|
||||
void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
|
||||
{
|
||||
Q_Q(QOpenGL2PaintEngineEx);
|
||||
@ -304,16 +310,18 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
|
||||
currentBrushImage = currentBrush.textureImage();
|
||||
|
||||
int max_texture_size = ctx->d_func()->maxTextureSize();
|
||||
if (currentBrushImage.width() > max_texture_size || currentBrushImage.height() > max_texture_size)
|
||||
currentBrushImage = currentBrushImage.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
|
||||
QSize newSize = currentBrushImage.size();
|
||||
newSize = newSize.boundedTo(QSize(max_texture_size, max_texture_size));
|
||||
if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) {
|
||||
if (!isPowerOfTwo(newSize.width()) || !isPowerOfTwo(newSize.height())) {
|
||||
newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
|
||||
newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
|
||||
}
|
||||
}
|
||||
if (currentBrushImage.size() != newSize)
|
||||
currentBrushImage = currentBrushImage.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
GLuint wrapMode = GL_REPEAT;
|
||||
if (QOpenGLContext::currentContext()->isOpenGLES()) {
|
||||
// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
|
||||
// we emulate GL_REPEAT by only taking the fractional part of the texture coords
|
||||
// in the qopenglslTextureBrushSrcFragmentShader program.
|
||||
wrapMode = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
|
||||
updateTexture(QT_BRUSH_TEXTURE_UNIT, currentBrushImage, wrapMode, filterMode, ForceUpdate);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user