WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
34681
[Qt] the above website does not render properly when in compositing mode
https://bugs.webkit.org/show_bug.cgi?id=34681
Summary
[Qt] the above website does not render properly when in compositing mode
Noam Rosenthal
Reported
2010-02-06 12:30:54 PST
This is due to a wrong path for rendering compositing masks - the opacity effect doesn't get updated when the mask is updated.
Attachments
GraphicsLayerQt: masks are now being handled outside the layer's paintEvent
(10.78 KB, patch)
2010-02-06 18:58 PST
,
Noam Rosenthal
ariya.hidayat
: review-
Details
Formatted Diff
Diff
Masks in GraphicsLayerQt; +added in-code comments
(10.62 KB, patch)
2010-02-07 23:08 PST
,
Noam Rosenthal
no flags
Details
Formatted Diff
Diff
Masks in GraphicsLayerQt; +added in-code comments +removed some whitespace
(10.65 KB, patch)
2010-02-07 23:53 PST
,
Noam Rosenthal
no flags
Details
Formatted Diff
Diff
Masks in GraphicsLayerQt; +added in-code comments +removed some whitespace +even more comments!
(10.81 KB, patch)
2010-02-08 11:45 PST
,
Noam Rosenthal
no flags
Details
Formatted Diff
Diff
Masks in GraphicsLayerQt; +removed unnecessary assert/whitepsace/funny English
(10.44 KB, patch)
2010-02-08 12:53 PST
,
Noam Rosenthal
no flags
Details
Formatted Diff
Diff
Show Obsolete
(4)
View All
Add attachment
proposed patch, testcase, etc.
Noam Rosenthal
Comment 1
2010-02-06 18:58:17 PST
Created
attachment 48302
[details]
GraphicsLayerQt: masks are now being handled outside the layer's paintEvent
Ariya Hidayat
Comment 2
2010-02-07 22:13:46 PST
Comment on
attachment 48302
[details]
GraphicsLayerQt: masks are now being handled outside the layer's paintEvent
> +class MaskEffectQt : public QGraphicsEffect {
If we still need to support Qt 4.5, better enclose this in #ifdef QT_VERSION for 4.6 and beyond. And yes, there should be an alternative code path for Qt 4.5 even if it means the test site will not work.
> + QPixmap srcPixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::NoPad); > + QPixmap pixmap(srcPixmap.size()); > + pixmap.fill(Qt::transparent); > + > + if (pixmap.isNull()) > + return; > + > + QPainter pixmapPainter(&pixmap); > + pixmapPainter.setRenderHints(painter->renderHints()); > + pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); > + pixmapPainter.drawPixmap(0, 0, srcPixmap);
That sounds inefficient. Why do you need to create 'pixmap', fill it transparent, then draw those pixels over again with srcPixmap? I guess, simple QPIxmap pixmap = srcPixmap should work (QPixmap will detach as soon as you start the pixmapPainter).
> + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); > + pixmapPainter.drawPixmap(0, 0, maskPixmap); > + pixmapPainter.end(); > + painter->drawPixmap(offset, pixmap);
Brings me another question: do we need 'pixmap' at all? Can't we just do: painter->save(); painter->setCompositionMode(QPainter::CompositionMode_Source); painter->drawPixmap(offset, srcPixmap); painter->setCompositionMode(QPainter::CompositionMode_DestinationIn); painter->drawPixmap(0, 0, maskPixmap); painter->restore();
> void GraphicsLayerQt::setBackgroundColor(const Color& c) > { > + if (c == backgroundColor()) > + return;
Is this necessary for this patch or is it actually a separate optimization? Otherwise, looks really good :)
Noam Rosenthal
Comment 3
2010-02-07 22:29:45 PST
Re. 4.5: the whole file GraphicsLayerQt.cpp will not be compiled in 4.5 anyway, see WebCore.pro. (In reply to
comment #2
)
> (From update of
attachment 48302
[details]
) > > +class MaskEffectQt : public QGraphicsEffect { > > If we still need to support Qt 4.5, better enclose this in #ifdef QT_VERSION > for 4.6 and beyond.
The whole GraphicsLayerQt.cpp file and the rest of the compositing features don't get compiled in 4.5 anyway, they rely on QAnimation and other goodies.
> That sounds inefficient. Why do you need to create 'pixmap', fill it > transparent, then draw those pixels over again with srcPixmap? > I guess, simple QPIxmap pixmap = srcPixmap should work (QPixmap will detach as > soon as you start the pixmapPainter).
It SEEMS inefficient, but it actually a lot more efficient! QPixmap::detach in OpenGL engine calls QPixmap::toImage, meaning copy from video memory to system memory. Painting to a new pixmap in video memory is a lot more efficient. Without this code path I end up with 10% of the total time in copying pixels from video memory to system memory (or so valgrind claims). See
http://bugreports.qt.nokia.com/browse/QTBUG-7986
The website I put as a test-case here runs with ~15fps now, and ~8FPS when I use QGraphicsOpacityEffect, which does the QPixmap detach thingy.
> > > > + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); > > + pixmapPainter.drawPixmap(0, 0, maskPixmap); > > + pixmapPainter.end(); > > + painter->drawPixmap(offset, pixmap); > > Brings me another question: do we need 'pixmap' at all? Can't we just do: > > painter->save(); > painter->setCompositionMode(QPainter::CompositionMode_Source); > painter->drawPixmap(offset, srcPixmap); > painter->setCompositionMode(QPainter::CompositionMode_DestinationIn); > painter->drawPixmap(0, 0, maskPixmap); > painter->restore();
Then I'd be setting a DestinationIn composition mode on the whole viewport in case I'm not in a cache-mode - potentially masking things I shouldn't. I tried this :)
> > > > void GraphicsLayerQt::setBackgroundColor(const Color& c) > > { > > + if (c == backgroundColor()) > > + return; > > Is this necessary for this patch or is it actually a separate optimization? >
Necessary for this patch. Apparently when I have manage the mask layer in the new way WebCore keeps calling setBackgroundColor with the old color, which constantly updates the layer.
Noam Rosenthal
Comment 4
2010-02-07 22:55:28 PST
Disregard the last remark - the BackgroundColor optimization is separate and not actually necessary.
Noam Rosenthal
Comment 5
2010-02-07 23:08:47 PST
Created
attachment 48321
[details]
Masks in GraphicsLayerQt; +added in-code comments Based on Ariya's comments: - Removed an optimization that's unrelated to the bug - Added in-code comments in places where I feel my approach is justified :)
Noam Rosenthal
Comment 6
2010-02-07 23:53:14 PST
Created
attachment 48323
[details]
Masks in GraphicsLayerQt; +added in-code comments +removed some whitespace oops, found some whitespace, saving a re-re-review
Ariya Hidayat
Comment 7
2010-02-08 09:40:10 PST
> The whole GraphicsLayerQt.cpp file and the rest of the compositing features > don't get compiled in 4.5 anyway, they rely on QAnimation and other goodies.
Ah OK, my bad, I missed that.
> It SEEMS inefficient, but it actually a lot more efficient! QPixmap::detach in > OpenGL engine calls QPixmap::toImage, meaning copy from video memory to system > memory. Painting to a new pixmap in video memory is a lot more efficient. > Without this code path I end up with 10% of the total time in copying pixels > from video memory to system memory (or so valgrind claims). > See
http://bugreports.qt.nokia.com/browse/QTBUG-7986
Seems that this is only for OpenGL graphics system? I can't imagine this is faster in X11 or raster engine, though. Also, even if you insist on doing that, is the Qt::transparent fill absolutely necessary? You replace all pixels in that pixmap (due to CompositionMode_Source) right after that.
> Then I'd be setting a DestinationIn composition mode on the whole viewport in > case I'm not in a cache-mode - potentially masking things I shouldn't. > I tried this :)
Even with clipping out QRect(offset, pixmap.size())?
Ariya Hidayat
Comment 8
2010-02-08 09:42:38 PST
> Even with clipping out QRect(offset, pixmap.size())?
Ignore this, I finally understood why you don't want to mask anything outside the item cache.
Noam Rosenthal
Comment 9
2010-02-08 10:34:04 PST
> > See
http://bugreports.qt.nokia.com/browse/QTBUG-7986
> > Seems that this is only for OpenGL graphics system? I can't imagine this is > faster in X11 or raster engine, though.
Drawing a pixmap I would think that detaching a QPixmap and drawing a QPixmap to another one should be similar cost on raster/X11, and definitely not as costly as detaching on OpenGL. Also I'd rather optimize for raster/OpenGL paint engines, which are what we use on embedded, rather than for the X11 paint engine which is slower for everything anyway :)
Noam Rosenthal
Comment 10
2010-02-08 11:17:13 PST
btw, the QPixmap::fill(Qt::transparent) is important to make the pixmap have "hasAlpha". any better way of doing that?
Ariya Hidayat
Comment 11
2010-02-08 11:29:24 PST
> I would think that detaching a QPixmap and drawing a QPixmap to another one > should be similar cost on raster/X11, and definitely not as costly as detaching > on OpenGL. Also I'd rather optimize for raster/OpenGL paint engines, which are > what we use on embedded, rather than for the X11 paint engine which is slower > for everything anyway :)
It's not the detach, it's because instead detach you have to do these 3 steps: Create a new pixmap with the same size Open a painter Draw srcPixmap before masking it. I suspect on X11/raster, these steps are faster: Create a copy of the pixmap Open a painter (implies a detach) Mask the pixmap And according to your test, these are faster on OpenGL: Create a new pixmap (from scratch) with the same size (Fill it with transparent pixels) Open a painter Draw srcPixmap Mask the pixmap Hence, my concerns that your approach will have an impact on non-GL engine. However, this is just a wild guess. A proper fps benchmark is necessary to justify the worry :)
Noam Rosenthal
Comment 12
2010-02-08 11:45:51 PST
Created
attachment 48348
[details]
Masks in GraphicsLayerQt; +added in-code comments +removed some whitespace +even more comments! Captured the comments thread in in-code comments
Kenneth Rohde Christiansen
Comment 13
2010-02-08 12:09:07 PST
Comment on
attachment 48348
[details]
Masks in GraphicsLayerQt; +added in-code comments +removed some whitespace +even more comments!
> + QPixmap srcPixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::NoPad); > + > +
One newline too much
> + if (m_state.drawsContent) { > + // this is the "expensive" bit. we try to minimize calls to this neck of the woods by proper caching
Better to get to the point, instead of using sophisticated/funny English :-)
> + Q_ASSERT(this);
I'm not sure if it is better to use WebCore ASSERT or not?
Noam Rosenthal
Comment 14
2010-02-08 12:53:22 PST
Created
attachment 48355
[details]
Masks in GraphicsLayerQt; +removed unnecessary assert/whitepsace/funny English
Noam Rosenthal
Comment 15
2010-02-08 22:41:50 PST
I saw that it failed the commit bot due to ChangeLog... do I need to resubmit?
WebKit Commit Bot
Comment 16
2010-02-09 02:08:06 PST
Comment on
attachment 48355
[details]
Masks in GraphicsLayerQt; +removed unnecessary assert/whitepsace/funny English Clearing flags on attachment: 48355 Committed
r54541
: <
http://trac.webkit.org/changeset/54541
>
WebKit Commit Bot
Comment 17
2010-02-09 02:08:12 PST
All reviewed patches have been landed. Closing bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug