diff options
author | Leith Bade <leith@mapbox.com> | 2015-01-23 11:11:04 +1100 |
---|---|---|
committer | Leith Bade <leith@mapbox.com> | 2015-01-23 11:11:04 +1100 |
commit | 42d1972732a2f8cc59cf3c3041944b7831b4c97b (patch) | |
tree | 0b28f7476f805f55b67a621552c73b15dc7a358e /src | |
parent | 5234cd9f79d7aa1ac7843693f1f28f9d358edf2c (diff) | |
parent | 0c2ffc251c519af76a0ed6dd1925621ebe393e7b (diff) | |
download | qtlocation-mapboxgl-42d1972732a2f8cc59cf3c3041944b7831b4c97b.tar.gz |
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
Conflicts:
src/mbgl/renderer/painter_prerender.cpp
src/mbgl/renderer/prerendered_texture.cpp
src/mbgl/renderer/prerendered_texture.hpp
Diffstat (limited to 'src')
34 files changed, 465 insertions, 439 deletions
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp new file mode 100644 index 0000000000..b396d93259 --- /dev/null +++ b/src/mbgl/geometry/line_atlas.cpp @@ -0,0 +1,171 @@ +#include <mbgl/geometry/line_atlas.hpp> +#include <mbgl/platform/gl.hpp> +#include <mbgl/platform/platform.hpp> + +#include <sstream> +#include <cmath> + +using namespace mbgl; + +LineAtlas::LineAtlas(uint16_t w, uint16_t h) + : width(w), + height(h), + data(new char[w * h]), + dirty(true) { +} + +LineAtlas::~LineAtlas() { + std::lock_guard<std::recursive_mutex> lock(mtx); + + MBGL_CHECK_ERROR(glDeleteTextures(1, &texture)); + texture = 0; +} + +LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round) { + std::lock_guard<std::recursive_mutex> lock(mtx); + + std::ostringstream sskey; + + for (const float &part : dasharray) { + sskey << part << "-"; + } + sskey << round; + std::string key = sskey.str(); + + if (positions.find(key) == positions.end()) { + positions[key] = addDash(dasharray, round); + } + + return positions[key]; +} + +LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round) { + + int n = round ? 7 : 0; + int dashheight = 2 * n + 1; + const uint8_t offset = 128; + + if (nextRow + dashheight > height) { + fprintf(stderr, "[WARNING] line atlas bitmap overflow\n"); + return LinePatternPos(); + } + + float length = 0; + for (const float &part : dasharray) { + length += part; + } + + float stretch = width / length; + float halfWidth = stretch * 0.5; + // If dasharray has an odd length, both the first and last parts + // are dashes and should be joined seamlessly. + bool oddLength = dasharray.size() % 2 == 1; + + for (int y = -n; y <= n; y++) { + int row = nextRow + n + y; + int index = width * row; + + float left = 0; + float right = dasharray[0]; + unsigned int partIndex = 1; + + if (oddLength) { + left -= dasharray.back(); + } + + for (int x = 0; x < width; x++) { + + while (right < x / stretch) { + left = right; + right = right + dasharray[partIndex]; + + if (oddLength && partIndex == dasharray.size() - 1) { + right += dasharray.front(); + } + + partIndex++; + } + + float distLeft = fabs(x - left * stretch); + float distRight = fabs(x - right * stretch); + float dist = fmin(distLeft, distRight); + bool inside = (partIndex % 2) == 1; + int signedDistance; + + if (round) { + float distMiddle = n ? (float)y / n * (halfWidth + 1) : 0; + if (inside) { + float distEdge = halfWidth - fabs(distMiddle); + signedDistance = sqrt(dist * dist + distEdge * distEdge); + } else { + signedDistance = halfWidth - sqrt(dist * dist + distMiddle * distMiddle); + } + + } else { + signedDistance = int((inside ? 1 : -1) * dist); + } + + data[index + x] = fmax(0, fmin(255, signedDistance + offset)); + } + } + + LinePatternPos position; + position.y = (0.5 + nextRow + n) / height; + position.height = (2.0 * n) / height; + position.width = length; + + nextRow += dashheight; + + dirty = true; + bind(); + + return position; +}; + +void LineAtlas::bind() { + std::lock_guard<std::recursive_mutex> lock(mtx); + + bool first = false; + if (!texture) { + MBGL_CHECK_ERROR(glGenTextures(1, &texture)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + first = true; + } else { + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + } + + if (dirty) { + if (first) { + glTexImage2D( + GL_TEXTURE_2D, // GLenum target + 0, // GLint level + GL_ALPHA, // GLint internalformat + width, // GLsizei width + height, // GLsizei height + 0, // GLint border + GL_ALPHA, // GLenum format + GL_UNSIGNED_BYTE, // GLenum type + data // const GLvoid * data + ); + } else { + glTexSubImage2D( + GL_TEXTURE_2D, // GLenum target + 0, // GLint level + 0, // GLint xoffset + 0, // GLint yoffset + width, // GLsizei width + height, // GLsizei height + GL_ALPHA, // GLenum format + GL_UNSIGNED_BYTE, // GLenum type + data // const GLvoid *pixels + ); + } + + + dirty = false; + } +}; diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp new file mode 100644 index 0000000000..191dc0c4d4 --- /dev/null +++ b/src/mbgl/geometry/line_atlas.hpp @@ -0,0 +1,41 @@ +#ifndef MBGL_GEOMETRY_LINE_ATLAS +#define MBGL_GEOMETRY_LINE_ATLAS + +#include <vector> +#include <map> +#include <mutex> +#include <atomic> + +namespace mbgl { + +typedef struct { + float width; + float height; + float y; +} LinePatternPos; + +class LineAtlas { +public: + LineAtlas(uint16_t width, uint16_t height); + ~LineAtlas(); + + void bind(); + + LinePatternPos getDashPosition(const std::vector<float>&, bool); + LinePatternPos addDash(const std::vector<float> &dasharray, bool round); + + const int width; + const int height; + +private: + std::recursive_mutex mtx; + char *const data = nullptr; + std::atomic<bool> dirty; + uint32_t texture = 0; + int nextRow = 0; + std::map<std::string, LinePatternPos> positions; +}; + +}; + +#endif diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 923ce326a2..ff584c54ba 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -20,6 +20,7 @@ #include <mbgl/style/style_bucket.hpp> #include <mbgl/util/texture_pool.hpp> #include <mbgl/geometry/sprite_atlas.hpp> +#include <mbgl/geometry/line_atlas.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/string.hpp> @@ -99,8 +100,9 @@ Map::Map(View& view_, FileSource& fileSource_) glyphAtlas(util::make_unique<GlyphAtlas>(1024, 1024)), glyphStore(std::make_shared<GlyphStore>(fileSource)), spriteAtlas(util::make_unique<SpriteAtlas>(512, 512)), + lineAtlas(util::make_unique<LineAtlas>(512, 512)), texturePool(std::make_shared<TexturePool>()), - painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas)) + painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas)) { view.initialize(this); // Make sure that we're doing an initial drawing in all cases. @@ -662,12 +664,8 @@ void Map::updateSources(const util::ptr<StyleLayerGroup> &group) { } for (const util::ptr<StyleLayer> &layer : group->layers) { if (!layer) continue; - if (layer->bucket) { - if (layer->bucket->style_source) { - (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true; - } - } else if (layer->layers) { - updateSources(layer->layers); + if (layer->bucket && layer->bucket->style_source) { + (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true; } } } diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp index 1e12e5fc16..e72bb79dcf 100644 --- a/src/mbgl/map/tile_parser.cpp +++ b/src/mbgl/map/tile_parser.cpp @@ -70,10 +70,8 @@ void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) { if (layer_desc->isBackground()) { // background is a special, fake bucket continue; - } else if (layer_desc->layers) { - // This is a layer group. - parseStyleLayers(layer_desc->layers); } + if (layer_desc->bucket) { // This is a singular layer. Check if this bucket already exists. If not, // parse this bucket. @@ -88,7 +86,7 @@ void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) { } } } else { - fprintf(stderr, "[WARNING] layer '%s' does not have child layers or buckets\n", layer_desc->id.c_str()); + fprintf(stderr, "[WARNING] layer '%s' does not have buckets\n", layer_desc->id.c_str()); } } } @@ -117,8 +115,6 @@ std::unique_ptr<Bucket> TileParser::createBucket(util::ptr<StyleBucket> bucket_d } else { fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s' (source layer '%s')\n", bucket_desc->name.c_str(), bucket_desc->source_layer.c_str()); } - } else if (bucket_desc->render.is<StyleBucketRaster>() && bucket_desc->render.get<StyleBucketRaster>().prerendered == true) { - return createRasterBucket(bucket_desc->render.get<StyleBucketRaster>()); } else { // The layer specified in the bucket does not exist. Do nothing. if (debug::tileParseWarnings) { diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index e88b771eef..4937c8ac63 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -374,6 +374,20 @@ void LineBucket::drawLines(LineShader& shader) { } } +void LineBucket::drawLineSDF(LineSDFShader& shader) { + char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize); + char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer.itemSize); + for (triangle_group_type& group : triangleGroups) { + if (!group.elements_length) { + continue; + } + group.array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); + vertex_index += group.vertex_length * vertexBuffer.itemSize; + elements_index += group.elements_length * triangleElementsBuffer.itemSize; + } +} + void LineBucket::drawLinePatterns(LinepatternShader& shader) { char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize); char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer.itemSize); diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index 7337ca80ad..c4d0d4a050 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -16,11 +16,12 @@ class LineVertexBuffer; class TriangleElementsBuffer; class LineShader; class LinejoinShader; +class LineSDFShader; class LinepatternShader; struct pbf; class LineBucket : public Bucket { - typedef ElementGroup<2> triangle_group_type; + typedef ElementGroup<3> triangle_group_type; typedef ElementGroup<1> point_group_type; public: @@ -38,6 +39,7 @@ public: bool hasPoints() const; void drawLines(LineShader& shader); + void drawLineSDF(LineSDFShader& shader); void drawLinePatterns(LinepatternShader& shader); void drawPoints(LinejoinShader& shader); diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 1af33c4130..0c17d52b5d 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -24,9 +24,10 @@ using namespace mbgl; #define BUFFER_OFFSET(i) ((char *)nullptr + (i)) -Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_) +Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_, LineAtlas& lineAtlas_) : spriteAtlas(spriteAtlas_) , glyphAtlas(glyphAtlas_) + , lineAtlas(lineAtlas_) { } @@ -93,6 +94,7 @@ void Painter::setupShaders() { if (!outlineShader) outlineShader = util::make_unique<OutlineShader>(); if (!lineShader) lineShader = util::make_unique<LineShader>(); if (!linejoinShader) linejoinShader = util::make_unique<LinejoinShader>(); + if (!linesdfShader) linesdfShader = util::make_unique<LineSDFShader>(); if (!linepatternShader) linepatternShader = util::make_unique<LinepatternShader>(); if (!patternShader) patternShader = util::make_unique<PatternShader>(); if (!iconShader) iconShader = util::make_unique<IconShader>(); diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index a39a368acb..4d4876a6f1 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -14,6 +14,7 @@ #include <mbgl/shader/pattern_shader.hpp> #include <mbgl/shader/line_shader.hpp> #include <mbgl/shader/linejoin_shader.hpp> +#include <mbgl/shader/linesdf_shader.hpp> #include <mbgl/shader/linepattern_shader.hpp> #include <mbgl/shader/icon_shader.hpp> #include <mbgl/shader/raster_shader.hpp> @@ -38,6 +39,7 @@ class Tile; class Sprite; class SpriteAtlas; class GlyphAtlas; +class LineAtlas; class Source; class StyleSource; class StyleLayerGroup; @@ -56,7 +58,7 @@ class RasterTileData; class Painter : private util::noncopyable { public: - Painter(SpriteAtlas&, GlyphAtlas&); + Painter(SpriteAtlas&, GlyphAtlas&, LineAtlas&); ~Painter(); void setup(); @@ -194,11 +196,13 @@ public: SpriteAtlas& spriteAtlas; GlyphAtlas& glyphAtlas; + LineAtlas& lineAtlas; std::unique_ptr<PlainShader> plainShader; std::unique_ptr<OutlineShader> outlineShader; std::unique_ptr<LineShader> lineShader; std::unique_ptr<LinejoinShader> linejoinShader; + std::unique_ptr<LineSDFShader> linesdfShader; std::unique_ptr<LinepatternShader> linepatternShader; std::unique_ptr<PatternShader> patternShader; std::unique_ptr<IconShader> iconShader; diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index 71364f40c4..2d57bb26ea 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -4,6 +4,7 @@ #include <mbgl/style/style_layer.hpp> #include <mbgl/map/sprite.hpp> #include <mbgl/geometry/sprite_atlas.hpp> +#include <mbgl/geometry/line_atlas.hpp> #include <mbgl/map/map.hpp> using namespace mbgl; @@ -41,9 +42,6 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c color[2] *= properties.opacity; color[3] *= properties.opacity; - float dash_length = properties.dash_array[0]; - float dash_gap = properties.dash_array[1]; - float ratio = state.getPixelRatio(); mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor); @@ -72,7 +70,32 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c bucket.drawPoints(*linejoinShader); } - if (properties.image.size()) { + if (properties.dash_array.size()) { + + useProgram(linesdfShader->program); + + linesdfShader->u_matrix = vtxMatrix; + linesdfShader->u_exmatrix = extrudeMatrix; + linesdfShader->u_linewidth = {{ outset, inset }}; + linesdfShader->u_ratio = ratio; + linesdfShader->u_blur = blur; + linesdfShader->u_color = color; + + LinePatternPos pos = lineAtlas.getDashPosition(properties.dash_array, bucket.properties.cap == CapType::Round); + lineAtlas.bind(); + + float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0; + float scaleX = patternratio / pos.width / properties.dash_line_width; + float scaleY = -pos.height / 2.0; + + linesdfShader->u_patternscale = {{ scaleX, scaleY }}; + linesdfShader->u_tex_y = pos.y; + linesdfShader->u_image = 0; + linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * pos.width * 256.0 * state.getPixelRatio()); + + bucket.drawLineSDF(*linesdfShader); + + } else if (properties.image.size()) { SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true); float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z); @@ -107,7 +130,6 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c lineShader->u_blur = blur; lineShader->u_color = color; - lineShader->u_dasharray = {{ dash_length, dash_gap }}; bucket.drawLines(*lineShader); } diff --git a/src/mbgl/renderer/painter_prerender.cpp b/src/mbgl/renderer/painter_prerender.cpp deleted file mode 100644 index 4f07331a86..0000000000 --- a/src/mbgl/renderer/painter_prerender.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include <mbgl/renderer/painter.hpp> -#include <mbgl/style/style_properties.hpp> -#include <mbgl/renderer/prerendered_texture.hpp> -#include <mbgl/renderer/raster_bucket.hpp> - -using namespace mbgl; - -void Painter::preparePrerender(RasterBucket &bucket) { - MBGL_CHECK_ERROR(glDisable(GL_DEPTH_TEST)); - MBGL_CHECK_ERROR(glDisable(GL_STENCIL_TEST)); - -// Render the actual tile. -#if GL_EXT_discard_framebuffer && !__ANDROID__ - const GLenum discards[] = {GL_COLOR_ATTACHMENT0}; - MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards)); -#endif - MBGL_CHECK_ERROR(glClearColor(0.0, 0.0, 0.0, 0.0)); - MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT)); - - MBGL_CHECK_ERROR(glViewport(0, 0, bucket.properties.size, bucket.properties.size)); -} - -void Painter::renderPrerenderedTexture(RasterBucket &bucket, const mat4 &matrix, const RasterProperties& properties) { - const int buffer = bucket.properties.buffer * 4096.0f; - - // draw the texture on a quad - useProgram(rasterShader->program); - rasterShader->u_matrix = matrix; - rasterShader->u_opacity = 1; - - depthRange(strata, 1.0f); - - MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - rasterShader->u_image = 0; - rasterShader->u_buffer = buffer; - rasterShader->u_opacity = properties.opacity; - rasterShader->u_brightness_low = properties.brightness[0]; - rasterShader->u_brightness_high = properties.brightness[1]; - rasterShader->u_saturation_factor = saturationFactor(properties.saturation); - rasterShader->u_contrast_factor = contrastFactor(properties.contrast); - rasterShader->u_spin_weights = spinWeights(properties.hue_rotate); - bucket.texture.bindTexture(); - coveringRasterArray.bind(*rasterShader, tileStencilBuffer, BUFFER_OFFSET(0)); - MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index())); -} diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index 4c98a5e65b..a85b773788 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -9,53 +9,11 @@ using namespace mbgl; -void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix) { +void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_desc, const Tile::ID&, const mat4 &matrix) { if (pass != RenderPass::Translucent) return; const RasterProperties &properties = layer_desc->getProperties<RasterProperties>(); - if (layer_desc->layers) { - - if (!bucket.texture.getTexture()) { - - bucket.texture.bindFramebuffer(); - - preparePrerender(bucket); - - const int buffer = bucket.properties.buffer * 4096.0f; - - const mat4 preMatrix = [&]{ - mat4 vtxMatrix; - matrix::ortho(vtxMatrix, -buffer, 4096 + buffer, -4096 - buffer, buffer, 0, 1); - matrix::translate(vtxMatrix, vtxMatrix, 0, -4096, 0); - return vtxMatrix; - }(); - - for (const util::ptr<StyleLayer> &layer : layer_desc->layers->layers) { - setOpaque(); - renderLayer(layer, &id, &preMatrix); - setTranslucent(); - renderLayer(layer, &id, &preMatrix); - } - - if (bucket.properties.blur > 0) { - bucket.texture.blur(*this, bucket.properties.blur); - } - - bucket.texture.unbindFramebuffer(); - - MBGL_CHECK_ERROR(glEnable(GL_DEPTH_TEST)); - MBGL_CHECK_ERROR(glEnable(GL_STENCIL_TEST)); - - MBGL_CHECK_ERROR(glViewport(0, 0, gl_viewport[0], gl_viewport[1])); - - } - - renderPrerenderedTexture(bucket, matrix, properties); - - } - - // Only draw non-prerendered raster here if (bucket.hasData()) { depthMask(false); @@ -75,7 +33,6 @@ void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_des depthMask(true); } - } float Painter::saturationFactor(float saturation) { diff --git a/src/mbgl/renderer/prerendered_texture.cpp b/src/mbgl/renderer/prerendered_texture.cpp deleted file mode 100644 index 6d8af3c3be..0000000000 --- a/src/mbgl/renderer/prerendered_texture.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include <mbgl/renderer/prerendered_texture.hpp> - -#include <mbgl/renderer/painter.hpp> -#include <mbgl/style/style_bucket.hpp> - -#include <mbgl/platform/log.hpp> - -using namespace mbgl; - -PrerenderedTexture::PrerenderedTexture(const StyleBucketRaster &properties_) - : properties(properties_) { -} - -PrerenderedTexture::~PrerenderedTexture() { - if (texture != 0) { - MBGL_CHECK_ERROR(glDeleteTextures(1, &texture)); - texture = 0; - } - - if (fboDepth != 0) { - MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboDepth)); - fboDepth = 0; - } - - if (fboStencil != 0) { - MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboStencil)); - fboStencil = 0; - } - - if (fbo != 0) { - MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &fbo)); - fbo = 0; - } -} - - -void PrerenderedTexture::bindTexture() { - if (texture == 0) { - bindFramebuffer(); - unbindFramebuffer(); - } - - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); -} - -void PrerenderedTexture::bindFramebuffer() { - MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previousFbo)); - - if (texture == 0) { - MBGL_CHECK_ERROR(glGenTextures(1, &texture)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); -#ifndef GL_ES_VERSION_2_0 - MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); -#endif - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0)); - } - - if (fboDepth == 0) { - // Create depth buffer - MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboDepth)); - MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboDepth)); - if (gl::isPackedDepthStencilSupported) { - MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, properties.size, properties.size)); - } else { - if (gl::isDepth24Supported) { - MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, properties.size, properties.size)); - } else { - MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, properties.size, properties.size)); - } - } - - MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0)); - } - - if (!gl::isPackedDepthStencilSupported && (fboStencil == 0)) { - // Create stencil buffer - MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboStencil)); - MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboStencil)); - MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, properties.size, properties.size)); - - MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0)); - } - - if (fbo == 0) { - MBGL_CHECK_ERROR(glGenFramebuffers(1, &fbo)); - MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); - MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0)); - - if (gl::isPackedDepthStencilSupported) { -#ifdef GL_ES_VERSION_2_0 - MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepth)); - MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboDepth)); -#else - MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboDepth)); -#endif - } else { - MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepth)); - MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboStencil)); - } - - GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER)); - if (status != GL_FRAMEBUFFER_COMPLETE) { - mbgl::Log::Error(mbgl::Event::OpenGL, "Couldn't create framebuffer: "); - switch (status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete attachment\n"); break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete missing attachment\n"); break; -#ifdef GL_ES_VERSION_2_0 - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete dimensions\n"); break; -#else - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete draw buffer\n"); break; -#endif - case GL_FRAMEBUFFER_UNSUPPORTED: mbgl::Log::Error(mbgl::Event::OpenGL, "unsupported\n"); break; - default: mbgl::Log::Error(mbgl::Event::OpenGL, "other\n"); break; - } - return; - } - } else { - MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); - } -} - -void PrerenderedTexture::unbindFramebuffer() { - MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, previousFbo)); - - if (fbo != 0) { - MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &fbo)); - fbo = 0; - } -} - -void PrerenderedTexture::blur(Painter& painter, uint16_t passes) { - const GLuint originalTexture = texture; - - // Create a secondary texture - GLuint secondaryTexture; - MBGL_CHECK_ERROR(glGenTextures(1, &secondaryTexture)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, secondaryTexture)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0)); - - painter.useProgram(painter.gaussianShader->program); - painter.gaussianShader->u_matrix = painter.flipMatrix; - painter.gaussianShader->u_image = 0; - MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - - for (int i = 0; i < passes; i++) { - // Render horizontal - MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, secondaryTexture, 0)); -#if GL_EXT_discard_framebuffer - const GLenum discards[] = { GL_COLOR_ATTACHMENT0 }; - MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards)); -#endif - MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT)); - - painter.gaussianShader->u_offset = {{ 1.0f / float(properties.size), 0 }}; - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, originalTexture)); - painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0)); - MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index())); - - - - // Render vertical - MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, originalTexture, 0)); -#if GL_EXT_discard_framebuffer - MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards)); -#endif - MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT)); - - painter.gaussianShader->u_offset = {{ 0, 1.0f / float(properties.size) }}; - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, secondaryTexture)); - painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0)); - MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index())); - } - - MBGL_CHECK_ERROR(glDeleteTextures(1, &secondaryTexture)); -} diff --git a/src/mbgl/renderer/prerendered_texture.hpp b/src/mbgl/renderer/prerendered_texture.hpp deleted file mode 100644 index 3ccd24038d..0000000000 --- a/src/mbgl/renderer/prerendered_texture.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MBGL_RENDERER_PRERENDERED_TEXTURE -#define MBGL_RENDERER_PRERENDERED_TEXTURE - -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/platform/gl.hpp> - -namespace mbgl { - -class StyleBucketRaster; -class Painter; - -class PrerenderedTexture : private util::noncopyable { -public: - PrerenderedTexture(const StyleBucketRaster &properties); - ~PrerenderedTexture(); - - void bindTexture(); - void bindFramebuffer(); - void unbindFramebuffer(); - - inline GLuint getTexture() const { return texture; } - - void blur(Painter& painter, uint16_t passes); - -public: - const StyleBucketRaster &properties; - -private: - GLint previousFbo = 0; - GLuint fbo = 0; - GLuint texture = 0; - GLuint fboDepth= 0; - GLuint fboStencil = 0; -}; - -} - -#endif diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp index dfba8cee22..6d09e41fdd 100644 --- a/src/mbgl/renderer/raster_bucket.cpp +++ b/src/mbgl/renderer/raster_bucket.cpp @@ -5,7 +5,6 @@ using namespace mbgl; RasterBucket::RasterBucket(TexturePool& texturePool, const StyleBucketRaster& properties_) : properties(properties_), - texture(properties_), raster(texturePool) { } diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp index 0a7651d7cc..e03b08aa5f 100644 --- a/src/mbgl/renderer/raster_bucket.hpp +++ b/src/mbgl/renderer/raster_bucket.hpp @@ -3,7 +3,6 @@ #include <mbgl/renderer/bucket.hpp> #include <mbgl/util/raster.hpp> -#include <mbgl/renderer/prerendered_texture.hpp> #include <mbgl/style/style_bucket.hpp> @@ -24,7 +23,6 @@ public: bool setImage(const std::string &data); const StyleBucketRaster &properties; - PrerenderedTexture texture; void drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array); diff --git a/src/mbgl/shader/line.fragment.glsl b/src/mbgl/shader/line.fragment.glsl index f4ac1458b3..717c46e10d 100644 --- a/src/mbgl/shader/line.fragment.glsl +++ b/src/mbgl/shader/line.fragment.glsl @@ -2,10 +2,7 @@ uniform vec2 u_linewidth; uniform vec4 u_color; uniform float u_blur; -uniform vec2 u_dasharray; - varying vec2 v_normal; -varying float v_linesofar; void main() { // Calculate the distance of the pixel from the line in pixels. @@ -16,10 +13,5 @@ void main() { // (v_linewidth.s) float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0); - // Calculate the antialiasing fade factor based on distance to the dash. - // Only affects alpha when line is dashed - float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y); - alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0)); - gl_FragColor = u_color * alpha; } diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl index bf0b537e83..1f5432991c 100644 --- a/src/mbgl/shader/line.vertex.glsl +++ b/src/mbgl/shader/line.vertex.glsl @@ -20,11 +20,9 @@ uniform vec2 u_linewidth; uniform vec4 u_color; varying vec2 v_normal; -varying float v_linesofar; void main() { vec2 a_extrude = a_data.xy; - float a_linesofar = a_data.z * 128.0 + a_data.w; // We store the texture normals in the most insignificant bit // transform y so that 0 => -1 and 1 => 1 @@ -43,5 +41,4 @@ void main() { // because we're extruding the line in pixel space, regardless of the current // tile's zoom level. gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist; - v_linesofar = a_linesofar * u_ratio; } diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp index c6adc0ff8d..85152d6e0c 100644 --- a/src/mbgl/shader/line_shader.hpp +++ b/src/mbgl/shader/line_shader.hpp @@ -16,7 +16,6 @@ public: UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this}; Uniform<std::array<float, 4>> u_color = {"u_color", *this}; Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this}; - Uniform<std::array<float, 2>> u_dasharray = {"u_dasharray", *this}; Uniform<float> u_ratio = {"u_ratio", *this}; Uniform<float> u_blur = {"u_blur", *this}; diff --git a/src/mbgl/shader/linesdf.fragment.glsl b/src/mbgl/shader/linesdf.fragment.glsl new file mode 100644 index 0000000000..90a5eac3e2 --- /dev/null +++ b/src/mbgl/shader/linesdf.fragment.glsl @@ -0,0 +1,23 @@ +uniform vec2 u_linewidth; +uniform vec4 u_color; +uniform float u_blur; +uniform sampler2D u_image; +uniform float u_sdfgamma; + +varying vec2 v_normal; +varying vec2 v_tex; + +void main() { + // Calculate the distance of the pixel from the line in pixels. + float dist = length(v_normal) * u_linewidth.s; + + // Calculate the antialiasing fade factor. This is either when fading in + // the line in case of an offset line (v_linewidth.t) or when fading out + // (v_linewidth.s) + float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0); + + float sdfdist = texture2D(u_image, v_tex).a; + alpha *= smoothstep(0.5 - u_sdfgamma, 0.5 + u_sdfgamma, sdfdist); + + gl_FragColor = u_color * alpha; +} diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl new file mode 100644 index 0000000000..0ab6804ab5 --- /dev/null +++ b/src/mbgl/shader/linesdf.vertex.glsl @@ -0,0 +1,49 @@ +// floor(127 / 2) == 63.0 +// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is +// stored in a byte (-128..127). we scale regular normals up to length 63, but +// there are also "special" normals that have a bigger length (of up to 126 in +// this case). +// #define scale 63.0 +#define scale 0.015873016 + +attribute vec2 a_pos; +attribute vec4 a_data; + +// matrix is for the vertex position, exmatrix is for rotating and projecting +// the extrusion vector. +uniform mat4 u_matrix; +uniform mat4 u_exmatrix; + +// shared +uniform float u_ratio; +uniform vec2 u_linewidth; +uniform vec2 u_patternscale; +uniform float u_tex_y; + +varying vec2 v_normal; +varying vec2 v_tex; + +void main() { + vec2 a_extrude = a_data.xy; + float a_linesofar = a_data.z * 128.0 + a_data.w; + + // We store the texture normals in the most insignificant bit + // transform y so that 0 => -1 and 1 => 1 + // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap + // y is 1 if the normal points up, and -1 if it points down + vec2 normal = mod(a_pos, 2.0); + normal.y = sign(normal.y - 0.5); + v_normal = normal; + + // Scale the extrusion vector down to a normal and then up by the line width + // of this vertex. + vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0); + + // Remove the texture normal bit of the position before scaling it with the + // model/view matrix. Add the extrusion vector *after* the model/view matrix + // because we're extruding the line in pixel space, regardless of the current + // tile's zoom level. + gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist; + + v_tex = vec2(a_linesofar * u_patternscale.x, normal.y * u_patternscale.y + u_tex_y); +} diff --git a/src/mbgl/shader/linesdf_shader.cpp b/src/mbgl/shader/linesdf_shader.cpp new file mode 100644 index 0000000000..9802afb532 --- /dev/null +++ b/src/mbgl/shader/linesdf_shader.cpp @@ -0,0 +1,30 @@ +#include <mbgl/shader/linesdf_shader.hpp> +#include <mbgl/shader/shaders.hpp> +#include <mbgl/platform/gl.hpp> + +#include <cstdio> + +using namespace mbgl; + +LineSDFShader::LineSDFShader() + : Shader( + "line", + shaders[LINESDF_SHADER].vertex, + shaders[LINESDF_SHADER].fragment + ) { + if (!valid) { + fprintf(stderr, "invalid line shader\n"); + return; + } + + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos")); + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +} + +void LineSDFShader::bind(char *offset) { + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset + 0)); + + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 4, GL_BYTE, false, 8, offset + 4)); +} diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp new file mode 100644 index 0000000000..918ed5cbab --- /dev/null +++ b/src/mbgl/shader/linesdf_shader.hpp @@ -0,0 +1,34 @@ +#ifndef MBGL_SHADER_SHADER_LINESDF +#define MBGL_SHADER_SHADER_LINESDF + +#include <mbgl/shader/shader.hpp> +#include <mbgl/shader/uniform.hpp> + +namespace mbgl { + +class LineSDFShader : public Shader { +public: + LineSDFShader(); + + void bind(char *offset); + + UniformMatrix<4> u_matrix = {"u_matrix", *this}; + UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this}; + Uniform<std::array<float, 4>> u_color = {"u_color", *this}; + Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this}; + Uniform<float> u_ratio = {"u_ratio", *this}; + Uniform<float> u_blur = {"u_blur", *this}; + Uniform<std::array<float, 2>> u_patternscale = { "u_patternscale", *this }; + Uniform<float> u_tex_y = {"u_tex_y", *this}; + Uniform<int32_t> u_image = {"u_image", *this}; + Uniform<float> u_sdfgamma = {"u_sdfgamma", *this}; + +private: + int32_t a_pos = -1; + int32_t a_data = -1; +}; + + +} + +#endif diff --git a/src/mbgl/style/function_properties.cpp b/src/mbgl/style/function_properties.cpp index 69466c1f64..81b1c85c72 100644 --- a/src/mbgl/style/function_properties.cpp +++ b/src/mbgl/style/function_properties.cpp @@ -12,6 +12,7 @@ inline T defaultStopsValue(); template <> inline bool defaultStopsValue() { return true; } template <> inline float defaultStopsValue() { return 1.0f; } template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; } +template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; } template <typename T> @@ -64,5 +65,6 @@ T StopsFunction<T>::evaluate(float z) const { template bool StopsFunction<bool>::evaluate(float z) const; template float StopsFunction<float>::evaluate(float z) const; template Color StopsFunction<Color>::evaluate(float z) const; +template std::vector<float> StopsFunction<std::vector<float>>::evaluate(float z) const; } diff --git a/src/mbgl/style/property_fallback.cpp b/src/mbgl/style/property_fallback.cpp index 965baf6c4b..dc747b37e6 100644 --- a/src/mbgl/style/property_fallback.cpp +++ b/src/mbgl/style/property_fallback.cpp @@ -20,8 +20,6 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = { { PropertyKey::LineWidth, defaultStyleProperties<LineProperties>().width }, { PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width }, { PropertyKey::LineBlur, defaultStyleProperties<LineProperties>().blur }, - { PropertyKey::LineDashLand, defaultStyleProperties<LineProperties>().dash_array[0] }, - { PropertyKey::LineDashGap, defaultStyleProperties<LineProperties>().dash_array[1] }, { PropertyKey::IconOpacity, defaultStyleProperties<SymbolProperties>().icon.opacity }, { PropertyKey::IconRotate, defaultStyleProperties<SymbolProperties>().icon.rotate }, diff --git a/src/mbgl/style/property_key.hpp b/src/mbgl/style/property_key.hpp index efeebf0242..e283f11579 100644 --- a/src/mbgl/style/property_key.hpp +++ b/src/mbgl/style/property_key.hpp @@ -24,8 +24,6 @@ enum class PropertyKey { LineGapWidth, LineBlur, LineDashArray, // for transitions only - LineDashLand, - LineDashGap, LineImage, IconOpacity, diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp index 1b22b31177..e017981dee 100644 --- a/src/mbgl/style/property_value.hpp +++ b/src/mbgl/style/property_value.hpp @@ -5,6 +5,8 @@ #include <mbgl/style/function_properties.hpp> #include <mbgl/style/types.hpp> +#include <vector> + namespace mbgl { typedef mapbox::util::variant< @@ -13,7 +15,8 @@ typedef mapbox::util::variant< RotateAnchorType, Function<bool>, Function<float>, - Function<Color> + Function<Color>, + Function<std::vector<float>> > PropertyValue; } diff --git a/src/mbgl/style/style_bucket.hpp b/src/mbgl/style/style_bucket.hpp index d84d35d5b2..cc71ea99f7 100644 --- a/src/mbgl/style/style_bucket.hpp +++ b/src/mbgl/style/style_bucket.hpp @@ -80,10 +80,6 @@ public: class StyleBucketRaster { public: - bool prerendered = false; - uint16_t size = 256; - float blur = 0.0f; - float buffer = 0.03125f; }; typedef mapbox::util::variant<StyleBucketFill, StyleBucketLine, StyleBucketSymbol, diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp index e58756afa4..262ca23af8 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/style/style_layer.cpp @@ -51,11 +51,6 @@ void StyleLayer::setClasses(const std::vector<std::string> &class_names, const t appliedProperties.add(ClassID::Fallback, begin, end, value); } } - - // Update all child layers as well. - if (layers) { - layers->setClasses(class_names, now, defaultTransition); - } } // Helper function for applying all properties of a a single class that haven't been applied yet. @@ -185,9 +180,11 @@ void StyleLayer::applyStyleProperties<LineProperties>(const float z, const times applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now); applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now); applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now); - applyTransitionedStyleProperty(PropertyKey::LineDashLand, line.dash_array[0], z, now); - applyTransitionedStyleProperty(PropertyKey::LineDashGap, line.dash_array[1], z, now); + applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now); applyStyleProperty(PropertyKey::LineImage, line.image, z, now); + + // for scaling dasharrays + applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now + 10000); } template <> @@ -239,10 +236,6 @@ void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const } void StyleLayer::updateProperties(float z, const timestamp now) { - if (layers) { - layers->updateProperties(z, now); - } - cleanupAppliedStyleProperties(now); switch (type) { diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp index 641dc1e71c..7cf661ca33 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/style/style_layer.hpp @@ -79,9 +79,6 @@ public: // Stores the evaluated, and cascaded styling information, specific to this // layer's type. StyleProperties properties; - - // Child layer array (if this layer has child layers). - util::ptr<StyleLayerGroup> layers; }; } diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index 2dec648aff..cdec991a16 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -209,6 +209,24 @@ Color parseColor(JSVal value) { css_color.a}}; } +std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) { + if (!value.IsArray()) { + Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers"); + return std::tuple<bool, std::vector<float>> { false, std::vector<float>() }; + } + + std::vector<float> vec; + for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { + JSVal part = value[i]; + if (!part.IsNumber()) { + Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers"); + return std::tuple<bool, std::vector<float>> { false, std::vector<float>() }; + } + vec.push_back(part.GetDouble()); + } + return std::tuple<bool, std::vector<float>> { true, vec }; +} + template <> bool StyleParser::parseFunctionArgument(JSVal value) { JSVal rvalue = replaceConstant(value); @@ -239,6 +257,12 @@ Color StyleParser::parseFunctionArgument(JSVal value) { return parseColor(rvalue); } +template <> +std::vector<float> StyleParser::parseFunctionArgument(JSVal value) { + JSVal rvalue = replaceConstant(value); + return std::get<1>(parseFloatArray(rvalue)); +} + template <typename T> inline float defaultBaseValue() { return 1.75; } template <> inline float defaultBaseValue<Color>() { return 1.0; } @@ -293,17 +317,6 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) { template <typename T> -bool StyleParser::parseFunction(PropertyKey key, ClassProperties &klass, JSVal value) { - bool parsed; - Function<T> function; - std::tie(parsed, function) = parseFunction<T>(value); - if (parsed) { - klass.set(key, function); - } - return parsed; -} - -template <typename T> bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) { bool parsed; T result; @@ -314,18 +327,6 @@ bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKe return parsed; } -template <typename T> -bool StyleParser::setProperty(JSVal value, const char *property_name, T &target) { - bool parsed; - T result; - std::tie(parsed, result) = parseProperty<T>(value, property_name); - if (parsed) { - target = std::move(result); - } - return parsed; -} - - template<typename T> bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value) { if (!value.HasMember(property_name)) { @@ -335,15 +336,6 @@ bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey k } } -template <typename T> -bool StyleParser::parseOptionalProperty(const char *property_name, T &target, JSVal value) { - if (!value.HasMember(property_name)) { - return false; - } else { - return setProperty<T>(replaceConstant(value[property_name]), property_name, target); - } -} - template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) { if (!value.IsString()) { Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name); @@ -426,6 +418,18 @@ template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal va } } +template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char *property_name) { + if (value.IsObject()) { + return parseFunction<std::vector<float>>(value); + } else if (value.IsArray()) { + std::tuple<bool, std::vector<float>> parsed = parseFloatArray(value); + return std::tuple<bool, Function<std::vector<float>>> { std::get<0>(parsed), ConstantFunction<std::vector<float>>(std::get<1>(parsed)) }; + } else { + Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name); + return std::tuple<bool, Function<std::vector<float>>> { false, ConstantFunction<std::vector<float>>(std::vector<float>()) }; + } +} + template <typename T> bool StyleParser::parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value) { if (value.HasMember(property_name)) { @@ -490,10 +494,6 @@ util::ptr<StyleLayer> StyleParser::createLayer(JSVal value) { util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>( layer_id, std::move(paints)); - if (value.HasMember("layers")) { - layer->layers = createLayers(value["layers"]); - } - // Store the layer ID so we can reference it later. layers.emplace(layer_id, std::pair<JSVal, util::ptr<StyleLayer>> { value, layer }); @@ -523,7 +523,7 @@ void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) { } } - if (layer->bucket || (layer->layers && layer->type != StyleLayerType::Raster)) { + if (layer->bucket) { // Skip parsing this again. We already have a valid layer definition. return; } @@ -588,8 +588,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) { parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value); parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value); parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value); - parseOptionalProperty<Function<float>>("line-dasharray", { Key::LineDashLand, Key::LineDashGap }, klass, value); - parseOptionalProperty<PropertyTransition>("line-dasharray-transition", Key::LineDashArray, klass, value); + parseOptionalProperty<Function<std::vector<float>>>("line-dasharray", Key::LineDashArray, klass, value); parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value); parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value); @@ -661,18 +660,9 @@ void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) { parseLayer(it->second); stack.pop_front(); - util::ptr<StyleLayer> reference = it->second.second; - layer->type = reference->type; - - if (reference->layers) { - Log::Warning(Event::ParseStyle, "layer '%s' references composite layer", layer->id.c_str()); - // We cannot parse this layer further. - return; - } else { - layer->bucket = reference->bucket; - } + layer->bucket = reference->bucket; } #pragma mark - Parse Bucket @@ -812,17 +802,6 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleLayer> &layer) { parseRenderProperty(value, render.text.optional, "text-optional"); } break; - case StyleLayerType::Raster: { - StyleBucketRaster &render = bucket.render.get<StyleBucketRaster>(); - - parseRenderProperty(value, render.size, "raster-size"); - parseRenderProperty(value, render.blur, "raster-blur"); - parseRenderProperty(value, render.buffer, "raster-buffer"); - if (layer->layers) { - render.prerendered = true; - } - } break; - default: // There are no render properties for these layer types. break; diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index c37e856034..42e22f9458 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -69,18 +69,12 @@ private: template <typename T> bool parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value); template <typename T> - bool parseOptionalProperty(const char *property_name, T &target, JSVal value); - template <typename T> bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass); - template <typename T> - bool setProperty(JSVal value, const char *property_name, T &target); template <typename T> std::tuple<bool, T> parseProperty(JSVal value, const char *property_name); template <typename T> - bool parseFunction(PropertyKey key, ClassProperties &klass, JSVal value); - template <typename T> std::tuple<bool, Function<T>> parseFunction(JSVal value); template <typename T> T parseFunctionArgument(JSVal value); diff --git a/src/mbgl/style/style_properties.hpp b/src/mbgl/style/style_properties.hpp index c44b7c34c8..c5149b2d1c 100644 --- a/src/mbgl/style/style_properties.hpp +++ b/src/mbgl/style/style_properties.hpp @@ -9,6 +9,7 @@ #include <string> #include <type_traits> #include <memory> +#include <vector> namespace mbgl { @@ -36,7 +37,8 @@ struct LineProperties { float width = 1; float gap_width = 0; float blur = 0; - std::array<float, 2> dash_array = {{ 1, -1 }}; + std::vector<float> dash_array; + float dash_line_width = 1; std::string image; inline bool isVisible() const { diff --git a/src/mbgl/util/interpolate.hpp b/src/mbgl/util/interpolate.hpp index c9232db4eb..952d7b9c10 100644 --- a/src/mbgl/util/interpolate.hpp +++ b/src/mbgl/util/interpolate.hpp @@ -2,6 +2,7 @@ #define MBGL_UTIL_INTERPOLATE #include <array> +#include <vector> namespace mbgl { namespace util { @@ -21,6 +22,10 @@ inline std::array<T, 4> interpolate(const std::array<T, 4>& a, const std::array< }}; } +inline std::vector<float> interpolate(const std::vector<float> &a, const std::vector<float>, const double) { + return a; +} + } } diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp index ff27f509f4..bbdfc5321d 100644 --- a/src/mbgl/util/raster.hpp +++ b/src/mbgl/util/raster.hpp @@ -5,7 +5,6 @@ #include <mbgl/util/texture_pool.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/ptr.hpp> -#include <mbgl/renderer/prerendered_texture.hpp> #include <string> #include <mutex> |