summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp55
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h13
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h18
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp163
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h36
5 files changed, 217 insertions, 68 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index ac89599..4b73ca9 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -191,7 +191,29 @@ QGLEngineShaderManager::~QGLEngineShaderManager()
}
+uint QGLEngineShaderManager::getUniformIdentifier(const char *uniformName)
+{
+ uniformIdentifiers << uniformName;
+ return uniformIdentifiers.size() - 1;
+}
+
+uint QGLEngineShaderManager::getUniformLocation(uint id)
+{
+ QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
+ uint oldSize = uniformLocations.size();
+ if (oldSize <= id) {
+ uint newSize = id + 1;
+ uniformLocations.resize(newSize);
+
+ for (uint i = oldSize; i < newSize; ++i)
+ uniformLocations[i] = GLuint(-1);
+ }
+ if (uniformLocations.at(id) == GLuint(-1))
+ uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformIdentifiers.at(id));
+
+ return uniformLocations.at(id);
+}
void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform)
@@ -206,43 +228,61 @@ void QGLEngineShaderManager::setDirty()
void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
{
+ if (srcPixelType == PixelSrcType(style))
+ return;
+
srcPixelType = style;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
{
+ if (srcPixelType == type)
+ return;
+
srcPixelType = type;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setTextureCoordsEnabled(bool enabled)
{
+ if (useTextureCoords == enabled)
+ return;
+
useTextureCoords = enabled;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setUseGlobalOpacity(bool useOpacity)
{
+ if (useGlobalOpacity == useOpacity)
+ return;
+
useGlobalOpacity = useOpacity;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setMaskType(MaskType type)
{
+ if (maskType == type)
+ return;
+
maskType = type;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
{
+ if (compositionMode == mode)
+ return;
+
compositionMode = mode;
shaderProgNeedsChanging = true; //###
}
QGLShaderProgram* QGLEngineShaderManager::currentProgram()
{
- return currentShaderProg;
+ return currentShaderProg->program;
}
QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
@@ -432,15 +472,16 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
// At this point, requiredProgram is fully populated so try to find the program in the cache
- foreach (const QGLEngineShaderProg &prog, cachedPrograms) {
+ for (int i = 0; i < cachedPrograms.size(); ++i) {
+ QGLEngineShaderProg &prog = cachedPrograms[i];
if ( (prog.mainVertexShader == requiredProgram.mainVertexShader)
&& (prog.positionVertexShader == requiredProgram.positionVertexShader)
&& (prog.mainFragShader == requiredProgram.mainFragShader)
&& (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader)
&& (prog.compositionFragShader == requiredProgram.compositionFragShader) )
{
- currentShaderProg = prog.program;
- currentShaderProg->enable();
+ currentShaderProg = &prog;
+ currentShaderProg->program->enable();
shaderProgNeedsChanging = false;
return true;
}
@@ -480,8 +521,10 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
}
else {
cachedPrograms.append(requiredProgram);
- currentShaderProg = requiredProgram.program;
- currentShaderProg->enable();
+ // taking the address here is safe since
+ // cachePrograms isn't resized anywhere else
+ currentShaderProg = &cachedPrograms.last();
+ currentShaderProg->program->enable();
}
shaderProgNeedsChanging = false;
return true;
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 9013884..34f0768 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -237,6 +237,8 @@ struct QGLEngineShaderProg
QGLShader* maskFragShader; // Can be null for no mask
QGLShader* compositionFragShader; // Can be null for GL-handled mode
QGLShaderProgram* program;
+
+ QVector<uint> uniformLocations;
};
/*
@@ -283,6 +285,9 @@ public:
void setMaskType(MaskType);
void setCompositionMode(QPainter::CompositionMode);
+ uint getUniformIdentifier(const char *uniformName);
+ uint getUniformLocation(uint id);
+
void setDirty(); // someone has manually changed the current shader program
bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
@@ -374,9 +379,9 @@ private:
bool useTextureCoords;
QPainter::CompositionMode compositionMode;
- QGLShaderProgram* blitShaderProg;
- QGLShaderProgram* simpleShaderProg;
- QGLShaderProgram* currentShaderProg;
+ QGLShaderProgram* blitShaderProg;
+ QGLShaderProgram* simpleShaderProg;
+ QGLEngineShaderProg* currentShaderProg;
// TODO: Possibly convert to a LUT
QList<QGLEngineShaderProg> cachedPrograms;
@@ -386,6 +391,8 @@ private:
void compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type);
static const char* qglEngineShaderSourceCode[TotalShaderCount];
+
+ QVector<const char *> uniformIdentifiers;
};
QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index 4959b60..4e32f91 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -64,19 +64,23 @@ QT_MODULE(OpenGL)
static const char* const qglslMainVertexShader = "\
+ uniform highp float depth;\
void setPosition();\
void main(void)\
{\
setPosition();\
+ gl_Position.z = depth * gl_Position.w;\
}";
static const char* const qglslMainWithTexCoordsVertexShader = "\
attribute lowp vec2 textureCoordArray; \
varying lowp vec2 textureCoords; \
+ uniform highp float depth;\
void setPosition();\
void main(void) \
{\
setPosition();\
+ gl_Position.z = depth * gl_Position.w;\
textureCoords = textureCoordArray; \
}";
@@ -84,20 +88,16 @@ static const char* const qglslMainWithTexCoordsVertexShader = "\
static const char* const qglslPositionOnlyVertexShader = "\
attribute highp vec4 vertexCoordsArray;\
uniform highp mat4 pmvMatrix;\
- uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
- gl_Position.z = depth;\
}";
static const char* const qglslUntransformedPositionVertexShader = "\
attribute highp vec4 vertexCoordsArray;\
- uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = vertexCoordsArray;\
- gl_Position.z = depth;\
}";
// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
@@ -108,11 +108,9 @@ static const char* const qglslPositionWithPatternBrushVertexShader = "\
uniform mediump vec2 invertedTextureSize; \
uniform mediump mat3 brushTransform; \
varying mediump vec2 patternTexCoords; \
- uniform highp float depth;\
void setPosition(void) { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
- gl_Position.z = depth;\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -142,11 +140,9 @@ static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
uniform highp vec3 linearData; \
uniform highp mat3 brushTransform; \
varying mediump float index ; \
- uniform highp float depth;\
void setPosition() { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
- gl_Position.z = depth;\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -174,12 +170,10 @@ static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
uniform mediump vec2 halfViewportSize; \
uniform highp mat3 brushTransform; \
varying highp vec2 A; \
- uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
- gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -215,12 +209,10 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
uniform highp vec2 fmp; \
varying highp float b; \
varying highp vec2 A; \
- uniform highp float depth;\
void setPosition(void) \
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
- gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -254,11 +246,9 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\
uniform mediump vec2 invertedTextureSize; \
uniform mediump mat3 brushTransform; \
varying mediump vec2 brushTextureCoords; \
- uniform highp float depth;\
void setPosition(void) { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
- gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 6ff0c53..f261ca2 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -88,8 +88,9 @@ static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush
static const GLuint QT_MASK_TEXTURE_UNIT = 1;
static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2;
-class QGLTextureGlyphCache : public QTextureGlyphCache
+class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache
{
+ Q_OBJECT
public:
QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix);
~QGLTextureGlyphCache();
@@ -105,6 +106,24 @@ public:
inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
+
+public Q_SLOTS:
+ void contextDestroyed(const QGLContext *context) {
+ if (context == ctx) {
+ QList<const QGLContext *> shares = qgl_share_reg()->shares(ctx);
+ if (shares.isEmpty()) {
+ glDeleteFramebuffers(1, &m_fbo);
+ if (m_width || m_height)
+ glDeleteTextures(1, &m_texture);
+ } else {
+ // since the context holding the texture is shared, and
+ // about to be destroyed, we have to transfer ownership
+ // of the texture to one of the share contexts
+ ctx = const_cast<QGLContext *>(shares.at(0));
+ }
+ }
+ }
+
private:
QGLContext *ctx;
@@ -126,6 +145,8 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph
, m_height(0)
{
glGenFramebuffers(1, &m_fbo);
+ connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext *)),
+ SLOT(contextDestroyed(const QGLContext *)));
}
QGLTextureGlyphCache::~QGLTextureGlyphCache()
@@ -248,9 +269,13 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
}
}
-void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform)
+void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
{
// glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
+ if (id != GLuint(-1) && id == lastTexture)
+ return;
+
+ lastTexture = id;
if (smoothPixmapTransform) {
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -368,7 +393,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style == Qt::SolidPattern) {
QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue("fragmentColor", col);
+ shaderManager->currentProgram()->setUniformValue(location(FragmentColor), col);
}
else {
// All other brushes have a transform and thus need the translation point:
@@ -379,10 +404,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue("patternColor", col);
+ shaderManager->currentProgram()->setUniformValue(location(PatternColor), col);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize);
}
else if (style == Qt::LinearGradientPattern) {
const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient());
@@ -399,10 +424,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
1.0f / (l.x() * l.x() + l.y() * l.y())
);
- shaderManager->currentProgram()->setUniformValue("linearData", linearData);
+ shaderManager->currentProgram()->setUniformValue(location(LinearData), linearData);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize);
}
else if (style == Qt::ConicalGradientPattern) {
const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient());
@@ -410,10 +435,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0;
- shaderManager->currentProgram()->setUniformValue("angle", angle);
+ shaderManager->currentProgram()->setUniformValue(location(Angle), angle);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize);
}
else if (style == Qt::RadialGradientPattern) {
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient());
@@ -423,15 +448,15 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
- shaderManager->currentProgram()->setUniformValue("fmp", fmp);
+ shaderManager->currentProgram()->setUniformValue(location(Fmp), fmp);
GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
- shaderManager->currentProgram()->setUniformValue("fmp2_m_radius2", fmp2_m_radius2);
- shaderManager->currentProgram()->setUniformValue("inverse_2_fmp2_m_radius2",
+ shaderManager->currentProgram()->setUniformValue(location(Fmp2MRadius2), fmp2_m_radius2);
+ shaderManager->currentProgram()->setUniformValue(location(Inverse2Fmp2MRadius2),
GLfloat(1.0 / (2.0*fmp2_m_radius2)));
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize);
}
else if (style == Qt::TexturePattern) {
translationPoint = q->state()->brushOrigin;
@@ -440,14 +465,14 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) {
QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue("patternColor", col);
+ shaderManager->currentProgram()->setUniformValue(location(PatternColor), col);
}
QSizeF invertedTextureSize( 1.0 / texPixmap.width(), 1.0 / texPixmap.height() );
- shaderManager->currentProgram()->setUniformValue("invertedTextureSize", invertedTextureSize);
+ shaderManager->currentProgram()->setUniformValue(location(InvertedTextureSize), invertedTextureSize);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize);
}
else
qWarning("QGL2PaintEngineEx: Unimplemented fill style");
@@ -456,8 +481,8 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QTransform gl_to_qt(1, 0, 0, -1, 0, height);
QTransform inv_matrix = gl_to_qt * (brushQTransform * q->state()->matrix).inverted() * translate;
- shaderManager->currentProgram()->setUniformValue("brushTransform", inv_matrix);
- shaderManager->currentProgram()->setUniformValue("brushTexture", QT_BRUSH_TEXTURE_UNIT);
+ shaderManager->currentProgram()->setUniformValue(location(BrushTransform), inv_matrix);
+ shaderManager->currentProgram()->setUniformValue(location(BrushTexture), QT_BRUSH_TEXTURE_UNIT);
}
brushUniformsDirty = false;
}
@@ -591,22 +616,17 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect)
void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
{
- transferMode(ImageDrawingMode);
-
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
-
// Setup for texture drawing
shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
shaderManager->setTextureCoordsEnabled(true);
- prepareForDraw(opaque);
+ if (prepareForDraw(opaque))
+ shaderManager->currentProgram()->setUniformValue(location(ImageTexture), QT_IMAGE_TEXTURE_UNIT);
if (pattern) {
QColor col = premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue("patternColor", col);
+ shaderManager->currentProgram()->setUniformValue(location(PatternColor), col);
}
- shaderManager->currentProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
-
GLfloat dx = 1.0 / textureSize.width();
GLfloat dy = 1.0 / textureSize.height();
@@ -651,8 +671,17 @@ void QGL2PaintEngineEx::sync()
glLoadMatrixf(&mv_matrix[0][0]);
#endif
+ d->lastTexture = GLuint(-1);
+
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
+
+ glDisable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glDepthMask(true);
+ glClearDepth(1);
+
+ d->needsSync = true;
}
void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
@@ -663,6 +692,8 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
if (mode == TextDrawingMode || mode == ImageDrawingMode) {
glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+
+ lastTexture = GLuint(-1);
}
if (mode == TextDrawingMode)
@@ -796,7 +827,7 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
-void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
+bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
if (brushTextureDirty && mode != ImageDrawingMode)
updateBrushTexture();
@@ -808,12 +839,14 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
updateMatrix();
const bool stateHasOpacity = q->state()->opacity < 0.99f;
- if (q->state()->compositionMode() == QPainter::CompositionMode_Source
- || (q->state()->compositionMode() == QPainter::CompositionMode_SourceOver
+ if (q->state()->composition_mode == QPainter::CompositionMode_Source
+ || (q->state()->composition_mode == QPainter::CompositionMode_SourceOver
&& srcPixelsAreOpaque && !stateHasOpacity))
+ {
glDisable(GL_BLEND);
- else
+ } else {
glEnable(GL_BLEND);
+ }
bool useGlobalOpacityUniform = stateHasOpacity;
if (stateHasOpacity && (mode != ImageDrawingMode)) {
@@ -826,30 +859,35 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
}
shaderManager->setUseGlobalOpacity(useGlobalOpacityUniform);
-
+ bool changed = shaderManager->useCorrectShaderProg();
// If the shader program needs changing, we change it and mark all uniforms as dirty
- if (shaderManager->useCorrectShaderProg()) {
+ if (changed) {
// The shader program has changed so mark all uniforms as dirty:
brushUniformsDirty = true;
shaderMatrixUniformDirty = true;
depthUniformDirty = true;
+ opacityUniformDirty = true;
}
if (brushUniformsDirty && mode != ImageDrawingMode)
updateBrushUniforms();
if (shaderMatrixUniformDirty) {
- shaderManager->currentProgram()->setUniformValue("pmvMatrix", pmvMatrix);
+ shaderManager->currentProgram()->setUniformValue(location(PmvMatrix), pmvMatrix);
shaderMatrixUniformDirty = false;
}
if (depthUniformDirty) {
- shaderManager->currentProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth);
+ shaderManager->currentProgram()->setUniformValue(location(Depth), (GLfloat)q->state()->currentDepth);
depthUniformDirty = false;
}
- if (useGlobalOpacityUniform)
- shaderManager->currentProgram()->setUniformValue("globalOpacity", (GLfloat)q->state()->opacity);
+ if (useGlobalOpacityUniform && opacityUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue(location(GlobalOpacity), (GLfloat)q->state()->opacity);
+ opacityUniformDirty = false;
+ }
+
+ return changed;
}
void QGL2PaintEngineExPrivate::composite(const QGLRect& boundingRect)
@@ -971,6 +1009,7 @@ void QGL2PaintEngineEx::opacityChanged()
Q_ASSERT(d->shaderManager);
d->brushUniformsDirty = true;
+ d->opacityUniformDirty = true;
}
void QGL2PaintEngineEx::compositionModeChanged()
@@ -990,6 +1029,8 @@ void QGL2PaintEngineEx::renderHintsChanged()
glDisable(GL_MULTISAMPLE);
#endif
+ Q_D(QGL2PaintEngineEx);
+ d->lastTexture = GLuint(-1);
// qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!");
}
@@ -1008,11 +1049,13 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ GLuint id = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
+ d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT,
+ state()->renderHints & QPainter::SmoothPixmapTransform, id);
d->drawTexture(dest, src, pixmap.size(), isOpaque, isBitmap);
}
@@ -1025,8 +1068,10 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ GLuint id = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT,
+ state()->renderHints & QPainter::SmoothPixmapTransform, id);
d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
}
@@ -1121,7 +1166,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
prepareForDraw(false); // Text always causes src pixels to be transparent
- shaderManager->currentProgram()->setUniformValue("maskTexture", QT_MASK_TEXTURE_UNIT);
+ shaderManager->currentProgram()->setUniformValue(location(MaskTexture), QT_MASK_TEXTURE_UNIT);
if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
@@ -1161,9 +1206,29 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
qt_resolve_version_2_0_functions(d->ctx);
#endif
- if (!d->shaderManager)
+ if (d->shaderManager) {
+ d->shaderManager->setDirty();
+ } else {
d->shaderManager = new QGLEngineShaderManager(d->ctx);
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::ImageTexture] = d->shaderManager->getUniformIdentifier("imageTexture");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::PatternColor] = d->shaderManager->getUniformIdentifier("patternColor");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::GlobalOpacity] = d->shaderManager->getUniformIdentifier("globalOpacity");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::Depth] = d->shaderManager->getUniformIdentifier("depth");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::PmvMatrix] = d->shaderManager->getUniformIdentifier("pmvMatrix");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::MaskTexture] = d->shaderManager->getUniformIdentifier("maskTexture");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::FragmentColor] = d->shaderManager->getUniformIdentifier("fragmentColor");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::LinearData] = d->shaderManager->getUniformIdentifier("linearData");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::Angle] = d->shaderManager->getUniformIdentifier("angle");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::HalfViewportSize] = d->shaderManager->getUniformIdentifier("halfViewportSize");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::Fmp] = d->shaderManager->getUniformIdentifier("fmp");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::Fmp2MRadius2] = d->shaderManager->getUniformIdentifier("fmp2_m_radius2");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::Inverse2Fmp2MRadius2] = d->shaderManager->getUniformIdentifier("inverse_2_fmp2_m_radius2");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::InvertedTextureSize] = d->shaderManager->getUniformIdentifier("invertedTextureSize");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::BrushTransform] = d->shaderManager->getUniformIdentifier("brushTransform");
+ d->uniformIdentifiers[QGL2PaintEngineExPrivate::BrushTexture] = d->shaderManager->getUniformIdentifier("brushTexture");
+ }
+
glViewport(0, 0, d->width, d->height);
// glClearColor(0.0, 1.0, 0.0, 1.0);
@@ -1179,6 +1244,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->stencilBufferDirty = true;
d->simpleShaderDepthUniformDirty = true;
d->depthUniformDirty = true;
+ d->opacityUniformDirty = true;
+ d->needsSync = false;
d->use_system_clip = !systemClip().isEmpty();
@@ -1210,6 +1277,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
source->bind(false);
QRect rect(0, 0, source->width(), source->height());
+ d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
d->drawTexture(QRectF(rect), QRectF(rect), rect.size(), true);
}
@@ -1256,11 +1324,15 @@ void QGL2PaintEngineEx::ensureActive()
ctx->d_ptr->active_engine = this;
- glDisable(GL_DEPTH_TEST);
+ d->needsSync = true;
+ }
+ if (d->needsSync) {
glViewport(0, 0, d->width, d->height);
-
+ glDepthMask(false);
+ glDepthFunc(GL_LEQUAL);
setState(state());
+ d->needsSync = false;
}
}
@@ -1362,7 +1434,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
if (state()->matrix.type() <= QTransform::TxScale) {
rect = state()->matrix.mapRect(rect);
- if (d->use_system_clip && rect.contains(d->systemClip.boundingRect())
+ if ((d->use_system_clip && rect.contains(d->systemClip.boundingRect()))
|| rect.contains(QRect(0, 0, d->width, d->height)))
return;
}
@@ -1506,6 +1578,9 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state)
d->depthUniformDirty = true;
d->simpleShaderMatrixUniformDirty = true;
d->shaderMatrixUniformDirty = true;
+ d->opacityUniformDirty = true;
+
+ d->shaderManager->setDirty();
if (old_state && old_state != s && old_state->canRestoreClip) {
d->updateDepthScissorTest();
@@ -1557,3 +1632,5 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState()
}
QT_END_NAMESPACE
+
+#include "qpaintengineex_opengl2.moc"
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index a2a44c0..0d28a49 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -156,7 +156,7 @@ public:
void updateBrushUniforms();
void updateMatrix();
void updateCompositionMode();
- void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform);
+ void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1);
void setBrush(const QBrush* brush);
@@ -175,7 +175,8 @@ public:
void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill);
// ^ Calls drawVertexArrays to render into stencil buffer
- void prepareForDraw(bool srcPixelsAreOpaque);
+ bool prepareForDraw(bool srcPixelsAreOpaque);
+ // ^ returns whether the current program changed or not
inline void useSimpleShader();
inline QColor premultiplyColor(QColor c, GLfloat opacity);
@@ -198,6 +199,7 @@ public:
bool stencilBufferDirty;
bool depthUniformDirty;
bool simpleShaderDepthUniformDirty;
+ bool opacityUniformDirty;
const QBrush* currentBrush; // May not be the state's brush!
@@ -218,6 +220,36 @@ public:
void regenerateDepthClip();
void systemStateChanged();
uint use_system_clip : 1;
+
+ enum Uniform {
+ ImageTexture,
+ PatternColor,
+ GlobalOpacity,
+ Depth,
+ PmvMatrix,
+ MaskTexture,
+ FragmentColor,
+ LinearData,
+ Angle,
+ HalfViewportSize,
+ Fmp,
+ Fmp2MRadius2,
+ Inverse2Fmp2MRadius2,
+ InvertedTextureSize,
+ BrushTransform,
+ BrushTexture,
+ NumUniforms
+ };
+
+ uint location(Uniform uniform)
+ {
+ return shaderManager->getUniformLocation(uniformIdentifiers[uniform]);
+ }
+
+ uint uniformIdentifiers[NumUniforms];
+ GLuint lastTexture;
+
+ bool needsSync;
};
QT_END_NAMESPACE