On Mon, 2010-07-12 at 21:53 +0200, [email protected] wrote:
> You should start by adding a reduction to
> https://bugs.webkit.org/show_bug.cgi?id=41682 in order to get people
> interested.
We're now trying to make a test page which reproduces the problem
independently of the AOL page. This should turn out a lot simpler than
the test case presently attached, and will probably not depend on the
atlas map being infeasibly large.
> You also mentioned you modified Qt, but you do not contribute the code
> back to Qt. So people have now way reproduce the problem you mention,
> and some contributors probably feel you take code but don't contribute
> back.
Attached are the patches we're using. They're against Qt 4.6.2. As
previously mentioned, there are minor problems with these patches,
mostly in ConstantOpacity support which can be bypassed by setting
QT_X11_NO_CONSTANT_OPACITY in the environment.
The key thing we're looking for is the software fallbacks, which have
relatively little performance impact on desktop platforms but which are
catastrophically slow on our device. The best way to spot them is to
watch for GetImage calls in xtrace output. (The xtrace that is an X11
protocol logger, not the low-level debugging tool.)
--
------
From: Jonathan Morton
[email protected]
>From 3668678e8f450b12db2594a7f88edf9edc35eed1 Mon Sep 17 00:00:00 2001
From: Jonathan Morton <[email protected]>
Date: Sun, 4 Jul 2010 04:37:05 +0300
Subject: [PATCH] XRender patch sent before weekend.
---
src/gui/painting/qpaintengine_x11.cpp | 132 ++++++++++++++++++++++++++++++---
src/gui/painting/qpaintengine_x11_p.h | 3 +
src/gui/painting/qpainter.cpp | 11 ++-
3 files changed, 130 insertions(+), 16 deletions(-)
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index e7a4905..2f83383 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -433,12 +433,28 @@ static QPaintEngine::PaintEngineFeatures qt_decide_features()
features |= QPaintEngine::Antialiasing;
features |= QPaintEngine::PorterDuff;
features |= QPaintEngine::MaskedBrush;
-#if 0
- if (X11->xrender_version > 10) {
- features |= QPaintEngine::LinearGradientFill;
- // ###
+#ifndef QT_NO_XRENDER
+ if (X11->xrender_version >= 6 && !getenv("QT_X11_NO_TRANSFORM")) { // XRender 0.6
+ features |= QPaintEngine::PixmapTransform;
+ features |= QPaintEngine::PerspectiveTransform;
}
#endif
+ if (X11->xrender_version >= 10 && !getenv("QT_X11_NO_LINEAR_GRADIENT")) { // XRender 0.10
+ features |= QPaintEngine::LinearGradientFill;
+ }
+ if (!getenv("QT_X11_NO_CONSTANT_OPACITY")) {
+ features |= QPaintEngine::ConstantOpacity;
+ }
+ if (getenv("QT_X11_EXTRA_FEATS")) {
+ char *end;
+ int f = (int) strtol(getenv("QT_X11_EXTRA_FEATS"), &end, 16);
+ features |= (QPaintEngine::PaintEngineFeature) f;
+ }
+ if (getenv("QT_X11_NO_FEATS")) {
+ char *end;
+ int f = (int) strtol(getenv("QT_X11_NO_FEATS"), &end, 16);
+ features &= ~((QPaintEngine::PaintEngineFeature) f);
+ }
}
return features;
@@ -833,7 +849,7 @@ void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
::Picture pict = d->picture;
if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1
- && (d->has_texture || d->has_alpha_brush))
+ && (d->has_texture || d->has_alpha_brush || d->has_gradient))
{
XRenderColor xc;
if (!d->has_texture && !d->has_pattern)
@@ -856,7 +872,10 @@ void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
if (r.isEmpty())
continue;
if (d->has_texture || d->has_pattern) {
- XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict,
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
+ XRenderComposite(d->dpy, d->composition_mode, d->current_brush, mask, pict,
qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()),
0, 0, r.x(), r.y(), r.width(), r.height());
} else {
@@ -1328,6 +1347,9 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
d->has_texture = bs == Qt::TexturePattern;
d->has_alpha_brush = brush.color().alpha() != 255;
d->has_alpha_texture = d->has_texture && d->cbrush.texture().hasAlphaChannel();
+ d->has_gradient = (bs == Qt::LinearGradientPattern
+ || bs == Qt::RadialGradientPattern
+ || bs == Qt::ConicalGradientPattern);
ulong mask = GCForeground | GCBackground | GCGraphicsExposures
| GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle;
@@ -1357,7 +1379,17 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
vals.join_style = JoinMiter;
vals.line_style = LineSolid;
- if (d->has_pattern || d->has_texture) {
+ if (d->has_pattern || d->has_texture || d->has_gradient) {
+#if !defined(QT_NO_XRENDER)
+ if (X11->use_xrender && d->opacity < 1.0) {
+ XRenderColor alpha = { 0, 0, 0, 0 };
+ if (d->opacity_mask_picture)
+ XRenderFreePicture(d->dpy, d->opacity_mask_picture);
+ alpha.alpha = (unsigned short) (d->opacity * 65535.0);
+ d->opacity_mask_picture = XRenderCreateSolidFill(d->dpy, &alpha);
+ }
+#endif
+
if (bs == Qt::TexturePattern) {
d->brush_pm = qt_toX11Pixmap(d->cbrush.texture());
#if !defined(QT_NO_XRENDER)
@@ -1370,6 +1402,36 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs);
}
#endif
+ } else if (bs == Qt::LinearGradientPattern) {
+#if !defined(QT_NO_XRENDER)
+ if (X11->use_xrender) {
+ if(d->brush_procedural_picture)
+ XRenderFreePicture(d->dpy, d->brush_procedural_picture);
+
+ const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient());
+ const QGradientStops s = g->stops();
+ const int n = s.size();
+
+ XLinearGradient geometry = {
+ { XDoubleToFixed(g->start().x()), XDoubleToFixed(g->start().y()) },
+ { XDoubleToFixed(g->finalStop().x()), XDoubleToFixed(g->finalStop().y()) }
+ };
+ XFixed stopPos[n];
+ XRenderColor stopVal[n];
+
+ for (int i = 0; i < n; i++) {
+ stopPos[i] = XDoubleToFixed(s[i].first);
+ stopVal[i].alpha = s[i].second.alpha() * 0x101;
+ stopVal[i].red = s[i].second.red() * 0x101;
+ stopVal[i].green = s[i].second.green() * 0x101;
+ stopVal[i].blue = s[i].second.blue() * 0x101;
+ }
+
+ d->brush_procedural_picture = XRenderCreateLinearGradient(
+ d->dpy, &geometry, stopPos, stopVal, n);
+ d->current_brush = d->brush_procedural_picture;
+ }
+#endif
} else {
d->brush_pm = qt_toX11Pixmap(qt_pixmapForBrush(bs, true));
}
@@ -1398,7 +1460,7 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
d->current_brush = d->bitmap_texture.x11PictureHandle();
}
#endif
- } else {
+ } else if (!d->has_gradient) {
mask |= GCTile;
#ifndef QT_NO_XRENDER
if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) {
@@ -1572,7 +1634,8 @@ void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int p
#ifndef QT_NO_XRENDER
//we use the pens brush
has_fill_texture = (fill.style() == Qt::TexturePattern);
- has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern);
+// has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern); // XXX
+ has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::LinearGradientPattern);
if (has_fill_texture)
src = fill.texture().x11PictureHandle();
else if (has_fill_pattern)
@@ -1924,8 +1987,29 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
sx, sy, x, y, sw, sh, d->cpen);
return;
} else if (pDepth != 1 && (pDepth == 32 || pDepth != d->pdev_depth)) {
- XRenderComposite(d->dpy, d->composition_mode,
- src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
+ QTransform t = d->systemTransform;
+
+ if (!t.isIdentity()) {
+ QRect before(sx, sy, sw, sh);
+ QRect after = t.mapRect(before);
+
+ x = after.x();
+ y = after.y();
+ sw = after.width();
+ sh = after.height();
+
+ // HACK: take the duplicate translate portion out of the matrix before inverting it
+ QTransform ti = QTransform(t.m11(), t.m12(), t.m13(), t.m21(), t.m22(), t.m23(), t.m31()-x, t.m32()-y, t.m33()).inverted();
+
+ XTransform trans = { {
+ { XDoubleToFixed(ti.m11()), XDoubleToFixed(ti.m21()), XDoubleToFixed(ti.m31()) },
+ { XDoubleToFixed(ti.m12()), XDoubleToFixed(ti.m22()), XDoubleToFixed(ti.m32()) },
+ { XDoubleToFixed(ti.m13()), XDoubleToFixed(ti.m23()), XDoubleToFixed(ti.m33()) }
+ } };
+ XRenderSetPictureTransform(d->dpy, src_pict, &trans);
+ // TODO XRenderSetPictureFilter() to enable smooth scaling/rotation
+ }
+ XRenderComposite(d->dpy, d->composition_mode, src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
return;
}
}
@@ -1990,7 +2074,33 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
restore_clip = true;
} else {
+#ifndef QT_NO_XRENDER
+ QTransform t = d->systemTransform;
+
+ if (!t.isIdentity()) {
+ QRect before(sx, sy, sw, sh);
+ QRect after = t.mapRect(before);
+
+ x = after.x();
+ y = after.y();
+ sw = after.width();
+ sh = after.height();
+
+ // HACK: take the duplicate translate portion out of the matrix before inverting it
+ QTransform ti = QTransform(t.m11(), t.m12(), t.m13(), t.m21(), t.m22(), t.m23(), t.m31()-x, t.m32()-y, t.m33()).inverted();
+
+ XTransform trans = { {
+ { XDoubleToFixed(ti.m11()), XDoubleToFixed(ti.m21()), XDoubleToFixed(ti.m31()) },
+ { XDoubleToFixed(ti.m12()), XDoubleToFixed(ti.m22()), XDoubleToFixed(ti.m32()) },
+ { XDoubleToFixed(ti.m13()), XDoubleToFixed(ti.m23()), XDoubleToFixed(ti.m33()) }
+ } };
+ XRenderSetPictureTransform(d->dpy, src_pict, &trans);
+ // TODO XRenderSetPictureFilter() to enable smooth scaling/rotation
+ }
+ XRenderComposite(d->dpy, d->composition_mode, src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
+#else
XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
+#endif
}
if (d->pdev->devType() == QInternal::Pixmap) {
diff --git a/src/gui/painting/qpaintengine_x11_p.h b/src/gui/painting/qpaintengine_x11_p.h
index c71000a..34d934e 100644
--- a/src/gui/painting/qpaintengine_x11_p.h
+++ b/src/gui/painting/qpaintengine_x11_p.h
@@ -196,6 +196,8 @@ public:
QPixmap brush_pm;
#if !defined (QT_NO_XRENDER)
Qt::HANDLE picture;
+ Qt::HANDLE brush_procedural_picture;
+ Qt::HANDLE opacity_mask_picture;
Qt::HANDLE current_brush;
QPixmap bitmap_texture;
int composition_mode;
@@ -227,6 +229,7 @@ public:
uint has_pattern : 1;
uint has_alpha_pen : 1;
uint has_alpha_brush : 1;
+ uint has_gradient : 1;
uint render_hints;
const QX11Info *xinfo;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 51b1164..a15f272 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5281,7 +5281,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
drawRect(pm.rect());
restore();
} else {
- if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
+ if (1 || !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
@@ -5405,10 +5405,11 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
drawRect(QRectF(0, 0, sw, sh));
restore();
} else {
- if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
+ if (1 || !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
+
d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
}
}
@@ -5563,7 +5564,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
}
if (d->state->matrix.type() == QTransform::TxTranslate
- && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
+ && (1 || !d->engine->hasFeature(QPaintEngine::PixmapTransform))) {
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
@@ -5675,7 +5676,7 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
}
if (d->state->matrix.type() == QTransform::TxTranslate
- && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
+ && (1 || !d->engine->hasFeature(QPaintEngine::PixmapTransform))) {
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
@@ -6447,7 +6448,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
qreal x = r.x();
qreal y = r.y();
if (d->state->matrix.type() == QTransform::TxTranslate
- && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
+ && (1 || !d->engine->hasFeature(QPaintEngine::PixmapTransform))) {
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
--
1.6.0.4
>From c24cb9ddd8b501d962a9013aa6cfa74fec188ae6 Mon Sep 17 00:00:00 2001
From: Jonathan Morton <[email protected]>
Date: Sun, 4 Jul 2010 04:49:00 +0300
Subject: [PATCH] Add remainder of ConstantOpacity support.
---
src/gui/painting/qpaintengine_x11.cpp | 35 ++++++++++++++++++++++++--------
1 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index 2f83383..f0c0bf6 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -871,7 +871,7 @@ void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
r = r.intersected(clip);
if (r.isEmpty())
continue;
- if (d->has_texture || d->has_pattern) {
+ if (d->has_texture || d->has_pattern || d->has_gradient) {
::Picture mask = 0;
if (d->opacity < 1.0)
mask = d->opacity_mask_picture;
@@ -2009,7 +2009,11 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
XRenderSetPictureTransform(d->dpy, src_pict, &trans);
// TODO XRenderSetPictureFilter() to enable smooth scaling/rotation
}
- XRenderComposite(d->dpy, d->composition_mode, src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
+
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
+ XRenderComposite(d->dpy, d->composition_mode, src_pict, mask, d->picture, sx, sy, 0, 0, x, y, sw, sh);
return;
}
}
@@ -2097,7 +2101,11 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
XRenderSetPictureTransform(d->dpy, src_pict, &trans);
// TODO XRenderSetPictureFilter() to enable smooth scaling/rotation
}
- XRenderComposite(d->dpy, d->composition_mode, src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
+
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
+ XRenderComposite(d->dpy, d->composition_mode, src_pict, mask, d->picture, sx, sy, 0, 0, x, y, sw, sh);
#else
XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
#endif
@@ -2235,8 +2243,11 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture,
sx, sy, x, y, w, h, d->cpen);
} else {
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
XRenderComposite(d->dpy, d->composition_mode,
- pixmap.x11PictureHandle(), XNone, d->picture,
+ pixmap.x11PictureHandle(), mask, d->picture,
sx, sy, 0, 0, x, y, w, h);
}
#else
@@ -2261,8 +2272,11 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture,
xOff, yOff, xPos, yPos, drawW, drawH, d->cpen);
} else {
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
XRenderComposite(d->dpy, d->composition_mode,
- pixmap.x11PictureHandle(), XNone, d->picture,
+ pixmap.x11PictureHandle(), mask, d->picture,
xOff, yOff, 0, 0, xPos, yPos, drawW, drawH);
}
xPos += drawW;
@@ -2287,8 +2301,11 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
const ::Picture pmPicture = pm.x11PictureHandle();
// first tile
+ ::Picture mask = 0;
+ if (d->opacity < 1.0)
+ mask = d->opacity_mask_picture;
XRenderComposite(d->dpy, mode,
- pixmap.x11PictureHandle(), XNone, pmPicture,
+ pixmap.x11PictureHandle(), mask, pmPicture,
0, 0, 0, 0, 0, 0, qMin(pw, pixmap.width()), qMin(ph, pixmap.height()));
// first row of tiles
@@ -2297,7 +2314,7 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
while (xPos < pw) {
const int sw = qMin(xPos, pw - xPos);
XRenderComposite(d->dpy, mode,
- pmPicture, XNone, pmPicture,
+ pmPicture, mask, pmPicture,
0, 0, 0, 0, xPos, 0, sw, sh);
xPos *= 2;
}
@@ -2308,7 +2325,7 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
while (yPos < ph) {
const int sh = qMin(yPos, ph - yPos);
XRenderComposite(d->dpy, mode,
- pmPicture, XNone, pmPicture,
+ pmPicture, mask, pmPicture,
0, 0, 0, 0, 0, yPos, sw, sh);
yPos *= 2;
}
@@ -2319,7 +2336,7 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
sx, sy, x, y, w, h, d->cpen);
else
XRenderComposite(d->dpy, d->composition_mode,
- pmPicture, XNone, d->picture,
+ pmPicture, mask, d->picture,
sx, sy, 0, 0, x, y, w, h);
}
#endif
--
1.6.0.4
_______________________________________________
webkit-qt mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-qt