Merge pull request #10525 from rokuz/rendering-fixes

Rendering fixes and some optimizations
This commit is contained in:
gmoryes 2019-03-13 17:22:01 +03:00 committed by GitHub
commit 4d30a72b4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 348 additions and 174 deletions

View file

@ -362,7 +362,8 @@ bool Framework::AttachSurface(JNIEnv * env, jobject jSurface)
if (m_isSurfaceDestroyed)
{
LOG(LINFO, ("Recover surface, viewport size:", w, h));
m_work.OnRecoverSurface(w, h);
bool const recreateContextDependentResources = (m_vulkanContextFactory == nullptr);
m_work.OnRecoverSurface(w, h, recreateContextDependentResources);
m_isSurfaceDestroyed = false;
m_work.EnterForeground();

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -19,8 +19,6 @@ namespace dp
// OpenGL data), use FR/BR threads for that.
class DrapeRoutine
{
friend class Promise;
public:
class Result
{
@ -64,7 +62,7 @@ public:
static ResultPtr Run(Task && t)
{
ResultPtr result(new Result(Instance().GetNextId()));
bool const success = Instance().m_workerThread.Push([result, t]() mutable
bool const success = Instance().m_workerThread.Push([result, t = std::move(t)]() mutable
{
t();
Instance().Notify(result->Finish());
@ -80,7 +78,24 @@ public:
static ResultPtr RunDelayed(base::thread_pool::delayed::ThreadPool::Duration const & duration, Task && t)
{
ResultPtr result(new Result(Instance().GetNextId()));
bool const success = Instance().m_workerThread.PushDelayed(duration, [result, t]() mutable
bool const success = Instance().m_workerThread.PushDelayed(duration, [result, t = std::move(t)]() mutable
{
t();
Instance().Notify(result->Finish());
});
if (!success)
return {};
return result;
}
// Asynchronous execution for tasks when execution order matters.
template <typename Task>
static ResultPtr RunSequential(Task && t)
{
ResultPtr result(new Result(Instance().GetNextId()));
bool const success = Instance().m_sequentialWorkerThread.Push([result, t = std::move(t)]() mutable
{
t();
Instance().Notify(result->Finish());
@ -129,6 +144,7 @@ private:
void FinishAll()
{
m_workerThread.ShutdownAndJoin();
m_sequentialWorkerThread.ShutdownAndJoin();
std::lock_guard<std::mutex> lock(m_mutex);
m_finished = true;
@ -141,6 +157,7 @@ private:
std::condition_variable m_condition;
std::mutex m_mutex;
base::thread_pool::delayed::ThreadPool m_workerThread;
base::thread_pool::delayed::ThreadPool m_sequentialWorkerThread;
};
// This is a helper class, which aggregates logic of waiting for active
@ -179,10 +196,9 @@ public:
void Remove(std::shared_ptr<TaskType> const & task)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_tasks.erase(
std::remove_if(m_tasks.begin(), m_tasks.end(),
[task](ActiveTask const & t) { return t.m_task == task; }),
m_tasks.end());
m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(),
[task](ActiveTask const & t) { return t.m_task == task; }),
m_tasks.end());
}
void FinishAll()

View file

@ -36,6 +36,8 @@ public:
void RenderRange(ref_ptr<GraphicsContext> context, bool drawAsLine,
IndicesRange const & range) override
{
CHECK(m_vertexArrayBuffer->HasBuffers(), ());
ref_ptr<dp::metal::MetalBaseContext> metalContext = context;
if (!metalContext->HasAppliedPipelineState())
return;

View file

@ -180,7 +180,7 @@ void VertexArrayBuffer::Render(ref_ptr<GraphicsContext> context, bool drawAsLine
void VertexArrayBuffer::RenderRange(ref_ptr<GraphicsContext> context,
bool drawAsLine, IndicesRange const & range)
{
if (!(m_staticBuffers.empty() && m_dynamicBuffers.empty()) && GetIndexCount() > 0)
if (HasBuffers() && GetIndexCount() > 0)
{
// If OES_vertex_array_object is supported than all bindings have already saved in VAO
// and we need only bind VAO.
@ -202,6 +202,9 @@ void VertexArrayBuffer::Build(ref_ptr<GraphicsContext> context, ref_ptr<GpuProgr
if (m_moveToGpuOnBuild && !m_isPreflushed)
PreflushImpl(context);
if (!HasBuffers())
return;
if (!m_impl)
{
auto const apiVersion = context->GetApiVersion();
@ -226,9 +229,7 @@ void VertexArrayBuffer::Build(ref_ptr<GraphicsContext> context, ref_ptr<GpuProgr
}
}
if (m_staticBuffers.empty())
return;
CHECK(m_impl != nullptr, ());
if (!m_impl->Build(program))
return;
@ -408,13 +409,17 @@ void VertexArrayBuffer::ApplyMutation(ref_ptr<GraphicsContext> context,
bool VertexArrayBuffer::Bind() const
{
CHECK(m_impl != nullptr, ());
if (m_impl == nullptr)
return false;
return m_impl->Bind();
}
void VertexArrayBuffer::Unbind() const
{
CHECK(m_impl != nullptr, ());
if (m_impl == nullptr)
return;
m_impl->Unbind();
}

View file

@ -84,6 +84,7 @@ public:
void ResetChangingTracking() { m_isChanged = false; }
bool IsChanged() const { return m_isChanged; }
bool HasBuffers() const { return !m_staticBuffers.empty() || !m_dynamicBuffers.empty(); }
private:
ref_ptr<DataBuffer> GetOrCreateStaticBuffer(BindingInfo const & bindingInfo);

View file

@ -53,6 +53,8 @@ public:
void RenderRange(ref_ptr<GraphicsContext> context, bool drawAsLine,
IndicesRange const & range) override
{
CHECK(m_vertexArrayBuffer->HasBuffers(), ());
ref_ptr<dp::vulkan::VulkanBaseContext> vulkanContext = context;
VkCommandBuffer commandBuffer = vulkanContext->GetCurrentRenderingCommandBuffer();
CHECK(commandBuffer != nullptr, ());

View file

@ -134,7 +134,7 @@ DrapeEngine::~DrapeEngine()
m_glyphGenerator.reset();
}
void DrapeEngine::Update(int w, int h)
void DrapeEngine::RecoverSurface(int w, int h, bool recreateContextDependentResources)
{
if (m_choosePositionMode)
{
@ -142,13 +142,15 @@ void DrapeEngine::Update(int w, int h)
make_unique_dp<ShowChoosePositionMarkMessage>(),
MessagePriority::Normal);
}
RecacheGui(false);
RecacheMapShapes();
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<RecoverGLResourcesMessage>(),
MessagePriority::Normal);
if (recreateContextDependentResources)
{
RecacheGui(false);
RecacheMapShapes();
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<RecoverContextDependentResourcesMessage>(),
MessagePriority::Normal);
}
ResizeImpl(w, h);
}

View file

@ -117,7 +117,7 @@ public:
DrapeEngine(Params && params);
~DrapeEngine();
void Update(int w, int h);
void RecoverSurface(int w, int h, bool recreateContextDependentResources);
void Resize(int w, int h);
void Invalidate();

View file

@ -474,8 +474,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
m_routeRenderer->UpdateDistanceFromBegin(info.GetDistanceFromBegin());
// Here we have to recache route arrows.
m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(),
std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
m_routeRenderer->PrepareRouteArrows(m_userEventStream.GetCurrentScreen(),
std::bind(&FrontendRenderer::OnPrepareRouteArrows, this, _1, _2));
}
break;
@ -514,8 +514,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
m_routeRenderer->AddSubrouteData(m_context, std::move(subrouteData), make_ref(m_gpuProgramManager));
// Here we have to recache route arrows.
m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(),
std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
m_routeRenderer->PrepareRouteArrows(m_userEventStream.GetCurrentScreen(),
std::bind(&FrontendRenderer::OnPrepareRouteArrows, this, _1, _2));
if (m_pendingFollowRoute != nullptr)
{
@ -642,9 +642,18 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::Type::RecoverGLResources:
case Message::Type::PrepareSubrouteArrows:
{
UpdateGLResources();
ref_ptr<PrepareSubrouteArrowsMessage> msg = message;
m_routeRenderer->CacheRouteArrows(m_userEventStream.GetCurrentScreen(),
msg->GetSubrouteId(), msg->AcceptBorders(),
std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
break;
}
case Message::Type::RecoverContextDependentResources:
{
UpdateContextDependentResources();
break;
}
@ -683,7 +692,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
blocker.Wait();
}
UpdateGLResources();
UpdateContextDependentResources();
break;
}
@ -996,7 +1005,7 @@ unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine()
return make_unique<Routine>(*this);
}
void FrontendRenderer::UpdateGLResources()
void FrontendRenderer::UpdateContextDependentResources()
{
++m_lastRecacheRouteId;
@ -1011,7 +1020,7 @@ void FrontendRenderer::UpdateGLResources()
m_trafficRenderer->ClearContextDependentResources();
// In some cases UpdateGLResources can be called before the rendering of
// In some cases UpdateContextDependentResources can be called before the rendering of
// the first frame. m_currentZoomLevel will be equal to -1, so ResolveTileKeys
// could not be called.
if (m_currentZoomLevel > 0)
@ -2406,7 +2415,7 @@ void FrontendRenderer::PrepareScene(ScreenBase const & modelView)
RefreshPivotTransform(modelView);
m_myPositionController->OnUpdateScreen(modelView);
m_routeRenderer->UpdateRoute(modelView, std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
m_routeRenderer->PrepareRouteArrows(modelView, std::bind(&FrontendRenderer::OnPrepareRouteArrows, this, _1, _2));
}
void FrontendRenderer::UpdateScene(ScreenBase const & modelView)
@ -2448,10 +2457,17 @@ void FrontendRenderer::EmitModelViewChanged(ScreenBase const & modelView) const
m_modelViewChangedFn(modelView);
}
void FrontendRenderer::OnCacheRouteArrows(int routeIndex, std::vector<ArrowBorders> const & borders)
void FrontendRenderer::OnPrepareRouteArrows(dp::DrapeID subrouteIndex, std::vector<ArrowBorders> && borders)
{
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<PrepareSubrouteArrowsMessage>(subrouteIndex, std::move(borders)),
MessagePriority::Normal);
}
void FrontendRenderer::OnCacheRouteArrows(dp::DrapeID subrouteIndex, std::vector<ArrowBorders> const & borders)
{
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheSubrouteArrowsMessage>(routeIndex, borders, m_lastRecacheRouteId),
make_unique_dp<CacheSubrouteArrowsMessage>(subrouteIndex, borders, m_lastRecacheRouteId),
MessagePriority::Normal);
}

View file

@ -226,7 +226,7 @@ private:
};
void ReleaseResources();
void UpdateGLResources();
void UpdateContextDependentResources();
void BeginUpdateOverlayTree(ScreenBase const & modelView);
void UpdateOverlayTree(ScreenBase const & modelView, drape_ptr<RenderGroup> & renderGroup);
@ -255,7 +255,8 @@ private:
void ProcessSelection(ref_ptr<SelectObjectMessage> msg);
void OnCacheRouteArrows(int routeIndex, std::vector<ArrowBorders> const & borders);
void OnPrepareRouteArrows(dp::DrapeID subrouteIndex, std::vector<ArrowBorders> && borders);
void OnCacheRouteArrows(dp::DrapeID subrouteIndex, std::vector<ArrowBorders> const & borders);
void CollectShowOverlaysEvents();

View file

@ -37,6 +37,7 @@ std::string DebugPrint(Message::Type msgType)
case Message::Type::SelectObject: return "SelectObject";
case Message::Type::AddSubroute: return "AddSubroute";
case Message::Type::RemoveSubroute: return "RemoveSubroute";
case Message::Type::PrepareSubrouteArrows: return "PrepareSubrouteArrows";
case Message::Type::CacheSubrouteArrows: return "CacheSubrouteArrows";
case Message::Type::FlushSubroute: return "FlushSubroute";
case Message::Type::FlushSubrouteArrows: return "FlushSubrouteArrows";
@ -64,7 +65,7 @@ std::string DebugPrint(Message::Type msgType)
case Message::Type::SetDisplacementMode: return "SetDisplacementMode";
case Message::Type::AllowAutoZoom: return "AllowAutoZoom";
case Message::Type::RequestSymbolsSize: return "RequestSymbolsSize";
case Message::Type::RecoverGLResources: return "RecoverGLResources";
case Message::Type::RecoverContextDependentResources: return "RecoverContextDependentResources";
case Message::Type::SetVisibleViewport: return "SetVisibleViewport";
case Message::Type::EnableTraffic: return "EnableTraffic";
case Message::Type::FlushTrafficGeometry: return "FlushTrafficGeometry";

View file

@ -38,6 +38,7 @@ public:
SelectObject,
AddSubroute,
RemoveSubroute,
PrepareSubrouteArrows,
CacheSubrouteArrows,
FlushSubroute,
FlushSubrouteArrows,
@ -65,7 +66,7 @@ public:
SetDisplacementMode,
AllowAutoZoom,
RequestSymbolsSize,
RecoverGLResources,
RecoverContextDependentResources,
SetVisibleViewport,
EnableTraffic,
FlushTrafficGeometry,

View file

@ -561,6 +561,24 @@ private:
int const m_recacheId;
};
class PrepareSubrouteArrowsMessage : public Message
{
public:
PrepareSubrouteArrowsMessage(dp::DrapeID subrouteId,
std::vector<ArrowBorders> && borders)
: m_subrouteId(subrouteId)
, m_borders(std::move(borders))
{}
Type GetType() const override { return Type::PrepareSubrouteArrows; }
dp::DrapeID GetSubrouteId() const { return m_subrouteId; }
std::vector<ArrowBorders> && AcceptBorders() { return std::move(m_borders); }
private:
dp::DrapeID m_subrouteId;
std::vector<ArrowBorders> m_borders;
};
class CacheSubrouteArrowsMessage : public Message
{
public:
@ -711,10 +729,10 @@ public:
Type GetType() const override { return Type::Invalidate; }
};
class RecoverGLResourcesMessage : public Message
class RecoverContextDependentResourcesMessage : public Message
{
public:
Type GetType() const override { return Type::RecoverGLResources; }
Type GetType() const override { return Type::RecoverContextDependentResources; }
bool IsGraphicsContextDependent() const override { return true; }
};

View file

@ -5,6 +5,7 @@
#include "shaders/programs.hpp"
#include "drape/drape_routine.hpp"
#include "drape/glsl_func.hpp"
#include "drape/utils/projection.hpp"
#include "drape/vertex_array_buffer.hpp"
@ -145,17 +146,17 @@ bool AreEqualArrowBorders(std::vector<ArrowBorders> const & borders1,
return true;
}
std::vector<ArrowBorders> CalculateArrowBorders(ScreenBase const & screen, float currentHalfWidth,
RouteRenderer::SubrouteInfo const & subrouteInfo,
double distanceFromBegin)
std::vector<ArrowBorders> CalculateArrowBorders(m2::RectD screenRect, double screenScale,
float currentHalfWidth, SubrouteConstPtr const & subroute,
double subrouteLength, double distanceFromBegin)
{
auto const & turns = subrouteInfo.m_subroute->m_turns;
auto const & turns = subroute->m_turns;
if (turns.empty())
return {};
// Calculate arrow mercator length.
double glbHalfLen = 0.5 * kArrowSize;
double const glbHalfTextureWidth = currentHalfWidth * kArrowHeightFactor * screen.GetScale();
double const glbHalfTextureWidth = currentHalfWidth * kArrowHeightFactor * screenScale;
double const glbHalfTextureLen = glbHalfTextureWidth * kArrowAspect;
if (glbHalfLen < glbHalfTextureLen)
glbHalfLen = glbHalfTextureLen;
@ -164,20 +165,20 @@ std::vector<ArrowBorders> CalculateArrowBorders(ScreenBase const & screen, float
double const glbArrowTail = 2.0 * kArrowTailSize * glbHalfTextureLen;
double const glbMinArrowSize = glbArrowHead + glbArrowTail;
double const kExtendCoef = 1.1;
m2::RectD screenRect = screen.ClipRect();
screenRect.Scale(kExtendCoef);
double constexpr kExtentCoef = 1.1;
screenRect.Scale(kExtentCoef);
// Calculate arrow borders.
size_t constexpr kAverageArrowsCount = 10;
std::vector<ArrowBorders> newArrowBorders;
newArrowBorders.reserve(turns.size());
auto const & polyline = subrouteInfo.m_subroute->m_polyline;
newArrowBorders.reserve(kAverageArrowsCount);
auto const & polyline = subroute->m_polyline;
for (size_t i = 0; i < turns.size(); i++)
{
ArrowBorders arrowBorders;
arrowBorders.m_groupIndex = static_cast<int>(i);
arrowBorders.m_startDistance = std::max(0.0, turns[i] - glbHalfLen * 0.8);
arrowBorders.m_endDistance = std::min(subrouteInfo.m_length, turns[i] + glbHalfLen * 1.2);
arrowBorders.m_endDistance = std::min(subrouteLength, turns[i] + glbHalfLen * 1.2);
if ((arrowBorders.m_endDistance - arrowBorders.m_startDistance) < glbMinArrowSize ||
arrowBorders.m_startDistance < distanceFromBegin)
@ -248,9 +249,9 @@ RouteRenderer::RouteRenderer(PreviewPointsRequestCallback && previewPointsReques
ASSERT(m_previewPointsRequest != nullptr, ());
}
void RouteRenderer::UpdateRoute(ScreenBase const & screen, CacheRouteArrowsCallback const & callback)
void RouteRenderer::PrepareRouteArrows(ScreenBase const & screen,
PrepareRouteArrowsCallback const & prepareCallback)
{
ASSERT(callback != nullptr, ());
for (auto & subrouteInfo : m_subroutes)
{
// Interpolate values by zoom level.
@ -270,18 +271,49 @@ void RouteRenderer::UpdateRoute(ScreenBase const & screen, CacheRouteArrowsCallb
double dist = kInvalidDistance;
if (m_followingEnabled)
dist = m_distanceFromBegin - subrouteInfo.m_subroute->m_baseDistance;
auto newArrowBorders = CalculateArrowBorders(screen, halfWidth, subrouteInfo, dist);
if (newArrowBorders.empty())
// We run asynchronous task to calculate new positions of route arrows.
auto const subrouteId = subrouteInfo.m_subrouteId;
auto const screenRect = screen.ClipRect();
auto const screenScale = screen.GetScale();
auto const subrouteLength = subrouteInfo.m_length;
auto subroute = subrouteInfo.m_subroute;
dp::DrapeRoutine::RunSequential([subrouteId, screenRect, screenScale, halfWidth,
subroute = std::move(subroute), subrouteLength,
dist, prepareCallback]()
{
// Clear arrows.
subrouteInfo.m_arrowsData.reset();
subrouteInfo.m_arrowBorders.clear();
}
else if (!AreEqualArrowBorders(newArrowBorders, subrouteInfo.m_arrowBorders))
{
subrouteInfo.m_arrowBorders = std::move(newArrowBorders);
callback(subrouteInfo.m_subrouteId, subrouteInfo.m_arrowBorders);
}
ASSERT(prepareCallback != nullptr, ());
prepareCallback(subrouteId, CalculateArrowBorders(screenRect, screenScale, halfWidth,
subroute, subrouteLength, dist));
});
}
}
void RouteRenderer::CacheRouteArrows(ScreenBase const & screen, dp::DrapeID subrouteId,
std::vector<ArrowBorders> && arrowBorders,
CacheRouteArrowsCallback const & cacheCallback)
{
ASSERT(cacheCallback != nullptr, ());
auto const it = FindSubroute(m_subroutes, subrouteId);
if (it == m_subroutes.end())
return;
auto & subrouteInfo = *it;
double zoom = 0.0;
float halfWidth = 0.0;
InterpolateByZoom(subrouteInfo.m_subroute, screen, halfWidth, zoom);
if (arrowBorders.empty() || zoom < kArrowAppearingZoomLevel)
{
// Clear arrows.
subrouteInfo.m_arrowsData.reset();
subrouteInfo.m_arrowBorders.clear();
}
else if (!AreEqualArrowBorders(arrowBorders, subrouteInfo.m_arrowBorders))
{
subrouteInfo.m_arrowBorders = std::move(arrowBorders);
cacheCallback(subrouteInfo.m_subrouteId, subrouteInfo.m_arrowBorders);
}
}
@ -435,8 +467,14 @@ void RouteRenderer::RenderSubroute(ref_ptr<dp::GraphicsContext> context, ref_ptr
mng->GetParamsSetter()->Apply(context, prg, params);
// Render buckets.
for (auto const & bucket : subrouteData->m_renderProperty.m_buckets)
bucket->Render(context, state.GetDrawAsLine());
auto const & clipRect = screen.ClipRect();
CHECK_EQUAL(subrouteData->m_renderProperty.m_buckets.size(),
subrouteData->m_renderProperty.m_boundingBoxes.size(), ());
for (size_t i = 0; i < subrouteData->m_renderProperty.m_buckets.size(); ++i)
{
if (subrouteData->m_renderProperty.m_boundingBoxes[i].IsIntersect(clipRect))
subrouteData->m_renderProperty.m_buckets[i]->Render(context, state.GetDrawAsLine());
}
}
void RouteRenderer::RenderSubrouteArrows(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,
@ -470,8 +508,15 @@ void RouteRenderer::RenderSubrouteArrows(ref_ptr<dp::GraphicsContext> context, r
prg->Bind();
dp::ApplyState(context, prg, state);
mng->GetParamsSetter()->Apply(context, prg, params);
for (auto const & bucket : subrouteInfo.m_arrowsData->m_renderProperty.m_buckets)
bucket->Render(context, state.GetDrawAsLine());
auto const & clipRect = screen.ClipRect();
CHECK_EQUAL(subrouteInfo.m_arrowsData->m_renderProperty.m_buckets.size(),
subrouteInfo.m_arrowsData->m_renderProperty.m_boundingBoxes.size(), ());
for (size_t i = 0; i < subrouteInfo.m_arrowsData->m_renderProperty.m_buckets.size(); ++i)
{
if (subrouteInfo.m_arrowsData->m_renderProperty.m_boundingBoxes[i].IsIntersect(clipRect))
subrouteInfo.m_arrowsData->m_renderProperty.m_buckets[i]->Render(context, state.GetDrawAsLine());
}
}
void RouteRenderer::RenderSubrouteMarkers(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,

View file

@ -29,6 +29,7 @@ extern std::string const kTransitStopInnerMarkerColor;
class RouteRenderer final
{
public:
using PrepareRouteArrowsCallback = std::function<void(dp::DrapeID, std::vector<ArrowBorders> &&)>;
using CacheRouteArrowsCallback = std::function<void(dp::DrapeID, std::vector<ArrowBorders> const &)>;
using PreviewPointsRequestCallback = std::function<void(uint32_t)>;
@ -55,7 +56,10 @@ public:
explicit RouteRenderer(PreviewPointsRequestCallback && previewPointsRequest);
void UpdateRoute(ScreenBase const & screen, CacheRouteArrowsCallback const & callback);
void PrepareRouteArrows(ScreenBase const & screen, PrepareRouteArrowsCallback const & prepareCallback);
void CacheRouteArrows(ScreenBase const & screen, dp::DrapeID subrouteId,
std::vector<ArrowBorders> && arrowBorders,
CacheRouteArrowsCallback const & cacheCallback);
void RenderRoute(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,
ScreenBase const & screen, bool trafficShown, FrameValues const & frameValues);

View file

@ -13,7 +13,10 @@
#include "drape/glsl_types.hpp"
#include "drape/texture_manager.hpp"
#include "geometry/mercator.hpp"
#include "base/logging.hpp"
#include "base/math.hpp"
namespace df
{
@ -116,7 +119,7 @@ float SideByNormal(glsl::vec2 const & normal, bool isLeft)
void GenerateJoinsTriangles(glsl::vec3 const & pivot, std::vector<glsl::vec2> const & normals,
glsl::vec4 const & color, glsl::vec2 const & length, bool isLeft,
RouteShape::TGeometryBuffer & joinsGeometry)
RouteShape::GeometryBuffer & joinsGeometry)
{
size_t const trianglesCount = normals.size() / 3;
for (size_t j = 0; j < trianglesCount; j++)
@ -125,9 +128,9 @@ void GenerateJoinsTriangles(glsl::vec3 const & pivot, std::vector<glsl::vec2> co
glsl::vec3 const len2 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 1], isLeft));
glsl::vec3 const len3 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 2], isLeft));
joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j], len1, color));
joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j + 1], len2, color));
joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j + 2], len3, color));
joinsGeometry.emplace_back(pivot, normals[3 * j], len1, color);
joinsGeometry.emplace_back(pivot, normals[3 * j + 1], len2, color);
joinsGeometry.emplace_back(pivot, normals[3 * j + 2], len3, color);
}
}
@ -144,17 +147,17 @@ glsl::vec2 GetUV(m2::RectF const & texRect, glsl::vec2 const & uv)
void GenerateArrowsTriangles(glsl::vec4 const & pivot, std::vector<glsl::vec2> const & normals,
m2::RectF const & texRect, std::vector<glsl::vec2> const & uv,
bool normalizedUV, RouteShape::TArrowGeometryBuffer & joinsGeometry)
bool normalizedUV, RouteShape::ArrowGeometryBuffer & joinsGeometry)
{
size_t const trianglesCount = normals.size() / 3;
for (size_t j = 0; j < trianglesCount; j++)
{
joinsGeometry.push_back(RouteShape::AV(pivot, normals[3 * j],
normalizedUV ? GetUV(texRect, uv[3 * j]) : uv[3 * j]));
joinsGeometry.push_back(RouteShape::AV(pivot, normals[3 * j + 1],
normalizedUV ? GetUV(texRect, uv[3 * j + 1]) : uv[3 * j + 1]));
joinsGeometry.push_back(RouteShape::AV(pivot, normals[3 * j + 2],
normalizedUV ? GetUV(texRect, uv[3 * j + 2]) : uv[3 * j + 2]));
joinsGeometry.emplace_back(pivot, normals[3 * j],
normalizedUV ? GetUV(texRect, uv[3 * j]) : uv[3 * j]);
joinsGeometry.emplace_back(pivot, normals[3 * j + 1],
normalizedUV ? GetUV(texRect, uv[3 * j + 1]) : uv[3 * j + 1]);
joinsGeometry.emplace_back(pivot, normals[3 * j + 2],
normalizedUV ? GetUV(texRect, uv[3 * j + 2]) : uv[3 * j + 2]);
}
}
@ -178,7 +181,7 @@ void Subroute::AddStyle(SubrouteStyle const & style)
void RouteShape::PrepareGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
std::vector<glsl::vec4> const & segmentsColors, float baseDepth,
TGeometryBuffer & geometry, TGeometryBuffer & joinsGeometry)
std::vector<GeometryBufferData<GeometryBuffer>> & geometryBufferData)
{
ASSERT(path.size() > 1, ());
@ -195,13 +198,24 @@ void RouteShape::PrepareGeometry(std::vector<m2::PointD> const & path, m2::Point
for (auto const & segment : segments)
length += glsl::length(segment.m_points[EndPoint] - segment.m_points[StartPoint]);
geometryBufferData.emplace_back(GeometryBufferData<GeometryBuffer>());
uint32_t constexpr kMinVertices = 5000;
double constexpr kMinExtent = MercatorBounds::kRangeX / (1 << 10);
float depth = baseDepth;
float const depthStep = kRouteDepth / (1 + segments.size());
for (auto i = static_cast<int>(segments.size() - 1); i >= 0; i--)
{
auto & geomBufferData = geometryBufferData.back();
auto & geometry = geomBufferData.m_geometry;
UpdateNormals(&segments[i], (i > 0) ? &segments[i - 1] : nullptr,
(i < static_cast<int>(segments.size()) - 1) ? &segments[i + 1] : nullptr);
geomBufferData.m_boundingBox.Add(glsl::FromVec2(segments[i].m_points[StartPoint]));
geomBufferData.m_boundingBox.Add(glsl::FromVec2(segments[i].m_points[EndPoint]));
// Generate main geometry.
m2::PointD const startPt = MapShape::ConvertToLocal(glsl::FromVec2(segments[i].m_points[StartPoint]),
pivot, kShapeCoordScalar);
@ -224,23 +238,25 @@ void RouteShape::PrepareGeometry(std::vector<m2::PointD> const & path, m2::Point
float const projRightStart = -segments[i].m_rightWidthScalar[StartPoint].y;
float const projRightEnd = segments[i].m_rightWidthScalar[EndPoint].y;
geometry.push_back(RV(startPivot, glsl::vec2(0, 0),
glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
geometry.push_back(RV(startPivot, leftNormalStart,
glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color));
geometry.push_back(RV(endPivot, glsl::vec2(0, 0),
glsl::vec3(length, 0, kCenter), segments[i].m_color));
geometry.push_back(RV(endPivot, leftNormalEnd,
glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color));
geometry.emplace_back(startPivot, glsl::vec2(0, 0),
glsl::vec3(startLength, 0, kCenter), segments[i].m_color);
geometry.emplace_back(startPivot, leftNormalStart,
glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color);
geometry.emplace_back(endPivot, glsl::vec2(0, 0),
glsl::vec3(length, 0, kCenter), segments[i].m_color);
geometry.emplace_back(endPivot, leftNormalEnd,
glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color);
geometry.push_back(RV(startPivot, rightNormalStart,
glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color));
geometry.push_back(RV(startPivot, glsl::vec2(0, 0),
glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
geometry.push_back(RV(endPivot, rightNormalEnd,
glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color));
geometry.push_back(RV(endPivot, glsl::vec2(0, 0),
glsl::vec3(length, 0, kCenter), segments[i].m_color));
geometry.emplace_back(startPivot, rightNormalStart,
glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color);
geometry.emplace_back(startPivot, glsl::vec2(0, 0),
glsl::vec3(startLength, 0, kCenter), segments[i].m_color);
geometry.emplace_back(endPivot, rightNormalEnd,
glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color);
geometry.emplace_back(endPivot, glsl::vec2(0, 0),
glsl::vec3(length, 0, kCenter), segments[i].m_color);
auto & joinsGeometry = geomBufferData.m_joinsGeometry;
// Generate joins.
if (segments[i].m_generateJoin && i < static_cast<int>(segments.size()) - 1)
@ -287,13 +303,18 @@ void RouteShape::PrepareGeometry(std::vector<m2::PointD> const & path, m2::Point
true, joinsGeometry);
}
auto const verticesCount = geomBufferData.m_geometry.size() + geomBufferData.m_joinsGeometry.size();
auto const extent = std::max(geomBufferData.m_boundingBox.SizeX(), geomBufferData.m_boundingBox.SizeY());
if (verticesCount > kMinVertices && extent > kMinExtent)
geometryBufferData.emplace_back(GeometryBufferData<GeometryBuffer>());
length = startLength;
}
}
void RouteShape::PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
m2::RectF const & texRect, float depthStep, float depth,
TArrowGeometryBuffer & geometry, TArrowGeometryBuffer & joinsGeometry)
GeometryBufferData<ArrowGeometryBuffer> & geometryBufferData)
{
ASSERT(path.size() > 1, ());
@ -310,9 +331,14 @@ void RouteShape::PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::
float const depthInc = depthStep / (segments.size() + 1);
for (size_t i = 0; i < segments.size(); i++)
{
auto & geometry = geometryBufferData.m_geometry;
UpdateNormals(&segments[i], (i > 0) ? &segments[i - 1] : nullptr,
(i < segments.size() - 1) ? &segments[i + 1] : nullptr);
geometryBufferData.m_boundingBox.Add(glsl::FromVec2(segments[i].m_points[StartPoint]));
geometryBufferData.m_boundingBox.Add(glsl::FromVec2(segments[i].m_points[EndPoint]));
// Generate main geometry.
m2::PointD const startPt = MapShape::ConvertToLocal(glsl::FromVec2(segments[i].m_points[StartPoint]),
pivot, kShapeCoordScalar);
@ -332,15 +358,17 @@ void RouteShape::PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::
glsl::vec2 const uvLeft = GetUV(tr, 0.5f, 0.0f);
glsl::vec2 const uvRight = GetUV(tr, 0.5f, 1.0f);
geometry.push_back(AV(startPivot, glsl::vec2(0, 0), uvCenter));
geometry.push_back(AV(startPivot, leftNormalStart, uvLeft));
geometry.push_back(AV(endPivot, glsl::vec2(0, 0), uvCenter));
geometry.push_back(AV(endPivot, leftNormalEnd, uvLeft));
geometry.emplace_back(startPivot, glsl::vec2(0, 0), uvCenter);
geometry.emplace_back(startPivot, leftNormalStart, uvLeft);
geometry.emplace_back(endPivot, glsl::vec2(0, 0), uvCenter);
geometry.emplace_back(endPivot, leftNormalEnd, uvLeft);
geometry.push_back(AV(startPivot, rightNormalStart, uvRight));
geometry.push_back(AV(startPivot, glsl::vec2(0, 0), uvCenter));
geometry.push_back(AV(endPivot, rightNormalEnd, uvRight));
geometry.push_back(AV(endPivot, glsl::vec2(0, 0), uvCenter));
geometry.emplace_back(startPivot, rightNormalStart, uvRight);
geometry.emplace_back(startPivot, glsl::vec2(0, 0), uvCenter);
geometry.emplace_back(endPivot, rightNormalEnd, uvRight);
geometry.emplace_back(endPivot, glsl::vec2(0, 0), uvCenter);
auto & joinsGeometry = geometryBufferData.m_joinsGeometry;
// Generate joins.
if (segments[i].m_generateJoin && i < segments.size() - 1)
@ -411,7 +439,7 @@ void RouteShape::PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::
void RouteShape::PrepareMarkersGeometry(std::vector<SubrouteMarker> const & markers,
m2::PointD const & pivot, float baseDepth,
TMarkersGeometryBuffer & geometry)
MarkersGeometryBuffer & geometry)
{
ASSERT(!markers.empty(), ());
@ -488,8 +516,7 @@ void RouteShape::CacheRouteArrows(ref_ptr<dp::GraphicsContext> context,
std::vector<ArrowBorders> const & borders, double baseDepthIndex,
SubrouteArrowsData & routeArrowsData)
{
TArrowGeometryBuffer geometry;
TArrowGeometryBuffer joinsGeometry;
GeometryBufferData<ArrowGeometryBuffer> geometryData;
dp::TextureManager::SymbolRegion region;
GetArrowTextureRegion(mng, region);
auto state = CreateRenderState(gpu::Program::RouteArrow, DepthLayer::GeometryLayer);
@ -504,18 +531,23 @@ void RouteShape::CacheRouteArrows(ref_ptr<dp::GraphicsContext> context,
std::vector<m2::PointD> points = CalculatePoints(polyline, b.m_startDistance, b.m_endDistance);
ASSERT_LESS_OR_EQUAL(points.size(), polyline.GetSize(), ());
PrepareArrowGeometry(points, routeArrowsData.m_pivot, region.GetTexRect(), depthStep,
depth, geometry, joinsGeometry);
depth, geometryData);
}
BatchGeometry(context, state, make_ref(geometry.data()), static_cast<uint32_t>(geometry.size()),
make_ref(joinsGeometry.data()), static_cast<uint32_t>(joinsGeometry.size()),
AV::GetBindingInfo(), routeArrowsData.m_renderProperty);
double constexpr kBoundingBoxScale = 1.2;
geometryData.m_boundingBox.Scale(kBoundingBoxScale);
BatchGeometry(context, state, make_ref(geometryData.m_geometry.data()),
static_cast<uint32_t>(geometryData.m_geometry.size()),
make_ref(geometryData.m_joinsGeometry.data()),
static_cast<uint32_t>(geometryData.m_joinsGeometry.size()),
geometryData.m_boundingBox, AV::GetBindingInfo(),
routeArrowsData.m_renderProperty);
}
drape_ptr<df::SubrouteData> RouteShape::CacheRoute(ref_ptr<dp::GraphicsContext> context,
dp::DrapeID subrouteId,
SubrouteConstPtr subroute, size_t styleIndex,
int recacheId,
dp::DrapeID subrouteId, SubrouteConstPtr subroute,
size_t styleIndex, int recacheId,
ref_ptr<dp::TextureManager> textures)
{
size_t startIndex;
@ -565,28 +597,34 @@ drape_ptr<df::SubrouteData> RouteShape::CacheRoute(ref_ptr<dp::GraphicsContext>
subrouteData->m_recacheId = recacheId;
subrouteData->m_distanceOffset = subroute->m_polyline.GetLength(startIndex);
TGeometryBuffer geometry;
TGeometryBuffer joinsGeometry;
std::vector<GeometryBufferData<GeometryBuffer>> geometryBufferData;
PrepareGeometry(points, subrouteData->m_pivot, segmentsColors,
static_cast<float>(subroute->m_baseDepthIndex * kDepthPerSubroute),
geometry, joinsGeometry);
geometryBufferData);
auto state = CreateRenderState(subroute->m_style[styleIndex].m_pattern.m_isDashed ?
gpu::Program::RouteDash : gpu::Program::Route, DepthLayer::GeometryLayer);
state.SetColorTexture(textures->GetSymbolsTexture());
BatchGeometry(context, state, make_ref(geometry.data()), static_cast<uint32_t>(geometry.size()),
make_ref(joinsGeometry.data()), static_cast<uint32_t>(joinsGeometry.size()),
RV::GetBindingInfo(), subrouteData->m_renderProperty);
double constexpr kBoundingBoxScale = 1.2;
for (auto & data : geometryBufferData)
{
data.m_boundingBox.Scale(kBoundingBoxScale);
BatchGeometry(context, state, make_ref(data.m_geometry.data()),
static_cast<uint32_t>(data.m_geometry.size()),
make_ref(data.m_joinsGeometry.data()),
static_cast<uint32_t>(data.m_joinsGeometry.size()),
data.m_boundingBox, RV::GetBindingInfo(),
subrouteData->m_renderProperty);
}
return subrouteData;
}
drape_ptr<df::SubrouteMarkersData> RouteShape::CacheMarkers(ref_ptr<dp::GraphicsContext> context,
dp::DrapeID subrouteId,
SubrouteConstPtr subroute,
int recacheId,
ref_ptr<dp::TextureManager> textures)
dp::DrapeID subrouteId, SubrouteConstPtr subroute,
int recacheId, ref_ptr<dp::TextureManager> textures)
{
if (subroute->m_markers.empty())
return nullptr;
@ -596,7 +634,7 @@ drape_ptr<df::SubrouteMarkersData> RouteShape::CacheMarkers(ref_ptr<dp::Graphics
markersData->m_pivot = subroute->m_polyline.GetLimitRect().Center();
markersData->m_recacheId = recacheId;
TMarkersGeometryBuffer geometry;
MarkersGeometryBuffer geometry;
auto const depth = static_cast<float>(subroute->m_baseDepthIndex * kDepthPerSubroute + kMarkersDepth);
PrepareMarkersGeometry(subroute->m_markers, markersData->m_pivot, depth, geometry);
if (geometry.empty())
@ -628,19 +666,27 @@ drape_ptr<df::SubrouteMarkersData> RouteShape::CacheMarkers(ref_ptr<dp::Graphics
void RouteShape::BatchGeometry(ref_ptr<dp::GraphicsContext> context, dp::RenderState const & state,
ref_ptr<void> geometry, uint32_t geomSize,
ref_ptr<void> joinsGeometry, uint32_t joinsGeomSize,
dp::BindingInfo const & bindingInfo, RouteRenderProperty & property)
m2::RectD const & boundingBox, dp::BindingInfo const & bindingInfo,
RouteRenderProperty & property)
{
size_t const verticesCount = geomSize + joinsGeomSize;
auto verticesCount = geomSize + joinsGeomSize;
if (verticesCount == 0)
return;
uint32_t const kBatchSize = 5000;
dp::Batcher batcher(kBatchSize, kBatchSize);
uint32_t constexpr kMinBatchSize = 100;
uint32_t constexpr kMaxBatchSize = 65000;
uint32_t constexpr kIndicesScalar = 2;
verticesCount = base::clamp(verticesCount, kMinBatchSize, kMaxBatchSize);
auto const indicesCount = base::clamp(verticesCount * kIndicesScalar, kMinBatchSize, kMaxBatchSize);
dp::Batcher batcher(indicesCount, verticesCount);
batcher.SetBatcherHash(static_cast<uint64_t>(BatcherBucket::Routing));
dp::SessionGuard guard(context, batcher, [&property](dp::RenderState const & state,
drape_ptr<dp::RenderBucket> && b)
dp::SessionGuard guard(context, batcher, [&property, &boundingBox](dp::RenderState const & state,
drape_ptr<dp::RenderBucket> && b)
{
property.m_buckets.push_back(std::move(b));
property.m_boundingBoxes.push_back(boundingBox);
property.m_state = state;
});

View file

@ -50,10 +50,6 @@ enum class RouteType : uint8_t
struct RoutePattern
{
bool m_isDashed = false;
double m_dashLength = 0.0;
double m_gapLength = 0.0;
RoutePattern() = default;
RoutePattern(double dashLength, double gapLength)
@ -69,6 +65,10 @@ struct RoutePattern
std::fabs(m_dashLength - pattern.m_dashLength) < kEps &&
std::fabs(m_gapLength - pattern.m_gapLength) < kEps;
}
bool m_isDashed = false;
double m_dashLength = 0.0;
double m_gapLength = 0.0;
};
enum class SubrouteStyleType
@ -79,14 +79,8 @@ enum class SubrouteStyleType
struct SubrouteStyle
{
df::ColorConstant m_color;
df::ColorConstant m_outlineColor;
df::RoutePattern m_pattern;
size_t m_startIndex = 0;
size_t m_endIndex = 0;
SubrouteStyle() = default;
SubrouteStyle(df::ColorConstant const & color)
explicit SubrouteStyle(df::ColorConstant const & color)
: m_color(color)
, m_outlineColor(color)
{}
@ -106,16 +100,19 @@ struct SubrouteStyle
, m_pattern(pattern)
{}
bool operator == (SubrouteStyle const & style) const
bool operator==(SubrouteStyle const & style) const
{
return m_color == style.m_color && m_outlineColor == style.m_outlineColor &&
m_pattern == style.m_pattern;
}
bool operator != (SubrouteStyle const & style) const
{
return !operator == (style);
}
bool operator!=(SubrouteStyle const & style) const { return !operator==(style); }
df::ColorConstant m_color;
df::ColorConstant m_outlineColor;
df::RoutePattern m_pattern;
size_t m_startIndex = 0;
size_t m_endIndex = 0;
};
// Colored circle on the subroute.
@ -157,11 +154,13 @@ using SubrouteConstPtr = std::shared_ptr<Subroute const>;
struct RouteRenderProperty
{
dp::RenderState m_state;
std::vector<drape_ptr<dp::RenderBucket>> m_buckets;
RouteRenderProperty()
: m_state(CreateRenderState(gpu::Program::Route, DepthLayer::GeometryLayer))
{}
dp::RenderState m_state;
std::vector<drape_ptr<dp::RenderBucket>> m_buckets;
std::vector<m2::RectD> m_boundingBoxes;
};
struct BaseSubrouteData
@ -196,11 +195,11 @@ class RouteShape
{
public:
using RV = gpu::RouteVertex;
using TGeometryBuffer = buffer_vector<RV, 128>;
using GeometryBuffer = buffer_vector<RV, 128>;
using AV = gpu::SolidTexturingVertex;
using TArrowGeometryBuffer = buffer_vector<AV, 128>;
using ArrowGeometryBuffer = buffer_vector<AV, 128>;
using MV = gpu::RouteMarkerVertex;
using TMarkersGeometryBuffer = buffer_vector<MV, 32>;
using MarkersGeometryBuffer = buffer_vector<MV, 32>;
static drape_ptr<df::SubrouteData> CacheRoute(ref_ptr<dp::GraphicsContext> context,
dp::DrapeID subrouteId, SubrouteConstPtr subroute,
@ -218,20 +217,30 @@ public:
SubrouteArrowsData & routeArrowsData);
private:
template<typename GeometryBufferType>
struct GeometryBufferData
{
GeometryBufferData()
: m_boundingBox(m2::RectD::GetEmptyRect())
{}
GeometryBufferType m_geometry;
GeometryBufferType m_joinsGeometry;
m2::RectD m_boundingBox;
};
static void PrepareGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
std::vector<glsl::vec4> const & segmentsColors, float baseDepth,
TGeometryBuffer & geometry, TGeometryBuffer & joinsGeometry);
std::vector<GeometryBufferData<GeometryBuffer>> & geometryBufferData);
static void PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::PointD const & pivot,
m2::RectF const & texRect, float depthStep, float depth,
TArrowGeometryBuffer & geometry,
TArrowGeometryBuffer & joinsGeometry);
GeometryBufferData<ArrowGeometryBuffer> & geometryBufferData);
static void PrepareMarkersGeometry(std::vector<SubrouteMarker> const & markers,
m2::PointD const & pivot, float baseDepth,
TMarkersGeometryBuffer & geometry);
MarkersGeometryBuffer & geometry);
static void BatchGeometry(ref_ptr<dp::GraphicsContext> context, dp::RenderState const & state,
ref_ptr<void> geometry, uint32_t geomSize, ref_ptr<void> joinsGeometry,
uint32_t joinsGeomSize, dp::BindingInfo const & bindingInfo,
RouteRenderProperty & property);
uint32_t joinsGeomSize, m2::RectD const & boundingBox,
dp::BindingInfo const & bindingInfo, RouteRenderProperty & property);
};
} // namespace df

View file

@ -575,7 +575,7 @@ using namespace osm_auth_ios;
if ([AppInfo sharedInfo].openGLDriver == MWMOpenGLDriverMetalPre103)
{
m2::PointU const size = ((EAGLView *)self.mapViewController.view).pixelSize;
f.OnRecoverSurface(static_cast<int>(size.x), static_cast<int>(size.y));
f.OnRecoverSurface(static_cast<int>(size.x), static_cast<int>(size.y), true /* recreateContextDependentResources */);
}
[MWMLocationManager applicationDidBecomeActive];
[MWMSearch addCategoriesToSpotlight];

View file

@ -390,7 +390,8 @@ void Framework::Migrate(bool keepDownloaded)
{
m_drapeEngine->SetRenderingEnabled();
OnRecoverSurface(m_currentModelView.PixelRectIn3d().SizeX(),
m_currentModelView.PixelRectIn3d().SizeY());
m_currentModelView.PixelRectIn3d().SizeY(),
true /* recreateContextDependentResources */);
}
InvalidateRect(MercatorBounds::FullRect());
}
@ -1910,11 +1911,11 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::GraphicsContextFactory> contextFac
benchmark::RunGraphicsBenchmark(this);
}
void Framework::OnRecoverSurface(int width, int height)
void Framework::OnRecoverSurface(int width, int height, bool recreateContextDependentResources)
{
if (m_drapeEngine)
{
m_drapeEngine->Update(width, height);
m_drapeEngine->RecoverSurface(width, height, recreateContextDependentResources);
InvalidateUserMarks();
@ -2447,21 +2448,20 @@ df::SelectionShape::ESelectedObject Framework::OnTapEventImpl(TapEvent const & t
}
FeatureID featureTapped = tapInfo.m_featureTapped;
if (!featureTapped.IsValid())
featureTapped = FindBuildingAtPoint(tapInfo.m_mercator);
bool showMapSelection = false;
if (featureTapped.IsValid())
{
FillFeatureInfo(featureTapped, outInfo);
showMapSelection = true;
}
else if (tapInfo.m_isLong || tapEvent.m_source == TapEvent::Source::Search)
if (tapInfo.m_isLong || tapEvent.m_source == TapEvent::Source::Search)
{
FillPointInfo(tapInfo.m_mercator, {} /* customTitle */, outInfo);
showMapSelection = true;
}
else if (featureTapped.IsValid())
{
FillFeatureInfo(featureTapped, outInfo);
showMapSelection = true;
}
if (showMapSelection)
{

View file

@ -510,7 +510,7 @@ public:
void SetRenderingEnabled(ref_ptr<dp::GraphicsContextFactory> contextFactory = nullptr);
void SetRenderingDisabled(bool destroySurface);
void OnRecoverSurface(int width, int height);
void OnRecoverSurface(int width, int height, bool recreateContextDependentResources);
void OnDestroySurface();
private:

View file

@ -19,6 +19,10 @@ void main()
pos.xyw = (pos * u_projection).xyw;
pos.z = a_position.z * u_zScale;
gl_Position = u_pivotTransform * pos;
#ifdef VULKAN
gl_Position.y = -gl_Position.y;
gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;
#endif
#ifdef ENABLE_VTF
v_color = texture2D(u_colorTex, a_colorTexCoords);