diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index 2e4de3edbe7..f272101a5ba 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -107,8 +108,25 @@ DashPatternTexture::DashPatternTexture(const std::vector& from_, const LinePatternCap cap) { const bool patternsIdentical = from_ == to_; const int32_t patternHeight = cap == LinePatternCap::Round ? 15 : 1; - - AlphaImage image({256, static_cast((patternsIdentical ? 1 : 2) * patternHeight)}); + const uint32_t height = (patternsIdentical ? 1 : 2) * patternHeight; + + // The OpenGL ES 2.0 spec, section 3.8.2 states: + // + // Calling a sampler from a fragment shader will return (R,G,B,A) = (0,0,0,1) if any of the + // following conditions are true: + // […] + // - A two-dimensional sampler is called, the corresponding texture image is a + // non-power-of-two image […], and either the texture wrap mode is not CLAMP_TO_EDGE, or + // the minification filter is neither NEAREST nor LINEAR. + // […] + // + // This means that texture lookups won't work for NPOT textures unless they use GL_CLAMP_TO_EDGE. + // We're using GL_CLAMP_TO_EDGE for the vertical direction, but GL_REPEAT for the horizontal + // direction, which means that we need a power-of-two texture for our line dash patterns to work + // on OpenGL ES 2.0 conforming implementations. Fortunately, this just means changing the height + // from 15 to 16, and from 30 to 32, so we don't waste many pixels. + const uint32_t textureHeight = 1 << util::ceil_log2(height); + AlphaImage image({256, textureHeight}); from = addDashPattern(image, 0, from_, cap); to = patternsIdentical ? from : addDashPattern(image, patternHeight, to_, cap);