Bug 114938

Summary: Background painting tries to paint too much
Product: [Applications] konqueror Reporter: estevam
Component: generalAssignee: Konqueror Developers <konq-bugs>
Status: RESOLVED FIXED    
Severity: normal CC: maksim, raditzman, thundercloud
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description estevam 2005-10-23 15:14:24 UTC
Version:           3.4.3 (using KDE 3.4.3 Level "b" , SUSE 10.0 UNSUPPORTED)
Compiler:          Target: i586-suse-linux
OS:                Linux (i686) release 2.6.13-15-default

Try to visit http://www.largadoemguarapari.blogspot.com and Konqueror will work very slow. 100% of cpu usage!
Comment 1 Maksim Orlovich 2005-10-23 17:14:26 UTC
Here is where it's getting stuck:
#7  0xb7069eb5 in QPainter::drawTiledPixmap () from /opt/kde3.4/lib/libqt-mt.so.3
#8  0xb63d5b81 in khtml::RenderBox::paintBackgroundExtended (this=0x84f24f8, p=0x84bf5d0, c=@0xbfaa200c,
    bgLayer=0x851b254, clipy=706, cliph=128, _tx=0, _ty=0, w=780, h=34323, bleft=0, bright=0)
    at /home/maksim/kde3/kdelibs/khtml/rendering/render_box.cpp:539


538             if (cw>0 && ch>0)
539                 p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c), sx, sy);

(gdb) print ch
34323

this should clearly use cliph!
Comment 2 estevam 2005-11-17 03:55:34 UTC
Same problem in 3.5RC1. Fix it pls!
Comment 3 Maksim Orlovich 2006-01-19 19:13:50 UTC
*** Bug 107812 has been marked as a duplicate of this bug. ***
Comment 4 Maksim Orlovich 2006-01-19 21:48:02 UTC
*** Bug 111218 has been marked as a duplicate of this bug. ***
Comment 5 Maksim Orlovich 2006-01-26 16:40:11 UTC
SVN commit 502582 by orlovich:

Speedup: Cleanup and consolidate the tiled_pixmap background handling code into just one path.
This adds preblend and fixes other bugs in the alpha-specific path I added. 
The net result is that some web pages paint a lot faster. In particular, most of the stuff in 
#114938 and its dupes are pretty decent now. (I still need to investigate whether there 
was some truth in my original analysis, though, so keeping it open for now until I talk it over
with Carewolf)

Thanks to BCoppens and FredrikH for help with this, in particular in spotting the real problem.
CCBUG:114938


 M  +20 -59    loader.cpp  


--- branches/KDE/3.5/kdelibs/khtml/misc/loader.cpp #502581:502582
@@ -492,8 +492,8 @@
 
 const QPixmap &CachedImage::tiled_pixmap(const QColor& newc)
 {
-    static QRgb bgTransparant = qRgba( 0, 0, 0, 0xFF );
-    if ( (bgColor != bgTransparant) && (bgColor != newc.rgb()) ) {
+    static QRgb bgTransparent = qRgba( 0, 0, 0, 0xFF );
+    if ( (bgColor != bgTransparent) && (bgColor != newc.rgb()) ) {
         delete bg; bg = 0;
     }
 
@@ -511,6 +511,21 @@
     QSize s(pixmap_size());
     int w = r.width();
     int h = r.height();
+
+    const QPixmap* src; //source for pretiling, if any
+    //See whether we can - and should - pre-blend
+    if (isvalid && (r.hasAlphaChannel() || r.mask() )) {
+        bg = new QPixmap(w, h);
+        bg->fill(newc);
+        bitBlt(bg, 0, 0, &r);
+        bgColor = newc.rgb();
+        src     = bg;
+    } else {
+        src     = &r;
+        bgColor = bgTransparent;
+    }
+
+    //See whether to pre-tile.
     if ( w*h < 8192 )
     {
         if ( r.width() < BGMINWIDTH )
@@ -519,74 +534,20 @@
             h = ((BGMINHEIGHT / s.height())+1) * s.height();
     }
 
-#ifdef Q_WS_X11
-    if ( r.hasAlphaChannel() &&
-         ((w != r.width()) || (h != r.height())) )
+    if ( w != r.width() || h != r.height() )
     {
         bg = new QPixmap(w, h);
         //Tile horizontally on the first stripe
         for (int x = 0; x < w; x += r.width())
-            copyBlt(bg, x, 0, &r, 0, 0, r.width(), r.height());
+            copyBlt(bg, x, 0, src, 0, 0, r.width(), r.height());
 
         //Copy first stripe down
         for (int y = r.height(); y < h; y += r.height())
             copyBlt(bg, 0, y, bg, 0, 0, w, r.height());
-
-        return *bg;
     }
-#endif
 
-    if (
-#ifdef Q_WS_X11
-        !r.hasAlphaChannel() &&
-#endif
-        ( (w != r.width()) || (h != r.height()) || (isvalid && r.mask())) )
-    {
-        QPixmap pix = r;
-        if ( w != r.width() || (isvalid && pix.mask()))
-        {
-            bg = new QPixmap(w, r.height());
-            QPainter p(bg);
-            if(isvalid) p.fillRect(0, 0, w, r.height(), newc);
-            p.drawTiledPixmap(0, 0, w, r.height(), pix);
-            p.end();
-
-            if(!isvalid && pix.mask())
-            {
-                // unfortunately our anti-transparency trick doesn't work here
-                // we need to create a mask.
-                QBitmap newmask(w, r.height());
-                QPainter pm(&newmask);
-                pm.drawTiledPixmap(0, 0, w, r.height(), *pix.mask());
-                bg->setMask(newmask);
-                bgColor = bgTransparant;
-            }
-            else
-                bgColor= newc.rgb();
-            pix = *bg;
-        }
-        if ( h != r.height() )
-        {
-            delete bg;
-            bg = new QPixmap(w, h);
-            QPainter p(bg);
-            if(isvalid) p.fillRect(0, 0, w, h, newc);
-            p.drawTiledPixmap(0, 0, w, h, pix);
-            if(!isvalid && pix.mask())
-            {
-                // unfortunately our anti-transparency trick doesn't work here
-                // we need to create a mask.
-                QBitmap newmask(w, h);
-                QPainter pm(&newmask);
-                pm.drawTiledPixmap(0, 0, w, h, *pix.mask());
-                bg->setMask(newmask);
-                bgColor = bgTransparant;
-            }
-            else
-                bgColor= newc.rgb();
-        }
+    if (bg)
         return *bg;
-    }
 
     return r;
 }
Comment 6 Leo Spalteholz 2006-04-01 01:08:52 UTC
Well with 3.5.2 this seems to be mostly fixed.  At least konqueror doesn't slow down very much.  There is something weird still going on though.  When I load the page, konqueror CPU is low, but then climbs to about 30% as I scroll down the page.  Then the CPU usage of Xorg goes to about 65% and stays there.  When I click "stop animations", konqueror CPU usage goes to zero, and xorg drops to 30%.  This happens even with no animated images on the screen. 
Comment 7 Allan Sandfeld 2006-06-19 23:35:36 UTC
The exact complain of this bug report have been fixed in 3.5.3 (background restrained to clip). And the linked webpage doesn't seem so slow either.