diff options
author | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-06-18 19:11:30 +0300 |
---|---|---|
committer | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-06-20 13:24:20 +0300 |
commit | df5a39570819abc6e083bee8bc1fc9da8d92b68c (patch) | |
tree | ef323e670ec3768f577e9b1f57cd0d102bd8e9b2 | |
parent | 7e549b90202655ca0de9f503178f42012c534dbc (diff) | |
download | qtlocation-mapboxgl-df5a39570819abc6e083bee8bc1fc9da8d92b68c.tar.gz |
[core] Refactor wireframe to match JS overdraw mode
-rw-r--r-- | src/mbgl/map/map.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.cpp | 13 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_background.cpp | 16 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_circle.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_fill.cpp | 22 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_line.cpp | 17 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_raster.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_symbol.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/shader/shader.cpp | 61 | ||||
-rw-r--r-- | src/mbgl/shader/shader.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/style/style.hpp | 2 |
13 files changed, 91 insertions, 70 deletions
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 11bc89a1a0..f4cca3b2b5 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -794,7 +794,7 @@ void Map::cycleDebugOptions() { impl->debugOptions = MapDebugOptions::NoDebug; #endif // GL_ES_VERSION_2_0 else if (impl->debugOptions & MapDebugOptions::Collision) - impl->debugOptions = MapDebugOptions::Collision | MapDebugOptions::Wireframe; + impl->debugOptions = MapDebugOptions::Wireframe; else if (impl->debugOptions & MapDebugOptions::Timestamps) impl->debugOptions = impl->debugOptions | MapDebugOptions::Collision; else if (impl->debugOptions & MapDebugOptions::ParseStatus) diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index ca536f6671..fae5c74d7b 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -92,7 +92,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a spriteAtlas = style.spriteAtlas.get(); lineAtlas = style.lineAtlas.get(); - RenderData renderData = style.getRenderData(); + RenderData renderData = style.getRenderData(frame.debugOptions); const std::vector<RenderItem>& order = renderData.order; const std::set<Source*>& sources = renderData.sources; const Color& background = renderData.backgroundColor; @@ -144,7 +144,12 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a config.depthTest = GL_FALSE; config.depthMask = GL_TRUE; config.colorMask = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE }; - if (frame.debugOptions & MapDebugOptions::Wireframe) { + + if (isWireframe()) { + config.blend = GL_TRUE; + config.blendFunc = { GL_CONSTANT_COLOR, GL_ONE }; + const float overdraw = 1.0f / 8.0f; + config.blendColor = { overdraw, overdraw, overdraw, 0.0f }; config.clearColor = Color::black(); } else { config.clearColor = background; @@ -243,7 +248,9 @@ void Painter::renderPass(RenderPass pass_, if (!layer.baseImpl->hasRenderPass(pass)) continue; - if (pass == RenderPass::Translucent) { + if (isWireframe()) { + config.blend = GL_TRUE; + } else if (pass == RenderPass::Translucent) { config.blendFunc.reset(); config.blend = GL_TRUE; } else { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 4c51543bde..d2d722ef7f 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -156,6 +156,8 @@ private: void setDepthSublayer(int n); + bool isWireframe() const { return frame.debugOptions & MapDebugOptions::Wireframe; } + mat4 projMatrix; mat4 nativeMatrix; diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp index 022d3dd7ab..f9a67ee59c 100644 --- a/src/mbgl/renderer/painter_background.cpp +++ b/src/mbgl/renderer/painter_background.cpp @@ -21,9 +21,6 @@ void Painter::renderBackground(const BackgroundLayer& layer) { optional<SpriteAtlasPosition> imagePosA; optional<SpriteAtlasPosition> imagePosB; - bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe; - isPatterned &= !wireframe; - if (isPatterned) { imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from, true); imagePosB = spriteAtlas->getPosition(properties.backgroundPattern.value.to, true); @@ -31,7 +28,7 @@ void Painter::renderBackground(const BackgroundLayer& layer) { if (!imagePosA || !imagePosB) return; - config.program = patternShader->getID(); + config.program = isWireframe() ? patternShader->getOverdrawID() : patternShader->getID(); patternShader->u_matrix = identityMatrix; patternShader->u_pattern_tl_a = imagePosA->tl; patternShader->u_pattern_br_a = imagePosA->br; @@ -44,15 +41,10 @@ void Painter::renderBackground(const BackgroundLayer& layer) { backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store); } else { - if (wireframe) { - plainShader->u_color = Color::black(); - plainShader->u_opacity = 1.0f; - } else { - plainShader->u_color = properties.backgroundColor; - plainShader->u_opacity = properties.backgroundOpacity; - } + plainShader->u_color = properties.backgroundColor; + plainShader->u_opacity = properties.backgroundOpacity; - config.program = plainShader->getID(); + config.program = isWireframe() ? plainShader->getOverdrawID() : plainShader->getID(); backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store); } diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp index 24cc9806e9..d92ca1ae9b 100644 --- a/src/mbgl/renderer/painter_circle.cpp +++ b/src/mbgl/renderer/painter_circle.cpp @@ -27,7 +27,7 @@ void Painter::renderCircle(CircleBucket& bucket, mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID, properties.circleTranslateAnchor); - config.program = circleShader->getID(); + config.program = isWireframe() ? circleShader->getOverdrawID() : circleShader->getID(); circleShader->u_matrix = vtxMatrix; circleShader->u_extrude_scale = extrudeScale; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 710fa444e2..62e808614e 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -36,16 +36,6 @@ void Painter::renderFill(FillBucket& bucket, bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined; bool fringeline = properties.fillAntialias && !pattern && !isOutlineColorDefined; - bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe; - if (wireframe) { - fillColor = Color::white(); - strokeColor = Color::white(); - opacity = 1.0f; - pattern = false; - outline = true; - fringeline = true; - } - config.stencilOp.reset(); config.stencilTest = GL_TRUE; config.depthFunc.reset(); @@ -56,7 +46,7 @@ void Painter::renderFill(FillBucket& bucket, // Because we're drawing top-to-bottom, and we update the stencil mask // befrom, we have to draw the outline first (!) if (outline && pass == RenderPass::Translucent) { - config.program = outlineShader->getID(); + config.program = isWireframe() ? outlineShader->getOverdrawID() : outlineShader->getID(); outlineShader->u_matrix = vertexMatrix; outlineShader->u_outline_color = strokeColor; @@ -86,7 +76,7 @@ void Painter::renderFill(FillBucket& bucket, // Image fill. if (pass == RenderPass::Translucent && imagePosA && imagePosB) { - config.program = patternShader->getID(); + config.program = isWireframe() ? patternShader->getOverdrawID() : patternShader->getID(); patternShader->u_matrix = vertexMatrix; patternShader->u_pattern_tl_a = imagePosA->tl; patternShader->u_pattern_br_a = imagePosA->br; @@ -115,7 +105,7 @@ void Painter::renderFill(FillBucket& bucket, bucket.drawElements(*patternShader, store); if (properties.fillAntialias && !isOutlineColorDefined) { - config.program = outlinePatternShader->getID(); + config.program = isWireframe() ? outlinePatternShader->getOverdrawID() : outlinePatternShader->getID(); outlinePatternShader->u_matrix = vertexMatrix; // Draw the entire line @@ -143,14 +133,14 @@ void Painter::renderFill(FillBucket& bucket, bucket.drawVertices(*outlinePatternShader, store); } } - } else if (!wireframe) { + } else { // No image fill. if ((fillColor.a >= 1.0f && opacity >= 1.0f) == (pass == RenderPass::Opaque)) { // Only draw the fill when it's either opaque and we're drawing opaque // fragments or when it's translucent and we're drawing translucent // fragments // Draw filling rectangle. - config.program = plainShader->getID(); + config.program = isWireframe() ? plainShader->getOverdrawID() : plainShader->getID(); plainShader->u_matrix = vertexMatrix; plainShader->u_color = fillColor; plainShader->u_opacity = opacity; @@ -164,7 +154,7 @@ void Painter::renderFill(FillBucket& bucket, // Because we're drawing top-to-bottom, and we update the stencil mask // below, we have to draw the outline first (!) if (fringeline && pass == RenderPass::Translucent) { - config.program = outlineShader->getID(); + config.program = isWireframe() ? outlineShader->getOverdrawID() : outlineShader->getID(); outlineShader->u_matrix = vertexMatrix; outlineShader->u_outline_color = fillColor; diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index bb759abc5f..447e3f7400 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -33,17 +33,10 @@ void Painter::renderLine(LineBucket& bucket, // Retina devices need a smaller distance to avoid aliasing. float antialiasing = 1.0 / frame.pixelRatio; - bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe; - float blur = properties.lineBlur + antialiasing; - Color color = Color::white(); - float opacity = 1.0f; - if (!wireframe) { - color = properties.lineColor; - opacity = properties.lineOpacity; - } - + const Color color = properties.lineColor; + const float opacity = properties.lineOpacity; const float ratio = 1.0 / tileID.pixelsToTileUnits(1.0, state.getZoom()); mat2 antialiasingMatrix; @@ -64,7 +57,7 @@ void Painter::renderLine(LineBucket& bucket, if (!properties.lineDasharray.value.from.empty()) { - config.program = linesdfShader->getID(); + config.program = isWireframe() ? linesdfShader->getOverdrawID() : linesdfShader->getID(); linesdfShader->u_matrix = vtxMatrix; linesdfShader->u_linewidth = properties.lineWidth / 2; @@ -109,7 +102,7 @@ void Painter::renderLine(LineBucket& bucket, if (!imagePosA || !imagePosB) return; - config.program = linepatternShader->getID(); + config.program = isWireframe() ? linepatternShader->getOverdrawID() : linepatternShader->getID(); linepatternShader->u_matrix = vtxMatrix; linepatternShader->u_linewidth = properties.lineWidth / 2; @@ -145,7 +138,7 @@ void Painter::renderLine(LineBucket& bucket, bucket.drawLinePatterns(*linepatternShader, store); } else { - config.program = lineShader->getID(); + config.program = isWireframe() ? lineShader->getOverdrawID() : lineShader->getID(); lineShader->u_matrix = vtxMatrix; lineShader->u_linewidth = properties.lineWidth / 2; diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index f3a0b720e7..6394d61dcc 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -18,7 +18,7 @@ void Painter::renderRaster(RasterBucket& bucket, const RasterPaintProperties& properties = layer.impl->paint; if (bucket.hasData()) { - config.program = rasterShader->getID(); + config.program = isWireframe() ? rasterShader->getOverdrawID() : rasterShader->getID(); rasterShader->u_matrix = matrix; rasterShader->u_buffer = 0; rasterShader->u_opacity = properties.rasterOpacity; diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index b65ae34a12..374500986b 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -58,7 +58,7 @@ void Painter::renderSDF(SymbolBucket &bucket, exScale = {{ exScale[0] * scale, exScale[1] * scale }}; } - config.program = sdfShader.getID(); + config.program = isWireframe() ? sdfShader.getOverdrawID() : sdfShader.getID(); sdfShader.u_matrix = vtxMatrix; sdfShader.u_extrude_scale = exScale; sdfShader.u_texsize = texsize; @@ -199,7 +199,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, exScale = {{ exScale[0] * scale, exScale[1] * scale }}; } - config.program = iconShader->getID(); + config.program = isWireframe() ? iconShader->getOverdrawID() : iconShader->getID(); iconShader->u_matrix = vtxMatrix; iconShader->u_extrude_scale = exScale; iconShader->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }}; diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index e2c7776e4d..80c4c33efc 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -8,6 +8,7 @@ #include <cstring> #include <cassert> #include <iostream> +#include <string> #include <fstream> #include <cstdio> @@ -21,12 +22,12 @@ Shader::Shader(const char* name_, const char* vertexSource, const char* fragment { util::stopwatch stopwatch("shader compilation", Event::Shader); - if (!compileShader(vertexShader, &vertexSource)) { + if (!compileShader(vertexShader, vertexSource)) { Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource); throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile"); } - if (!compileShader(fragmentShader, &fragmentSource)) { + if (!compileShader(fragmentShader, fragmentSource)) { Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource); throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile"); } @@ -35,32 +36,50 @@ Shader::Shader(const char* name_, const char* vertexSource, const char* fragment MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get())); MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get())); - { - // Link program - GLint status; - MBGL_CHECK_ERROR(glLinkProgram(program.get())); + linkProgram(program); - MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status)); - if (status == 0) { - GLint logLength; - MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength)); - const auto log = std::make_unique<GLchar[]>(logLength); - if (logLength > 0) { - MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get())); - Log::Error(Event::Shader, "Program failed to link: %s", log.get()); - } - throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get()); + std::string overdrawSource(fragmentSource); + if (overdrawSource.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos) { + programOverdraw = store.createProgram(); + overdrawShader = store.createShader(GL_FRAGMENT_SHADER); + + overdrawSource.replace(overdrawSource.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n"); + if (!compileShader(*overdrawShader, overdrawSource.c_str())) { + Log::Error(Event::Shader, "Overdraw shader %s failed to compile: %s", name, overdrawSource.c_str()); + throw util::ShaderException(std::string { "Overdraw shader " } + name + " failed to compile"); } + + MBGL_CHECK_ERROR(glAttachShader(*programOverdraw, vertexShader.get())); + MBGL_CHECK_ERROR(glAttachShader(*programOverdraw, *overdrawShader)); + linkProgram(*programOverdraw); } a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), "a_pos")); } -bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source[]) { +void Shader::linkProgram(gl::UniqueProgram& program_) { + // Link program + GLint status; + MBGL_CHECK_ERROR(glLinkProgram(program_.get())); + + MBGL_CHECK_ERROR(glGetProgramiv(program_.get(), GL_LINK_STATUS, &status)); + if (status == 0) { + GLint logLength; + MBGL_CHECK_ERROR(glGetProgramiv(program_.get(), GL_INFO_LOG_LENGTH, &logLength)); + const auto log = std::make_unique<GLchar[]>(logLength); + if (logLength > 0) { + MBGL_CHECK_ERROR(glGetProgramInfoLog(program_.get(), logLength, &logLength, log.get())); + Log::Error(Event::Shader, "Program failed to link: %s", log.get()); + } + throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get()); + } +} + +bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source) { GLint status = 0; - const GLsizei lengths = static_cast<GLsizei>(std::strlen(*source)); - MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, source, &lengths)); + const GLsizei lengths = static_cast<GLsizei>(std::strlen(source)); + MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths)); MBGL_CHECK_ERROR(glCompileShader(shader.get())); @@ -90,6 +109,10 @@ Shader::~Shader() { MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get())); MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get())); } + if (programOverdraw) { + MBGL_CHECK_ERROR(glDetachShader(*programOverdraw, vertexShader.get())); + MBGL_CHECK_ERROR(glDetachShader(*programOverdraw, *overdrawShader)); + } } } // namespace mbgl diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp index 3ba1e044c7..4289b83a77 100644 --- a/src/mbgl/shader/shader.hpp +++ b/src/mbgl/shader/shader.hpp @@ -3,6 +3,7 @@ #include <mbgl/gl/gl.hpp> #include <mbgl/gl/object_store.hpp> #include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/optional.hpp> namespace mbgl { @@ -15,6 +16,10 @@ public: return program.get(); } + GLuint getOverdrawID() const { + return programOverdraw ? *programOverdraw : 0; + } + virtual void bind(GLbyte *offset) = 0; protected: @@ -22,11 +27,15 @@ protected: GLint a_pos = -1; private: - bool compileShader(gl::UniqueShader&, const GLchar *source[]); + bool compileShader(gl::UniqueShader&, const GLchar *source); + void linkProgram(gl::UniqueProgram&); gl::UniqueProgram program; gl::UniqueShader vertexShader; gl::UniqueShader fragmentShader; + + mbgl::optional<gl::UniqueProgram> programOverdraw; + mbgl::optional<gl::UniqueShader> overdrawShader; }; } // namespace mbgl diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index cfeff6d400..c3bc5d73a0 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -258,7 +258,7 @@ bool Style::isLoaded() const { return true; } -RenderData Style::getRenderData() const { +RenderData Style::getRenderData(MapDebugOptions debugOptions) const { RenderData result; for (const auto& source : sources) { @@ -272,6 +272,11 @@ RenderData Style::getRenderData() const { continue; if (const BackgroundLayer* background = layer->as<BackgroundLayer>()) { + if (debugOptions & MapDebugOptions::Wireframe) { + // We want to skip glClear optimization in wireframe mode. + result.order.emplace_back(*layer); + continue; + } const BackgroundPaintProperties& paint = background->impl->paint; if (layer.get() == layers[0].get() && paint.backgroundPattern.value.from.empty()) { // This is a solid background. We can use glClear(). diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 1a41c4ce40..35369ffca3 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -74,7 +74,7 @@ public: void setClasses(const std::vector<std::string>&, const TransitionOptions& = {}); std::vector<std::string> getClasses() const; - RenderData getRenderData() const; + RenderData getRenderData(MapDebugOptions) const; std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const; |