OSDN Git Service

Merge "When in singlesurfacemode, resist switching out - DO NOT MERGE" into ics-mr1
[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 "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)