Esempio n. 1
0
// -invScreenRect is the webView's rect with inverted Y screen coordinate.
// -visibleContentRect is the visible area in content coordinate.
// They are both based on  webView's rect and calculated in Java side.
//
// -screenClip is in screen coordinate, so we need to invert the Y axis before
// passing into GL functions. Clip can be smaller than the webView's rect.
//
// TODO: Try to decrease the number of parameters as some info is redundant.
int GLWebViewState::drawGL(IntRect& invScreenRect, SkRect& visibleContentRect,
                           IntRect* invalRect, IntRect& screenRect, int titleBarHeight,
                           IntRect& screenClip, float scale,
                           bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
                           bool shouldDraw)
{
    TilesManager* tilesManager = TilesManager::instance();
    if (shouldDraw)
        tilesManager->getProfiler()->nextFrame(visibleContentRect.fLeft,
                                               visibleContentRect.fTop,
                                               visibleContentRect.fRight,
                                               visibleContentRect.fBottom,
                                               scale);
    tilesManager->incDrawGLCount();

    ALOGV("drawGL, invScreenRect(%d, %d, %d, %d), visibleContentRect(%.2f, %.2f, %.2f, %.2f)",
          invScreenRect.x(), invScreenRect.y(), invScreenRect.width(), invScreenRect.height(),
          visibleContentRect.fLeft, visibleContentRect.fTop,
          visibleContentRect.fRight, visibleContentRect.fBottom);

    ALOGV("drawGL, invalRect(%d, %d, %d, %d), screenRect(%d, %d, %d, %d)"
          "screenClip (%d, %d, %d, %d), scale %f titleBarHeight %d",
          invalRect->x(), invalRect->y(), invalRect->width(), invalRect->height(),
          screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height(),
          screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height(), scale, titleBarHeight);

    m_inUnclippedDraw = shouldDraw && (screenRect == screenClip);

    resetLayersDirtyArea();

    if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
        ALOGW("WARNING, scale seems corrupted before update: %e", scale);

    tilesManager->updateTilesIfContextVerified();

    // gather the textures we can use, make sure this happens before any
    // texture preparation work.
    tilesManager->gatherTextures();

    // Upload any pending ImageTexture
    // Return true if we still have some images to upload.
    // TODO: upload as many textures as possible within a certain time limit
    int returnFlags = 0;
    if (ImagesManager::instance()->prepareTextures(this))
        returnFlags |= DrawGlInfo::kStatusDraw;

    // CAPP_REMOVE_SET_SCALE_AT_WARNING
    if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) {
        ALOGW("WARNING, scale seems corrupted after update: %e", scale);
        //scale = 1.0f; // WORKAROUND for corrupted scale: use 1.0
    }
    // CAPP_REMOVE_SET_SCALE_AT_WARNING_END

    double currentTime = setupDrawing(invScreenRect, visibleContentRect, screenRect,
                                      titleBarHeight, screenClip, scale);

    TexturesResult nbTexturesNeeded;
    bool scrolling = isScrolling();
    bool singleSurfaceMode = m_layersRenderingMode == kSingleSurfaceRendering;
    m_glExtras.setVisibleContentRect(visibleContentRect);

    returnFlags |= m_surfaceCollectionManager.drawGL(currentTime, invScreenRect,
                                                     visibleContentRect,
                                                     scale, scrolling,
                                                     singleSurfaceMode,
                                                     collectionsSwappedPtr,
                                                     newCollectionHasAnimPtr,
                                                     &nbTexturesNeeded, shouldDraw);

    int nbTexturesForImages = ImagesManager::instance()->nbTextures();
    ALOGV("*** We have %d textures for images, %d full, %d clipped, total %d / %d",
          nbTexturesForImages, nbTexturesNeeded.full, nbTexturesNeeded.clipped,
          nbTexturesNeeded.full + nbTexturesForImages,
          nbTexturesNeeded.clipped + nbTexturesForImages);
    nbTexturesNeeded.full += nbTexturesForImages;
    nbTexturesNeeded.clipped += nbTexturesForImages;

    if (setLayersRenderingMode(nbTexturesNeeded)) {
        TilesManager::instance()->dirtyAllTiles();
        returnFlags |= DrawGlInfo::kStatusDraw | DrawGlInfo::kStatusInvoke;
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    if (returnFlags & DrawGlInfo::kStatusDraw) {
        // returnFlags & kStatusDraw && empty inval region means we've inval'd everything,
        // but don't have new content. Keep redrawing full view (0,0,0,0)
        // until tile generation catches up and we swap pages.
        bool fullScreenInval = m_frameworkLayersInval.isEmpty() || m_doFrameworkFullInval;

        if (!fullScreenInval) {
            m_frameworkLayersInval.inflate(1);

            invalRect->setX(m_frameworkLayersInval.x());
            invalRect->setY(m_frameworkLayersInval.y());
            invalRect->setWidth(m_frameworkLayersInval.width());
            invalRect->setHeight(m_frameworkLayersInval.height());

            ALOGV("invalRect(%d, %d, %d, %d)", invalRect->x(),
                  invalRect->y(), invalRect->width(), invalRect->height());

            if (!invalRect->intersects(invScreenRect)) {
                // invalidate is occurring offscreen, do full inval to guarantee redraw
                fullScreenInval = true;
            }
        }

        if (fullScreenInval) {
            invalRect->setX(0);
            invalRect->setY(0);
            invalRect->setWidth(0);
            invalRect->setHeight(0);
        }
    }

    if (shouldDraw)
        showFrameInfo(invScreenRect, *collectionsSwappedPtr);

    return returnFlags;
}
Esempio n. 2
0
void TileGrid::prepareGL(GLWebViewState* state, float scale,
                         const IntRect& prepareArea, const IntRect& fullContentArea,
                         TilePainter* painter, int regionFlags, bool isLowResPrefetch,
                         bool updateWithBlit)
{
    // first, how many tiles do we need
    m_area = computeTilesArea(prepareArea, scale);
    if (m_area.isEmpty())
        return;

    ALOGV("prepare TileGrid %p with scale %.2f, prepareArea "
          " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
          this, scale,
          prepareArea.x(), prepareArea.y(),
          prepareArea.width(), prepareArea.height(),
          m_area.x(), m_area.y(),
          m_area.width(), m_area.height());

    bool goingDown = m_prevTileY < m_area.y();
    m_prevTileY = m_area.y();

    TilesManager* tilesManager = TilesManager::instance();
    if (scale != m_scale)
        tilesManager->removeOperationsForFilter(new ScaleFilter(painter, m_scale));

    m_scale = scale;

    // apply dirty region to affected tiles
    if (!m_dirtyRegion.isEmpty()) {
        for (unsigned int i = 0; i < m_tiles.size(); i++)
            m_tiles[i]->markAsDirty(m_dirtyRegion);

        // log inval region for the base surface
        if (m_isBaseSurface && tilesManager->getProfiler()->enabled()) {
            SkRegion::Iterator iterator(m_dirtyRegion);
            while (!iterator.done()) {
                SkIRect r = iterator.rect();
                tilesManager->getProfiler()->nextInval(r, scale);
                iterator.next();
            }
        }
        m_dirtyRegion.setEmpty();
    }

    if (regionFlags & StandardRegion) {
        for (int i = 0; i < m_area.width(); i++) {
            if (goingDown) {
                for (int j = 0; j < m_area.height(); j++)
                    prepareTile(m_area.x() + i, m_area.y() + j,
                                painter, state, isLowResPrefetch, false, updateWithBlit);
            } else {
                for (int j = m_area.height() - 1; j >= 0; j--)
                    prepareTile(m_area.x() + i, m_area.y() + j,
                                painter, state, isLowResPrefetch, false, updateWithBlit);
            }
        }
    }

    if (regionFlags & ExpandedRegion) {
        IntRect fullArea = computeTilesArea(fullContentArea, scale);
        IntRect expandedArea = m_area;

        // on systems reporting highEndGfx=true and useMinimalMemory not set, use expanded bounds
        if (tilesManager->highEndGfx() && !tilesManager->useMinimalMemory())
            expandedArea.inflate(EXPANDED_BOUNDS_INFLATE);

        if (isLowResPrefetch)
            expandedArea.inflateY(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE);

        // clip painting area to content
        expandedArea.intersect(fullArea);

        for (int i = expandedArea.x(); i < expandedArea.maxX(); i++)
            for (int j = expandedArea.y(); j < expandedArea.maxY(); j++)
                if (!m_area.contains(i, j))
                    prepareTile(i, j, painter, state, isLowResPrefetch, true, updateWithBlit);
    }
}