From kde-commits Mon Sep 15 04:31:12 2008 From: Germain Garand Date: Mon, 15 Sep 2008 04:31:12 +0000 To: kde-commits Subject: branches/KDE/4.1/kdelibs/khtml Message-Id: <1221453072.659736.19400.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=122145308221451 SVN commit 861089 by ggarand: automatically merged revision 861057: .avoid NVidia+Qt4 buffer clearing problems, by making our widgets have a private buffer. .for the same reason, always fully clear our shared opacity buffers - or we might get artifacts on NVidia cards such as on www.codetch.com/screenshots/ M +4 -1 misc/paintbuffer.h M +16 -2 rendering/render_layer.cpp M +2 -0 rendering/render_layer.h M +37 -14 rendering/render_replaced.cpp M +2 -1 rendering/render_replaced.h --- branches/KDE/4.1/kdelibs/khtml/misc/paintbuffer.h #861088:861089 @@ -86,7 +86,10 @@ BufferedPainter(QPixmap* px, QPainter*& p, const QRegion &rr, bool replacePainter) { QRect br = rr.boundingRect(); m_rect = br; - bool doFill = !px->hasAlphaChannel(); + bool doFill = 1 || !px->hasAlphaChannel(); // shared pixmaps aren't properly cleared + // with Qt 4 + NVidia proprietary driver. + // So we can't use this optimisation until + // we can detect this defect. if (doFill) px->fill(Qt::transparent); m_painter.begin(px); --- branches/KDE/4.1/kdelibs/khtml/rendering/render_layer.cpp #861088:861089 @@ -112,6 +112,8 @@ m_visibleContentStatusDirty = false; m_hasVisibleContent = object->style()->visibility() == VISIBLE; } + m_buffer[0] = 0; + m_buffer[1] = 0; } RenderLayer::~RenderLayer() @@ -120,6 +122,8 @@ // our destructor doesn't have to do anything. delete m_hBar; delete m_vBar; + delete m_buffer[0]; + delete m_buffer[1]; delete m_scrollMediator; delete m_posZOrderList; delete m_negZOrderList; @@ -945,12 +949,22 @@ return; if (m_hBar) { + if (!m_buffer[0] || m_buffer[0]->size() != m_hBar->size()) { + delete m_buffer[0]; + m_buffer[0] = new QPixmap( m_hBar->size() ); + } QPoint p = m_hBar->m_kwp->absolutePos(); - RenderWidget::paintWidget(pI, m_hBar, p.x(), p.y()); + RenderWidget::paintWidget(pI, m_hBar, p.x(), p.y(), m_buffer ); } if (m_vBar) { + if (!m_buffer[1] || m_buffer[1]->size() != m_vBar->size()) { + delete m_buffer[1]; + m_buffer[1] = new QPixmap( m_vBar->size() ); + } + QPixmap* tmp[1]; + tmp[0] = m_buffer[1]; QPoint p = m_vBar->m_kwp->absolutePos(); - RenderWidget::paintWidget(pI, m_vBar, p.x(), p.y()); + RenderWidget::paintWidget(pI, m_vBar, p.x(), p.y(), tmp); } } --- branches/KDE/4.1/kdelibs/khtml/rendering/render_layer.h #861088:861089 @@ -315,6 +315,8 @@ // For layers with overflow, we have a pair of scrollbars. ScrollBarWidget* m_hBar; ScrollBarWidget* m_vBar; + QPixmap* m_buffer[2]; + RenderScrollMediator* m_scrollMediator; // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the --- branches/KDE/4.1/kdelibs/khtml/rendering/render_replaced.cpp #861088:861089 @@ -188,6 +188,8 @@ { m_widget = 0; m_underMouse = 0; + m_buffer[0] = 0; + m_buffer[1] = 0; // a widget doesn't support being anonymous assert(!isAnonymous()); m_view = node->document()->view(); @@ -238,6 +240,8 @@ if (m_ownsWidget) m_widget->deleteLater(); } + delete m_buffer[0]; + delete m_buffer[1]; } class QWidgetResizeEvent : public QEvent @@ -637,8 +641,24 @@ else m_view->addChild( m_widget, xPos, -500000 +yPos); m_widget->show(); - if (khtmlw) - paintWidget(paintInfo, m_widget, xPos, yPos); + if (khtmlw) { + if ( KHTMLView* v = qobject_cast(m_widget) ) { + // our buffers are dedicated to scrollbars. + if (v->verticalScrollBar()->isVisible() && (!m_buffer[0] || v->verticalScrollBar()->size() != m_buffer[0]->size())) { + delete m_buffer[0]; + m_buffer[0] = new QPixmap( v->verticalScrollBar()->size() ); + } + if (v->horizontalScrollBar()->isVisible() && (!m_buffer[1] || v->horizontalScrollBar()->size() != m_buffer[1]->size())) { + delete m_buffer[1]; + m_buffer[1] = new QPixmap( v->horizontalScrollBar()->size() ); + } + } else if (!m_buffer[0] || (m_widget->size() != m_buffer[0]->size())) { + assert(!m_buffer[1]); + delete m_buffer[0]; + m_buffer[0] = new QPixmap( m_widget->size() ); + } + paintWidget(paintInfo, m_widget, xPos, yPos, m_buffer); + } } static void setInPaintEventFlag(QWidget* w, bool b = true, bool recurse=true) @@ -663,7 +683,7 @@ } } -static void copyWidget(const QRect& r, QPainter *p, QWidget *widget, int tx, int ty, bool buffered = false) +static void copyWidget(const QRect& r, QPainter *p, QWidget *widget, int tx, int ty, bool buffered = false, QPixmap* buffer = 0) { if (r.isNull() || r.isEmpty() ) return; @@ -688,11 +708,14 @@ if (buffered) { if (!widget->size().isValid()) return; - pm = PaintBuffer::grab(widget->size()); - // Qt 4.4 regression #1: - // QPainter::CompositionMode_Source is severly broken (cf. kde #160518) + // TT says Qt 4's widget painting hits an NVidia RenderAccel bug/shortcoming + // resulting in pixmap buffers being unsuitable for reuse by more than one widget. // - if (1 || !pm->hasAlphaChannel()) { + // Until a turnaround exist in Qt, we can't reliably use shared buffers. + // ### pm = PaintBuffer::grab(widget->size()); + assert( buffer ); + pm = buffer; + if (!pm->hasAlphaChannel()) { pm->fill(Qt::transparent); } else { QPainter pp(pm); @@ -701,7 +724,7 @@ } d = pm; } - // Qt 4.4 regression #2: + // Qt 4.4 regression #1: // can't let a painter active on the view as Qt thinks it is opened on the *pixmap* // and prints "paint device can only be painted by one painter at a time" warnings. // @@ -733,16 +756,16 @@ // transfer results QPoint off(r.x(), r.y()); p->drawPixmap(thePoint+off, static_cast(*d), r); - PaintBuffer::release(pm); + // ### PaintBuffer::release(pm); } } -void RenderWidget::paintWidget(PaintInfo& pI, QWidget *widget, int tx, int ty) +void RenderWidget::paintWidget(PaintInfo& pI, QWidget *widget, int tx, int ty, QPixmap* buffer[]) { QPainter* const p = pI.p; allowWidgetPaintEvents = true; - // Qt 4.4 regression #3: + // Qt 4.4 regression #2: // can't use QWidget::render to directly paint widgets on the view anymore. // Results are unreliable for subrects, leaving blank squares. (cf. kde #158607) // @@ -760,7 +783,7 @@ vbr &= r; vbr.translate( -of ); if (vbr.isValid() && !vbr.isEmpty()) - copyWidget(vbr, p, v->verticalScrollBar(), tx+of.x(), ty+of.y(), buffered); + copyWidget(vbr, p, v->verticalScrollBar(), tx+of.x(), ty+of.y(), buffered, buffer[0]); } if (v->horizontalScrollBar()->isVisible()) { QRect hbr = v->horizontalScrollBar()->rect(); @@ -769,13 +792,13 @@ hbr &= r; hbr.translate( -of ); if (hbr.isValid() && !hbr.isEmpty()) - copyWidget(hbr, p, v->horizontalScrollBar(), tx+ of.x(), ty+ of.y(), buffered); + copyWidget(hbr, p, v->horizontalScrollBar(), tx+ of.x(), ty+ of.y(), buffered, buffer[1]); } QRect vr = (r & v->viewport()->rect()); if (vr.isValid() && !vr.isEmpty()) v->render(p, vr, thePoint); } else { - copyWidget(r, p, widget, tx, ty, buffered); + copyWidget(r, p, widget, tx, ty, buffered, buffer[0]); } allowWidgetPaintEvents = false; } --- branches/KDE/4.1/kdelibs/khtml/rendering/render_replaced.h #861088:861089 @@ -101,7 +101,7 @@ void cancelPendingResize(); bool needsMask() const { return m_needsMask; } - static void paintWidget(PaintInfo& pI, QWidget *widget, int tx, int ty); + static void paintWidget(PaintInfo& pI, QWidget *widget, int tx, int ty, QPixmap* buffer[] = 0); virtual bool handleEvent(const DOM::EventImpl& ev); bool isRedirectedWidget() const; bool isDisabled() const { return m_widget && !m_widget->isEnabled(); } @@ -147,6 +147,7 @@ QWidget *m_widget; KHTMLView* m_view; QPointer m_underMouse; + QPixmap *m_buffer[2]; //Because we mess with normal detach due to ref/deref, //we need to keep track of the arena ourselves