double GLWebViewState::setupDrawing(const IntRect& invScreenRect, const SkRect& visibleContentRect, const IntRect& screenRect, int titleBarHeight, const IntRect& screenClip, float scale) { TilesManager* tilesManager = TilesManager::instance(); // Make sure GL resources are created on the UI thread. // They are created either for the first time, or after EGL context // recreation caused by onTrimMemory in the framework. ShaderProgram* shader = tilesManager->shader(); if (shader->needsInit()) { ALOGD("Reinit shader"); shader->initGLResources(); } TransferQueue* transferQueue = tilesManager->transferQueue(); if (transferQueue->needsInit()) { ALOGD("Reinit transferQueue"); transferQueue->initGLResources(TilesManager::tileWidth(), TilesManager::tileHeight()); } shader->setupDrawing(invScreenRect, visibleContentRect, screenRect, titleBarHeight, screenClip, scale); double currentTime = WTF::currentTime(); setVisibleContentRect(visibleContentRect, scale); return currentTime; }
void TileGrid::prepareTile(int x, int y, TilePainter* painter, GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch, bool shouldTryUpdateWithBlit) { Tile* tile = getTile(x, y); if (!tile) { bool isLayerTile = !m_isBaseSurface; tile = new Tile(isLayerTile); m_tiles.append(tile); } ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); tile->setContents(x, y, m_scale, isExpandPrefetch); if (shouldTryUpdateWithBlit && tryBlitFromContents(tile, painter)) return; if (tile->isDirty() || !tile->frontTexture()) tile->reserveTexture(); if (tile->backTexture() && tile->isDirty()) { TilesManager* tilesManager = TilesManager::instance(); // if a scheduled repaint is still outstanding, update it with the new painter if (tile->isRepaintPending() && tilesManager->tryUpdateOperationWithPainter(tile, painter)) return; ALOGV("painting TG %p's tile %d %d for LG %p, scale %f", this, x, y, painter, m_scale); PaintTileOperation *operation = new PaintTileOperation(tile, painter, state, isLowResPrefetch); tilesManager->scheduleOperation(operation); } }
void PaintTileOperation::endTime() { if (m_startTimeMS == 0.0) return; double timeDelta = currentTimeMS() - m_startTimeMS; m_startTimeMS = 0.0; #if ENABLE(IMPROVE_TEXTURES_GENERATOR_MULTI_CORE) TilesManager* tilesManager = TilesManager::instance(); bool supportMultiCoreTextGen = (tilesManager && tilesManager->supportMultiCoreTexturesGen()); XLOGD2("Support multi-thread texture generator = %d >> %f", supportMultiCoreTextGen, timeDelta); #else XLOGD2("%f", timeDelta); #endif }
void GLWebViewState::setVisibleContentRect(const SkRect& visibleContentRect, float scale) { // allocate max possible number of tiles visible with this visibleContentRect / expandedTileBounds const float invTileContentWidth = scale / TilesManager::tileWidth(); const float invTileContentHeight = scale / TilesManager::tileHeight(); int viewMaxTileX = static_cast<int>(ceilf((visibleContentRect.width()-1) * invTileContentWidth)) + 1; int viewMaxTileY = static_cast<int>(ceilf((visibleContentRect.height()-1) * invTileContentHeight)) + 1; TilesManager* tilesManager = TilesManager::instance(); int maxTextureCount = viewMaxTileX * viewMaxTileY * (tilesManager->highEndGfx() ? 4 : 2); tilesManager->setCurrentTextureCount(maxTextureCount); // TODO: investigate whether we can move this return earlier. if ((m_visibleContentRect == visibleContentRect) && (m_scale == scale)) { // everything below will stay the same, early return. m_isVisibleContentRectScrolling = false; return; } m_scale = scale; m_goingDown = m_visibleContentRect.fTop - visibleContentRect.fTop <= 0; m_goingLeft = m_visibleContentRect.fLeft - visibleContentRect.fLeft >= 0; // detect visibleContentRect scrolling from short programmatic scrolls/jumps m_isVisibleContentRectScrolling = m_visibleContentRect != visibleContentRect && SkRect::Intersects(m_visibleContentRect, visibleContentRect); m_visibleContentRect = visibleContentRect; ALOGV("New visibleContentRect %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f )", m_visibleContentRect.fLeft, m_visibleContentRect.fTop, m_visibleContentRect.fRight, m_visibleContentRect.fBottom, m_visibleContentRect.width(), m_visibleContentRect.height(), scale); }
// -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); } }
/* //Seems a SAMSUNG change BEGIN bool VideoLayerAndroid::captureImage(PlatformWebGLVideoTexture* tex, VideoImageCallback callback) { if (m_playerState == PLAYING && m_surfaceTexture.get()) { Locker<WTF::Mutex> lock(m_mutexRef->mutex); bool ret = (tex->*callback)(m_surfaceTexture); glFinish(); return ret; } return false; } //Seems a SAMSUNG change END */ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) { // Lazily allocated the textures. TilesManager* tilesManager = TilesManager::instance(); VideoLayerManager* manager = tilesManager->videoLayerManager(); manager->initGLResourcesIfNeeded(); ShaderProgram* shader = tilesManager->shader(); SkRect rect = SkRect::MakeSize(getSize()); GLfloat surfaceMatrix[16]; // Calculate the video rect based on the aspect ratio and the element rect. SkRect videoRect = calVideoRect(rect); PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad, &m_drawTransform, &rect); if (videoRect != rect) { // Paint the whole video element with black color when video content // can't cover the whole area. shader->drawQuad(&pureColorQuadData); } // Inner rect is for the progressing / play / pause animation. SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(), manager->getButtonSize()); if (innerRect.contains(videoRect)) innerRect = videoRect; double buttonSize = manager->getButtonSize(); innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2, videoRect.fTop + (videoRect.height() - buttonSize) / 2); // When we are drawing the animation of the play/pause button in the // middle of the video, we need to ask for redraw. bool needRedraw = false; TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad, &m_drawTransform, &innerRect); // Draw the poster image, the progressing image or the Video depending // on the player's state. if (m_playerState == PREPARING) { // Show the progressing animation, with two rotating circles showPreparingAnimation(videoRect, innerRect); needRedraw = true; } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { // Show the real video. Locker<WTF::Mutex> lock(m_mutexRef->mutex);//Seems a SAMSUNG change m_surfaceTexture->updateTexImage(); m_surfaceTexture->getTransformMatrix(surfaceMatrix); GLuint textureId = manager->getTextureId(uniqueId()); shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, videoRect, textureId); manager->updateMatrix(uniqueId(), surfaceMatrix); // Use the scale to control the fading the sizing during animation double scale = manager->drawIcon(uniqueId(), PlayIcon); if (scale) { innerRect.inset(manager->getButtonSize() / 4 * scale, manager->getButtonSize() / 4 * scale); iconQuadData.updateTextureId(manager->getPlayTextureId()); iconQuadData.updateOpacity(scale); shader->drawQuad(&iconQuadData); needRedraw = true; } glFinish(); //we can look probably at using a fence here //Seems a SAMSUNG change } else { GLuint textureId = manager->getTextureId(uniqueId()); GLfloat* matrix = manager->getMatrix(uniqueId()); if (textureId && matrix) { // Show the screen shot for each video. shader->drawVideoLayerQuad(m_drawTransform, matrix, videoRect, textureId); } else { // Show the static poster b/c there is no screen shot available. pureColorQuadData.updateColor(Color(128, 128, 128, 255)); shader->drawQuad(&pureColorQuadData); iconQuadData.updateTextureId(manager->getPosterTextureId()); iconQuadData.updateOpacity(1.0); shader->drawQuad(&iconQuadData); } // Use the scale to control the fading and the sizing during animation. double scale = manager->drawIcon(uniqueId(), PauseIcon); if (scale) { innerRect.inset(manager->getButtonSize() / 4 * scale, manager->getButtonSize() / 4 * scale); iconQuadData.updateTextureId(manager->getPauseTextureId()); iconQuadData.updateOpacity(scale); shader->drawQuad(&iconQuadData); needRedraw = true; } } return needRedraw; }