Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2010, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "GLWebViewState.h"
     28 
     29 #if USE(ACCELERATED_COMPOSITING)
     30 
     31 #include "BaseLayerAndroid.h"
     32 #include "ClassTracker.h"
     33 #include "GLUtils.h"
     34 #include "ImagesManager.h"
     35 #include "LayerAndroid.h"
     36 #include "ScrollableLayerAndroid.h"
     37 #include "SkPath.h"
     38 #include "TilesManager.h"
     39 #include "TilesTracker.h"
     40 #include "TreeManager.h"
     41 #include <wtf/CurrentTime.h>
     42 
     43 #include <pthread.h>
     44 
     45 #include <cutils/log.h>
     46 #include <wtf/text/CString.h>
     47 
     48 #undef XLOGC
     49 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
     50 
     51 #ifdef DEBUG
     52 
     53 #undef XLOG
     54 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
     55 
     56 #else
     57 
     58 #undef XLOG
     59 #define XLOG(...)
     60 
     61 #endif // DEBUG
     62 
     63 #define FIRST_TILED_PAGE_ID 1
     64 #define SECOND_TILED_PAGE_ID 2
     65 
     66 #define FRAMERATE_CAP 0.01666 // We cap at 60 fps
     67 
     68 // log warnings if scale goes outside this range
     69 #define MIN_SCALE_WARNING 0.1
     70 #define MAX_SCALE_WARNING 10
     71 
     72 namespace WebCore {
     73 
     74 using namespace android;
     75 
     76 GLWebViewState::GLWebViewState()
     77     : m_zoomManager(this)
     78     , m_currentPictureCounter(0)
     79     , m_usePageA(true)
     80     , m_frameworkInval(0, 0, 0, 0)
     81     , m_frameworkLayersInval(0, 0, 0, 0)
     82     , m_isScrolling(false)
     83     , m_goingDown(true)
     84     , m_goingLeft(false)
     85     , m_expandedTileBoundsX(0)
     86     , m_expandedTileBoundsY(0)
     87     , m_highEndGfx(false)
     88     , m_scale(1)
     89     , m_layersRenderingMode(kAllTextures)
     90 {
     91     m_viewport.setEmpty();
     92     m_futureViewportTileBounds.setEmpty();
     93     m_viewportTileBounds.setEmpty();
     94     m_preZoomBounds.setEmpty();
     95 
     96     m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this);
     97     m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this);
     98 
     99 #ifdef DEBUG_COUNT
    100     ClassTracker::instance()->increment("GLWebViewState");
    101 #endif
    102 #ifdef MEASURES_PERF
    103     m_timeCounter = 0;
    104     m_totalTimeCounter = 0;
    105     m_measurePerfs = false;
    106 #endif
    107 }
    108 
    109 GLWebViewState::~GLWebViewState()
    110 {
    111     // Take care of the transfer queue such that Tex Gen thread will not stuck
    112     TilesManager::instance()->unregisterGLWebViewState(this);
    113 
    114     // We have to destroy the two tiled pages first as their destructor
    115     // may depend on the existence of this GLWebViewState and some of its
    116     // instance variables in order to complete.
    117     // Explicitely, currently we need to have the m_paintingBaseLayer around
    118     // in order to complete any pending paint operations (the tiled pages
    119     // will remove any pending operations, and wait if one is underway).
    120     delete m_tiledPageA;
    121     delete m_tiledPageB;
    122 #ifdef DEBUG_COUNT
    123     ClassTracker::instance()->decrement("GLWebViewState");
    124 #endif
    125 
    126 }
    127 
    128 void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval,
    129                                   bool showVisualIndicator, bool isPictureAfterFirstLayout)
    130 {
    131     if (!layer || isPictureAfterFirstLayout) {
    132         // TODO: move this into TreeManager
    133         m_zoomManager.swapPages(); // reset zoom state
    134         m_tiledPageA->discardTextures();
    135         m_tiledPageB->discardTextures();
    136         m_layersRenderingMode = kAllTextures;
    137     }
    138     if (layer) {
    139         XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0));
    140         layer->setState(this);
    141         layer->markAsDirty(inval); // TODO: set in webview.cpp
    142     }
    143     m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout);
    144     m_glExtras.setDrawExtra(0);
    145 
    146 #ifdef MEASURES_PERF
    147     if (m_measurePerfs && !showVisualIndicator)
    148         dumpMeasures();
    149     m_measurePerfs = showVisualIndicator;
    150 #endif
    151 
    152     TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
    153 }
    154 
    155 void GLWebViewState::scrollLayer(int layerId, int x, int y)
    156 {
    157     m_treeManager.updateScrollableLayer(layerId, x, y);
    158 
    159     // TODO: only inval the area of the scrolled layer instead of
    160     // doing a fullInval()
    161     if (m_layersRenderingMode == kSingleSurfaceRendering)
    162         fullInval();
    163 }
    164 
    165 void GLWebViewState::invalRegion(const SkRegion& region)
    166 {
    167     if (m_layersRenderingMode == kSingleSurfaceRendering) {
    168         // TODO: do the union of both layers tree to compute
    169         //the minimum inval instead of doing a fullInval()
    170         fullInval();
    171         return;
    172     }
    173     SkRegion::Iterator iterator(region);
    174     while (!iterator.done()) {
    175         SkIRect r = iterator.rect();
    176         IntRect ir(r.fLeft, r.fTop, r.width(), r.height());
    177         inval(ir);
    178         iterator.next();
    179     }
    180 }
    181 
    182 void GLWebViewState::inval(const IntRect& rect)
    183 {
    184     m_currentPictureCounter++;
    185     if (!rect.isEmpty()) {
    186         // find which tiles fall within the invalRect and mark them as dirty
    187         m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
    188         m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
    189         if (m_frameworkInval.isEmpty())
    190             m_frameworkInval = rect;
    191         else
    192             m_frameworkInval.unite(rect);
    193         XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
    194              m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
    195              rect.x(), rect.y(), rect.width(), rect.height());
    196     }
    197     TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
    198 }
    199 
    200 unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
    201 {
    202     m_treeManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering);
    203     return m_currentPictureCounter;
    204 }
    205 
    206 TiledPage* GLWebViewState::sibling(TiledPage* page)
    207 {
    208     return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA;
    209 }
    210 
    211 TiledPage* GLWebViewState::frontPage()
    212 {
    213     android::Mutex::Autolock lock(m_tiledPageLock);
    214     return m_usePageA ? m_tiledPageA : m_tiledPageB;
    215 }
    216 
    217 TiledPage* GLWebViewState::backPage()
    218 {
    219     android::Mutex::Autolock lock(m_tiledPageLock);
    220     return m_usePageA ? m_tiledPageB : m_tiledPageA;
    221 }
    222 
    223 void GLWebViewState::swapPages()
    224 {
    225     android::Mutex::Autolock lock(m_tiledPageLock);
    226     m_usePageA ^= true;
    227     TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA;
    228     zoomManager()->swapPages();
    229     oldPage->discardTextures();
    230 }
    231 
    232 int GLWebViewState::baseContentWidth()
    233 {
    234     return m_treeManager.baseContentWidth();
    235 }
    236 int GLWebViewState::baseContentHeight()
    237 {
    238     return m_treeManager.baseContentHeight();
    239 }
    240 
    241 void GLWebViewState::setViewport(SkRect& viewport, float scale)
    242 {
    243     if ((m_viewport == viewport) &&
    244         (zoomManager()->futureScale() == scale))
    245         return;
    246 
    247     m_goingDown = m_viewport.fTop - viewport.fTop <= 0;
    248     m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0;
    249     m_viewport = viewport;
    250 
    251     XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)",
    252          m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom,
    253          m_viewport.width(), m_viewport.height(), scale,
    254          zoomManager()->currentScale(), zoomManager()->futureScale());
    255 
    256     const float invTileContentWidth = scale / TilesManager::tileWidth();
    257     const float invTileContentHeight = scale / TilesManager::tileHeight();
    258 
    259     m_viewportTileBounds.set(
    260             static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)),
    261             static_cast<int>(floorf(viewport.fTop * invTileContentHeight)),
    262             static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)),
    263             static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight)));
    264 
    265     // allocate max possible number of tiles visible with this viewport
    266     int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1;
    267     int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1;
    268 
    269     int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) *
    270         (viewMaxTileY + m_expandedTileBoundsY * 2) * (m_highEndGfx ? 4 : 2);
    271 
    272     TilesManager::instance()->setMaxTextureCount(maxTextureCount);
    273     m_tiledPageA->updateBaseTileSize();
    274     m_tiledPageB->updateBaseTileSize();
    275 }
    276 
    277 #ifdef MEASURES_PERF
    278 void GLWebViewState::dumpMeasures()
    279 {
    280     for (int i = 0; i < m_timeCounter; i++) {
    281         XLOGC("%d delay: %d ms", m_totalTimeCounter + i,
    282              static_cast<int>(m_delayTimes[i]*1000));
    283         m_delayTimes[i] = 0;
    284     }
    285     m_totalTimeCounter += m_timeCounter;
    286     m_timeCounter = 0;
    287 }
    288 #endif // MEASURES_PERF
    289 
    290 void GLWebViewState::resetFrameworkInval()
    291 {
    292     m_frameworkInval.setX(0);
    293     m_frameworkInval.setY(0);
    294     m_frameworkInval.setWidth(0);
    295     m_frameworkInval.setHeight(0);
    296 }
    297 
    298 void GLWebViewState::addDirtyArea(const IntRect& rect)
    299 {
    300     if (rect.isEmpty())
    301         return;
    302 
    303     IntRect inflatedRect = rect;
    304     inflatedRect.inflate(8);
    305     if (m_frameworkLayersInval.isEmpty())
    306         m_frameworkLayersInval = inflatedRect;
    307     else
    308         m_frameworkLayersInval.unite(inflatedRect);
    309 }
    310 
    311 void GLWebViewState::resetLayersDirtyArea()
    312 {
    313     m_frameworkLayersInval.setX(0);
    314     m_frameworkLayersInval.setY(0);
    315     m_frameworkLayersInval.setWidth(0);
    316     m_frameworkLayersInval.setHeight(0);
    317 }
    318 
    319 void GLWebViewState::drawBackground(Color& backgroundColor)
    320 {
    321     if (TilesManager::instance()->invertedScreen()) {
    322         float color = 1.0 - ((((float) backgroundColor.red() / 255.0) +
    323                       ((float) backgroundColor.green() / 255.0) +
    324                       ((float) backgroundColor.blue() / 255.0)) / 3.0);
    325         glClearColor(color, color, color, 1);
    326     } else {
    327         glClearColor((float)backgroundColor.red() / 255.0,
    328                      (float)backgroundColor.green() / 255.0,
    329                      (float)backgroundColor.blue() / 255.0, 1);
    330     }
    331     glClear(GL_COLOR_BUFFER_BIT);
    332 }
    333 
    334 double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
    335                                     IntRect& webViewRect, int titleBarHeight,
    336                                     IntRect& screenClip, float scale)
    337 {
    338     int left = viewRect.x();
    339     int top = viewRect.y();
    340     int width = viewRect.width();
    341     int height = viewRect.height();
    342 
    343     ShaderProgram* shader = TilesManager::instance()->shader();
    344     if (shader->program() == -1) {
    345         XLOG("Reinit shader");
    346         shader->init();
    347     }
    348     shader->setViewport(visibleRect, scale);
    349     shader->setViewRect(viewRect);
    350     shader->setWebViewRect(webViewRect);
    351     shader->setTitleBarHeight(titleBarHeight);
    352     shader->setScreenClip(screenClip);
    353     shader->resetBlending();
    354 
    355     shader->calculateAnimationDelta();
    356 
    357     glViewport(left + shader->getAnimationDeltaX(),
    358                top - shader->getAnimationDeltaY(),
    359                width, height);
    360 
    361     double currentTime = WTF::currentTime();
    362 
    363     setViewport(visibleRect, scale);
    364     m_zoomManager.processNewScale(currentTime, scale);
    365 
    366     return currentTime;
    367 }
    368 
    369 bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded)
    370 {
    371     bool invalBase = false;
    372 
    373     if (!nbTexturesNeeded.full)
    374         TilesManager::instance()->setMaxLayerTextureCount(0);
    375     else
    376         TilesManager::instance()->setMaxLayerTextureCount((2*nbTexturesNeeded.full)+1);
    377 
    378     int maxTextures = TilesManager::instance()->maxLayerTextureCount();
    379     LayersRenderingMode layersRenderingMode = m_layersRenderingMode;
    380 
    381     if (m_layersRenderingMode == kSingleSurfaceRendering) {
    382         // only switch out of SingleSurface mode, if we have 2x needed textures
    383         // to avoid changing too often
    384         maxTextures /= 2;
    385     }
    386 
    387     m_layersRenderingMode = kSingleSurfaceRendering;
    388     if (nbTexturesNeeded.fixed < maxTextures)
    389         m_layersRenderingMode = kFixedLayers;
    390     if (nbTexturesNeeded.scrollable < maxTextures)
    391         m_layersRenderingMode = kScrollableAndFixedLayers;
    392     if (nbTexturesNeeded.clipped < maxTextures)
    393         m_layersRenderingMode = kClippedTextures;
    394     if (nbTexturesNeeded.full < maxTextures)
    395         m_layersRenderingMode = kAllTextures;
    396 
    397     if (!maxTextures && !nbTexturesNeeded.full)
    398         m_layersRenderingMode = kAllTextures;
    399 
    400     if (m_layersRenderingMode < layersRenderingMode
    401         && m_layersRenderingMode != kAllTextures)
    402         invalBase = true;
    403 
    404     if (m_layersRenderingMode > layersRenderingMode
    405         && m_layersRenderingMode != kClippedTextures)
    406         invalBase = true;
    407 
    408 #ifdef DEBUG
    409     if (m_layersRenderingMode != layersRenderingMode) {
    410         char* mode[] = { "kAllTextures", "kClippedTextures",
    411             "kScrollableAndFixedLayers", "kFixedLayers", "kSingleSurfaceRendering" };
    412         XLOGC("Change from mode %s to %s -- We need textures: fixed: %d,"
    413               " scrollable: %d, clipped: %d, full: %d, max textures: %d",
    414               static_cast<char*>(mode[layersRenderingMode]),
    415               static_cast<char*>(mode[m_layersRenderingMode]),
    416               nbTexturesNeeded.fixed,
    417               nbTexturesNeeded.scrollable,
    418               nbTexturesNeeded.clipped,
    419               nbTexturesNeeded.full, maxTextures);
    420     }
    421 #endif
    422 
    423     // For now, anything below kClippedTextures is equivalent
    424     // to kSingleSurfaceRendering
    425     // TODO: implement the other rendering modes
    426     if (m_layersRenderingMode > kClippedTextures)
    427         m_layersRenderingMode = kSingleSurfaceRendering;
    428 
    429     // update the base surface if needed
    430     if (m_layersRenderingMode != layersRenderingMode
    431         && invalBase) {
    432         m_tiledPageA->discardTextures();
    433         m_tiledPageB->discardTextures();
    434         fullInval();
    435         return true;
    436     }
    437     return false;
    438 }
    439 
    440 void GLWebViewState::fullInval()
    441 {
    442     // TODO -- use base layer's size.
    443     IntRect ir(0, 0, 1E6, 1E6);
    444     inval(ir);
    445 }
    446 
    447 bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
    448                             IntRect& webViewRect, int titleBarHeight,
    449                             IntRect& clip, float scale,
    450                             bool* treesSwappedPtr, bool* newTreeHasAnimPtr)
    451 {
    452     m_scale = scale;
    453     TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
    454                                                        viewport.fTop,
    455                                                        viewport.fRight,
    456                                                        viewport.fBottom,
    457                                                        scale);
    458     TilesManager::instance()->incDrawGLCount();
    459 
    460 #ifdef DEBUG
    461     TilesManager::instance()->getTilesTracker()->clear();
    462 #endif
    463 
    464     float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO;
    465     float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO;
    466     bool useMinimalMemory = TilesManager::instance()->useMinimalMemory();
    467     bool useHorzPrefetch = useMinimalMemory ? 0 : viewWidth < baseContentWidth();
    468     bool useVertPrefetch = useMinimalMemory ? 0 : viewHeight < baseContentHeight();
    469     m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
    470     m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
    471 
    472     XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)",
    473          rect.x(), rect.y(), rect.width(), rect.height(),
    474          viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom);
    475 
    476     resetLayersDirtyArea();
    477 
    478     // when adding or removing layers, use the the paintingBaseLayer's tree so
    479     // that content that moves to the base layer from a layer is synchronized
    480 
    481     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
    482         XLOGC("WARNING, scale seems corrupted before update: %e", scale);
    483 
    484     // Here before we draw, update the BaseTile which has updated content.
    485     // Inside this function, just do GPU blits from the transfer queue into
    486     // the BaseTiles' texture.
    487     TilesManager::instance()->transferQueue()->updateDirtyBaseTiles();
    488 
    489     // Upload any pending ImageTexture
    490     // Return true if we still have some images to upload.
    491     // TODO: upload as many textures as possible within a certain time limit
    492     bool ret = ImagesManager::instance()->prepareTextures(this);
    493 
    494     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
    495         XLOGC("WARNING, scale seems corrupted after update: %e", scale);
    496 
    497     // gather the textures we can use
    498     TilesManager::instance()->gatherLayerTextures();
    499 
    500     double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
    501 
    502 
    503     TexturesResult nbTexturesNeeded;
    504     bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering;
    505     ret |= m_treeManager.drawGL(currentTime, rect, viewport,
    506                                 scale, fastSwap,
    507                                 treesSwappedPtr, newTreeHasAnimPtr,
    508                                 &nbTexturesNeeded);
    509     if (!ret)
    510         resetFrameworkInval();
    511 
    512     int nbTexturesForImages = ImagesManager::instance()->nbTextures();
    513     XLOG("*** We have %d textures for images, %d full, %d clipped, total %d / %d",
    514           nbTexturesForImages, nbTexturesNeeded.full, nbTexturesNeeded.clipped,
    515           nbTexturesNeeded.full + nbTexturesForImages,
    516           nbTexturesNeeded.clipped + nbTexturesForImages);
    517     nbTexturesNeeded.full += nbTexturesForImages;
    518     nbTexturesNeeded.clipped += nbTexturesForImages;
    519     ret |= setLayersRenderingMode(nbTexturesNeeded);
    520 
    521     FloatRect extrasclip(0, 0, rect.width(), rect.height());
    522     TilesManager::instance()->shader()->clip(extrasclip);
    523 
    524     m_glExtras.drawGL(webViewRect, viewport, titleBarHeight);
    525 
    526     glBindBuffer(GL_ARRAY_BUFFER, 0);
    527 
    528     // Clean up GL textures for video layer.
    529     TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
    530     ret |= TilesManager::instance()->invertedScreenSwitch();
    531 
    532     if (ret) {
    533         // ret==true && empty inval region means we've inval'd everything,
    534         // but don't have new content. Keep redrawing full view (0,0,0,0)
    535         // until tile generation catches up and we swap pages.
    536         bool fullScreenInval = m_frameworkInval.isEmpty();
    537 
    538         if (TilesManager::instance()->invertedScreenSwitch()) {
    539             fullScreenInval = true;
    540             TilesManager::instance()->setInvertedScreenSwitch(false);
    541         }
    542 
    543         if (!fullScreenInval) {
    544             FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord(
    545                     m_frameworkInval);
    546             // Inflate the invalidate rect to avoid precision lost.
    547             frameworkInval.inflate(1);
    548             IntRect inval(frameworkInval.x(), frameworkInval.y(),
    549                     frameworkInval.width(), frameworkInval.height());
    550 
    551             inval.unite(m_frameworkLayersInval);
    552 
    553             invalRect->setX(inval.x());
    554             invalRect->setY(inval.y());
    555             invalRect->setWidth(inval.width());
    556             invalRect->setHeight(inval.height());
    557 
    558             XLOG("invalRect(%d, %d, %d, %d)", inval.x(),
    559                     inval.y(), inval.width(), inval.height());
    560 
    561             if (!invalRect->intersects(rect)) {
    562                 // invalidate is occurring offscreen, do full inval to guarantee redraw
    563                 fullScreenInval = true;
    564             }
    565         }
    566 
    567         if (fullScreenInval) {
    568             invalRect->setX(0);
    569             invalRect->setY(0);
    570             invalRect->setWidth(0);
    571             invalRect->setHeight(0);
    572         }
    573     } else {
    574         resetFrameworkInval();
    575     }
    576 
    577 #ifdef MEASURES_PERF
    578     if (m_measurePerfs) {
    579         m_delayTimes[m_timeCounter++] = delta;
    580         if (m_timeCounter >= MAX_MEASURES_PERF)
    581             dumpMeasures();
    582     }
    583 #endif
    584 
    585 #ifdef DEBUG
    586     TilesManager::instance()->getTilesTracker()->showTrackTextures();
    587     ImagesManager::instance()->showImages();
    588 #endif
    589 
    590     return ret;
    591 }
    592 
    593 } // namespace WebCore
    594 
    595 #endif // USE(ACCELERATED_COMPOSITING)
    596