OSDN Git Service

85fa23f4b3a79a1da6b858412b2b572fa3ad343e
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / GLWebViewState.cpp
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 "LayerAndroid.h"
35 #include "SkPath.h"
36 #include "TilesManager.h"
37 #include "TilesTracker.h"
38 #include <wtf/CurrentTime.h>
39
40 #include <cutils/log.h>
41 #include <wtf/text/CString.h>
42
43 #undef XLOGC
44 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
45
46 #ifdef DEBUG
47
48 #undef XLOG
49 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
50
51 #else
52
53 #undef XLOG
54 #define XLOG(...)
55
56 #endif // DEBUG
57
58 #define FIRST_TILED_PAGE_ID 1
59 #define SECOND_TILED_PAGE_ID 2
60
61 #define FRAMERATE_CAP 0.01666 // We cap at 60 fps
62
63 // Touch ring border width. This is doubled if the ring is not pressed
64 #define RING_BORDER_WIDTH 1
65 // Color of the ring is 0x6633b5e5 (copied from framework)
66 #define RING_COLOR_ALPHA 0.4
67 #define RING_COLOR_R 0x33
68 #define RING_COLOR_G 0xb5
69 #define RING_COLOR_B 0xe5
70
71 // log warnings if scale goes outside this range
72 #define MIN_SCALE_WARNING 0.1
73 #define MAX_SCALE_WARNING 10
74
75 namespace WebCore {
76
77 using namespace android;
78
79 GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
80     : m_zoomManager(this)
81     , m_baseLayer(0)
82     , m_currentBaseLayer(0)
83     , m_previouslyUsedRoot(0)
84     , m_currentPictureCounter(0)
85     , m_usePageA(true)
86     , m_frameworkInval(0, 0, 0, 0)
87     , m_frameworkLayersInval(0, 0, 0, 0)
88     , m_globalButtonMutex(buttonMutex)
89     , m_baseLayerUpdate(true)
90     , m_backgroundColor(SK_ColorWHITE)
91     , m_displayRings(false)
92     , m_focusRingTexture(-1)
93     , m_isScrolling(false)
94     , m_goingDown(true)
95     , m_goingLeft(false)
96     , m_expandedTileBoundsX(0)
97     , m_expandedTileBoundsY(0)
98 {
99     m_viewport.setEmpty();
100     m_futureViewportTileBounds.setEmpty();
101     m_viewportTileBounds.setEmpty();
102     m_preZoomBounds.setEmpty();
103
104     m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this);
105     m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this);
106
107 #ifdef DEBUG_COUNT
108     ClassTracker::instance()->increment("GLWebViewState");
109 #endif
110 #ifdef MEASURES_PERF
111     m_timeCounter = 0;
112     m_totalTimeCounter = 0;
113     m_measurePerfs = false;
114 #endif
115 }
116
117 GLWebViewState::~GLWebViewState()
118 {
119     // Unref the existing tree/PaintedSurfaces
120     if (m_previouslyUsedRoot)
121         TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, 0);
122
123     // Take care of the transfer queue such that Tex Gen thread will not stuck
124     TilesManager::instance()->unregisterGLWebViewState(this);
125
126     // We have to destroy the two tiled pages first as their destructor
127     // may depend on the existence of this GLWebViewState and some of its
128     // instance variables in order to complete.
129     // Explicitely, currently we need to have the m_currentBaseLayer around
130     // in order to complete any pending paint operations (the tiled pages
131     // will remove any pending operations, and wait if one is underway).
132     delete m_tiledPageA;
133     delete m_tiledPageB;
134     SkSafeUnref(m_previouslyUsedRoot);
135     SkSafeUnref(m_currentBaseLayer);
136     SkSafeUnref(m_baseLayer);
137     m_previouslyUsedRoot = 0;
138     m_baseLayer = 0;
139     m_currentBaseLayer = 0;
140 #ifdef DEBUG_COUNT
141     ClassTracker::instance()->decrement("GLWebViewState");
142 #endif
143
144 }
145
146 void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval,
147                                   bool showVisualIndicator, bool isPictureAfterFirstLayout)
148 {
149     android::Mutex::Autolock lock(m_baseLayerLock);
150     if (!layer || isPictureAfterFirstLayout) {
151         m_tiledPageA->discardTextures();
152         m_tiledPageB->discardTextures();
153     }
154     if (isPictureAfterFirstLayout) {
155         m_baseLayerUpdate = true;
156         m_invalidateRegion.setEmpty();
157     }
158     if (m_baseLayer && layer)
159         m_baseLayer->swapExtra(layer);
160
161     SkSafeRef(layer);
162     SkSafeUnref(m_baseLayer);
163     m_baseLayer = layer;
164     if (m_baseLayer)
165         m_baseLayer->setGLWebViewState(this);
166
167     // We only update the layers if we are not currently
168     // waiting for a tiledPage to be painted
169     if (m_baseLayerUpdate) {
170         SkSafeRef(layer);
171         SkSafeUnref(m_currentBaseLayer);
172         m_currentBaseLayer = layer;
173     }
174     m_displayRings = false;
175     invalRegion(inval);
176
177 #ifdef MEASURES_PERF
178     if (m_measurePerfs && !showVisualIndicator)
179         dumpMeasures();
180     m_measurePerfs = showVisualIndicator;
181 #endif
182
183     TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
184 }
185
186 void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed)
187 {
188     android::Mutex::Autolock lock(m_baseLayerLock);
189     m_displayRings = true;
190     m_rings.setEmpty();
191     for (size_t i = 0; i < rings.size(); i++) {
192         if (i == 0)
193             m_rings.setRect(rings.at(i));
194         else
195             m_rings.op(rings.at(i), SkRegion::kUnion_Op);
196     }
197     m_ringsIsPressed = isPressed;
198 }
199
200 void GLWebViewState::invalRegion(const SkRegion& region)
201 {
202     SkRegion::Iterator iterator(region);
203     while (!iterator.done()) {
204         SkIRect r = iterator.rect();
205         IntRect ir(r.fLeft, r.fTop, r.width(), r.height());
206         inval(ir);
207         iterator.next();
208     }
209 }
210
211 void GLWebViewState::unlockBaseLayerUpdate() {
212     if (m_baseLayerUpdate)
213         return;
214
215     m_baseLayerUpdate = true;
216     android::Mutex::Autolock lock(m_baseLayerLock);
217     SkSafeRef(m_baseLayer);
218     SkSafeUnref(m_currentBaseLayer);
219     m_currentBaseLayer = m_baseLayer;
220
221     invalRegion(m_invalidateRegion);
222     m_invalidateRegion.setEmpty();
223 }
224
225 void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture,
226     const IntRect& rect, bool allowSame)
227 {
228     android::Mutex::Autolock lock(m_baseLayerLock);
229     if (!m_baseLayerUpdate)
230         return;
231
232     layer->setExtra(picture);
233
234     if (!allowSame && m_lastInval == rect)
235         return;
236
237     if (!rect.isEmpty())
238         inval(rect);
239     if (!m_lastInval.isEmpty())
240         inval(m_lastInval);
241     m_lastInval = rect;
242     m_displayRings = false;
243 }
244
245 void GLWebViewState::inval(const IntRect& rect)
246 {
247     if (m_baseLayerUpdate) {
248         // base layer isn't locked, so go ahead and issue the inval to both tiled pages
249         m_currentPictureCounter++;
250         if (!rect.isEmpty()) {
251             // find which tiles fall within the invalRect and mark them as dirty
252             frontPage()->invalidateRect(rect, m_currentPictureCounter);
253             if (m_frameworkInval.isEmpty())
254                 m_frameworkInval = rect;
255             else
256                 m_frameworkInval.unite(rect);
257             XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
258                  m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
259                  rect.x(), rect.y(), rect.width(), rect.height());
260         }
261     } else {
262         // base layer is locked, so defer invalidation until unlockBaseLayerUpdate()
263         m_invalidateRegion.op(rect.x(), rect.y(), rect.maxX(), rect.maxY(), SkRegion::kUnion_Op);
264     }
265     TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
266 }
267
268 void GLWebViewState::resetRings()
269 {
270     m_displayRings = false;
271 }
272
273 void GLWebViewState::drawFocusRing(SkRect& srcRect)
274 {
275     if (m_focusRingTexture == -1)
276         m_focusRingTexture = GLUtils::createSampleColorTexture(RING_COLOR_R,
277                                                                RING_COLOR_G,
278                                                                RING_COLOR_B);
279
280     TilesManager::instance()->shader()->drawQuad(srcRect, m_focusRingTexture,
281                                                  RING_COLOR_ALPHA);
282 }
283
284 void GLWebViewState::paintExtras()
285 {
286     if (m_displayRings && !m_rings.isEmpty()) {
287         if (m_ringsIsPressed) {
288             SkRegion::Iterator rgnIter(m_rings);
289             while (!rgnIter.done()) {
290                 SkIRect ir = rgnIter.rect();
291                 SkRect r;
292                 r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
293                 drawFocusRing(r);
294                 rgnIter.next();
295             }
296         }
297         SkPath path;
298         if (!m_rings.getBoundaryPath(&path))
299             return;
300         SkPath::Iter iter(path, true);
301         SkPath::Verb verb;
302         SkPoint pts[4];
303         SkRegion clip;
304         SkIRect startRect;
305         while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
306             if (verb == SkPath::kLine_Verb) {
307                 SkRect r;
308                 r.set(pts, 2);
309                 SkIRect line;
310                 int borderWidth = RING_BORDER_WIDTH;
311                 if (!m_ringsIsPressed)
312                     borderWidth *= 2;
313                 line.fLeft = r.fLeft - borderWidth;
314                 line.fRight = r.fRight + borderWidth;
315                 line.fTop = r.fTop - borderWidth;
316                 line.fBottom = r.fBottom + borderWidth;
317                 if (clip.intersects(line)) {
318                     clip.op(line, SkRegion::kReverseDifference_Op);
319                     if (clip.isEmpty())
320                         continue; // Nothing to draw, continue
321                     line = clip.getBounds();
322                     if (SkIRect::Intersects(startRect, line)) {
323                         clip.op(startRect, SkRegion::kDifference_Op);
324                         if (clip.isEmpty())
325                             continue; // Nothing to draw, continue
326                         line = clip.getBounds();
327                     }
328                 } else {
329                     clip.setRect(line);
330                 }
331                 r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
332                 drawFocusRing(r);
333                 if (!m_ringsIsPressed) {
334                     r.fLeft += RING_BORDER_WIDTH;
335                     r.fRight -= RING_BORDER_WIDTH;
336                     r.fTop += RING_BORDER_WIDTH;
337                     r.fBottom -= RING_BORDER_WIDTH;
338                     drawFocusRing(r);
339                 }
340                 if (startRect.isEmpty()) {
341                     startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
342                 }
343             }
344             if (verb == SkPath::kMove_Verb) {
345                 startRect.setEmpty();
346             }
347         }
348     }
349 }
350
351 unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
352 {
353     android::Mutex::Autolock lock(m_baseLayerLock);
354     if (m_currentBaseLayer) {
355         m_globalButtonMutex->lock();
356         m_currentBaseLayer->drawCanvas(canvas);
357         m_globalButtonMutex->unlock();
358     }
359     return m_currentPictureCounter;
360 }
361
362 TiledPage* GLWebViewState::sibling(TiledPage* page)
363 {
364     return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA;
365 }
366
367 TiledPage* GLWebViewState::frontPage()
368 {
369     android::Mutex::Autolock lock(m_tiledPageLock);
370     return m_usePageA ? m_tiledPageA : m_tiledPageB;
371 }
372
373 TiledPage* GLWebViewState::backPage()
374 {
375     android::Mutex::Autolock lock(m_tiledPageLock);
376     return m_usePageA ? m_tiledPageB : m_tiledPageA;
377 }
378
379 void GLWebViewState::swapPages()
380 {
381     android::Mutex::Autolock lock(m_tiledPageLock);
382     m_usePageA ^= true;
383     TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA;
384     zoomManager()->swapPages();
385     oldPage->discardTextures();
386 }
387
388 int GLWebViewState::baseContentWidth()
389 {
390     return m_currentBaseLayer ? m_currentBaseLayer->content()->width() : 0;
391 }
392 int GLWebViewState::baseContentHeight()
393 {
394     return m_currentBaseLayer ? m_currentBaseLayer->content()->height() : 0;
395 }
396
397 void GLWebViewState::setViewport(SkRect& viewport, float scale)
398 {
399     if ((m_viewport == viewport) &&
400         (zoomManager()->futureScale() == scale))
401         return;
402
403     m_goingDown = m_viewport.fTop - viewport.fTop <= 0;
404     m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0;
405     m_viewport = viewport;
406
407     XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)",
408          m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom,
409          m_viewport.width(), m_viewport.height(), scale,
410          zoomManager()->currentScale(), zoomManager()->futureScale());
411
412     const float invTileContentWidth = scale / TilesManager::tileWidth();
413     const float invTileContentHeight = scale / TilesManager::tileHeight();
414
415     m_viewportTileBounds.set(
416             static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)),
417             static_cast<int>(floorf(viewport.fTop * invTileContentHeight)),
418             static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)),
419             static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight)));
420
421     // allocate max possible number of tiles visible with this viewport
422     int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1;
423     int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1;
424     int maxTextureCount = (viewMaxTileX + TILE_PREFETCH_DISTANCE * 2) *
425         (viewMaxTileY + TILE_PREFETCH_DISTANCE * 2) * 2;
426     TilesManager::instance()->setMaxTextureCount(maxTextureCount);
427     m_tiledPageA->updateBaseTileSize();
428     m_tiledPageB->updateBaseTileSize();
429 }
430
431 #ifdef MEASURES_PERF
432 void GLWebViewState::dumpMeasures()
433 {
434     for (int i = 0; i < m_timeCounter; i++) {
435         XLOGC("%d delay: %d ms", m_totalTimeCounter + i,
436              static_cast<int>(m_delayTimes[i]*1000));
437         m_delayTimes[i] = 0;
438     }
439     m_totalTimeCounter += m_timeCounter;
440     m_timeCounter = 0;
441 }
442 #endif // MEASURES_PERF
443
444 void GLWebViewState::resetFrameworkInval()
445 {
446     m_frameworkInval.setX(0);
447     m_frameworkInval.setY(0);
448     m_frameworkInval.setWidth(0);
449     m_frameworkInval.setHeight(0);
450 }
451
452 void GLWebViewState::addDirtyArea(const IntRect& rect)
453 {
454     if (rect.isEmpty())
455         return;
456
457     IntRect inflatedRect = rect;
458     inflatedRect.inflate(8);
459     if (m_frameworkLayersInval.isEmpty())
460         m_frameworkLayersInval = inflatedRect;
461     else
462         m_frameworkLayersInval.unite(inflatedRect);
463 }
464
465 void GLWebViewState::resetLayersDirtyArea()
466 {
467     m_frameworkLayersInval.setX(0);
468     m_frameworkLayersInval.setY(0);
469     m_frameworkLayersInval.setWidth(0);
470     m_frameworkLayersInval.setHeight(0);
471 }
472
473 double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
474                                   IntRect& webViewRect, int titleBarHeight,
475                                   IntRect& screenClip, float scale)
476 {
477     int left = viewRect.x();
478     int top = viewRect.y();
479     int width = viewRect.width();
480     int height = viewRect.height();
481
482     if (TilesManager::instance()->invertedScreen()) {
483         float color = 1.0 - ((((float) m_backgroundColor.red() / 255.0) +
484                       ((float) m_backgroundColor.green() / 255.0) +
485                       ((float) m_backgroundColor.blue() / 255.0)) / 3.0);
486         glClearColor(color, color, color, 1);
487     } else {
488         glClearColor((float)m_backgroundColor.red() / 255.0,
489                      (float)m_backgroundColor.green() / 255.0,
490                      (float)m_backgroundColor.blue() / 255.0, 1);
491     }
492     glClear(GL_COLOR_BUFFER_BIT);
493
494     glViewport(left, top, width, height);
495
496     ShaderProgram* shader = TilesManager::instance()->shader();
497     if (shader->program() == -1) {
498         XLOG("Reinit shader");
499         shader->init();
500     }
501     glUseProgram(shader->program());
502     glUniform1i(shader->textureSampler(), 0);
503     shader->setViewRect(viewRect);
504     shader->setViewport(visibleRect);
505     shader->setWebViewRect(webViewRect);
506     shader->setTitleBarHeight(titleBarHeight);
507     shader->setScreenClip(screenClip);
508     shader->resetBlending();
509
510     double currentTime = WTF::currentTime();
511
512     setViewport(visibleRect, scale);
513     m_zoomManager.processNewScale(currentTime, scale);
514
515     return currentTime;
516 }
517
518 bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
519                             IntRect& webViewRect, int titleBarHeight,
520                             IntRect& clip, float scale, bool* buffersSwappedPtr)
521 {
522     TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
523                                                        viewport.fTop,
524                                                        viewport.fRight,
525                                                        viewport.fBottom,
526                                                        scale);
527     TilesManager::instance()->incDrawGLCount();
528
529 #ifdef DEBUG
530     TilesManager::instance()->getTilesTracker()->clear();
531 #endif
532
533     m_baseLayerLock.lock();
534     BaseLayerAndroid* baseLayer = m_currentBaseLayer;
535     SkSafeRef(baseLayer);
536     BaseLayerAndroid* baseForComposited = m_baseLayer;
537     SkSafeRef(baseForComposited);
538     m_baseLayerLock.unlock();
539     if (!baseLayer) {
540         SkSafeUnref(baseForComposited);
541         return false;
542     }
543
544     float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO;
545     float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO;
546     bool useHorzPrefetch = viewWidth < baseContentWidth();
547     bool useVertPrefetch = viewHeight < baseContentHeight();
548     m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
549     m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
550
551     XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)",
552          rect.x(), rect.y(), rect.width(), rect.height(),
553          viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom);
554
555     resetLayersDirtyArea();
556
557     if (!baseForComposited ||
558         (baseForComposited && !baseForComposited->countChildren())) {
559         SkSafeRef(baseLayer);
560         SkSafeUnref(baseForComposited);
561         baseForComposited = baseLayer;
562     }
563
564     LayerAndroid* compositedRoot = 0;
565     if (baseForComposited && baseForComposited->countChildren() >= 1)
566         compositedRoot = static_cast<LayerAndroid*>(baseForComposited->getChild(0));
567
568     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
569         XLOGC("WARNING, scale seems corrupted before update: %e", scale);
570
571     // Here before we draw, update the BaseTile which has updated content.
572     // Inside this function, just do GPU blits from the transfer queue into
573     // the BaseTiles' texture.
574     TilesManager::instance()->transferQueue()->updateDirtyBaseTiles();
575
576     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) {
577         XLOGC("WARNING, scale seems corrupted after update: %e", scale);
578         CRASH();
579     }
580
581     // gather the textures we can use
582     TilesManager::instance()->gatherLayerTextures();
583
584     if (compositedRoot != m_previouslyUsedRoot)
585         TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot);
586
587     // set up zoom manager, shaders, etc.
588     m_backgroundColor = baseLayer->getBackgroundColor();
589     double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
590     bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect,
591                                  viewport, scale, buffersSwappedPtr);
592     // Reset the clip to make sure we can draw the rings. If this isn't done, the
593     // current clip will be the clip of whatever layer was last drawn
594     TilesManager::instance()->shader()->clip(clip);
595     paintExtras();
596
597     glBindBuffer(GL_ARRAY_BUFFER, 0);
598
599     SkSafeRef(compositedRoot);
600     SkSafeUnref(m_previouslyUsedRoot);
601     m_previouslyUsedRoot = compositedRoot;
602
603     ret |= TilesManager::instance()->invertedScreenSwitch();
604
605     if (ret) {
606         // ret==true && empty inval region means we've inval'd everything,
607         // but don't have new content. Keep redrawing full view (0,0,0,0)
608         // until tile generation catches up and we swap pages.
609         bool fullScreenInval = m_frameworkInval.isEmpty();
610
611         if (TilesManager::instance()->invertedScreenSwitch()) {
612             fullScreenInval = true;
613             TilesManager::instance()->setInvertedScreenSwitch(false);
614         }
615
616         if (!fullScreenInval) {
617             FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord(
618                     m_frameworkInval);
619             // Inflate the invalidate rect to avoid precision lost.
620             frameworkInval.inflate(1);
621             IntRect inval(frameworkInval.x(), frameworkInval.y(),
622                     frameworkInval.width(), frameworkInval.height());
623
624             inval.unite(m_frameworkLayersInval);
625
626             invalRect->setX(inval.x());
627             invalRect->setY(inval.y());
628             invalRect->setWidth(inval.width());
629             invalRect->setHeight(inval.height());
630
631             XLOG("invalRect(%d, %d, %d, %d)", inval.x(),
632                     inval.y(), inval.width(), inval.height());
633
634             if (!invalRect->intersects(rect)) {
635                 // invalidate is occurring offscreen, do full inval to guarantee redraw
636                 fullScreenInval = true;
637             }
638         }
639
640         if (fullScreenInval) {
641             invalRect->setX(0);
642             invalRect->setY(0);
643             invalRect->setWidth(0);
644             invalRect->setHeight(0);
645         }
646     } else {
647         resetFrameworkInval();
648     }
649
650 #ifdef MEASURES_PERF
651     if (m_measurePerfs) {
652         m_delayTimes[m_timeCounter++] = delta;
653         if (m_timeCounter >= MAX_MEASURES_PERF)
654             dumpMeasures();
655     }
656 #endif
657
658     SkSafeUnref(baseForComposited);
659     SkSafeUnref(baseLayer);
660 #ifdef DEBUG
661     TilesManager::instance()->getTilesTracker()->showTrackTextures();
662     TilesManager::instance()->showImages();
663 #endif
664     return ret;
665 }
666
667 } // namespace WebCore
668
669 #endif // USE(ACCELERATED_COMPOSITING)