Changeset 143537 in webkit


Ignore:
Timestamp:
Feb 20, 2013, 4:48:45 PM (13 years ago)
Author:
Simon Fraser
Message:

Zoomed, slow-scrolling pages keep recreating tiles when scrolled
https://bugs.webkit.org/show_bug.cgi?id=110379

Source/WebCore:

Reviewed by Tim Horton.

On slow-scrolling pages the TileCache makes the tiles the size of
the visible rect to minimize per-tile painting overhead. If the size
of that rect changes, the TileCache re-creates all the tiles.

This was a problem whem zoomed, because mapping the visible rect
through the scale transform and then rounding it would cause the
size to keep changing, causing lots of tile re-creation.

Fix by carrying the visibleRect around as a FloatRect, and doing
the same for the exposedRect. We then only expand to integers
when computing the tile size. This also fixes an issue where we could
sometimes make extra tiles because of fractional bits of tiles at the edges,
as shown by the test result change.

  • platform/graphics/TiledBacking.h:
  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::updateVisibleRect):

  • platform/graphics/ca/mac/TileCache.h:
  • platform/graphics/ca/mac/TileCache.mm:

(WebCore::TileCache::setVisibleRect):
(WebCore::TileCache::setExposedRect):
(WebCore::TileCache::prepopulateRect):
(WebCore::TileCache::computeTileCoverageRect):
(WebCore::TileCache::tileSizeForCoverageRect):
(WebCore::TileCache::blankPixelCountForTiles):
(WebCore::TileCache::revalidateTiles):
(WebCore::TileCache::ensureTilesForRect):

  • platform/graphics/ca/mac/WebTileLayer.mm:

(-[WebTileLayer logFilledFreshTile]):

Source/WebKit2:

Reviewed by Tim Horton.

Make the visible rect and exposed rects passed through
the drawing area to the tile cache FloatRects instead of IntRects.

  • UIProcess/API/mac/WKView.mm:

(-[WKView setFrameSize:]):
(-[WKView _updateWindowAndViewFrames]):
(-[WKView enableFrameSizeUpdates]):
(-[WKView setMinimumWidthForAutoLayout:]):

  • UIProcess/WebPageProxy.h:
  • UIProcess/mac/WebPageProxyMac.mm:

(WebKit::WebPageProxy::viewExposedRectChanged):

  • WebProcess/WebPage/DrawingArea.h:

(WebKit::DrawingArea::setExposedRect):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::viewExposedRectChanged):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:
  • WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:

(TiledCoreAnimationDrawingArea):

  • WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:

(WebKit::TiledCoreAnimationDrawingArea::setExposedRect):

LayoutTests:

Reviewed by Tim Horton.

This test now just has one tile, rather than four. There is an apparent issue
with the integral tile cache coverage rect being smaller than the visible rect.
This is caused by rounding when dumping the tile coverage rect.

  • platform/mac-wk2/tiled-drawing/tile-size-slow-zoomed-expected.txt:
Location:
trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r143535 r143537  
     12013-02-20  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Zoomed, slow-scrolling pages keep recreating tiles when scrolled
     4        https://bugs.webkit.org/show_bug.cgi?id=110379
     5
     6        Reviewed by Tim Horton.
     7       
     8        This test now just has one tile, rather than four. There is an apparent issue
     9        with the integral tile cache coverage rect being smaller than the visible rect.
     10        This is caused by rounding when dumping the tile coverage rect.
     11
     12        * platform/mac-wk2/tiled-drawing/tile-size-slow-zoomed-expected.txt:
     13
    1142013-02-20  Julien Chaffraix  <jchaffraix@webkit.org>
    215
  • trunk/LayoutTests/platform/mac-wk2/tiled-drawing/tile-size-slow-zoomed-expected.txt

    r143423 r143537  
    1111      (transform [1.70 0.00 0.00 0.00] [0.00 1.70 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
    1212      (visible rect 0.00, 0.00 461.76 x 344.12)
    13       (tile cache coverage 0, 0 784 x 584)
    14       (tile size 785 x 586)
    15       (top left tile 0, 0 tiles grid 2 x 2)
     13      (tile cache coverage 0, 0 461 x 344)
     14      (tile size 785 x 585)
     15      (top left tile 0, 0 tiles grid 1 x 1)
    1616      (children 1
    1717        (GraphicsLayer
  • trunk/Source/WebCore/ChangeLog

    r143536 r143537  
     12013-02-20  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Zoomed, slow-scrolling pages keep recreating tiles when scrolled
     4        https://bugs.webkit.org/show_bug.cgi?id=110379
     5
     6        Reviewed by Tim Horton.
     7
     8        On slow-scrolling pages the TileCache makes the tiles the size of
     9        the visible rect to minimize per-tile painting overhead. If the size
     10        of that rect changes, the TileCache re-creates all the tiles.
     11       
     12        This was a problem whem zoomed, because mapping the visible rect
     13        through the scale transform and then rounding it would cause the
     14        size to keep changing, causing lots of tile re-creation.
     15       
     16        Fix by carrying the visibleRect around as a FloatRect, and doing
     17        the same for the exposedRect. We then only expand to integers
     18        when computing the tile size. This also fixes an issue where we could
     19        sometimes make extra tiles because of fractional bits of tiles at the edges,
     20        as shown by the test result change.
     21
     22        * platform/graphics/TiledBacking.h:
     23        * platform/graphics/ca/GraphicsLayerCA.cpp:
     24        (WebCore::GraphicsLayerCA::updateVisibleRect):
     25        * platform/graphics/ca/mac/TileCache.h:
     26        * platform/graphics/ca/mac/TileCache.mm:
     27        (WebCore::TileCache::setVisibleRect):
     28        (WebCore::TileCache::setExposedRect):
     29        (WebCore::TileCache::prepopulateRect):
     30        (WebCore::TileCache::computeTileCoverageRect):
     31        (WebCore::TileCache::tileSizeForCoverageRect):
     32        (WebCore::TileCache::blankPixelCountForTiles):
     33        (WebCore::TileCache::revalidateTiles):
     34        (WebCore::TileCache::ensureTilesForRect):
     35        * platform/graphics/ca/mac/WebTileLayer.mm:
     36        (-[WebTileLayer logFilledFreshTile]):
     37
    1382013-02-20  Julien Chaffraix  <jchaffraix@webkit.org>
    239
  • trunk/Source/WebCore/platform/graphics/TiledBacking.h

    r139822 r143537  
    4545    virtual ~TiledBacking() { }
    4646
    47     virtual void setVisibleRect(const IntRect&) = 0;
    48     virtual IntRect visibleRect() const = 0;
     47    virtual void setVisibleRect(const FloatRect&) = 0;
     48    virtual FloatRect visibleRect() const = 0;
    4949
    50     virtual void setExposedRect(const IntRect&) = 0;
     50    virtual void setExposedRect(const FloatRect&) = 0;
    5151    virtual void setClipsToExposedRect(bool) = 0;
    5252
    53     virtual void prepopulateRect(const IntRect&) = 0;
     53    virtual void prepopulateRect(const FloatRect&) = 0;
    5454
    5555    virtual void setIsInWindow(bool) = 0;
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r143417 r143537  
    16221622        tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, m_sizeAtLastVisibleRectUpdate);
    16231623
    1624     tiledBacking()->setVisibleRect(enclosingIntRect(tileArea));
     1624    tiledBacking()->setVisibleRect(tileArea);
    16251625
    16261626    m_sizeAtLastVisibleRectUpdate = m_size;
  • trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.h

    r140475 r143537  
    2727#define TileCache_h
    2828
     29#include "FloatRect.h"
    2930#include "IntPointHash.h"
    3031#include "IntRect.h"
     
    7778    void setTileDebugBorderColor(CGColorRef);
    7879
    79     virtual IntRect visibleRect() const OVERRIDE { return m_visibleRect; }
     80    virtual FloatRect visibleRect() const OVERRIDE { return m_visibleRect; }
    8081
    8182    unsigned blankPixelCount() const;
    82     static unsigned blankPixelCountForTiles(const WebTileLayerList&, const IntRect&, const IntPoint&);
     83    static unsigned blankPixelCountForTiles(const WebTileLayerList&, const FloatRect&, const IntPoint&);
    8384
    8485    // Only public for the WebTileCacheMapLayer.
     
    106107
    107108    // TiledBacking member functions.
    108     virtual void setVisibleRect(const IntRect&) OVERRIDE;
    109     virtual void setExposedRect(const IntRect&) OVERRIDE;
     109    virtual void setVisibleRect(const FloatRect&) OVERRIDE;
     110    virtual void setExposedRect(const FloatRect&) OVERRIDE;
    110111    virtual void setClipsToExposedRect(bool) OVERRIDE;
    111     virtual void prepopulateRect(const IntRect&) OVERRIDE;
     112    virtual void prepopulateRect(const FloatRect&) OVERRIDE;
    112113    virtual void setIsInWindow(bool) OVERRIDE;
    113114    virtual void setTileCoverage(TileCoverage) OVERRIDE;
     
    131132    void getTileIndexRangeForRect(const IntRect&, TileIndex& topLeft, TileIndex& bottomRight) const;
    132133
    133     IntRect computeTileCoverageRect(const IntRect& previousVisibleRect) const;
    134     IntSize tileSizeForCoverageRect(const IntRect&) const;
     134    FloatRect computeTileCoverageRect(const FloatRect& previousVisibleRect) const;
     135    IntSize tileSizeForCoverageRect(const FloatRect&) const;
    135136
    136137    void scheduleTileRevalidation(double interval);
     
    143144
    144145    void revalidateTiles(TileValidationPolicyFlags foregroundValidationPolicy = 0, TileValidationPolicyFlags backgroundValidationPolicy = 0);
    145     void ensureTilesForRect(const IntRect&);
     146    void ensureTilesForRect(const FloatRect&);
    146147    void updateTileCoverageMap();
    147148
     
    169170
    170171    IntSize m_tileSize;
    171     IntRect m_visibleRect;
    172     IntRect m_visibleRectAtLastRevalidate;
    173     IntRect m_exposedRect; // The exposed area of containing platform views.
     172    FloatRect m_visibleRect;
     173    FloatRect m_visibleRectAtLastRevalidate;
     174    FloatRect m_exposedRect; // The exposed area of containing platform views.
    174175
    175176    typedef HashMap<TileIndex, TileInfo> TileMap;
  • trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm

    r143423 r143537  
    298298}
    299299
    300 void TileCache::setVisibleRect(const IntRect& visibleRect)
     300void TileCache::setVisibleRect(const FloatRect& visibleRect)
    301301{
    302302    if (m_visibleRect == visibleRect)
     
    307307}
    308308
    309 void TileCache::setExposedRect(const IntRect& exposedRect)
     309void TileCache::setExposedRect(const FloatRect& exposedRect)
    310310{
    311311    if (m_exposedRect == exposedRect)
     
    328328}
    329329
    330 void TileCache::prepopulateRect(const IntRect& rect)
     330void TileCache::prepopulateRect(const FloatRect& rect)
    331331{
    332332    ensureTilesForRect(rect);
     
    418418}
    419419
    420 IntRect TileCache::computeTileCoverageRect(const IntRect& previousVisibleRect) const
    421 {
    422     IntRect visibleRect = m_visibleRect;
     420FloatRect TileCache::computeTileCoverageRect(const FloatRect& previousVisibleRect) const
     421{
     422    FloatRect visibleRect = m_visibleRect;
    423423
    424424    if (m_clipsToExposedRect)
     
    434434   
    435435    // FIXME: look at how far the document can scroll in each dimension.
    436     int coverageHorizontalSize = visibleRect.width();
    437     int coverageVerticalSize = visibleRect.height();
     436    float coverageHorizontalSize = visibleRect.width();
     437    float coverageVerticalSize = visibleRect.height();
    438438   
    439439    // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height.
     
    447447
    448448    // Don't extend coverage before 0 or after the end.
    449     IntRect coverageBounds = bounds();
    450     int coverageLeft = visibleRect.x() - (coverageHorizontalSize - visibleRect.width()) / 2;
     449    FloatRect coverageBounds = bounds();
     450    float coverageLeft = visibleRect.x() - (coverageHorizontalSize - visibleRect.width()) / 2;
    451451    coverageLeft = min(coverageLeft, coverageBounds.maxX() - coverageHorizontalSize);
    452452    coverageLeft = max(coverageLeft, coverageBounds.x());
    453453
    454     int coverageTop = visibleRect.y() - (coverageVerticalSize - visibleRect.height()) / 2;
     454    float coverageTop = visibleRect.y() - (coverageVerticalSize - visibleRect.height()) / 2;
    455455    coverageTop = min(coverageTop, coverageBounds.maxY() - coverageVerticalSize);
    456456    coverageTop = max(coverageTop, coverageBounds.y());
    457457
    458     return IntRect(coverageLeft, coverageTop, coverageHorizontalSize, coverageVerticalSize);
    459 }
    460 
    461 IntSize TileCache::tileSizeForCoverageRect(const IntRect& coverageRect) const
     458    return FloatRect(coverageLeft, coverageTop, coverageHorizontalSize, coverageVerticalSize);
     459}
     460
     461IntSize TileCache::tileSizeForCoverageRect(const FloatRect& coverageRect) const
    462462{
    463463    if (m_tileCoverage & CoverageForSlowScrolling) {
    464         IntSize tileSize = coverageRect.size();
     464        FloatSize tileSize = coverageRect.size();
    465465        tileSize.scale(m_scale);
    466         return tileSize;
     466        return expandedIntSize(tileSize);
    467467    }
    468468
     
    496496}
    497497
    498 unsigned TileCache::blankPixelCountForTiles(const WebTileLayerList& tiles, const IntRect& visibleRect, const IntPoint& tileTranslation)
     498unsigned TileCache::blankPixelCountForTiles(const WebTileLayerList& tiles, const FloatRect& visibleRect, const IntPoint& tileTranslation)
    499499{
    500500    Region paintedVisibleTiles;
     
    503503        const WebTileLayer* tileLayer = it->get();
    504504
    505         IntRect visiblePart(CGRectOffset([tileLayer frame], tileTranslation.x(), tileTranslation.y()));
     505        FloatRect visiblePart(CGRectOffset([tileLayer frame], tileTranslation.x(), tileTranslation.y()));
    506506        visiblePart.intersect(visibleRect);
    507507
    508508        if (!visiblePart.isEmpty())
    509             paintedVisibleTiles.unite(visiblePart);
    510     }
    511 
    512     Region uncoveredRegion(visibleRect);
     509            paintedVisibleTiles.unite(enclosingIntRect(visiblePart));
     510    }
     511
     512    Region uncoveredRegion(enclosingIntRect(visibleRect));
    513513    uncoveredRegion.subtract(paintedVisibleTiles);
    514514
     
    582582        return;
    583583
    584     IntRect visibleRect = m_visibleRect;
     584    FloatRect visibleRect = m_visibleRect;
    585585
    586586    if (m_clipsToExposedRect)
     
    592592    TileValidationPolicyFlags validationPolicy = m_isInWindow ? foregroundValidationPolicy : backgroundValidationPolicy;
    593593   
    594     IntRect tileCoverageRect = computeTileCoverageRect(m_visibleRectAtLastRevalidate);
     594    FloatRect tileCoverageRect = computeTileCoverageRect(m_visibleRectAtLastRevalidate);
    595595    FloatRect scaledRect(tileCoverageRect);
    596596    scaledRect.scale(m_scale);
     
    751751}
    752752
    753 void TileCache::ensureTilesForRect(const IntRect& rect)
     753void TileCache::ensureTilesForRect(const FloatRect& rect)
    754754{
    755755    if (m_unparentsOffscreenTiles && !m_isInWindow)
  • trunk/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm

    r136774 r143537  
    7979- (void)logFilledFreshTile
    8080{
    81     IntRect visiblePart(enclosingIntRect([self frame]));
     81    FloatRect visiblePart([self frame]);
    8282    visiblePart.intersect(_tileCache->visibleRect());
    8383
  • trunk/Source/WebKit2/ChangeLog

    r143505 r143537  
     12013-02-20  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Zoomed, slow-scrolling pages keep recreating tiles when scrolled
     4        https://bugs.webkit.org/show_bug.cgi?id=110379
     5
     6        Reviewed by Tim Horton.
     7
     8        Make the visible rect and exposed rects passed through
     9        the drawing area to the tile cache FloatRects instead of IntRects.
     10
     11        * UIProcess/API/mac/WKView.mm:
     12        (-[WKView setFrameSize:]):
     13        (-[WKView _updateWindowAndViewFrames]):
     14        (-[WKView enableFrameSizeUpdates]):
     15        (-[WKView setMinimumWidthForAutoLayout:]):
     16        * UIProcess/WebPageProxy.h:
     17        * UIProcess/mac/WebPageProxyMac.mm:
     18        (WebKit::WebPageProxy::viewExposedRectChanged):
     19        * WebProcess/WebPage/DrawingArea.h:
     20        (WebKit::DrawingArea::setExposedRect):
     21        * WebProcess/WebPage/WebPage.cpp:
     22        (WebKit::WebPage::viewExposedRectChanged):
     23        * WebProcess/WebPage/WebPage.h:
     24        * WebProcess/WebPage/WebPage.messages.in:
     25        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
     26        (TiledCoreAnimationDrawingArea):
     27        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
     28        (WebKit::TiledCoreAnimationDrawingArea::setExposedRect):
     29
    1302013-02-20  Dirk Schulze  <krit@webkit.org>
    231
  • trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm

    r141173 r143537  
    383383    if (![self frameSizeUpdatesDisabled]) {
    384384        if (_data->_expandsToFitContentViaAutoLayout)
    385             _data->_page->viewExposedRectChanged(enclosingIntRect([self visibleRect]));
     385            _data->_page->viewExposedRectChanged([self visibleRect]);
    386386        [self _setDrawingAreaSize:size];
    387387    }
     
    399399    _data->_page->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates), IntPoint(accessibilityPosition));
    400400    if (_data->_expandsToFitContentViaAutoLayout)
    401         _data->_page->viewExposedRectChanged(enclosingIntRect([self visibleRect]));
     401        _data->_page->viewExposedRectChanged([self visibleRect]);
    402402}
    403403
     
    32033203    if (!(--_data->_frameSizeUpdatesDisabledCount)) {
    32043204        if (_data->_expandsToFitContentViaAutoLayout)
    3205             _data->_page->viewExposedRectChanged(enclosingIntRect([self visibleRect]));
     3205            _data->_page->viewExposedRectChanged([self visibleRect]);
    32063206        [self _setDrawingAreaSize:[self frame].size];
    32073207    }
     
    32643264
    32653265    if (expandsToFit)
    3266         _data->_page->viewExposedRectChanged(enclosingIntRect([self visibleRect]));
     3266        _data->_page->viewExposedRectChanged([self visibleRect]);
    32673267
    32683268    _data->_page->setMainFrameIsScrollable(!expandsToFit);
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r143474 r143537  
    383383    void updateWindowIsVisible(bool windowIsVisible);
    384384    void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates);
    385     void viewExposedRectChanged(const WebCore::IntRect& exposedRect);
     385    void viewExposedRectChanged(const WebCore::FloatRect& exposedRect);
    386386    void setMainFrameIsScrollable(bool);
    387387
  • trunk/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm

    r139822 r143537  
    138138}
    139139
    140 void WebPageProxy::viewExposedRectChanged(const IntRect& exposedRect)
     140void WebPageProxy::viewExposedRectChanged(const FloatRect& exposedRect)
    141141{
    142142    if (!isValid())
  • trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h

    r143472 r143537  
    8585    virtual void mainFrameContentSizeChanged(const WebCore::IntSize&) { }
    8686
    87     virtual void setExposedRect(const WebCore::IntRect&) { }
     87    virtual void setExposedRect(const WebCore::FloatRect&) { }
    8888    virtual void mainFrameScrollabilityChanged(bool) { }
    8989
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp

    r143474 r143537  
    29122912#endif
    29132913
    2914 void WebPage::viewExposedRectChanged(const IntRect& exposedRect)
     2914void WebPage::viewExposedRectChanged(const FloatRect& exposedRect)
    29152915{
    29162916    m_drawingArea->setExposedRect(exposedRect);
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r143474 r143537  
    722722#endif
    723723
    724     void viewExposedRectChanged(const WebCore::IntRect& exposedRect);
     724    void viewExposedRectChanged(const WebCore::FloatRect& exposedRect);
    725725    void setMainFrameIsScrollable(bool);
    726726
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

    r143474 r143537  
    257257    SetWindowIsVisible(bool windowIsVisible)
    258258    WindowAndViewFramesChanged(WebCore::IntRect windowFrameInScreenCoordinates, WebCore::IntRect viewFrameInWindowCoordinates, WebCore::IntPoint accessibilityViewCoordinates)
    259     ViewExposedRectChanged(WebCore::IntRect exposedRect)
     259    ViewExposedRectChanged(WebCore::FloatRect exposedRect)
    260260    SetMainFrameIsScrollable(bool isScrollable)
    261261    RegisterUIProcessAccessibilityTokens(CoreIPC::DataReference elemenToken, CoreIPC::DataReference windowToken)
  • trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h

    r143472 r143537  
    3131#include "DrawingArea.h"
    3232#include "LayerTreeContext.h"
     33#include <WebCore/FloatRect.h>
    3334#include <WebCore/GraphicsLayerClient.h>
    3435#include <WebCore/LayerFlushScheduler.h>
     
    7374    virtual void mainFrameContentSizeChanged(const WebCore::IntSize&) OVERRIDE;
    7475
    75     virtual void setExposedRect(const WebCore::IntRect&) OVERRIDE;
     76    virtual void setExposedRect(const WebCore::FloatRect&) OVERRIDE;
    7677    virtual void mainFrameScrollabilityChanged(bool) OVERRIDE;
    7778
     
    121122    bool m_hasRootCompositingLayer;
    122123
    123     WebCore::IntRect m_exposedRect;
     124    WebCore::FloatRect m_exposedRect;
    124125
    125126    WebCore::IntSize m_lastSentIntrinsicContentSize;
  • trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

    r143472 r143537  
    340340}
    341341
    342 void TiledCoreAnimationDrawingArea::setExposedRect(const IntRect& exposedRect)
     342void TiledCoreAnimationDrawingArea::setExposedRect(const FloatRect& exposedRect)
    343343{
    344344    // FIXME: This should be mapped through the scroll offset, but we need to keep it up to date.
Note: See TracChangeset for help on using the changeset viewer.