void BackendRenderer::AcceptMessage(ref_ptr<Message> message) { switch (message->GetType()) { case Message::UpdateReadManager: { TTilesCollection tiles = m_requestedTiles->GetTiles(); if (!tiles.empty()) { ScreenBase const screen = m_requestedTiles->GetScreen(); m_readManager->UpdateCoverage(screen, tiles, m_texMng); gui::CountryStatusHelper & helper = gui::DrapeGui::Instance().GetCountryStatusHelper(); if ((*tiles.begin()).m_zoomLevel > scales::GetUpperWorldScale()) m_model.UpdateCountryIndex(helper.GetCountryIndex(), screen.ClipRect().Center()); else helper.Clear(); } break; } case Message::InvalidateReadManagerRect: { ref_ptr<InvalidateReadManagerRectMessage> msg = message; m_readManager->Invalidate(msg->GetTilesForInvalidate()); break; } case Message::CountryStatusRecache: { RecacheCountryStatus(); break; } case Message::GuiRecache: { ref_ptr<GuiRecacheMessage> msg = message; RecacheGui(msg->GetInitInfo(), msg->GetSizeInfoMap()); break; } case Message::GuiLayerLayout: { ref_ptr<GuiLayerLayoutMessage> msg = message; m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<GuiLayerLayoutMessage>(msg->AcceptLayoutInfo()), MessagePriority::Normal); RecacheCountryStatus(); break; } case Message::TileReadStarted: { m_batchersPool->ReserveBatcher(static_cast<ref_ptr<BaseTileMessage>>(message)->GetKey()); break; } case Message::TileReadEnded: { ref_ptr<TileReadEndMessage> msg = message; m_batchersPool->ReleaseBatcher(msg->GetKey()); break; } case Message::FinishReading: { ref_ptr<FinishReadingMessage> msg = message; m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FinishReadingMessage>(move(msg->MoveTiles())), MessagePriority::Normal); break; } case Message::MapShapeReaded: { ref_ptr<MapShapeReadedMessage> msg = message; auto const & tileKey = msg->GetKey(); if (m_requestedTiles->CheckTileKey(tileKey) && m_readManager->CheckTileKey(tileKey)) { ref_ptr<dp::Batcher> batcher = m_batchersPool->GetTileBatcher(tileKey); for (drape_ptr<MapShape> const & shape : msg->GetShapes()) shape->Draw(batcher, m_texMng); } break; } case Message::UpdateUserMarkLayer: { ref_ptr<UpdateUserMarkLayerMessage> msg = message; TileKey const & key = msg->GetKey(); UserMarksProvider const * marksProvider = msg->StartProcess(); if (marksProvider->IsDirty()) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<ClearUserMarkLayerMessage>(key), MessagePriority::Normal); m_batchersPool->ReserveBatcher(key); CacheUserMarks(marksProvider, m_batchersPool->GetTileBatcher(key), m_texMng); m_batchersPool->ReleaseBatcher(key); } msg->EndProcess(); break; } case Message::CountryInfoUpdate: { ref_ptr<CountryInfoUpdateMessage> msg = message; gui::CountryStatusHelper & helper = gui::DrapeGui::Instance().GetCountryStatusHelper(); if (!msg->NeedShow()) { // Country is already loaded, so there is no need to show status GUI // even if this country is updating. helper.Clear(); } else { gui::CountryInfo const & info = msg->GetCountryInfo(); if (msg->IsCurrentCountry() || helper.GetCountryIndex() == info.m_countryIndex) { helper.SetCountryInfo(info); } } break; } case Message::AddRoute: { ref_ptr<AddRouteMessage> msg = message; m_routeBuilder->Build(msg->GetRoutePolyline(), msg->GetTurns(), msg->GetColor(), m_texMng); break; } case Message::CacheRouteSign: { ref_ptr<CacheRouteSignMessage> msg = message; m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng); break; } case Message::RemoveRoute: { ref_ptr<RemoveRouteMessage> msg = message; // we have to resend the message to FR, because it guaranties that // RemoveRouteMessage will be precessed after FlushRouteMessage m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<RemoveRouteMessage>(msg->NeedDeactivateFollowing()), MessagePriority::Normal); break; } case Message::InvalidateTextures: { m_texMng->Invalidate(VisualParams::Instance().GetResourcePostfix()); RecacheMyPosition(); break; } case Message::StopRendering: { ProcessStopRenderingMessage(); break; } default: ASSERT(false, ()); break; } }
void ReadManager::UpdateCoverage(ScreenBase const & screen, bool is3dBuildings, TTilesCollection const & tiles, ref_ptr<dp::TextureManager> texMng) { if (screen == m_currentViewport && !m_forceUpdate) return; m_forceUpdate = false; m_modeChanged |= m_need3dBuildings != is3dBuildings; m_need3dBuildings = is3dBuildings; if (m_modeChanged || MustDropAllTiles(screen)) { m_modeChanged = false; IncreaseCounter(static_cast<int>(tiles.size())); m_generationCounter++; for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::CancelTileInfo, this, _1)); m_tileInfos.clear(); for_each(tiles.begin(), tiles.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1, texMng)); } else { // Find rects that go out from viewport buffer_vector<shared_ptr<TileInfo>, 8> outdatedTiles; #ifdef _MSC_VER vs_bug:: #endif set_difference(m_tileInfos.begin(), m_tileInfos.end(), tiles.begin(), tiles.end(), back_inserter(outdatedTiles), LessCoverageCell()); // Find rects that go in into viewport. buffer_vector<TileKey, 8> inputRects; #ifdef _MSC_VER vs_bug:: #endif set_difference(tiles.begin(), tiles.end(), m_tileInfos.begin(), m_tileInfos.end(), back_inserter(inputRects), LessCoverageCell()); // Find tiles which must be re-read. buffer_vector<shared_ptr<TileInfo>, 8> rereadTiles; for (shared_ptr<TileInfo> const & tile : m_tileInfos) { for (shared_ptr<TileInfo> & outTile : outdatedTiles) { if (IsNeighbours(tile->GetTileKey(), outTile->GetTileKey())) { rereadTiles.push_back(tile); break; } } } IncreaseCounter(static_cast<int>(inputRects.size() + rereadTiles.size())); for_each(outdatedTiles.begin(), outdatedTiles.end(), bind(&ReadManager::ClearTileInfo, this, _1)); for_each(rereadTiles.begin(), rereadTiles.end(), bind(&ReadManager::PushTaskFront, this, _1)); for_each(inputRects.begin(), inputRects.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1, texMng)); } m_currentViewport = screen; }
void BackendRenderer::AcceptMessage(ref_ptr<Message> message) { switch (message->GetType()) { case Message::UpdateReadManager: { TTilesCollection tiles = m_requestedTiles->GetTiles(); if (!tiles.empty()) { ScreenBase const screen = m_requestedTiles->GetScreen(); bool const have3dBuildings = m_requestedTiles->Have3dBuildings(); m_readManager->UpdateCoverage(screen, have3dBuildings, tiles, m_texMng); m_updateCurrentCountryFn(screen.ClipRect().Center(), (*tiles.begin()).m_zoomLevel); } break; } case Message::InvalidateReadManagerRect: { ref_ptr<InvalidateReadManagerRectMessage> msg = message; if (msg->NeedInvalidateAll()) m_readManager->InvalidateAll(); else m_readManager->Invalidate(msg->GetTilesForInvalidate()); break; } case Message::ShowChoosePositionMark: { RecacheChoosePositionMark(); break; } case Message::GuiRecache: { ref_ptr<GuiRecacheMessage> msg = message; RecacheGui(msg->GetInitInfo(), msg->NeedResetOldGui()); #ifdef RENRER_DEBUG_INFO_LABELS RecacheDebugLabels(); #endif break; } case Message::GuiLayerLayout: { ref_ptr<GuiLayerLayoutMessage> msg = message; m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<GuiLayerLayoutMessage>(msg->AcceptLayoutInfo()), MessagePriority::Normal); break; } case Message::TileReadStarted: { ref_ptr<TileReadStartMessage> msg = message; m_batchersPool->ReserveBatcher(msg->GetKey()); break; } case Message::TileReadEnded: { ref_ptr<TileReadEndMessage> msg = message; m_batchersPool->ReleaseBatcher(msg->GetKey()); break; } case Message::FinishTileRead: { ref_ptr<FinishTileReadMessage> msg = message; m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FinishTileReadMessage>(msg->MoveTiles()), MessagePriority::Normal); break; } case Message::FinishReading: { TOverlaysRenderData overlays; overlays.swap(m_overlays); if (!overlays.empty()) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FlushOverlaysMessage>(move(overlays)), MessagePriority::Normal); } break; } case Message::MapShapesRecache: { RecacheMapShapes(); break; } case Message::MapShapeReaded: { ref_ptr<MapShapeReadedMessage> msg = message; auto const & tileKey = msg->GetKey(); if (m_requestedTiles->CheckTileKey(tileKey) && m_readManager->CheckTileKey(tileKey)) { ref_ptr<dp::Batcher> batcher = m_batchersPool->GetTileBatcher(tileKey); for (drape_ptr<MapShape> const & shape : msg->GetShapes()) { batcher->SetFeatureMinZoom(shape->GetFeatureMinZoom()); shape->Draw(batcher, m_texMng); } } break; } case Message::OverlayMapShapeReaded: { ref_ptr<OverlayMapShapeReadedMessage> msg = message; auto const & tileKey = msg->GetKey(); if (m_requestedTiles->CheckTileKey(tileKey) && m_readManager->CheckTileKey(tileKey)) { CleanupOverlays(tileKey); OverlayBatcher batcher(tileKey); for (drape_ptr<MapShape> const & shape : msg->GetShapes()) batcher.Batch(shape, m_texMng); TOverlaysRenderData renderData; batcher.Finish(renderData); if (!renderData.empty()) { m_overlays.reserve(m_overlays.size() + renderData.size()); move(renderData.begin(), renderData.end(), back_inserter(m_overlays)); } } break; } case Message::UpdateUserMarkLayer: { ref_ptr<UpdateUserMarkLayerMessage> msg = message; UserMarksProvider const * marksProvider = msg->StartProcess(); if (marksProvider->IsDirty()) { size_t const layerId = msg->GetLayerId(); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<ClearUserMarkLayerMessage>(layerId), MessagePriority::Normal); TUserMarkShapes shapes = CacheUserMarks(marksProvider, m_texMng); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FlushUserMarksMessage>(layerId, move(shapes)), MessagePriority::Normal); } msg->EndProcess(); break; } case Message::AddRoute: { ref_ptr<AddRouteMessage> msg = message; m_routeBuilder->Build(msg->GetRoutePolyline(), msg->GetTurns(), msg->GetColor(), msg->GetPattern(), m_texMng, msg->GetRecacheId()); break; } case Message::CacheRouteSign: { ref_ptr<CacheRouteSignMessage> msg = message; m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng, msg->GetRecacheId()); break; } case Message::CacheRouteArrows: { ref_ptr<CacheRouteArrowsMessage> msg = message; m_routeBuilder->BuildArrows(msg->GetRouteIndex(), msg->GetBorders(), m_texMng, msg->GetRecacheId()); break; } case Message::RemoveRoute: { ref_ptr<RemoveRouteMessage> msg = message; m_routeBuilder->ClearRouteCache(); // We have to resend the message to FR, because it guaranties that // RemoveRouteMessage will be processed after FlushRouteMessage. m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<RemoveRouteMessage>(msg->NeedDeactivateFollowing()), MessagePriority::Normal); break; } case Message::InvalidateTextures: { m_texMng->Invalidate(VisualParams::Instance().GetResourcePostfix()); RecacheMapShapes(); break; } case Message::CacheGpsTrackPoints: { ref_ptr<CacheGpsTrackPointsMessage> msg = message; drape_ptr<GpsTrackRenderData> data = make_unique_dp<GpsTrackRenderData>(); data->m_pointsCount = msg->GetPointsCount(); GpsTrackShape::Draw(m_texMng, *data.get()); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FlushGpsTrackPointsMessage>(move(data)), MessagePriority::Normal); break; } case Message::Allow3dBuildings: { ref_ptr<Allow3dBuildingsMessage> msg = message; m_readManager->Allow3dBuildings(msg->Allow3dBuildings()); break; } case Message::RequestSymbolsSize: { ref_ptr<RequestSymbolsSizeMessage> msg = message; auto const & symbols = msg->GetSymbols(); vector<m2::PointU> sizes(symbols.size()); for (size_t i = 0; i < symbols.size(); i++) { dp::TextureManager::SymbolRegion region; m_texMng->GetSymbolRegion(symbols[i], region); sizes[i] = region.GetPixelSize(); } msg->InvokeCallback(sizes); break; } case Message::AddTrafficSegments: { ref_ptr<AddTrafficSegmentsMessage> msg = message; for (auto const & segment : msg->GetSegments()) m_trafficGenerator->AddSegment(segment.first, segment.second); break; } case Message::UpdateTraffic: { ref_ptr<UpdateTrafficMessage> msg = message; auto segments = m_trafficGenerator->GetSegmentsToUpdate(msg->GetSegmentsData()); if (!segments.empty()) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<UpdateTrafficMessage>(segments), MessagePriority::Normal); } if (segments.size() < msg->GetSegmentsData().size()) { vector<TrafficRenderData> data; m_trafficGenerator->GetTrafficGeom(m_texMng, msg->GetSegmentsData(), data); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<FlushTrafficDataMessage>(move(data)), MessagePriority::Normal); if (m_trafficGenerator->IsColorsCacheRefreshed()) { auto texCoords = m_trafficGenerator->ProcessCacheRefreshing(); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<SetTrafficTexCoordsMessage>(move(texCoords)), MessagePriority::Normal); } } break; } case Message::DrapeApiAddLines: { ref_ptr<DrapeApiAddLinesMessage> msg = message; vector<drape_ptr<DrapeApiRenderProperty>> properties; m_drapeApiBuilder->BuildLines(msg->GetLines(), m_texMng, properties); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<DrapeApiFlushMessage>(move(properties)), MessagePriority::Normal); break; } case Message::DrapeApiRemove: { ref_ptr<DrapeApiRemoveMessage> msg = message; m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<DrapeApiRemoveMessage>(msg->GetId(), msg->NeedRemoveAll()), MessagePriority::Normal); break; } default: ASSERT(false, ()); break; } }