summaryrefslogtreecommitdiff
path: root/src/mbgl/geometry
diff options
context:
space:
mode:
authorAleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com>2019-08-28 15:29:59 +0300
committerAleksandar Stojiljkovic <aleksandar.stojiljkovic@mapbox.com>2019-08-30 11:18:55 +0300
commit4ba1270dcc0a51c7c68be2bfbac283ee76ea8680 (patch)
treec10bd5ea423888f77bf82c5d9ca55e322b290ed8 /src/mbgl/geometry
parent6ef2710e5cfb5ee4258583a20d55320e90faa8a5 (diff)
downloadqtlocation-mapboxgl-4ba1270dcc0a51c7c68be2bfbac283ee76ea8680.tar.gz
[core] DEMData: do decode on GPU (port mapbox/mapbox-gl-js#8694)
This is first part of work on porting mapbox/mapbox-gl-js#8694 - in follow up patch(es) it is required to remove CPU side copy using 2d canvas support on all supported platforms, similar to approach taken in gl.js https://github.com/mapbox/mapbox-gl-js/pull/8694/files#diff-34dbe5f7de34dc4b9a8745dcde9bdc37R48 Decoding on CPU removed. Padding is still done in DEMData() but, instead od doing it wwhile decoding, it is using memcpy to pad original values. Rebase to latest mapbox-gl-js master and re-generate shaders. Partly fixes: #15503
Diffstat (limited to 'src/mbgl/geometry')
-rw-r--r--src/mbgl/geometry/dem_data.cpp70
-rw-r--r--src/mbgl/geometry/dem_data.hpp28
2 files changed, 47 insertions, 51 deletions
diff --git a/src/mbgl/geometry/dem_data.cpp b/src/mbgl/geometry/dem_data.cpp
index 92dd7aee26..79998a9c43 100644
--- a/src/mbgl/geometry/dem_data.cpp
+++ b/src/mbgl/geometry/dem_data.cpp
@@ -3,36 +3,23 @@
namespace mbgl {
-DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding encoding):
+DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding _encoding):
dim(_image.size.height),
// extra two pixels per row for border backfilling on either edge
stride(dim + 2),
+ encoding(_encoding),
image({ static_cast<uint32_t>(stride), static_cast<uint32_t>(stride) }) {
if (_image.size.height != _image.size.width){
throw std::runtime_error("raster-dem tiles must be square.");
}
- auto decodeMapbox = [] (const uint8_t r, const uint8_t g, const uint8_t b){
- // https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
- return (r * 256 * 256 + g * 256 + b)/10 - 10000;
- };
-
- auto decodeTerrarium = [] (const uint8_t r, const uint8_t g, const uint8_t b){
- // https://aws.amazon.com/public-datasets/terrain/
- return ((r * 256 + g + b / 256) - 32768);
- };
-
- auto decodeRGB = encoding == Tileset::DEMEncoding::Terrarium ? decodeTerrarium : decodeMapbox;
-
- std::memset(image.data.get(), 0, image.bytes());
-
+ auto* dest = reinterpret_cast<uint32_t*>(image.data.get()) + stride + 1;
+ auto* source = reinterpret_cast<uint32_t*>(_image.data.get());
for (int32_t y = 0; y < dim; y++) {
- for (int32_t x = 0; x < dim; x++) {
- const int32_t i = y * dim + x;
- const int32_t j = i * 4;
- set(x, y, decodeRGB(_image.data[j], _image.data[j+1], _image.data[j+2]));
- }
+ memcpy(dest, source, dim * 4);
+ dest += stride;
+ source += dim;
}
// in order to avoid flashing seams between tiles, here we are initially populating a 1px border of
@@ -40,25 +27,20 @@ DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding encoding
// replaced when the tile's neighboring tiles are loaded and the accurate data can be backfilled using
// DEMData#backfillBorder
+ auto* data = reinterpret_cast<uint32_t*>(image.data.get());
for (int32_t x = 0; x < dim; x++) {
+ auto rowOffset = stride * (x + 1);
// left vertical border
- set(-1, x, get(0, x));
+ data[rowOffset] = data[rowOffset + 1];
// right vertical border
- set(dim, x, get(dim - 1, x));
-
- //left horizontal border
- set(x, -1, get(x, 0));
-
- // right horizontal border
- set(x, dim, get(x, dim - 1));
+ data[rowOffset + dim + 1] = data[rowOffset + dim];
}
-
- // corners
- set(-1, -1, get(0, 0));
- set(dim, -1, get(dim - 1, 0));
- set( -1, dim, get(0, dim - 1));
- set(dim, dim, get(dim - 1, dim - 1));
+
+ // top horizontal border with corners
+ memcpy(data, data + stride, stride * 4);
+ // bottom horizontal border with corners
+ memcpy(data + (dim + 1) * stride, data + dim * stride, stride * 4);
}
// This function takes the DEMData from a neighboring tile and backfills the edge/corner
@@ -90,11 +72,29 @@ void DEMData::backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy
int32_t ox = -dx * dim;
int32_t oy = -dy * dim;
+ auto* dest = reinterpret_cast<uint32_t*>(image.data.get());
+ auto* source = reinterpret_cast<uint32_t*>(o.image.data.get());
+
for (int32_t y = yMin; y < yMax; y++) {
for (int32_t x = xMin; x < xMax; x++) {
- set(x, y, o.get(x + ox, y + oy));
+ dest[idx(x, y)] = source[idx(x + ox, y + oy)];
}
}
}
+int32_t DEMData::get(const int32_t x, const int32_t y) const {
+ const auto& unpack = getUnpackVector();
+ const uint8_t* value = image.data.get() + idx(x, y) * 4;
+ return value[0] * unpack[0] + value[1] * unpack[1] + value[2] * unpack[2] - unpack[3];
+}
+
+const std::array<float, 4>& DEMData::getUnpackVector() const {
+ // https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
+ static const std::array<float, 4> unpackMapbox = {{ 6553.6, 25.6, 0.1, 10000.0 }};
+ // https://aws.amazon.com/public-datasets/terrain/
+ static const std::array<float, 4> unpackTerrarium = {{ 256.0, 1.0, 1.0 / 256.0, 32768.0 }};
+
+ return encoding == Tileset::DEMEncoding::Terrarium ? unpackTerrarium : unpackMapbox;
+}
+
} // namespace mbgl
diff --git a/src/mbgl/geometry/dem_data.hpp b/src/mbgl/geometry/dem_data.hpp
index 21146bc468..537575873f 100644
--- a/src/mbgl/geometry/dem_data.hpp
+++ b/src/mbgl/geometry/dem_data.hpp
@@ -16,13 +16,8 @@ public:
DEMData(const PremultipliedImage& image, Tileset::DEMEncoding encoding);
void backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy);
- void set(const int32_t x, const int32_t y, const int32_t value) {
- reinterpret_cast<int32_t*>(image.data.get())[idx(x, y)] = value + 65536;
- }
-
- int32_t get(const int32_t x, const int32_t y) const {
- return reinterpret_cast<const int32_t*>(image.data.get())[idx(x, y)] - 65536;
- }
+ int32_t get(const int32_t x, const int32_t y) const;
+ const std::array<float, 4>& getUnpackVector() const;
const PremultipliedImage* getImage() const {
return &image;
@@ -32,16 +27,17 @@ public:
const int32_t stride;
- private:
- PremultipliedImage image;
+private:
+ Tileset::DEMEncoding encoding;
+ PremultipliedImage image;
- size_t idx(const int32_t x, const int32_t y) const {
- assert(x >= -1);
- assert(x < dim + 1);
- assert(y >= -1);
- assert(y < dim + 1);
- return (y + 1) * stride + (x + 1);
- }
+ size_t idx(const int32_t x, const int32_t y) const {
+ assert(x >= -1);
+ assert(x < dim + 1);
+ assert(y >= -1);
+ assert(y < dim + 1);
+ return (y + 1) * stride + (x + 1);
+ }
};