// -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; }
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); } }