void UserMarkGenerator::GenerateUserMarksGeometry(ref_ptr<dp::GraphicsContext> context, TileKey const & tileKey, ref_ptr<dp::TextureManager> textures) { auto const clippedTileKey = TileKey(tileKey.m_x, tileKey.m_y, ClipTileZoomByMaxDataZoom(tileKey.m_zoomLevel)); auto marksGroups = GetUserMarksGroups(clippedTileKey); auto linesGroups = GetUserLinesGroups(clippedTileKey); if (marksGroups == nullptr && linesGroups == nullptr) return; uint32_t constexpr kMaxSize = 65000; dp::Batcher batcher(kMaxSize, kMaxSize); batcher.SetBatcherHash(tileKey.GetHashValue(BatcherBucket::UserMark)); TUserMarksRenderData renderData; { dp::SessionGuard guard(context, batcher, [&tileKey, &renderData](dp::RenderState const & state, drape_ptr<dp::RenderBucket> && b) { renderData.emplace_back(state, std::move(b), tileKey); }); if (marksGroups != nullptr) CacheUserMarks(context, tileKey, *marksGroups.get(), textures, batcher); if (linesGroups != nullptr) CacheUserLines(context, tileKey, *linesGroups.get(), textures, batcher); } m_flushFn(std::move(renderData)); }
drape_ptr<ShapeRenderer> Watermark::Draw(ref_ptr<dp::GraphicsContext> context, m2::PointF & size, ref_ptr<dp::TextureManager> tex) const { dp::TextureManager::SymbolRegion region; tex->GetSymbolRegion("watermark", region); glsl::vec2 const halfSize = glsl::ToVec2(region.GetPixelSize() * 0.5f); m2::RectF const texRect = region.GetTexRect(); WatermarkVertex vertexes[] = { WatermarkVertex(glsl::vec2(-halfSize.x, halfSize.y), glsl::ToVec2(texRect.LeftTop())), WatermarkVertex(glsl::vec2(-halfSize.x, -halfSize.y), glsl::ToVec2(texRect.LeftBottom())), WatermarkVertex(glsl::vec2(halfSize.x, halfSize.y), glsl::ToVec2(texRect.RightTop())), WatermarkVertex(glsl::vec2(halfSize.x, -halfSize.y), glsl::ToVec2(texRect.RightBottom())) }; auto state = df::CreateRenderState(gpu::Program::TexturingGui, df::DepthLayer::GuiLayer); state.SetColorTexture(region.GetTexture()); state.SetDepthTestEnabled(false); dp::AttributeProvider provider(1 /* streamCount */, 4 /* vertexCount */); dp::BindingInfo info(2 /* count */); dp::BindingDecl & posDecl = info.GetBindingDecl(0); posDecl.m_attributeName = "a_position"; posDecl.m_componentCount = 2; posDecl.m_componentType = gl_const::GLFloatType; posDecl.m_offset = 0; posDecl.m_stride = sizeof(WatermarkVertex); dp::BindingDecl & texDecl = info.GetBindingDecl(1); texDecl.m_attributeName = "a_colorTexCoords"; texDecl.m_componentCount = 2; texDecl.m_componentType = gl_const::GLFloatType; texDecl.m_offset = sizeof(glsl::vec2); texDecl.m_stride = posDecl.m_stride; provider.InitStream(0, info, make_ref(&vertexes)); size = region.GetPixelSize(); drape_ptr<dp::OverlayHandle> handle = make_unique_dp<WatermarkVertexHandle>( EGuiHandle::GuiHandleWatermark, m_position.m_pixelPivot, m_position.m_anchor, size); drape_ptr<ShapeRenderer> renderer = make_unique_dp<ShapeRenderer>(); dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad); batcher.SetBatcherHash(static_cast<uint64_t>(df::BatcherBucket::Default)); dp::SessionGuard guard(context, batcher, std::bind(&ShapeRenderer::AddShape, renderer.get(), _1, _2)); batcher.InsertTriangleStrip(context, state, make_ref(&provider), std::move(handle)); return renderer; }
void MyPosition::CacheAccuracySector(ref_ptr<dp::TextureManager> mng) { int const TriangleCount = 40; int const VertexCount = 3 * TriangleCount; float const etalonSector = math::twicePi / static_cast<double>(TriangleCount); dp::TextureManager::ColorRegion color; mng->GetColorRegion(df::GetColorConstant(GetStyleReader().GetCurrentStyle(), df::MyPositionAccuracy), color); glsl::vec2 colorCoord = glsl::ToVec2(color.GetTexRect().Center()); buffer_vector<Vertex, TriangleCount> buffer; glsl::vec2 startNormal(0.0f, 1.0f); for (size_t i = 0; i < TriangleCount + 1; ++i) { glsl::vec2 normal = glsl::rotate(startNormal, i * etalonSector); glsl::vec2 nextNormal = glsl::rotate(startNormal, (i + 1) * etalonSector); buffer.emplace_back(startNormal, colorCoord); buffer.emplace_back(normal, colorCoord); buffer.emplace_back(nextNormal, colorCoord); } dp::GLState state(gpu::ACCURACY_PROGRAM, dp::GLState::OverlayLayer); state.SetColorTexture(color.GetTexture()); { dp::Batcher batcher(TriangleCount * dp::Batcher::IndexPerTriangle, VertexCount); dp::SessionGuard guard(batcher, [this](dp::GLState const & state, drape_ptr<dp::RenderBucket> && b) { drape_ptr<dp::RenderBucket> bucket = move(b); ASSERT(bucket->GetOverlayHandlesCount() == 0, ()); m_nodes.emplace_back(state, bucket->MoveBuffer()); m_parts[MY_POSITION_ACCURACY].second = m_nodes.size() - 1; }); dp::AttributeProvider provider(1 /*stream count*/, VertexCount); provider.InitStream(0 /*stream index*/, GetBindingInfo(), make_ref(buffer.data())); m_parts[MY_POSITION_ACCURACY].first = batcher.InsertTriangleList(state, make_ref(&provider), nullptr); ASSERT(m_parts[MY_POSITION_ACCURACY].first.IsValid(), ()); }
/* tail an oplog. ok to return, will be re-called. */ void SyncTail::oplogApplication() { OpQueueBatcher batcher(this); OperationContextImpl txn; auto replCoord = ReplicationCoordinator::get(&txn); ApplyBatchFinalizer finalizer(replCoord); auto minValidBoundaries = getMinValid(&txn); OpTime originalEndOpTime(minValidBoundaries.end); OpTime lastWriteOpTime{replCoord->getMyLastOptime()}; while (!inShutdown()) { OpQueue ops; do { if (BackgroundSync::get()->getInitialSyncRequestedFlag()) { // got a resync command return; } tryToGoLiveAsASecondary(&txn, replCoord, minValidBoundaries, lastWriteOpTime); // Blocks up to a second waiting for a batch to be ready to apply. If one doesn't become // ready in time, we'll loop again so we can do the above checks periodically. ops = batcher.getNextBatch(Seconds(1)); } while (!inShutdown() && ops.empty()); if (inShutdown()) return; invariant(!ops.empty()); const BSONObj lastOp = ops.back().raw; if (lastOp.isEmpty()) { // This means that the network thread has coalesced and we have processed all of its // data. invariant(ops.getDeque().size() == 1); if (replCoord->isWaitingForApplierToDrain()) { replCoord->signalDrainComplete(&txn); } continue; // This wasn't a real op. Don't try to apply it. } handleSlaveDelay(lastOp); // Set minValid to the last OpTime that needs to be applied, in this batch or from the // (last) failed batch, whichever is larger. // This will cause this node to go into RECOVERING state // if we should crash and restart before updating finishing. const OpTime start(getLastSetTimestamp(), OpTime::kUninitializedTerm); // Take the max of the first endOptime (if we recovered) and the end of our batch. const auto lastOpTime = fassertStatusOK(28773, OpTime::parseFromOplogEntry(lastOp)); // Setting end to the max of originalEndOpTime and lastOpTime (the end of the batch) // ensures that we keep pushing out the point where we can become consistent // and allow reads. If we recover and end up doing smaller batches we must pass the // originalEndOpTime before we are good. // // For example: // batch apply, 20-40, end = 40 // batch failure, // restart // batch apply, 20-25, end = max(25, 40) = 40 // batch apply, 25-45, end = 45 const OpTime end(std::max(originalEndOpTime, lastOpTime)); // This write will not journal/checkpoint. setMinValid(&txn, {start, end}); lastWriteOpTime = multiApply(&txn, ops); setNewTimestamp(lastWriteOpTime.getTimestamp()); setMinValid(&txn, end, DurableRequirement::None); minValidBoundaries.start = {}; minValidBoundaries.end = end; finalizer.record(lastWriteOpTime); } }
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; } }