diff options
Diffstat (limited to 'src/mbgl/renderer/sources/render_image_source.cpp')
-rw-r--r-- | src/mbgl/renderer/sources/render_image_source.cpp | 165 |
1 files changed, 99 insertions, 66 deletions
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index f5068b9d7f..d215dc8d13 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -1,19 +1,23 @@ #include <mbgl/map/transform_state.hpp> #include <mbgl/math/log2.hpp> #include <mbgl/renderer/buckets/raster_bucket.hpp> -#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/sources/render_image_source.hpp> #include <mbgl/renderer/tile_parameters.hpp> +#include <mbgl/renderer/render_static_data.hpp> +#include <mbgl/programs/programs.hpp> #include <mbgl/util/tile_coordinate.hpp> #include <mbgl/util/tile_cover.hpp> +#include <mbgl/util/logging.hpp> +#include <mbgl/util/constants.hpp> namespace mbgl { using namespace style; RenderImageSource::RenderImageSource(Immutable<style::ImageSource::Impl> impl_) - : RenderSource(impl_), shouldRender(false) { + : RenderSource(impl_) { } RenderImageSource::~RenderImageSource() = default; @@ -26,7 +30,7 @@ bool RenderImageSource::isLoaded() const { return !!bucket; } -void RenderImageSource::startRender(Painter& painter) { +void RenderImageSource::startRender(PaintParameters& parameters) { if (!isLoaded()) { return; } @@ -36,31 +40,53 @@ void RenderImageSource::startRender(Painter& painter) { for (size_t i = 0; i < tileIds.size(); i++) { mat4 matrix; matrix::identity(matrix); - painter.state.matrixFor(matrix, tileIds[i]); - matrix::multiply(matrix, painter.projMatrix, matrix); + parameters.state.matrixFor(matrix, tileIds[i]); + matrix::multiply(matrix, parameters.projMatrix, matrix); matrices.push_back(matrix); } - if (bucket->needsUpload() && shouldRender) { - bucket->upload(painter.context); + if (bucket->needsUpload()) { + bucket->upload(parameters.context); } } -void RenderImageSource::finishRender(Painter& painter) { - if (!isLoaded() || !shouldRender) { +void RenderImageSource::finishRender(PaintParameters& parameters) { + if (!isLoaded() || !(parameters.debugOptions & MapDebugOptions::TileBorders)) { return; } + + static const style::Properties<>::PossiblyEvaluated properties {}; + static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + for (auto matrix : matrices) { - painter.renderTileDebug(matrix); + parameters.programs.debug.draw( + parameters.context, + gl::LineStrip { 4.0f * parameters.pixelRatio }, + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + gl::ColorMode::unblended(), + DebugProgram::UniformValues { + uniforms::u_matrix::Value{ matrix }, + uniforms::u_color::Value{ Color::red() } + }, + parameters.staticData.tileVertexBuffer, + parameters.staticData.tileBorderIndexBuffer, + parameters.staticData.tileBorderSegments, + paintAttibuteData, + properties, + parameters.state.getZoom(), + "debug" + ); } } std::unordered_map<std::string, std::vector<Feature>> RenderImageSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, - const RenderStyle&, - const RenderedQueryOptions&) const { - return {}; + const std::vector<const RenderLayer*>&, + const RenderedQueryOptions&, + const CollisionIndex&) const { + return std::unordered_map<std::string, std::vector<Feature>> {}; } std::vector<Feature> RenderImageSource::querySourceFeatures(const SourceQueryOptions&) const { @@ -72,89 +98,106 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_, const bool needsRendering, const bool, const TileParameters& parameters) { - std::swap(baseImpl, baseImpl_); - enabled = needsRendering; + if (!needsRendering) { + return; + } auto transformState = parameters.transformState; - auto size = transformState.getSize(); - double viewportHeight = size.height; + std::swap(baseImpl, baseImpl_); auto coords = impl().getCoordinates(); + std::shared_ptr<PremultipliedImage> image = impl().getImage(); - // Compute the screen coordinates at wrap=0 for the given LatLng - ScreenCoordinate nePixel = { -INFINITY, -INFINITY }; - ScreenCoordinate swPixel = { INFINITY, INFINITY }; - - for (LatLng latLng : coords) { - ScreenCoordinate pixel = transformState.latLngToScreenCoordinate(latLng); - swPixel.x = std::min(swPixel.x, pixel.x); - nePixel.x = std::max(nePixel.x, pixel.x); - swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y); - nePixel.y = std::max(nePixel.y, viewportHeight - pixel.y); - } - double width = nePixel.x - swPixel.x; - double height = nePixel.y - swPixel.y; - - // Don't bother drawing the ImageSource unless it occupies >4 screen pixels - shouldRender = (width * height > 4); - if (!shouldRender) { + if (!image || !image->valid()) { + enabled = false; return; } + // Compute the z0 tile coordinates for the given LatLngs + TileCoordinatePoint nePoint = { -INFINITY, -INFINITY }; + TileCoordinatePoint swPoint = { INFINITY, INFINITY }; + std::vector<TileCoordinatePoint> tileCoordinates; + for (LatLng latLng : coords) { + auto point = TileCoordinate::fromLatLng(0, latLng).p; + tileCoordinates.push_back(point); + swPoint.x = std::min(swPoint.x, point.x); + nePoint.x = std::max(nePoint.x, point.x); + swPoint.y = std::min(swPoint.y, point.y); + nePoint.y = std::max(nePoint.y, point.y); + } + // Calculate the optimum zoom level to determine the tile ids to use for transforms - double minScale = INFINITY; - if (width > 0 || height > 0) { - double scaleX = double(size.width) / width; - double scaleY = double(size.height) / height; - minScale = util::min(scaleX, scaleY); + auto dx = nePoint.x - swPoint.x; + auto dy = nePoint.y - swPoint.y; + auto dMax = std::max(dx, dy); + double zoom = std::max(0.0, std::floor(-util::log2(dMax))); + + // Only enable if the long side of the image is > 2 pixels. Resulting in a + // display of at least 2 x 1 px image + // A tile coordinate unit represents the length of one tile (tileSize) at a given zoom. + // To convert a tile coordinate to pixels, multiply by tileSize. + // Here dMax is in z0 tile units, so we also scale by 2^z to match current zoom. + enabled = dMax * std::pow(2.0, transformState.getZoom()) * util::tileSize > 2.0; + if (!enabled) { + return; } - double zoom = transformState.getZoom() + util::log2(minScale); - zoom = util::clamp(zoom, transformState.getMinZoom(), transformState.getMaxZoom()); auto imageBounds = LatLngBounds::hull(coords[0], coords[1]); imageBounds.extend(coords[2]); imageBounds.extend(coords[3]); - auto tileCover = util::tileCover(imageBounds, ::floor(zoom)); + auto tileCover = util::tileCover(imageBounds, zoom); tileIds.clear(); tileIds.push_back(tileCover[0]); + bool hasVisibleTile = false; // Add additional wrapped tile ids if neccessary auto idealTiles = util::tileCover(transformState, transformState.getZoom()); for (auto tile : idealTiles) { if (tile.wrap != 0 && tileCover[0].canonical.isChildOf(tile.canonical)) { tileIds.push_back({ tile.wrap, tileCover[0].canonical }); + hasVisibleTile = true; + } + else if (!hasVisibleTile) { + for (auto coveringTile: tileCover) { + if(coveringTile.canonical == tile.canonical || + coveringTile.canonical.isChildOf(tile.canonical) || + tile.canonical.isChildOf(coveringTile.canonical)) { + hasVisibleTile = true; + } + } } } + enabled = hasVisibleTile; + if (!enabled) { + return; + } + // Calculate Geometry Coordinates based on tile cover at ideal zoom GeometryCoordinates geomCoords; - for (auto latLng : coords) { - auto tc = TileCoordinate::fromLatLng(0, latLng); - auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tc.p); + for (auto tileCoords : tileCoordinates) { + auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tileCoords); geomCoords.push_back(gc); } - - const UnassociatedImage& image = impl().getImage(); - if (!image.valid()) { - return; - } - - if (!bucket || image != bucket->image) { - bucket = std::make_unique<RasterBucket>(image.clone()); + if (!bucket) { + bucket = std::make_unique<RasterBucket>(image); } else { bucket->clear(); + if (image != bucket->image) { + bucket->setImage(image); + } } // Set Bucket Vertices, Indices, and segments bucket->vertices.emplace_back( RasterProgram::layoutVertex({ geomCoords[0].x, geomCoords[0].y }, { 0, 0 })); bucket->vertices.emplace_back( - RasterProgram::layoutVertex({ geomCoords[1].x, geomCoords[1].y }, { 32767, 0 })); + RasterProgram::layoutVertex({ geomCoords[1].x, geomCoords[1].y }, { util::EXTENT, 0 })); bucket->vertices.emplace_back( - RasterProgram::layoutVertex({ geomCoords[3].x, geomCoords[3].y }, { 0, 32767 })); + RasterProgram::layoutVertex({ geomCoords[3].x, geomCoords[3].y }, { 0, util::EXTENT })); bucket->vertices.emplace_back( - RasterProgram::layoutVertex({ geomCoords[2].x, geomCoords[2].y }, { 32767, 32767 })); + RasterProgram::layoutVertex({ geomCoords[2].x, geomCoords[2].y }, { util::EXTENT, util::EXTENT })); bucket->indices.emplace_back(0, 1, 2); bucket->indices.emplace_back(1, 2, 3); @@ -162,16 +205,6 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_, bucket->segments.emplace_back(0, 0, 4, 6); } -void RenderImageSource::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer) { - if (isLoaded() && !bucket->needsUpload() && shouldRender) { - for (auto matrix : matrices) { - bucket->render(painter, parameters, layer, matrix); - } - } -} - void RenderImageSource::dumpDebugLogs() const { Log::Info(Event::General, "RenderImageSource::id: %s", impl().id.c_str()); Log::Info(Event::General, "RenderImageSource::loaded: %s", isLoaded() ? "yes" : "no"); |