bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale,
                                              double currentTime)
{
    ZoomManager* zoomManager = m_state->zoomManager();

    bool goingDown = m_state->goingDown();
    bool goingLeft = m_state->goingLeft();

    const SkIRect& viewportTileBounds = m_state->viewportTileBounds();
    XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft,
            viewportTileBounds.fTop, scale);

    // Query the resulting state from the zoom manager
    bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();

    // Display the current page
    TiledPage* tiledPage = m_state->frontPage();
    TiledPage* nextTiledPage = m_state->backPage();
    tiledPage->setScale(zoomManager->currentScale());

    // Let's prepare the page if needed so that it will start painting
    if (prepareNextTiledPage) {
        nextTiledPage->setScale(scale);
        m_state->setFutureViewport(viewportTileBounds);

        // ignore dirtiness return value since while zooming we repaint regardless
        nextTiledPage->updateTileDirtiness(viewportTileBounds);

        nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
                               TiledPage::VisibleBounds);
        // Cancel pending paints for the foreground page
        TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
    }

    // If we fired a request, let's check if it's ready to use
    if (zoomManager->didFireRequest()) {
        if (nextTiledPage->swapBuffersIfReady(viewportTileBounds,
                                              zoomManager->futureScale()))
            zoomManager->setReceivedRequest(); // transition to received request state
    }

    float transparency = 1;
    bool doZoomPageSwap = false;

    // If the page is ready, display it. We do a short transition between
    // the two pages (current one and future one with the new scale factor)
    if (zoomManager->didReceivedRequest()) {
        float nextTiledPageTransparency = 1;
        m_state->resetFrameworkInval();
        zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
                                       &nextTiledPageTransparency, &transparency);
        nextTiledPage->prepareForDrawGL(nextTiledPageTransparency, viewportTileBounds);
    }

    const SkIRect& preZoomBounds = m_state->preZoomBounds();

    bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();

    if (doZoomPageSwap) {
        zoomManager->setCurrentScale(scale);
        m_state->swapPages();
    }

    bool needsRedraw = zooming;

    // if applied invals mark tiles dirty, need to redraw
    needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds);

    // paint what's needed unless we're zooming, since the new tiles won't
    // be relevant soon anyway
    if (!zooming)
        tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
                           TiledPage::ExpandedBounds);

    XLOG("scrolling %d, zooming %d, needsRedraw %d",
         scrolling, zooming, needsRedraw);

    // prefetch in the nextTiledPage if unused by zooming (even if not scrolling
    // since we want the tiles to be ready before they're needed)
    bool usePrefetchPage = !zooming;
    nextTiledPage->setIsPrefetchPage(usePrefetchPage);
    if (usePrefetchPage) {
        // if the non-prefetch page isn't missing tiles, don't bother drawing
        // prefetch page
        bool drawPrefetchPage = tiledPage->hasMissingContent(preZoomBounds);
        prefetchBasePicture(viewport, scale, nextTiledPage, drawPrefetchPage);
    }

    tiledPage->prepareForDrawGL(transparency, preZoomBounds);

    return needsRedraw;
}