OSDN Git Service

2f62223f90e11734cd442a2c9b4180ba2b0bb900
[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, bool isButton)
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     m_ringsIsButton = isButton;
199 }
200
201 void GLWebViewState::invalRegion(const SkRegion& region)
202 {
203     SkRegion::Iterator iterator(region);
204     while (!iterator.done()) {
205         SkIRect r = iterator.rect();
206         IntRect ir(r.fLeft, r.fTop, r.width(), r.height());
207         inval(ir);
208         iterator.next();
209     }
210 }
211
212 void GLWebViewState::unlockBaseLayerUpdate() {
213     if (m_baseLayerUpdate)
214         return;
215
216     m_baseLayerUpdate = true;
217     android::Mutex::Autolock lock(m_baseLayerLock);
218     SkSafeRef(m_baseLayer);
219     SkSafeUnref(m_currentBaseLayer);
220     m_currentBaseLayer = m_baseLayer;
221
222     invalRegion(m_invalidateRegion);
223     m_invalidateRegion.setEmpty();
224 }
225
226 void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture,
227     const IntRect& rect, bool allowSame)
228 {
229     android::Mutex::Autolock lock(m_baseLayerLock);
230     if (!m_baseLayerUpdate)
231         return;
232
233     layer->setExtra(picture);
234
235     if (!allowSame && m_lastInval == rect)
236         return;
237
238     if (!rect.isEmpty())
239         inval(rect);
240     if (!m_lastInval.isEmpty())
241         inval(m_lastInval);
242     m_lastInval = rect;
243     m_displayRings = false;
244 }
245
246 void GLWebViewState::inval(const IntRect& rect)
247 {
248     if (m_baseLayerUpdate) {
249         // base layer isn't locked, so go ahead and issue the inval to both tiled pages
250         m_currentPictureCounter++;
251         if (!rect.isEmpty()) {
252             // find which tiles fall within the invalRect and mark them as dirty
253             frontPage()->invalidateRect(rect, m_currentPictureCounter);
254             if (m_frameworkInval.isEmpty())
255                 m_frameworkInval = rect;
256             else
257                 m_frameworkInval.unite(rect);
258             XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
259                  m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
260                  rect.x(), rect.y(), rect.width(), rect.height());
261         }
262     } else {
263         // base layer is locked, so defer invalidation until unlockBaseLayerUpdate()
264         m_invalidateRegion.op(rect.x(), rect.y(), rect.maxX(), rect.maxY(), SkRegion::kUnion_Op);
265     }
266     TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
267 }
268
269 void GLWebViewState::resetRings()
270 {
271     m_displayRings = false;
272 }
273
274 void GLWebViewState::drawFocusRing(SkRect& srcRect)
275 {
276     if (m_focusRingTexture == -1)
277         m_focusRingTexture = GLUtils::createSampleColorTexture(RING_COLOR_R,
278                                                                RING_COLOR_G,
279                                                                RING_COLOR_B);
280
281     TilesManager::instance()->shader()->drawQuad(srcRect, m_focusRingTexture,
282                                                  RING_COLOR_ALPHA);
283 }
284
285 void GLWebViewState::paintExtras()
286 {
287     if (m_displayRings && !m_rings.isEmpty()) {
288         if (m_ringsIsPressed) {
289             SkRegion::Iterator rgnIter(m_rings);
290             while (!rgnIter.done()) {
291                 SkIRect ir = rgnIter.rect();
292                 SkRect r;
293                 r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
294                 drawFocusRing(r);
295                 rgnIter.next();
296             }
297         }
298         if (m_ringsIsButton && m_ringsIsPressed)
299             return;
300         SkPath path;
301         if (!m_rings.getBoundaryPath(&path))
302             return;
303         SkPath::Iter iter(path, true);
304         SkPath::Verb verb;
305         SkPoint pts[4];
306         SkRegion clip;
307         SkIRect startRect;
308         while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
309             if (verb == SkPath::kLine_Verb) {
310                 SkRect r;
311                 r.set(pts, 2);
312                 SkIRect line;
313                 int borderWidth = RING_BORDER_WIDTH;
314                 if (!m_ringsIsPressed)
315                     borderWidth *= 2;
316                 line.fLeft = r.fLeft - borderWidth;
317                 line.fRight = r.fRight + borderWidth;
318                 line.fTop = r.fTop - borderWidth;
319                 line.fBottom = r.fBottom + borderWidth;
320                 if (clip.intersects(line)) {
321                     clip.op(line, SkRegion::kReverseDifference_Op);
322                     if (clip.isEmpty())
323                         continue; // Nothing to draw, continue
324                     line = clip.getBounds();
325                     if (SkIRect::Intersects(startRect, line)) {
326                         clip.op(startRect, SkRegion::kDifference_Op);
327                         if (clip.isEmpty())
328                             continue; // Nothing to draw, continue
329                         line = clip.getBounds();
330                     }
331                 } else {
332                     clip.setRect(line);
333                 }
334                 r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
335                 drawFocusRing(r);
336                 if (!m_ringsIsPressed) {
337                     r.fLeft += RING_BORDER_WIDTH;
338                     r.fRight -= RING_BORDER_WIDTH;
339                     r.fTop += RING_BORDER_WIDTH;
340                     r.fBottom -= RING_BORDER_WIDTH;
341                     drawFocusRing(r);
342                 }
343                 if (startRect.isEmpty()) {
344                     startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
345                 }
346             }
347             if (verb == SkPath::kMove_Verb) {
348                 startRect.setEmpty();
349             }
350         }
351     }
352 }
353
354 unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
355 {
356     android::Mutex::Autolock lock(m_baseLayerLock);
357     if (m_currentBaseLayer) {
358         m_globalButtonMutex->lock();
359         m_currentBaseLayer->drawCanvas(canvas);
360         m_globalButtonMutex->unlock();
361     }
362     return m_currentPictureCounter;
363 }
364
365 TiledPage* GLWebViewState::sibling(TiledPage* page)
366 {
367     return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA;
368 }
369
370 TiledPage* GLWebViewState::frontPage()
371 {
372     android::Mutex::Autolock lock(m_tiledPageLock);
373     return m_usePageA ? m_tiledPageA : m_tiledPageB;
374 }
375
376 TiledPage* GLWebViewState::backPage()
377 {
378     android::Mutex::Autolock lock(m_tiledPageLock);
379     return m_usePageA ? m_tiledPageB : m_tiledPageA;
380 }
381
382 void GLWebViewState::swapPages()
383 {
384     android::Mutex::Autolock lock(m_tiledPageLock);
385     m_usePageA ^= true;
386     TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA;
387     zoomManager()->swapPages();
388     oldPage->discardTextures();
389 }
390
391 int GLWebViewState::baseContentWidth()
392 {
393     return m_currentBaseLayer ? m_currentBaseLayer->content()->width() : 0;
394 }
395 int GLWebViewState::baseContentHeight()
396 {
397     return m_currentBaseLayer ? m_currentBaseLayer->content()->height() : 0;
398 }
399
400 void GLWebViewState::setViewport(SkRect& viewport, float scale)
401 {
402     if ((m_viewport == viewport) &&
403         (zoomManager()->futureScale() == scale))
404         return;
405
406     m_goingDown = m_viewport.fTop - viewport.fTop <= 0;
407     m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0;
408     m_viewport = viewport;
409
410     XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)",
411          m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom,
412          m_viewport.width(), m_viewport.height(), scale,
413          zoomManager()->currentScale(), zoomManager()->futureScale());
414
415     const float invTileContentWidth = scale / TilesManager::tileWidth();
416     const float invTileContentHeight = scale / TilesManager::tileHeight();
417
418     m_viewportTileBounds.set(
419             static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)),
420             static_cast<int>(floorf(viewport.fTop * invTileContentHeight)),
421             static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)),
422             static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight)));
423
424     // allocate max possible number of tiles visible with this viewport
425     int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1;
426     int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1;
427     int maxTextureCount = (viewMaxTileX + TILE_PREFETCH_DISTANCE * 2) *
428         (viewMaxTileY + TILE_PREFETCH_DISTANCE * 2) * 2;
429     TilesManager::instance()->setMaxTextureCount(maxTextureCount);
430     m_tiledPageA->updateBaseTileSize();
431     m_tiledPageB->updateBaseTileSize();
432 }
433
434 #ifdef MEASURES_PERF
435 void GLWebViewState::dumpMeasures()
436 {
437     for (int i = 0; i < m_timeCounter; i++) {
438         XLOGC("%d delay: %d ms", m_totalTimeCounter + i,
439              static_cast<int>(m_delayTimes[i]*1000));
440         m_delayTimes[i] = 0;
441     }
442     m_totalTimeCounter += m_timeCounter;
443     m_timeCounter = 0;
444 }
445 #endif // MEASURES_PERF
446
447 void GLWebViewState::resetFrameworkInval()
448 {
449     m_frameworkInval.setX(0);
450     m_frameworkInval.setY(0);
451     m_frameworkInval.setWidth(0);
452     m_frameworkInval.setHeight(0);
453 }
454
455 void GLWebViewState::addDirtyArea(const IntRect& rect)
456 {
457     if (rect.isEmpty())
458         return;
459
460     IntRect inflatedRect = rect;
461     inflatedRect.inflate(8);
462     if (m_frameworkLayersInval.isEmpty())
463         m_frameworkLayersInval = inflatedRect;
464     else
465         m_frameworkLayersInval.unite(inflatedRect);
466 }
467
468 void GLWebViewState::resetLayersDirtyArea()
469 {
470     m_frameworkLayersInval.setX(0);
471     m_frameworkLayersInval.setY(0);
472     m_frameworkLayersInval.setWidth(0);
473     m_frameworkLayersInval.setHeight(0);
474 }
475
476 double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
477                                   IntRect& webViewRect, int titleBarHeight,
478                                   IntRect& screenClip, float scale)
479 {
480     int left = viewRect.x();
481     int top = viewRect.y();
482     int width = viewRect.width();
483     int height = viewRect.height();
484
485     if (TilesManager::instance()->invertedScreen()) {
486         float color = 1.0 - ((((float) m_backgroundColor.red() / 255.0) +
487                       ((float) m_backgroundColor.green() / 255.0) +
488                       ((float) m_backgroundColor.blue() / 255.0)) / 3.0);
489         glClearColor(color, color, color, 1);
490     } else {
491         glClearColor((float)m_backgroundColor.red() / 255.0,
492                      (float)m_backgroundColor.green() / 255.0,
493                      (float)m_backgroundColor.blue() / 255.0, 1);
494     }
495     glClear(GL_COLOR_BUFFER_BIT);
496
497     glViewport(left, top, width, height);
498
499     ShaderProgram* shader = TilesManager::instance()->shader();
500     if (shader->program() == -1) {
501         XLOG("Reinit shader");
502         shader->init();
503     }
504     glUseProgram(shader->program());
505     glUniform1i(shader->textureSampler(), 0);
506     shader->setViewRect(viewRect);
507     shader->setViewport(visibleRect);
508     shader->setWebViewRect(webViewRect);
509     shader->setTitleBarHeight(titleBarHeight);
510     shader->setScreenClip(screenClip);
511     shader->resetBlending();
512
513     double currentTime = WTF::currentTime();
514
515     setViewport(visibleRect, scale);
516     m_zoomManager.processNewScale(currentTime, scale);
517
518     return currentTime;
519 }
520
521 bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
522                             IntRect& webViewRect, int titleBarHeight,
523                             IntRect& clip, float scale, bool* buffersSwappedPtr)
524 {
525     TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
526                                                        viewport.fTop,
527                                                        viewport.fRight,
528                                                        viewport.fBottom,
529                                                        scale);
530     TilesManager::instance()->incDrawGLCount();
531
532 #ifdef DEBUG
533     TilesManager::instance()->getTilesTracker()->clear();
534 #endif
535
536     m_baseLayerLock.lock();
537     BaseLayerAndroid* baseLayer = m_currentBaseLayer;
538     SkSafeRef(baseLayer);
539     BaseLayerAndroid* baseForComposited = m_baseLayer;
540     SkSafeRef(baseForComposited);
541     m_baseLayerLock.unlock();
542     if (!baseLayer) {
543         SkSafeUnref(baseForComposited);
544         return false;
545     }
546
547     float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO;
548     float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO;
549     bool useHorzPrefetch = viewWidth < baseContentWidth();
550     bool useVertPrefetch = viewHeight < baseContentHeight();
551     m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
552     m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
553
554     XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)",
555          rect.x(), rect.y(), rect.width(), rect.height(),
556          viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom);
557
558     resetLayersDirtyArea();
559
560     if (!baseForComposited ||
561         (baseForComposited && !baseForComposited->countChildren())) {
562         SkSafeRef(baseLayer);
563         SkSafeUnref(baseForComposited);
564         baseForComposited = baseLayer;
565     }
566
567     LayerAndroid* compositedRoot = 0;
568     if (baseForComposited && baseForComposited->countChildren() >= 1)
569         compositedRoot = static_cast<LayerAndroid*>(baseForComposited->getChild(0));
570
571     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
572         XLOGC("WARNING, scale seems corrupted before update: %e", scale);
573
574     // Here before we draw, update the BaseTile which has updated content.
575     // Inside this function, just do GPU blits from the transfer queue into
576     // the BaseTiles' texture.
577     TilesManager::instance()->transferQueue()->updateDirtyBaseTiles();
578
579     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) {
580         XLOGC("WARNING, scale seems corrupted after update: %e", scale);
581         CRASH();
582     }
583
584     // gather the textures we can use
585     TilesManager::instance()->gatherLayerTextures();
586
587     if (compositedRoot != m_previouslyUsedRoot)
588         TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot);
589
590     // set up zoom manager, shaders, etc.
591     m_backgroundColor = baseLayer->getBackgroundColor();
592     double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
593     bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect,
594                                  viewport, scale, buffersSwappedPtr);
595     // Reset the clip to make sure we can draw the rings. If this isn't done, the
596     // current clip will be the clip of whatever layer was last drawn
597     TilesManager::instance()->shader()->clip(clip);
598     paintExtras();
599
600     glBindBuffer(GL_ARRAY_BUFFER, 0);
601
602     SkSafeRef(compositedRoot);
603     SkSafeUnref(m_previouslyUsedRoot);
604     m_previouslyUsedRoot = compositedRoot;
605
606     ret |= TilesManager::instance()->invertedScreenSwitch();
607
608     if (ret) {
609         // ret==true && empty inval region means we've inval'd everything,
610         // but don't have new content. Keep redrawing full view (0,0,0,0)
611         // until tile generation catches up and we swap pages.
612         bool fullScreenInval = m_frameworkInval.isEmpty();
613
614         if (TilesManager::instance()->invertedScreenSwitch()) {
615             fullScreenInval = true;
616             TilesManager::instance()->setInvertedScreenSwitch(false);
617         }
618
619         if (!fullScreenInval) {
620             FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord(
621                     m_frameworkInval);
622             // Inflate the invalidate rect to avoid precision lost.
623             frameworkInval.inflate(1);
624             IntRect inval(frameworkInval.x(), frameworkInval.y(),
625                     frameworkInval.width(), frameworkInval.height());
626
627             inval.unite(m_frameworkLayersInval);
628
629             invalRect->setX(inval.x());
630             invalRect->setY(inval.y());
631             invalRect->setWidth(inval.width());
632             invalRect->setHeight(inval.height());
633
634             XLOG("invalRect(%d, %d, %d, %d)", inval.x(),
635                     inval.y(), inval.width(), inval.height());
636
637             if (!invalRect->intersects(rect)) {
638                 // invalidate is occurring offscreen, do full inval to guarantee redraw
639                 fullScreenInval = true;
640             }
641         }
642
643         if (fullScreenInval) {
644             invalRect->setX(0);
645             invalRect->setY(0);
646             invalRect->setWidth(0);
647             invalRect->setHeight(0);
648         }
649     } else {
650         resetFrameworkInval();
651     }
652
653 #ifdef MEASURES_PERF
654     if (m_measurePerfs) {
655         m_delayTimes[m_timeCounter++] = delta;
656         if (m_timeCounter >= MAX_MEASURES_PERF)
657             dumpMeasures();
658     }
659 #endif
660
661     SkSafeUnref(baseForComposited);
662     SkSafeUnref(baseLayer);
663 #ifdef DEBUG
664     TilesManager::instance()->getTilesTracker()->showTrackTextures();
665     TilesManager::instance()->showImages();
666 #endif
667     return ret;
668 }
669
670 } // namespace WebCore
671
672 #endif // USE(ACCELERATED_COMPOSITING)