summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar@trolltech.com>2009-04-03 06:45:40 (GMT)
committerGunnar Sletta <gunnar@trolltech.com>2009-04-03 06:45:40 (GMT)
commitac7484e36bfab69473278d7268cf37f7c69abfd2 (patch)
treefe9e6dee7f9333a205e9f00e012e2ae9d4ab68e5 /src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
parent0bb93751c80109a13f6391c8bbfb74693b484699 (diff)
parent855aa89e0ba99f8a0f75d7b31930bab2cefb93f8 (diff)
downloadQt-ac7484e36bfab69473278d7268cf37f7c69abfd2.zip
Qt-ac7484e36bfab69473278d7268cf37f7c69abfd2.tar.gz
Qt-ac7484e36bfab69473278d7268cf37f7c69abfd2.tar.bz2
Merge branch 'graphics-main'
Diffstat (limited to 'src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp271
1 files changed, 155 insertions, 116 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index a74f044..89ed1f7 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -86,6 +86,11 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
#include <QDebug>
+enum EngineMode {
+ ImageDrawingMode,
+ TextDrawingMode,
+ DefaultMode
+};
static const GLuint QT_VERTEX_COORDS_ATTR = 0;
static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
@@ -114,7 +119,10 @@ public:
void setBrush(const QBrush* brush);
- void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight);
+ void transferMode(EngineMode newMode);
+
+ void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize);
+ void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
void fill(const QVectorPath &path);
void drawOutline(const QVectorPath& path);
@@ -133,10 +141,11 @@ public:
inline QColor premultiplyColor(QColor c, GLfloat opacity);
QGL2PaintEngineEx* q;
-
- //### Move into QGLDrawable
+ QGLDrawable drawable;
int width, height;
- QGLContext* ctx;
+ QGLContext *ctx;
+
+ EngineMode mode;
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
@@ -153,7 +162,11 @@ public:
GLfloat inverseScale;
- QGL2PEXVertexArray pathVertexArray;
+ QGL2PEXVertexArray vertexCoordinateArray;
+ QGL2PEXVertexArray textureCoordinateArray;
+
+ GLfloat staticVertexCoordinateArray[8];
+ GLfloat staticTextureCoordinateArray[8];
GLfloat pmvMatrix[4][4];
@@ -400,8 +413,8 @@ void QGL2PaintEngineExPrivate::updateMatrix()
// Use the (3x3) transform for the Model~View matrix:
const QTransform& transform = q->state()->matrix;
GLfloat MV[4][4] = {
- {transform.m11(), transform.m21(), 0.0, transform.dx() + 0.5},
- {transform.m12(), transform.m22(), 0.0, transform.dy() + 0.5},
+ {transform.m11(), transform.m21(), 0.0, transform.dx()},
+ {transform.m12(), transform.m22(), 0.0, transform.dy()},
{0.0, 0.0, 1.0, 0.0},
{transform.m13(), transform.m23(), 0.0, transform.m33()}
};
@@ -411,7 +424,9 @@ void QGL2PaintEngineExPrivate::updateMatrix()
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
pmvMatrix[col][row] = 0.0;
- for (int n = 0; n < 4; ++n)
+
+ // P[row][n] is 0.0 for n < row
+ for (int n = row; n < 4; ++n)
pmvMatrix[col][row] += P[row][n] * MV[n][col];
}
}
@@ -485,15 +500,22 @@ void QGL2PaintEngineExPrivate::updateCompositionMode()
compositionModeDirty = false;
}
+static inline void setCoords(GLfloat *coords, const QGLRect &rect)
+{
+ coords[0] = rect.left;
+ coords[1] = rect.top;
+ coords[2] = rect.right;
+ coords[3] = rect.top;
+ coords[4] = rect.right;
+ coords[5] = rect.bottom;
+ coords[6] = rect.left;
+ coords[7] = rect.bottom;
+}
-void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight)
+void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize)
{
// qDebug("QGL2PaintEngineExPrivate::drawImage()");
-
- // We have a shader specifically for drawPixmap/drawImage...
- shaderManager->imageShader()->use();
-
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
if (compositionModeDirty)
updateCompositionMode();
@@ -506,66 +528,89 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s
imageShaderMatrixUniformDirty = false;
}
- shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
-
-// if (q->state()->opacity < 0.99f)
+ if (q->state()->opacity < 0.99f)
shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)q->state()->opacity;
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
+ GLfloat dx = 1.0 / textureSize.width();
+ GLfloat dy = 1.0 / textureSize.height();
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
+ QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
- GLfloat dx = 1.0 / txtWidth;
- GLfloat dy = 1.0 / txtHeight;
+ setCoords(staticVertexCoordinateArray, dest);
+ setCoords(staticTextureCoordinateArray, srcTextureRect);
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
- };
+void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
+{
+ if (newMode == mode)
+ return;
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ if (mode == TextDrawingMode || mode == ImageDrawingMode) {
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ }
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ if (newMode == TextDrawingMode) {
+ glEnable(GL_BLEND);
+ glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
-}
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+
+ shaderManager->textShader()->use();
+ shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
+ }
+
+ if (newMode == ImageDrawingMode) {
+ // We have a shader specifically for drawPixmap/drawImage...
+ shaderManager->imageShader()->use();
+ shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
+ shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)1.0;
+
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticVertexCoordinateArray);
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
+ glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ }
+
+ mode = newMode;
+}
void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
{
+ transferMode(DefaultMode);
+
// qDebug("QGL2PaintEngineExPrivate::drawOutline()");
if (matrixDirty)
updateMatrix();
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
if (path.hasImplicitClose()) {
// Close the path's outline
- pathVertexArray.lineToArray(path.points()[0], path.points()[1]);
- pathVertexArray.stops().last() += 1;
+ vertexCoordinateArray.lineToArray(path.points()[0], path.points()[1]);
+ vertexCoordinateArray.stops().last() += 1;
}
prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_LINE_STRIP);
+ drawVertexArrays(vertexCoordinateArray, GL_LINE_STRIP);
}
// Assumes everything is configured for the brush you want to use
void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
+ transferMode(DefaultMode);
+
if (matrixDirty)
updateMatrix();
@@ -579,26 +624,26 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
composite(rect);
}
else if (path.shape() == QVectorPath::EllipseHint) {
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_TRIANGLE_FAN);
+ drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
}
else {
// The path is too complicated & needs the stencil technique
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
- fillStencilWithVertexArray(pathVertexArray, path.hasWindingFill());
+ fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
// Stencil the brush onto the dest buffer
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
glEnable(GL_STENCIL_TEST);
prepareForDraw();
- composite(pathVertexArray.boundingRect());
+ composite(vertexCoordinateArray.boundingRect());
glDisable(GL_STENCIL_TEST);
- cleanStencilBuffer(pathVertexArray.boundingRect());
+ cleanStencilBuffer(vertexCoordinateArray.boundingRect());
}
}
@@ -749,8 +794,6 @@ void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray,
QGL2PaintEngineEx::QGL2PaintEngineEx()
: QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
{
- qDebug("QGL2PaintEngineEx::QGL2PaintEngineEx()");
-
}
QGL2PaintEngineEx::~QGL2PaintEngineEx()
@@ -761,8 +804,6 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QGL2PaintEngineEx);
- QTime startTime = QTime::currentTime();
-
d->setBrush(&brush);
d->fill(path);
d->setBrush(&(state()->brush)); // reset back to the state's brush
@@ -845,9 +886,10 @@ void QGL2PaintEngineEx::transformChanged()
void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ d->transferMode(ImageDrawingMode);
- d->ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLContext *ctx = d->ctx;
+ ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
//FIXME: we should use hasAlpha() instead, but that's SLOW at the moment
if ((state()->opacity < 0.99f) || pixmap.hasAlphaChannel())
@@ -855,26 +897,29 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
else
glDisable(GL_BLEND);
- d->drawTexture(dest, src, pixmap.width(), pixmap.height());
+ d->drawTexture(dest, src, pixmap.size());
}
void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
Qt::ImageConversionFlags)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ d->transferMode(ImageDrawingMode);
+
+ QGLContext *ctx = d->ctx;
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
if ((state()->opacity < 0.99f) || image.hasAlphaChannel())
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
- d->drawTexture(dest, src, image.width(), image.height());
+ d->drawTexture(dest, src, image.size());
}
void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
+ Q_D(QGL2PaintEngineEx);
QOpenGLPaintEngineState *s = state();
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
@@ -892,17 +937,19 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
drawCached = false;
if (drawCached) {
- drawCachedGlyphs(p, ti);
+ d->drawCachedGlyphs(p, ti);
return;
}
QPaintEngineEx::drawTextItem(p, ti);
}
-void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
+void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
{
- Q_D(QGL2PaintEngineEx);
- QOpenGLPaintEngineState *s = state();
+ Q_Q(QGL2PaintEngineEx);
+ QOpenGLPaintEngineState *s = q->state();
+
+ transferMode(TextDrawingMode);
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
@@ -926,66 +973,48 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t
const QImage &image = cache->image();
int margin = cache->glyphMargin();
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
-
- glEnable(GL_BLEND);
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
- d->shaderManager->textShader()->use();
- d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
- if (d->compositionModeDirty)
- d->updateCompositionMode();
+ if (compositionModeDirty)
+ updateCompositionMode();
- if (d->matrixDirty)
- d->updateMatrix();
+ if (matrixDirty)
+ updateMatrix();
- if (d->textShaderMatrixUniformDirty) {
- d->shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = d->pmvMatrix;
- d->textShaderMatrixUniformDirty = false;
+ if (textShaderMatrixUniformDirty) {
+ shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
+ textShaderMatrixUniformDirty = false;
}
- d->shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
- QColor col = d->premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
- d->shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
+ QColor col = premultiplyColor(s->pen.color(), (GLfloat)s->opacity);
+ shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
GLfloat dx = 1.0 / image.width();
GLfloat dy = 1.0 / image.height();
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ QGLPoint *oldVertexCoordinateDataPtr = vertexCoordinateArray.data();
+ QGLPoint *oldTextureCoordinateDataPtr = textureCoordinateArray.data();
+
+ vertexCoordinateArray.clear();
+ textureCoordinateArray.clear();
+
for (int i=0; i<glyphs.size(); ++i) {
const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
int x = positions[i].x.toInt() + c.baseLineX - margin;
int y = positions[i].y.toInt() - c.baseLineY - margin;
- QGLRect dest = QRectF(x, y, c.w, c.h);
- QGLRect src = QRectF(c.x, c.y, c.w, c.h);
-
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
-
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
-
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
-
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
- };
+ vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
+ textureCoordinateArray.addRect(QRectF(c.x*dx, 1 - c.y*dy, c.w * dx, -c.h * dy));
+ }
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
}
bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
@@ -994,11 +1023,16 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
// qDebug("QGL2PaintEngineEx::begin()");
- QGLWidget* widget = static_cast<QGLWidget*>(pdev);
- d->ctx = const_cast<QGLContext*>(widget->context());
- d->ctx->makeCurrent();
- d->width = widget->width();
- d->height = widget->height();
+ d->drawable.setDevice(pdev);
+ d->drawable.makeCurrent();
+ d->ctx = d->drawable.context();
+ QSize sz = d->drawable.size();
+ d->width = sz.width();
+ d->height = sz.height();
+ d->mode = DefaultMode;
+
+ qt_resolve_version_1_3_functions(d->ctx);
+ qt_resolve_glsl_extensions(d->ctx);
if (!d->shaderManager)
d->shaderManager = new QGLPEXShaderManager(d->ctx);
@@ -1021,13 +1055,18 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
glDisable(GL_DEPTH_TEST);
+ updateClipRegion(QRegion(), Qt::NoClip);
return true;
}
bool QGL2PaintEngineEx::end()
{
Q_D(QGL2PaintEngineEx);
- d->ctx->swapBuffers();
+ QGLContext *ctx = d->ctx;
+ glUseProgram(0);
+ d->transferMode(DefaultMode);
+ d->drawable.swapBuffers();
+ d->drawable.doneCurrent();
return false;
}