summaryrefslogtreecommitdiffstats
path: root/src/gui/opengl
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-07-18 16:42:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-07-27 16:10:45 +0000
commit0bb760260eb055f813247bf9ef06e372cac219d3 (patch)
treeb1d3fe9efcb88696c85bd390a261048f570e07ab /src/gui/opengl
parente65371caf9d067a28566bfcf361ead445194b955 (diff)
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>
Diffstat (limited to 'src/gui/opengl')
-rw-r--r--src/gui/opengl/qopenglengineshadermanager.cpp7
-rw-r--r--src/gui/opengl/qopenglengineshadersource_p.h14
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp24
3 files changed, 20 insertions, 25 deletions
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
index f66193cb01..b7bac2728a 100644
--- a/src/gui/opengl/qopenglengineshadermanager.cpp
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -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;
diff --git a/src/gui/opengl/qopenglengineshadersource_p.h b/src/gui/opengl/qopenglengineshadersource_p.h
index 5d9ee8110b..3ac599b6c2 100644
--- a/src/gui/opengl/qopenglengineshadersource_p.h
+++ b/src/gui/opengl/qopenglengineshadersource_p.h
@@ -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\
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 5902713faa..aca57d664a 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -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);
}