1 #include <mbgl/tile/raster_dem_tile.hpp>
2 #include <mbgl/tile/raster_dem_tile_worker.hpp>
3 #include <mbgl/tile/tile_observer.hpp>
4 #include <mbgl/tile/tile_loader_impl.hpp>
5 #include <mbgl/style/source.hpp>
6 #include <mbgl/storage/resource.hpp>
7 #include <mbgl/storage/response.hpp>
8 #include <mbgl/storage/file_source.hpp>
9 #include <mbgl/renderer/tile_parameters.hpp>
10 #include <mbgl/renderer/buckets/hillshade_bucket.hpp>
11 #include <mbgl/actor/scheduler.hpp>
12 
13 namespace mbgl {
14 
RasterDEMTile(const OverscaledTileID & id_,const TileParameters & parameters,const Tileset & tileset)15 RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_,
16                        const TileParameters& parameters,
17                        const Tileset& tileset)
18     : Tile(id_),
19       loader(*this, id_, parameters, tileset),
20       mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
21       worker(parameters.workerScheduler,
22              ActorRef<RasterDEMTile>(*this, mailbox)) {
23 
24     encoding = tileset.encoding;
25     if ( id.canonical.y == 0 ){
26         // this tile doesn't have upper neighboring tiles so marked those as backfilled
27         neighboringTiles = neighboringTiles | DEMTileNeighbors::NoUpper;
28     }
29 
30     if (id.canonical.y + 1 == std::pow(2, id.canonical.z)){
31         // this tile doesn't have lower neighboring tiles so marked those as backfilled
32         neighboringTiles = neighboringTiles | DEMTileNeighbors::NoLower;
33     }
34 }
35 
36 RasterDEMTile::~RasterDEMTile() = default;
37 
setError(std::exception_ptr err)38 void RasterDEMTile::setError(std::exception_ptr err) {
39     loaded = true;
40     observer->onTileError(*this, err);
41 }
42 
setMetadata(optional<Timestamp> modified_,optional<Timestamp> expires_)43 void RasterDEMTile::setMetadata(optional<Timestamp> modified_, optional<Timestamp> expires_) {
44     modified = modified_;
45     expires = expires_;
46 }
47 
setData(std::shared_ptr<const std::string> data)48 void RasterDEMTile::setData(std::shared_ptr<const std::string> data) {
49     pending = true;
50     ++correlationID;
51     worker.self().invoke(&RasterDEMTileWorker::parse, data, correlationID, encoding);
52 }
53 
onParsed(std::unique_ptr<HillshadeBucket> result,const uint64_t resultCorrelationID)54 void RasterDEMTile::onParsed(std::unique_ptr<HillshadeBucket> result, const uint64_t resultCorrelationID) {
55     bucket = std::move(result);
56     loaded = true;
57     if (resultCorrelationID == correlationID) {
58         pending = false;
59     }
60     renderable = bucket ? true : false;
61     observer->onTileChanged(*this);
62 }
63 
onError(std::exception_ptr err,const uint64_t resultCorrelationID)64 void RasterDEMTile::onError(std::exception_ptr err, const uint64_t resultCorrelationID) {
65     loaded = true;
66     if (resultCorrelationID == correlationID) {
67         pending = false;
68     }
69     observer->onTileError(*this, err);
70 }
71 
upload(gl::Context & context)72 void RasterDEMTile::upload(gl::Context& context) {
73     if (bucket) {
74         bucket->upload(context);
75     }
76 }
77 
78 
getBucket(const style::Layer::Impl &) const79 Bucket* RasterDEMTile::getBucket(const style::Layer::Impl&) const {
80     return bucket.get();
81 }
82 
getBucket() const83 HillshadeBucket* RasterDEMTile::getBucket() const {
84     return bucket.get();
85 }
86 
backfillBorder(const RasterDEMTile & borderTile,const DEMTileNeighbors mask)87 void RasterDEMTile::backfillBorder(const RasterDEMTile& borderTile, const DEMTileNeighbors mask) {
88     int32_t dx = borderTile.id.canonical.x - id.canonical.x;
89     const int8_t dy = borderTile.id.canonical.y - id.canonical.y;
90     const uint32_t dim = pow(2, id.canonical.z);
91     if (dx == 0 && dy == 0) return;
92     if (std::abs(dy) > 1) return;
93     // neighbor is in another world wrap
94     if (std::abs(dx) > 1) {
95         if (std::abs(int(dx + dim)) == 1) {
96             dx += dim;
97         } else if (std::abs(int(dx - dim)) == 1) {
98             dx -= dim;
99         }
100     }
101     const HillshadeBucket* borderBucket = borderTile.getBucket();
102     if (borderBucket) {
103         const DEMData& borderDEM = borderBucket->getDEMData();
104         DEMData& tileDEM = bucket->getDEMData();
105 
106         tileDEM.backfillBorder(borderDEM, dx, dy);
107         // update the bitmask to indicate that this tiles have been backfilled by flipping the relevant bit
108         this->neighboringTiles = this->neighboringTiles | mask;
109         // mark HillshadeBucket.prepared as false so it runs through the prepare render pass
110         // with the new texture data we just backfilled
111         bucket->setPrepared(false);
112     }
113 }
114 
setMask(TileMask && mask)115 void RasterDEMTile::setMask(TileMask&& mask) {
116     if (bucket) {
117         bucket->setMask(std::move(mask));
118     }
119 }
120 
setNecessity(TileNecessity necessity)121 void RasterDEMTile::setNecessity(TileNecessity necessity) {
122     loader.setNecessity(necessity);
123 }
124 
125 } // namespace mbgl
126