mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Add some comments and rename
This commit is contained in:
parent
a150d8776c
commit
9c5dc1965b
@ -3,9 +3,9 @@ use maplibre::coords::{WorldTileCoords, ZoomLevel};
|
|||||||
use maplibre::error::Error;
|
use maplibre::error::Error;
|
||||||
use maplibre::io::pipeline::Processable;
|
use maplibre::io::pipeline::Processable;
|
||||||
use maplibre::io::pipeline::{PipelineContext, PipelineProcessor};
|
use maplibre::io::pipeline::{PipelineContext, PipelineProcessor};
|
||||||
use maplibre::io::pipeline_steps::build_vector_tile_pipeline;
|
|
||||||
use maplibre::io::scheduler::ScheduleMethod;
|
use maplibre::io::scheduler::ScheduleMethod;
|
||||||
use maplibre::io::source_client::{HttpClient, HttpSourceClient};
|
use maplibre::io::source_client::{HttpClient, HttpSourceClient};
|
||||||
|
use maplibre::io::tile_pipelines::build_vector_tile_pipeline;
|
||||||
use maplibre::io::tile_repository::StoredLayer;
|
use maplibre::io::tile_repository::StoredLayer;
|
||||||
use maplibre::io::{RawLayer, TileRequest, TileRequestID};
|
use maplibre::io::{RawLayer, TileRequest, TileRequestID};
|
||||||
use maplibre::map_schedule::{EventuallyMapContext, InteractiveMapSchedule};
|
use maplibre::map_schedule::{EventuallyMapContext, InteractiveMapSchedule};
|
||||||
@ -70,7 +70,7 @@ struct HeadlessPipelineProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineProcessor for HeadlessPipelineProcessor {
|
impl PipelineProcessor for HeadlessPipelineProcessor {
|
||||||
fn finished_layer_tesselation(
|
fn layer_tesselation_finished(
|
||||||
&mut self,
|
&mut self,
|
||||||
coords: &WorldTileCoords,
|
coords: &WorldTileCoords,
|
||||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||||
|
|||||||
@ -136,9 +136,7 @@ where
|
|||||||
let dt = now - last_render_time;
|
let dt = now - last_render_time;
|
||||||
last_render_time = now;
|
last_render_time = now;
|
||||||
|
|
||||||
{
|
input_controller.update_state(map_schedule.view_state_mut(), dt);
|
||||||
input_controller.update_state(map_schedule.view_state_mut(), dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
match map_schedule.update_and_redraw() {
|
match map_schedule.update_and_redraw() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ pub mod static_tile_fetcher;
|
|||||||
|
|
||||||
pub mod geometry_index;
|
pub mod geometry_index;
|
||||||
pub mod pipeline;
|
pub mod pipeline;
|
||||||
pub mod pipeline_steps;
|
pub mod tile_pipelines;
|
||||||
pub mod tile_repository;
|
pub mod tile_repository;
|
||||||
pub mod tile_request_state;
|
pub mod tile_request_state;
|
||||||
|
|
||||||
|
|||||||
@ -10,19 +10,19 @@ use std::marker::PhantomData;
|
|||||||
use std::process::Output;
|
use std::process::Output;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
/// Processes events which happen during the pipeline execution
|
||||||
pub trait PipelineProcessor: Downcast {
|
pub trait PipelineProcessor: Downcast {
|
||||||
fn finished_tile_tesselation(&mut self, request_id: TileRequestID, coords: &WorldTileCoords) {}
|
fn tile_finished(&mut self, request_id: TileRequestID, coords: &WorldTileCoords) {}
|
||||||
fn unavailable_layer(&mut self, coords: &WorldTileCoords, layer_name: &str) {}
|
fn layer_unavailable(&mut self, coords: &WorldTileCoords, layer_name: &str) {}
|
||||||
fn finished_layer_tesselation(
|
fn layer_tesselation_finished(
|
||||||
&mut self,
|
&mut self,
|
||||||
coords: &WorldTileCoords,
|
coords: &WorldTileCoords,
|
||||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||||
// Holds for each feature the count of indices.
|
|
||||||
feature_indices: Vec<u32>,
|
feature_indices: Vec<u32>,
|
||||||
layer_data: tile::Layer,
|
layer_data: tile::Layer,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
fn finished_layer_indexing(
|
fn layer_indexing_finished(
|
||||||
&mut self,
|
&mut self,
|
||||||
coords: &WorldTileCoords,
|
coords: &WorldTileCoords,
|
||||||
geometries: Vec<IndexedGeometry<f64>>,
|
geometries: Vec<IndexedGeometry<f64>>,
|
||||||
@ -32,6 +32,7 @@ pub trait PipelineProcessor: Downcast {
|
|||||||
|
|
||||||
impl_downcast!(PipelineProcessor);
|
impl_downcast!(PipelineProcessor);
|
||||||
|
|
||||||
|
/// Context which is available to each step within a [`DataPipeline`]
|
||||||
pub struct PipelineContext {
|
pub struct PipelineContext {
|
||||||
processor: Box<dyn PipelineProcessor>,
|
processor: Box<dyn PipelineProcessor>,
|
||||||
}
|
}
|
||||||
@ -52,6 +53,7 @@ impl PipelineContext {
|
|||||||
{
|
{
|
||||||
self.processor.into_any().downcast::<P>().ok()
|
self.processor.into_any().downcast::<P>().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn processor_mut(&mut self) -> &mut dyn PipelineProcessor {
|
pub fn processor_mut(&mut self) -> &mut dyn PipelineProcessor {
|
||||||
self.processor.as_mut()
|
self.processor.as_mut()
|
||||||
}
|
}
|
||||||
@ -64,26 +66,28 @@ pub trait Processable {
|
|||||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output;
|
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PipelineStep<P, N>
|
/// A pipeline which consists of multiple steps. Steps are [`Processable`] workloads. Later steps
|
||||||
|
/// depend on previous ones.
|
||||||
|
pub struct DataPipeline<P, N>
|
||||||
where
|
where
|
||||||
P: Processable,
|
P: Processable,
|
||||||
N: Processable<Input = P::Output>,
|
N: Processable<Input = P::Output>,
|
||||||
{
|
{
|
||||||
process: P,
|
step: P,
|
||||||
next: N,
|
next_step: N,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P, N> PipelineStep<P, N>
|
impl<P, N> DataPipeline<P, N>
|
||||||
where
|
where
|
||||||
P: Processable,
|
P: Processable,
|
||||||
N: Processable<Input = P::Output>,
|
N: Processable<Input = P::Output>,
|
||||||
{
|
{
|
||||||
pub fn new(process: P, next: N) -> Self {
|
pub fn new(step: P, next_step: N) -> Self {
|
||||||
Self { process, next }
|
Self { step, next_step }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P, N> Processable for PipelineStep<P, N>
|
impl<P, N> Processable for DataPipeline<P, N>
|
||||||
where
|
where
|
||||||
P: Processable,
|
P: Processable,
|
||||||
N: Processable<Input = P::Output>,
|
N: Processable<Input = P::Output>,
|
||||||
@ -92,16 +96,17 @@ where
|
|||||||
type Output = N::Output;
|
type Output = N::Output;
|
||||||
|
|
||||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
||||||
let output = self.process.process(input, context);
|
let output = self.step.process(input, context);
|
||||||
self.next.process(output, context)
|
self.next_step.process(output, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EndStep<I> {
|
/// Marks the end of a [`DataPipeline`]
|
||||||
|
pub struct PipelineEnd<I> {
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Default for EndStep<I> {
|
impl<I> Default for PipelineEnd<I> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
phantom: PhantomData::default(),
|
phantom: PhantomData::default(),
|
||||||
@ -109,7 +114,7 @@ impl<I> Default for EndStep<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Processable for EndStep<I> {
|
impl<I> Processable for PipelineEnd<I> {
|
||||||
type Input = I;
|
type Input = I;
|
||||||
type Output = I;
|
type Output = I;
|
||||||
|
|
||||||
@ -173,7 +178,8 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::io::pipeline::{
|
use crate::io::pipeline::{
|
||||||
ClosureProcessable, EndStep, PipelineContext, PipelineProcessor, PipelineStep, Processable,
|
ClosureProcessable, DataPipeline, PipelineContext, PipelineEnd, PipelineProcessor,
|
||||||
|
Processable,
|
||||||
};
|
};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
@ -190,65 +196,48 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test_fn_pointer() {
|
||||||
let mut context = PipelineContext {
|
let mut context = PipelineContext::new(DummyPipelineProcessor);
|
||||||
processor: Box::new(DummyPipelineProcessor),
|
let output: u32 = DataPipeline::new(
|
||||||
};
|
add_two as fn(u8, &mut PipelineContext) -> u32,
|
||||||
let output: u32 = PipelineStep {
|
PipelineEnd::default(),
|
||||||
process: add_two as fn(u8, &mut PipelineContext) -> u32,
|
|
||||||
next: EndStep::default(),
|
|
||||||
}
|
|
||||||
.process(5u8, &mut context);
|
|
||||||
|
|
||||||
assert_eq!(output, 7);
|
|
||||||
|
|
||||||
let output = PipelineStep {
|
|
||||||
process: add_one as fn(u32, &mut PipelineContext) -> u8,
|
|
||||||
next: PipelineStep {
|
|
||||||
process: add_two as fn(u8, &mut PipelineContext) -> u32,
|
|
||||||
next: EndStep::default(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
.process(5u32, &mut context);
|
|
||||||
|
|
||||||
assert_eq!(output, 8);
|
|
||||||
|
|
||||||
let mut a = 3;
|
|
||||||
let closure = |input: u8, context: &mut PipelineContext| -> u32 {
|
|
||||||
return input as u32 + 2 + a;
|
|
||||||
};
|
|
||||||
let output: u32 = PipelineStep {
|
|
||||||
process: ClosureProcessable {
|
|
||||||
func: closure,
|
|
||||||
phantom_i: Default::default(),
|
|
||||||
},
|
|
||||||
next: EndStep::default(),
|
|
||||||
}
|
|
||||||
.process(5u8, &mut context);
|
|
||||||
|
|
||||||
assert_eq!(output, 10);
|
|
||||||
|
|
||||||
let processable =
|
|
||||||
ClosureProcessable::from(|input: u8, context: &mut PipelineContext| -> u32 {
|
|
||||||
return input as u32 + 2 + a;
|
|
||||||
});
|
|
||||||
let output: u32 = PipelineStep {
|
|
||||||
process: processable,
|
|
||||||
next: EndStep::default(),
|
|
||||||
}
|
|
||||||
.process(5u8, &mut context);
|
|
||||||
|
|
||||||
assert_eq!(output, 10);
|
|
||||||
|
|
||||||
let output: u32 = PipelineStep::<ClosureProcessable<_, u8, u32>, _>::new(
|
|
||||||
(|input: u8, context: &mut PipelineContext| -> u32 {
|
|
||||||
return input as u32 + 2 + a;
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
EndStep::<u32>::default(),
|
|
||||||
)
|
)
|
||||||
.process(5u8, &mut context);
|
.process(5u8, &mut context);
|
||||||
|
assert_eq!(output, 7);
|
||||||
|
|
||||||
|
let output: u32 = DataPipeline::new(
|
||||||
|
add_one as fn(u32, &mut PipelineContext) -> u8,
|
||||||
|
DataPipeline::new(
|
||||||
|
add_two as fn(u8, &mut PipelineContext) -> u32,
|
||||||
|
PipelineEnd::default(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.process(5u32, &mut context);
|
||||||
|
assert_eq!(output, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_closure() {
|
||||||
|
let mut context = PipelineContext::new(DummyPipelineProcessor);
|
||||||
|
let mut outer_value = 3;
|
||||||
|
|
||||||
|
// using from()
|
||||||
|
let closure = ClosureProcessable::from(|input: u8, context: &mut PipelineContext| -> u32 {
|
||||||
|
return input as u32 + 2 + outer_value;
|
||||||
|
});
|
||||||
|
let output: u32 =
|
||||||
|
DataPipeline::new(closure, PipelineEnd::default()).process(5u8, &mut context);
|
||||||
|
assert_eq!(output, 10);
|
||||||
|
|
||||||
|
// with into()
|
||||||
|
let output: u32 = DataPipeline::<ClosureProcessable<_, u8, u32>, _>::new(
|
||||||
|
(|input: u8, context: &mut PipelineContext| -> u32 {
|
||||||
|
return input as u32 + 2 + outer_value;
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
PipelineEnd::<u32>::default(),
|
||||||
|
)
|
||||||
|
.process(5u8, &mut context);
|
||||||
assert_eq!(output, 10);
|
assert_eq!(output, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::io::geometry_index::IndexProcessor;
|
use crate::io::geometry_index::IndexProcessor;
|
||||||
use crate::io::pipeline::{EndStep, PipelineContext, PipelineStep, Processable};
|
use crate::io::pipeline::{DataPipeline, PipelineContext, PipelineEnd, Processable};
|
||||||
use crate::io::{TileRequest, TileRequestID};
|
use crate::io::{TileRequest, TileRequestID};
|
||||||
use crate::tessellation::zero_tessellator::ZeroTessellator;
|
use crate::tessellation::zero_tessellator::ZeroTessellator;
|
||||||
use crate::tessellation::IndexDataType;
|
use crate::tessellation::IndexDataType;
|
||||||
@ -7,9 +7,9 @@ use geozero::GeozeroDatasource;
|
|||||||
use prost::Message;
|
use prost::Message;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub struct ParseTileStep;
|
pub struct ParseTile;
|
||||||
|
|
||||||
impl Processable for ParseTileStep {
|
impl Processable for ParseTile {
|
||||||
type Input = (TileRequest, TileRequestID, Box<[u8]>);
|
type Input = (TileRequest, TileRequestID, Box<[u8]>);
|
||||||
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ impl Processable for ParseTileStep {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IndexLayerStep;
|
pub struct IndexLayer;
|
||||||
|
|
||||||
impl Processable for IndexLayerStep {
|
impl Processable for IndexLayer {
|
||||||
type Input = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
type Input = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
||||||
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
||||||
|
|
||||||
@ -40,14 +40,14 @@ impl Processable for IndexLayerStep {
|
|||||||
|
|
||||||
context
|
context
|
||||||
.processor_mut()
|
.processor_mut()
|
||||||
.finished_layer_indexing(&tile_request.coords, index.get_geometries());
|
.layer_indexing_finished(&tile_request.coords, index.get_geometries());
|
||||||
(tile_request, request_id, tile)
|
(tile_request, request_id, tile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TessellateLayerStep;
|
pub struct TessellateLayer;
|
||||||
|
|
||||||
impl Processable for TessellateLayerStep {
|
impl Processable for TessellateLayer {
|
||||||
type Input = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
type Input = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
||||||
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
type Output = (TileRequest, TileRequestID, geozero::mvt::Tile);
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ impl Processable for TessellateLayerStep {
|
|||||||
if let Err(e) = layer.process(&mut tessellator) {
|
if let Err(e) = layer.process(&mut tessellator) {
|
||||||
context
|
context
|
||||||
.processor_mut()
|
.processor_mut()
|
||||||
.unavailable_layer(coords, layer_name);
|
.layer_unavailable(coords, layer_name);
|
||||||
|
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
"layer {} at {} tesselation failed {:?}",
|
"layer {} at {} tesselation failed {:?}",
|
||||||
@ -81,7 +81,7 @@ impl Processable for TessellateLayerStep {
|
|||||||
e
|
e
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
context.processor_mut().finished_layer_tesselation(
|
context.processor_mut().layer_tesselation_finished(
|
||||||
coords,
|
coords,
|
||||||
tessellator.buffer.into(),
|
tessellator.buffer.into(),
|
||||||
tessellator.feature_indices,
|
tessellator.feature_indices,
|
||||||
@ -99,7 +99,7 @@ impl Processable for TessellateLayerStep {
|
|||||||
for missing_layer in tile_request.layers.difference(&available_layers) {
|
for missing_layer in tile_request.layers.difference(&available_layers) {
|
||||||
context
|
context
|
||||||
.processor_mut()
|
.processor_mut()
|
||||||
.unavailable_layer(coords, missing_layer);
|
.layer_unavailable(coords, missing_layer);
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"requested layer {} at {} not found in tile",
|
"requested layer {} at {} not found in tile",
|
||||||
@ -112,23 +112,23 @@ impl Processable for TessellateLayerStep {
|
|||||||
|
|
||||||
context
|
context
|
||||||
.processor_mut()
|
.processor_mut()
|
||||||
.finished_tile_tesselation(request_id, &tile_request.coords);
|
.tile_finished(request_id, &tile_request.coords);
|
||||||
|
|
||||||
(tile_request, request_id, tile)
|
(tile_request, request_id, tile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_vector_tile_pipeline(
|
pub fn build_vector_tile_pipeline() -> impl Processable<Input = <ParseTile as Processable>::Input> {
|
||||||
) -> impl Processable<Input = <ParseTileStep as Processable>::Input> {
|
DataPipeline::new(
|
||||||
PipelineStep::new(
|
ParseTile,
|
||||||
ParseTileStep,
|
DataPipeline::new(TessellateLayer, PipelineEnd::default()),
|
||||||
PipelineStep::new(TessellateLayerStep, EndStep::default()),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::build_vector_tile_pipeline;
|
use super::build_vector_tile_pipeline;
|
||||||
|
use crate::coords::ZoomLevel;
|
||||||
use crate::io::pipeline::{PipelineContext, PipelineProcessor, Processable};
|
use crate::io::pipeline::{PipelineContext, PipelineProcessor, Processable};
|
||||||
use crate::io::TileRequest;
|
use crate::io::TileRequest;
|
||||||
pub struct DummyPipelineProcessor;
|
pub struct DummyPipelineProcessor;
|
||||||
@ -144,7 +144,7 @@ mod tests {
|
|||||||
let output = pipeline.process(
|
let output = pipeline.process(
|
||||||
(
|
(
|
||||||
TileRequest {
|
TileRequest {
|
||||||
coords: (0, 0, 0).into(),
|
coords: (0, 0, ZoomLevel::default()).into(),
|
||||||
layers: Default::default(),
|
layers: Default::default(),
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
@ -47,7 +47,8 @@ pub mod benchmarking;
|
|||||||
pub(crate) mod tessellation;
|
pub(crate) mod tessellation;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
/// Map's configuration and execution.
|
/// The [`Map`] defines the public interface of the map renderer.
|
||||||
|
// DO NOT IMPLEMENT INTERNALS ON THIS STRUCT.
|
||||||
pub struct Map<MWC, SM, HC>
|
pub struct Map<MWC, SM, HC>
|
||||||
where
|
where
|
||||||
MWC: MapWindowConfig,
|
MWC: MapWindowConfig,
|
||||||
@ -114,6 +115,7 @@ where
|
|||||||
map_schedule: SimpleMapSchedule<MWC, SM, HC>,
|
map_schedule: SimpleMapSchedule<MWC, SM, HC>,
|
||||||
window: MWC::MapWindow,
|
window: MWC::MapWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MWC, SM, HC> HeadlessMap<MWC, SM, HC>
|
impl<MWC, SM, HC> HeadlessMap<MWC, SM, HC>
|
||||||
where
|
where
|
||||||
MWC: MapWindowConfig,
|
MWC: MapWindowConfig,
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
//! Node which copies the contents of the GPU-side texture in [`BufferedTextureHead`] to an
|
||||||
|
//! unmapped GPU-side buffer. This buffer will be mapped in
|
||||||
|
//! [`crate::render::stages::write_surface_buffer_stage::WriteSurfaceBufferStage`].
|
||||||
|
|
||||||
use crate::render::graph::{Node, NodeRunError, RenderContext, RenderGraphContext, SlotInfo};
|
use crate::render::graph::{Node, NodeRunError, RenderContext, RenderGraphContext, SlotInfo};
|
||||||
use crate::render::render_commands::{DrawMasks, DrawTiles};
|
use crate::render::render_commands::{DrawMasks, DrawTiles};
|
||||||
use crate::render::render_phase::{PhaseItem, RenderCommand};
|
use crate::render::render_phase::{PhaseItem, RenderCommand};
|
||||||
|
|||||||
@ -31,17 +31,19 @@ use crate::{HeadedMapWindow, MapWindow, MapWindowConfig};
|
|||||||
use log::info;
|
use log::info;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// Rendering internals
|
|
||||||
#[cfg(feature = "headless")]
|
#[cfg(feature = "headless")]
|
||||||
mod copy_surface_to_buffer_node;
|
// Exposed because it should be addable conditionally
|
||||||
|
pub mod copy_surface_to_buffer_node;
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
pub mod resource;
|
||||||
|
pub mod stages;
|
||||||
|
|
||||||
|
// Rendering internals
|
||||||
mod graph_runner;
|
mod graph_runner;
|
||||||
mod main_pass;
|
mod main_pass;
|
||||||
mod render_commands;
|
mod render_commands;
|
||||||
mod render_phase;
|
mod render_phase;
|
||||||
pub mod resource;
|
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod stages;
|
|
||||||
mod tile_pipeline;
|
mod tile_pipeline;
|
||||||
mod tile_view_pattern;
|
mod tile_view_pattern;
|
||||||
mod util;
|
mod util;
|
||||||
@ -434,7 +436,7 @@ mod tests {
|
|||||||
.ok()
|
.ok()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let render_state = RenderState::new(Surface::from_image::<HeadlessMapWindowConfig>(
|
let render_state = RenderState::new(Surface::from_image(
|
||||||
&device,
|
&device,
|
||||||
&HeadlessMapWindow {
|
&HeadlessMapWindow {
|
||||||
size: WindowSize::new(100, 100).unwrap(),
|
size: WindowSize::new(100, 100).unwrap(),
|
||||||
|
|||||||
@ -578,6 +578,7 @@ impl RingIndex {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::coords::ZoomLevel;
|
||||||
use crate::style::layer::StyleLayer;
|
use crate::style::layer::StyleLayer;
|
||||||
use lyon::tessellation::VertexBuffers;
|
use lyon::tessellation::VertexBuffers;
|
||||||
|
|
||||||
@ -638,7 +639,7 @@ mod tests {
|
|||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer.clone(),
|
style_layer.clone(),
|
||||||
&data48bytes_aligned,
|
&data48bytes_aligned,
|
||||||
2,
|
2,
|
||||||
@ -652,7 +653,7 @@ mod tests {
|
|||||||
|
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer.clone(),
|
style_layer.clone(),
|
||||||
&data24bytes_aligned,
|
&data24bytes_aligned,
|
||||||
2,
|
2,
|
||||||
@ -666,7 +667,7 @@ mod tests {
|
|||||||
|
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer.clone(),
|
style_layer.clone(),
|
||||||
&data24bytes_aligned,
|
&data24bytes_aligned,
|
||||||
2,
|
2,
|
||||||
@ -678,7 +679,7 @@ mod tests {
|
|||||||
|
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer.clone(),
|
style_layer.clone(),
|
||||||
&data24bytes_aligned,
|
&data24bytes_aligned,
|
||||||
2,
|
2,
|
||||||
@ -689,7 +690,7 @@ mod tests {
|
|||||||
|
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer.clone(),
|
style_layer.clone(),
|
||||||
&data24bytes_aligned,
|
&data24bytes_aligned,
|
||||||
2,
|
2,
|
||||||
@ -700,7 +701,7 @@ mod tests {
|
|||||||
|
|
||||||
pool.allocate_layer_geometry(
|
pool.allocate_layer_geometry(
|
||||||
&queue,
|
&queue,
|
||||||
(0, 0, 0).into(),
|
(0, 0, ZoomLevel::default()).into(),
|
||||||
style_layer,
|
style_layer,
|
||||||
&data24bytes_aligned,
|
&data24bytes_aligned,
|
||||||
2,
|
2,
|
||||||
|
|||||||
@ -19,8 +19,10 @@ mod phase_sort_stage;
|
|||||||
mod queue_stage;
|
mod queue_stage;
|
||||||
mod resource_stage;
|
mod resource_stage;
|
||||||
mod upload_stage;
|
mod upload_stage;
|
||||||
|
|
||||||
#[cfg(feature = "headless")]
|
#[cfg(feature = "headless")]
|
||||||
mod write_surface_buffer_stage;
|
// Exposed because it should be addable conditionally
|
||||||
|
pub mod write_surface_buffer_stage;
|
||||||
|
|
||||||
/// The labels of the default App rendering stages.
|
/// The labels of the default App rendering stages.
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
//! Sorts items of the [RenderPhases](RenderPhase).
|
//! Stage which writes the current contents of the GPU/CPU buffer in [`BufferedTextureHead`]
|
||||||
|
//! to disk as PNG.
|
||||||
|
|
||||||
use crate::context::MapContext;
|
use crate::context::MapContext;
|
||||||
use crate::coords::{ViewRegion, Zoom};
|
use crate::coords::{ViewRegion, Zoom};
|
||||||
@ -18,6 +19,7 @@ use std::future::Future;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::sync::Arc;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use wgpu::{BufferAsyncError, BufferSlice};
|
use wgpu::{BufferAsyncError, BufferSlice};
|
||||||
@ -38,7 +40,7 @@ impl Stage for WriteSurfaceBufferStage {
|
|||||||
match state.surface.head() {
|
match state.surface.head() {
|
||||||
Head::Headed(_) => {}
|
Head::Headed(_) => {}
|
||||||
Head::Headless(buffered_texture) => {
|
Head::Headless(buffered_texture) => {
|
||||||
let buffered_texture = buffered_texture.clone();
|
let buffered_texture: Arc<BufferedTextureHead> = buffered_texture.clone();
|
||||||
|
|
||||||
let device = device.clone();
|
let device = device.clone();
|
||||||
let current_frame = self.frame;
|
let current_frame = self.frame;
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::error::Error;
|
|||||||
use crate::io::geometry_index::{GeometryIndex, IndexedGeometry};
|
use crate::io::geometry_index::{GeometryIndex, IndexedGeometry};
|
||||||
use crate::io::pipeline::PipelineContext;
|
use crate::io::pipeline::PipelineContext;
|
||||||
use crate::io::pipeline::Processable;
|
use crate::io::pipeline::Processable;
|
||||||
use crate::io::pipeline_steps::build_vector_tile_pipeline;
|
use crate::io::tile_pipelines::build_vector_tile_pipeline;
|
||||||
use crate::io::tile_repository::StoredLayer;
|
use crate::io::tile_repository::StoredLayer;
|
||||||
use crate::io::tile_request_state::TileRequestState;
|
use crate::io::tile_request_state::TileRequestState;
|
||||||
use crate::io::{TileRequest, TileRequestID};
|
use crate::io::{TileRequest, TileRequestID};
|
||||||
|
|||||||
@ -7,8 +7,8 @@ use crate::io::geometry_index::GeometryIndex;
|
|||||||
use crate::io::geometry_index::{IndexProcessor, IndexedGeometry, TileIndex};
|
use crate::io::geometry_index::{IndexProcessor, IndexedGeometry, TileIndex};
|
||||||
use crate::io::pipeline::Processable;
|
use crate::io::pipeline::Processable;
|
||||||
use crate::io::pipeline::{PipelineContext, PipelineProcessor};
|
use crate::io::pipeline::{PipelineContext, PipelineProcessor};
|
||||||
use crate::io::pipeline_steps::build_vector_tile_pipeline;
|
|
||||||
use crate::io::source_client::{HttpSourceClient, SourceClient};
|
use crate::io::source_client::{HttpSourceClient, SourceClient};
|
||||||
|
use crate::io::tile_pipelines::build_vector_tile_pipeline;
|
||||||
use crate::io::tile_repository::StoredLayer;
|
use crate::io::tile_repository::StoredLayer;
|
||||||
use crate::io::tile_request_state::TileRequestState;
|
use crate::io::tile_request_state::TileRequestState;
|
||||||
use crate::io::{TileRequest, TileRequestID};
|
use crate::io::{TileRequest, TileRequestID};
|
||||||
@ -34,6 +34,7 @@ mod message;
|
|||||||
mod populate_tile_store_stage;
|
mod populate_tile_store_stage;
|
||||||
mod request_stage;
|
mod request_stage;
|
||||||
|
|
||||||
|
/// Register stages required for requesting and preparing new tiles.
|
||||||
pub fn register_stages<HC: HttpClient, SM: ScheduleMethod>(
|
pub fn register_stages<HC: HttpClient, SM: ScheduleMethod>(
|
||||||
schedule: &mut Schedule,
|
schedule: &mut Schedule,
|
||||||
http_source_client: HttpSourceClient<HC>,
|
http_source_client: HttpSourceClient<HC>,
|
||||||
@ -61,7 +62,7 @@ pub struct HeadedPipelineProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineProcessor for HeadedPipelineProcessor {
|
impl PipelineProcessor for HeadedPipelineProcessor {
|
||||||
fn finished_tile_tesselation(&mut self, request_id: TileRequestID, coords: &WorldTileCoords) {
|
fn tile_finished(&mut self, request_id: TileRequestID, coords: &WorldTileCoords) {
|
||||||
self.state
|
self.state
|
||||||
.message_sender
|
.message_sender
|
||||||
.send(TessellateMessage::Tile(TileTessellateMessage {
|
.send(TessellateMessage::Tile(TileTessellateMessage {
|
||||||
@ -71,7 +72,7 @@ impl PipelineProcessor for HeadedPipelineProcessor {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unavailable_layer(&mut self, coords: &WorldTileCoords, layer_name: &str) {
|
fn layer_unavailable(&mut self, coords: &WorldTileCoords, layer_name: &str) {
|
||||||
self.state
|
self.state
|
||||||
.message_sender
|
.message_sender
|
||||||
.send(TessellateMessage::Layer(
|
.send(TessellateMessage::Layer(
|
||||||
@ -83,7 +84,7 @@ impl PipelineProcessor for HeadedPipelineProcessor {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finished_layer_tesselation(
|
fn layer_tesselation_finished(
|
||||||
&mut self,
|
&mut self,
|
||||||
coords: &WorldTileCoords,
|
coords: &WorldTileCoords,
|
||||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||||
@ -103,7 +104,7 @@ impl PipelineProcessor for HeadedPipelineProcessor {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finished_layer_indexing(
|
fn layer_indexing_finished(
|
||||||
&mut self,
|
&mut self,
|
||||||
coords: &WorldTileCoords,
|
coords: &WorldTileCoords,
|
||||||
geometries: Vec<IndexedGeometry<f64>>,
|
geometries: Vec<IndexedGeometry<f64>>,
|
||||||
|
|||||||
@ -3,23 +3,29 @@
|
|||||||
use crate::{HttpClient, InteractiveMapSchedule, ScheduleMethod};
|
use crate::{HttpClient, InteractiveMapSchedule, ScheduleMethod};
|
||||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||||
|
|
||||||
/// Window with a [carte::window::WindowSize].
|
/// Window of a certain [`WindowSize`]. This can either be a proper window or a headless one.
|
||||||
pub trait MapWindow {
|
pub trait MapWindow {
|
||||||
fn size(&self) -> WindowSize;
|
fn size(&self) -> WindowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Window which references a physical `RawWindow`. This is only implemented by headed windows and
|
||||||
|
/// not by headless windows.
|
||||||
pub trait HeadedMapWindow: MapWindow {
|
pub trait HeadedMapWindow: MapWindow {
|
||||||
type RawWindow: HasRawWindowHandle;
|
type RawWindow: HasRawWindowHandle;
|
||||||
|
|
||||||
fn inner(&self) -> &Self::RawWindow;
|
fn inner(&self) -> &Self::RawWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A configuration for a window which determines the corresponding implementation of a
|
||||||
|
/// [`MapWindow`] and is able to create it.
|
||||||
pub trait MapWindowConfig: 'static {
|
pub trait MapWindowConfig: 'static {
|
||||||
type MapWindow: MapWindow;
|
type MapWindow: MapWindow;
|
||||||
|
|
||||||
fn create(&self) -> Self::MapWindow;
|
fn create(&self) -> Self::MapWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The event loop is responsible for processing events and propagating them to the map renderer.
|
||||||
|
/// Only non-headless windows use an [`EventLoop`].
|
||||||
pub trait EventLoop<MWC, SM, HC>
|
pub trait EventLoop<MWC, SM, HC>
|
||||||
where
|
where
|
||||||
MWC: MapWindowConfig,
|
MWC: MapWindowConfig,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user