예제 #1
0
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));
}
예제 #2
0
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;
}
예제 #3
0
파일: my_position.cpp 프로젝트: 65apps/omim
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);
    }
}
예제 #5
0
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;
  }
}