reduce GfxCtx surface area

This commit is contained in:
Dustin Carlino 2020-08-05 07:56:57 -07:00
parent 2139f0e5f4
commit e82fe996ad
23 changed files with 88 additions and 122 deletions

View File

@ -1,6 +1,5 @@
use crate::drawing::Uniforms;
use crate::{Canvas, Color, FancyColor, ScreenDims, ScreenRectangle};
use geom::Polygon;
use crate::{Canvas, Color, GeomBatch, ScreenDims, ScreenRectangle};
use glium::uniforms::UniformValue;
use glium::Surface;
use std::cell::Cell;
@ -225,11 +224,11 @@ pub struct PrerenderInnards {
}
impl PrerenderInnards {
pub fn actually_upload(&self, permanent: bool, list: Vec<(FancyColor, &Polygon)>) -> Drawable {
pub fn actually_upload(&self, permanent: bool, batch: GeomBatch) -> Drawable {
let mut vertices: Vec<Vertex> = Vec::new();
let mut indices: Vec<u32> = Vec::new();
for (color, poly) in list {
for (color, poly) in batch.consume() {
let idx_offset = vertices.len();
let (pts, raw_indices) = poly.raw_for_rendering();
for pt in pts {

View File

@ -1,6 +1,5 @@
use crate::drawing::Uniforms;
use crate::{Canvas, Color, FancyColor, ScreenDims, ScreenRectangle};
use geom::Polygon;
use crate::{Canvas, Color, GeomBatch, ScreenDims, ScreenRectangle};
use glow::HasContext;
use std::cell::Cell;
@ -207,11 +206,11 @@ pub struct PrerenderInnards {
}
impl PrerenderInnards {
pub fn actually_upload(&self, permanent: bool, list: Vec<(FancyColor, &Polygon)>) -> Drawable {
pub fn actually_upload(&self, permanent: bool, batch: GeomBatch) -> Drawable {
let mut vertices: Vec<[f32; 6]> = Vec::new();
let mut indices: Vec<u32> = Vec::new();
for (color, poly) in list {
for (color, poly) in batch.consume() {
let idx_offset = vertices.len();
let (pts, raw_indices) = poly.raw_for_rendering();
for pt in pts {

View File

@ -1,6 +1,5 @@
use crate::drawing::Uniforms;
use crate::{Canvas, Color, FancyColor, ScreenDims, ScreenRectangle};
use geom::Polygon;
use crate::{Canvas, Color, GeomBatch, ScreenDims, ScreenRectangle};
use glow::HasContext;
use std::cell::Cell;
use stdweb::traits::INode;
@ -212,11 +211,11 @@ pub struct PrerenderInnards {
}
impl PrerenderInnards {
pub fn actually_upload(&self, permanent: bool, list: Vec<(FancyColor, &Polygon)>) -> Drawable {
pub fn actually_upload(&self, permanent: bool, batch: GeomBatch) -> Drawable {
let mut vertices: Vec<[f32; 6]> = Vec::new();
let mut indices: Vec<u32> = Vec::new();
for (color, poly) in list {
for (color, poly) in batch.consume() {
let idx_offset = vertices.len();
let (pts, raw_indices) = poly.raw_for_rendering();
for pt in pts {

View File

@ -1,10 +1,9 @@
use crate::assets::Assets;
use crate::backend::{GfxCtxInnards, PrerenderInnards};
use crate::{
Canvas, Color, Drawable, FancyColor, GeomBatch, ScreenDims, ScreenPt, ScreenRectangle, Style,
Text,
Canvas, Color, Drawable, GeomBatch, ScreenDims, ScreenPt, ScreenRectangle, Style, Text,
};
use geom::{ArrowCap, Bounds, Circle, Distance, Line, Polygon, Pt2D};
use geom::{Bounds, Polygon, Pt2D};
use std::cell::Cell;
// Lower is more on top
@ -115,47 +114,10 @@ impl<'a> GfxCtx<'a> {
self.inner.clear(color);
}
pub fn draw_line(&mut self, color: Color, thickness: Distance, line: &Line) {
self.draw_polygon(color, &line.make_polygons(thickness));
}
pub fn draw_rounded_line(&mut self, color: Color, thickness: Distance, line: &Line) {
self.draw_polygons(
color,
&vec![
line.make_polygons(thickness),
Circle::new(line.pt1(), thickness / 2.0).to_polygon(),
Circle::new(line.pt2(), thickness / 2.0).to_polygon(),
],
);
}
pub fn draw_arrow(&mut self, color: Color, thickness: Distance, line: &Line) {
self.draw_polygon(
color,
&line.to_polyline().make_arrow(thickness, ArrowCap::Triangle),
);
}
pub fn draw_circle(&mut self, color: Color, circle: &Circle) {
self.draw_polygon(color, &circle.to_polygon());
}
pub fn draw_polygon(&mut self, color: Color, poly: &Polygon) {
let obj = self
.prerender
.upload_temporary(vec![(FancyColor::RGBA(color), poly)]);
self.redraw(&obj);
}
pub fn draw_polygons(&mut self, color: Color, polygons: &Vec<Polygon>) {
let obj = self.prerender.upload_temporary(
polygons
.iter()
.map(|p| (FancyColor::RGBA(color), p))
.collect(),
);
self.redraw(&obj);
// Doesn't take &Polygon, because this is inherently inefficient. If performance matters,
// upload, cache, and redraw.
pub fn draw_polygon(&mut self, color: Color, poly: Polygon) {
GeomBatch::from(vec![(color, poly)]).draw(self);
}
pub fn redraw(&mut self, obj: &Drawable) {
@ -231,7 +193,7 @@ impl<'a> GfxCtx<'a> {
self.canvas.get_cursor_in_map_space()
}
pub fn get_num_uploads(&self) -> usize {
pub(crate) fn get_num_uploads(&self) -> usize {
self.prerender.num_uploads.get()
}
@ -269,25 +231,24 @@ pub struct Prerender {
impl Prerender {
pub fn upload(&self, batch: GeomBatch) -> Drawable {
let borrows = batch.list.iter().map(|(c, p)| (c.clone(), p)).collect();
self.actually_upload(true, borrows)
self.actually_upload(true, batch)
}
pub(crate) fn upload_temporary(&self, batch: GeomBatch) -> Drawable {
self.actually_upload(false, batch)
}
pub fn get_total_bytes_uploaded(&self) -> usize {
self.inner.total_bytes_uploaded.get()
}
pub(crate) fn upload_temporary(&self, list: Vec<(FancyColor, &Polygon)>) -> Drawable {
self.actually_upload(false, list)
}
fn actually_upload(&self, permanent: bool, list: Vec<(FancyColor, &Polygon)>) -> Drawable {
fn actually_upload(&self, permanent: bool, batch: GeomBatch) -> Drawable {
// println!("{:?}", backtrace::Backtrace::new());
self.num_uploads.set(self.num_uploads.get() + 1);
self.inner.actually_upload(permanent, list)
self.inner.actually_upload(permanent, batch)
}
pub fn request_redraw(&self) {
pub(crate) fn request_redraw(&self) {
self.inner.request_redraw()
}
}

View File

@ -60,12 +60,7 @@ impl GeomBatch {
/// Draws the batch, consuming it. Only use this for drawing things once.
pub fn draw(self, g: &mut GfxCtx) {
let refs = self
.list
.iter()
.map(|(color, p)| (color.clone(), p))
.collect();
let obj = g.prerender.upload_temporary(refs);
let obj = g.prerender.upload_temporary(self);
g.redraw(&obj);
}

View File

@ -790,7 +790,7 @@ impl Composite {
// Debugging
if false {
g.fork_screenspace();
g.draw_polygon(Color::RED.alpha(0.5), &self.top_level.rect.to_polygon());
g.draw_polygon(Color::RED.alpha(0.5), self.top_level.rect.to_polygon());
let top_left = g.canvas.align_window(
&g.prerender.assets,
@ -800,7 +800,7 @@ impl Composite {
);
g.draw_polygon(
Color::BLUE.alpha(0.5),
&Polygon::rectangle(self.container_dims.width, self.container_dims.height)
Polygon::rectangle(self.container_dims.width, self.container_dims.height)
.translate(top_left.x, top_left.y),
);
}

View File

@ -233,7 +233,7 @@ impl<T: Yvalue<T>> WidgetImpl for LinePlot<T> {
}
if !txt.is_empty() {
g.fork_screenspace();
g.draw_circle(Color::RED, &Circle::new(cursor.to_pt(), radius));
g.draw_polygon(Color::RED, Circle::new(cursor.to_pt(), radius).to_polygon());
g.draw_mouse_tooltip(txt);
g.unfork();
}

View File

@ -197,8 +197,7 @@ impl App {
if let Some(ID::Area(id)) = self.primary.current_selection {
g.draw_polygon(
self.cs.selected,
&self
.primary
self.primary
.draw_map
.get_a(id)
.get_outline(&self.primary.map),
@ -206,17 +205,16 @@ impl App {
} else if let Some(ID::Road(id)) = self.primary.current_selection {
g.draw_polygon(
self.cs.selected,
&self
.primary
self.primary
.draw_map
.get_r(id)
.get_outline(&self.primary.map),
);
} else if let Some(ID::Intersection(id)) = self.primary.current_selection {
// Actually, don't use get_outline here! Full polygon is easier to see.
g.draw_polygon(self.cs.selected, &self.primary.map.get_i(id).polygon);
g.draw_polygon(self.cs.selected, self.primary.map.get_i(id).polygon.clone());
} else if let Some(ID::Building(id)) = self.primary.current_selection {
g.draw_polygon(self.cs.selected, &self.primary.map.get_b(id).polygon);
g.draw_polygon(self.cs.selected, self.primary.map.get_b(id).polygon.clone());
}
let mut cache = self.primary.draw_map.agents.borrow_mut();
@ -268,7 +266,7 @@ impl App {
};
if self.primary.current_selection == Some(obj.get_id()) {
g.draw_polygon(self.cs.selected, &obj.get_outline(&self.primary.map));
g.draw_polygon(self.cs.selected, obj.get_outline(&self.primary.map));
}
if g.is_screencap() && sample_intersection.is_none() {

View File

@ -178,7 +178,7 @@ impl State for CityPicker {
1.0,
None,
);
g.draw_polygon(color.alpha(0.5), poly);
g.draw_polygon(color.alpha(0.5), poly.clone());
g.unfork();
g.draw_mouse_tooltip(Text::from(Line(nice_map_name(name))));

View File

@ -297,7 +297,7 @@ impl Minimap {
};
g.draw_polygon(
Color::BLACK,
&Ring::must_new(vec![
Ring::must_new(vec![
Pt2D::new(x1, y1),
Pt2D::new(x2, y1),
Pt2D::new(x2, y2),

View File

@ -123,10 +123,10 @@ impl State for PolygonDebugger {
.centered_on(g.canvas.map_to_screen(*pt).to_pt()),
);
}
g.draw_polygon(app.cs.selected, &Polygon::from_triangle(tri));
g.draw_polygon(app.cs.selected, Polygon::from_triangle(tri));
}
Item::Polygon(ref poly) => {
g.draw_polygon(app.cs.selected, poly);
g.draw_polygon(app.cs.selected, poly.clone());
batch.append(
Text::from(Line(idx.to_string()))
.bg(app.cs.panel_bg)

View File

@ -181,7 +181,7 @@ impl State for ViewKML {
if let Some(idx) = self.selected {
let obj = &self.objects[idx];
g.draw_polygon(Color::BLUE, &obj.polygon);
g.draw_polygon(Color::BLUE, obj.polygon.clone());
let mut txt = Text::new();
for (k, v) in &obj.attribs {
txt.add(Line(format!("{} = {}", k, v)));
@ -189,7 +189,7 @@ impl State for ViewKML {
g.draw_mouse_tooltip(txt);
if let Some(b) = obj.osm_bldg {
g.draw_polygon(Color::GREEN, &app.primary.map.get_b(b).polygon);
g.draw_polygon(Color::GREEN, app.primary.map.get_b(b).polygon.clone());
}
}
}

View File

@ -108,14 +108,15 @@ impl State for PolygonEditor {
let pts: Vec<Pt2D> = app.primary.map.get_gps_bounds().convert(&self.points);
if pts.len() == 2 {
g.draw_line(
g.draw_polygon(
POINT_COLOR,
POINT_RADIUS / 2.0,
&geom::Line::must_new(pts[0], pts[1]),
geom::Line::must_new(pts[0], pts[1]).make_polygons(POINT_RADIUS / 2.0),
);
}
if pts.len() >= 3 {
g.draw_polygon(POLYGON_COLOR, &Ring::must_new(pts.clone()).to_polygon());
let mut pts = pts.clone();
pts.push(pts[0]);
g.draw_polygon(POLYGON_COLOR, Ring::must_new(pts).to_polygon());
}
for (idx, pt) in pts.iter().enumerate() {
let color = if Some(idx) == self.mouseover_pt {
@ -125,7 +126,10 @@ impl State for PolygonEditor {
} else {
POINT_COLOR
};
g.draw_circle(color, &Circle::new(*pt, POINT_RADIUS / g.canvas.cam_zoom));
g.draw_polygon(
color,
Circle::new(*pt, POINT_RADIUS / g.canvas.cam_zoom).to_polygon(),
);
}
self.composite.draw(g);

View File

@ -572,8 +572,7 @@ impl Lasso {
fn draw(&self, g: &mut GfxCtx) {
g.draw_polygon(
Color::RED.alpha(0.8),
&self
.pl
self.pl
.make_polygons(Distance::meters(5.0) / g.canvas.cam_zoom),
);
}

View File

@ -224,7 +224,7 @@ impl State for LaneEditor {
fn draw(&self, g: &mut GfxCtx, app: &App) {
g.draw_polygon(
app.cs.perma_selected_object,
&app.primary
app.primary
.draw_map
.get_l(self.l)
.get_outline(&app.primary.map),

View File

@ -312,7 +312,7 @@ impl RoadSelector {
} = self.mode
{
if let Some(i) = i1 {
g.draw_polygon(Color::GREEN, &app.primary.map.get_i(*i).polygon);
g.draw_polygon(Color::GREEN, app.primary.map.get_i(*i).polygon.clone());
}
if let Some((_, _, ref p)) = preview_path {
g.redraw(p);

View File

@ -263,7 +263,7 @@ impl dyn State {
// TODO - OSD height
g.draw_polygon(
app.cs.fade_map_dark,
&Polygon::rectangle(g.canvas.window_width, g.canvas.window_height),
Polygon::rectangle(g.canvas.window_width, g.canvas.window_height),
);
g.unfork();
}

View File

@ -412,8 +412,8 @@ impl State for AgentSpawner {
g.draw_polygon(
Color::BLUE.alpha(0.8),
match endpt {
TripEndpoint::Border(i, _) => &app.primary.map.get_i(*i).polygon,
TripEndpoint::Bldg(b) => &app.primary.map.get_b(*b).polygon,
TripEndpoint::Border(i, _) => app.primary.map.get_i(*i).polygon.clone(),
TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(),
},
);
}
@ -421,12 +421,12 @@ impl State for AgentSpawner {
g.draw_polygon(
Color::GREEN.alpha(0.8),
match endpt {
TripEndpoint::Border(i, _) => &app.primary.map.get_i(*i).polygon,
TripEndpoint::Bldg(b) => &app.primary.map.get_b(*b).polygon,
TripEndpoint::Border(i, _) => app.primary.map.get_i(*i).polygon.clone(),
TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(),
},
);
if let Some(p) = poly {
g.draw_polygon(Color::PURPLE, p);
g.draw_polygon(Color::PURPLE, p.clone());
}
}
}

View File

@ -370,7 +370,7 @@ impl GameplayState for Tutorial {
]) {
g.draw_polygon(
Color::RED,
&pl.make_arrow(Distance::meters(20.0), ArrowCap::Triangle),
pl.make_arrow(Distance::meters(20.0), ArrowCap::Triangle),
);
}
g.unfork();
@ -383,7 +383,7 @@ impl GameplayState for Tutorial {
if tut.interaction() == Task::Camera {
g.draw_polygon(
Color::hex("#e25822"),
&app.primary.map.get_b(tut.fire_station).polygon,
app.primary.map.get_b(tut.fire_station).polygon.clone(),
);
}
}

View File

@ -201,8 +201,7 @@ impl State for TurnExplorer {
for turn in &app.primary.map.get_turns_from_lane(self.l) {
g.draw_polygon(
color_turn_type(turn.turn_type).alpha(0.5),
&turn
.geom
turn.geom
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
);
}

View File

@ -7,7 +7,7 @@ use ezgui::{
HorizontalAlignment, Key, Line, Outcome, ScreenPt, Text, VerticalAlignment, Widget, Wizard,
GUI,
};
use geom::{Distance, Line, Polygon, Pt2D};
use geom::{ArrowCap, Distance, Line, PolyLine, Polygon, Pt2D};
use map_model::raw::{OriginalBuilding, OriginalIntersection, OriginalRoad, RestrictionType};
use map_model::{osm, NORMAL_LANE_THICKNESS};
use model::{Model, ID};
@ -507,10 +507,13 @@ impl GUI for UI {
g.clear(Color::BLACK);
// It's useful to see the origin.
g.draw_polygon(Color::WHITE, &Polygon::rectangle(100.0, 10.0));
g.draw_polygon(Color::WHITE, &Polygon::rectangle(10.0, 100.0));
g.draw_polygon(Color::WHITE, Polygon::rectangle(100.0, 10.0));
g.draw_polygon(Color::WHITE, Polygon::rectangle(10.0, 100.0));
g.draw_polygon(Color::rgb(242, 239, 233), &self.model.map.boundary_polygon);
g.draw_polygon(
Color::rgb(242, 239, 233),
self.model.map.boundary_polygon.clone(),
);
match self.state {
State::PreviewIntersection(_, _) => self.model.world.draw(g, |id| match id {
ID::Intersection(_) => false,
@ -523,7 +526,7 @@ impl GUI for UI {
State::CreatingRoad(i1) => {
if let Some(cursor) = g.get_cursor_in_map_space() {
if let Some(l) = Line::new(self.model.map.intersections[&i1].point, cursor) {
g.draw_line(Color::GREEN, Distance::meters(5.0), &l);
g.draw_polygon(Color::GREEN, l.make_polygons(Distance::meters(5.0)));
}
}
}
@ -536,7 +539,7 @@ impl GUI for UI {
State::Viewing { ref short_roads } => {
for r in short_roads {
if let Some(p) = self.model.world.get_unioned_polygon(ID::Road(*r)) {
g.draw_polygon(Color::CYAN, p);
g.draw_polygon(Color::CYAN, p.clone());
}
}
}
@ -546,21 +549,28 @@ impl GUI for UI {
| State::StampingRoads(_, _, _, _) => {}
State::SelectingRectangle(pt1, pt2, _) => {
if let Some(rect) = Polygon::rectangle_two_corners(pt1, pt2) {
g.draw_polygon(Color::BLUE.alpha(0.5), &rect);
g.draw_polygon(Color::BLUE.alpha(0.5), rect);
}
}
State::CreatingTurnRestrictionPt1(from) => {
if let Some(cursor) = g.get_cursor_in_map_space() {
if let Some(l) = Line::new(self.model.get_r_center(from), cursor) {
g.draw_arrow(Color::PURPLE, NORMAL_LANE_THICKNESS, &l);
if let Ok(l) = PolyLine::new(vec![self.model.get_r_center(from), cursor]) {
g.draw_polygon(
Color::PURPLE,
l.make_arrow(NORMAL_LANE_THICKNESS, ArrowCap::Triangle),
);
}
}
}
State::CreatingTurnRestrictionPt2(from, to, ref wizard) => {
if let Some(l) =
Line::new(self.model.get_r_center(from), self.model.get_r_center(to))
{
g.draw_arrow(Color::PURPLE, NORMAL_LANE_THICKNESS, &l);
if let Ok(l) = PolyLine::new(vec![
self.model.get_r_center(from),
self.model.get_r_center(to),
]) {
g.draw_polygon(
Color::PURPLE,
l.make_arrow(NORMAL_LANE_THICKNESS, ArrowCap::Triangle),
);
}
wizard.draw(g);
}

View File

@ -85,7 +85,7 @@ impl<ID: ObjectID> World<ID> {
if let Some(id) = self.current_selection {
let obj = &self.objects[&id];
g.draw_polygon(Color::CYAN.alpha(0.5), &obj.unioned_polygon);
g.draw_polygon(Color::CYAN.alpha(0.5), obj.unioned_polygon.clone());
}
}

View File

@ -48,7 +48,10 @@ pub fn intersection_polygon(
l.pt1().angle_to(intersection_center).normalized_degrees() as i64
});
if i.id.osm_node_id == 29484936 {
if i.id.osm_node_id == 29484936
|| i.id.osm_node_id == 29545445
|| i.id.osm_node_id == 1864943558
{
on_off_ramp(driving_side, roads, i.id, lines)
} else if lines.len() == 1 {
deadend(driving_side, roads, i.id, &lines)