[core] convert LineAtlas to use managed texture handling
This commit is contained in:
@@ -11,10 +11,8 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
LineAtlas::LineAtlas(uint16_t w, uint16_t h)
|
||||
: width(w),
|
||||
height(h),
|
||||
data(std::make_unique<char[]>(w * h)),
|
||||
LineAtlas::LineAtlas(const Size size)
|
||||
: image(size),
|
||||
dirty(true) {
|
||||
}
|
||||
|
||||
@@ -40,11 +38,11 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float>& dasharray,
|
||||
}
|
||||
|
||||
LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatternCap patternCap) {
|
||||
int n = patternCap == LinePatternCap::Round ? 7 : 0;
|
||||
int dashheight = 2 * n + 1;
|
||||
const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0;
|
||||
const uint8_t dashheight = 2 * n + 1;
|
||||
const uint8_t offset = 128;
|
||||
|
||||
if (nextRow + dashheight > height) {
|
||||
if (nextRow + dashheight > image.size.height) {
|
||||
Log::Warning(Event::OpenGL, "line atlas bitmap overflow");
|
||||
return LinePatternPos();
|
||||
}
|
||||
@@ -54,7 +52,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
|
||||
length += part;
|
||||
}
|
||||
|
||||
float stretch = width / length;
|
||||
float stretch = image.size.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.
|
||||
@@ -62,7 +60,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
|
||||
|
||||
for (int y = -n; y <= n; y++) {
|
||||
int row = nextRow + n + y;
|
||||
int index = width * row;
|
||||
int index = image.size.width * row;
|
||||
|
||||
float left = 0;
|
||||
float right = dasharray[0];
|
||||
@@ -72,7 +70,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
|
||||
left -= dasharray.back();
|
||||
}
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (uint32_t x = 0; x < image.size.width; x++) {
|
||||
|
||||
while (right < x / stretch) {
|
||||
left = right;
|
||||
@@ -104,13 +102,13 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
|
||||
signedDistance = int((inside ? 1 : -1) * dist);
|
||||
}
|
||||
|
||||
data[index + x] = fmax(0, fmin(255, signedDistance + offset));
|
||||
image.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.y = (0.5 + nextRow + n) / image.size.height;
|
||||
position.height = (2.0 * n) / image.size.height;
|
||||
position.width = length;
|
||||
|
||||
nextRow += dashheight;
|
||||
@@ -120,59 +118,24 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
|
||||
return position;
|
||||
}
|
||||
|
||||
Size LineAtlas::getSize() const {
|
||||
return image.size;
|
||||
}
|
||||
|
||||
void LineAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
|
||||
if (dirty) {
|
||||
bind(context, unit);
|
||||
if (!texture) {
|
||||
texture = context.createTexture(image, unit);
|
||||
} else if (dirty) {
|
||||
context.updateTexture(*texture, image, unit);
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void LineAtlas::bind(gl::Context& context, gl::TextureUnit unit) {
|
||||
bool first = false;
|
||||
if (!texture) {
|
||||
texture = context.createTexture();
|
||||
context.activeTexture = unit;
|
||||
context.texture[unit] = *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 if (context.texture[unit] != *texture) {
|
||||
context.activeTexture = unit;
|
||||
context.texture[unit] = *texture;
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
context.activeTexture = unit;
|
||||
if (first) {
|
||||
MBGL_CHECK_ERROR(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.get() // const GLvoid * data
|
||||
));
|
||||
} else {
|
||||
MBGL_CHECK_ERROR(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.get() // const GLvoid *pixels
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
upload(context, unit);
|
||||
context.bindTexture(*texture, unit, gl::TextureFilter::Linear, gl::TextureMipMap::No,
|
||||
gl::TextureWrap::Repeat, gl::TextureWrap::Clamp);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gl/texture.hpp>
|
||||
#include <mbgl/gl/object.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <vector>
|
||||
@@ -27,7 +29,7 @@ enum class LinePatternCap : bool {
|
||||
|
||||
class LineAtlas {
|
||||
public:
|
||||
LineAtlas(uint16_t width, uint16_t height);
|
||||
LineAtlas(Size);
|
||||
~LineAtlas();
|
||||
|
||||
// Binds the atlas texture to the GPU, and uploads data if it is out of date.
|
||||
@@ -40,14 +42,13 @@ public:
|
||||
LinePatternPos getDashPosition(const std::vector<float>&, LinePatternCap);
|
||||
LinePatternPos addDash(const std::vector<float>& dasharray, LinePatternCap);
|
||||
|
||||
const uint16_t width;
|
||||
const uint16_t height;
|
||||
Size getSize() const;
|
||||
|
||||
private:
|
||||
const std::unique_ptr<char[]> data;
|
||||
const AlphaImage image;
|
||||
bool dirty;
|
||||
mbgl::optional<gl::UniqueTexture> texture;
|
||||
int nextRow = 0;
|
||||
mbgl::optional<gl::Texture> texture;
|
||||
uint32_t nextRow = 0;
|
||||
std::unordered_map<size_t, LinePatternPos> positions;
|
||||
};
|
||||
|
||||
|
||||
@@ -211,19 +211,38 @@ void Context::updateTexture(
|
||||
void Context::bindTexture(Texture& obj,
|
||||
TextureUnit unit,
|
||||
TextureFilter filter,
|
||||
TextureMipMap mipmap) {
|
||||
if (filter != obj.filter || mipmap != obj.mipmap) {
|
||||
TextureMipMap mipmap,
|
||||
TextureWrap wrapX,
|
||||
TextureWrap wrapY) {
|
||||
if (filter != obj.filter || mipmap != obj.mipmap || wrapX != obj.wrapX || wrapY != obj.wrapY) {
|
||||
activeTexture = unit;
|
||||
texture[unit] = obj.texture;
|
||||
MBGL_CHECK_ERROR(glTexParameteri(
|
||||
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
filter == TextureFilter::Linear
|
||||
? (mipmap == TextureMipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
|
||||
: (mipmap == TextureMipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
filter == TextureFilter::Linear ? GL_LINEAR : GL_NEAREST));
|
||||
obj.filter = filter;
|
||||
obj.mipmap = mipmap;
|
||||
|
||||
if (filter != obj.filter || mipmap != obj.mipmap) {
|
||||
MBGL_CHECK_ERROR(glTexParameteri(
|
||||
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
filter == TextureFilter::Linear
|
||||
? (mipmap == TextureMipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
|
||||
: (mipmap == TextureMipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
|
||||
MBGL_CHECK_ERROR(
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
filter == TextureFilter::Linear ? GL_LINEAR : GL_NEAREST));
|
||||
obj.filter = filter;
|
||||
obj.mipmap = mipmap;
|
||||
}
|
||||
if (wrapX != obj.wrapX) {
|
||||
|
||||
MBGL_CHECK_ERROR(
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||
wrapX == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT));
|
||||
obj.wrapX = wrapX;
|
||||
}
|
||||
if (wrapY != obj.wrapY) {
|
||||
MBGL_CHECK_ERROR(
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
||||
wrapY == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT));
|
||||
obj.wrapY = wrapY;
|
||||
}
|
||||
} else if (texture[unit] != obj.texture) {
|
||||
// We are checking first to avoid setting the active texture without a subsequent
|
||||
// texture bind.
|
||||
|
||||
@@ -86,7 +86,9 @@ public:
|
||||
void bindTexture(Texture&,
|
||||
TextureUnit = 0,
|
||||
TextureFilter = TextureFilter::Nearest,
|
||||
TextureMipMap = TextureMipMap::No);
|
||||
TextureMipMap = TextureMipMap::No,
|
||||
TextureWrap wrapX = TextureWrap::Clamp,
|
||||
TextureWrap wrapY = TextureWrap::Clamp);
|
||||
|
||||
void clear(optional<mbgl::Color> color,
|
||||
optional<float> depth,
|
||||
|
||||
@@ -12,6 +12,8 @@ public:
|
||||
UniqueTexture texture;
|
||||
TextureFilter filter = TextureFilter::Nearest;
|
||||
TextureMipMap mipmap = TextureMipMap::No;
|
||||
TextureWrap wrapX = TextureWrap::Clamp;
|
||||
TextureWrap wrapY = TextureWrap::Clamp;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -46,6 +46,7 @@ enum class RenderbufferType : uint32_t {
|
||||
|
||||
enum class TextureMipMap : bool { No = false, Yes = true };
|
||||
enum class TextureFilter : bool { Nearest = false, Linear = true };
|
||||
enum class TextureWrap : bool { Clamp, Repeat };
|
||||
enum class TextureFormat : uint32_t {
|
||||
RGBA = 0x1908,
|
||||
Alpha = 0x1906,
|
||||
|
||||
@@ -55,7 +55,7 @@ void Painter::renderLine(PaintParameters& parameters,
|
||||
posA,
|
||||
posB,
|
||||
layer.impl->dashLineWidth,
|
||||
lineAtlas->width));
|
||||
lineAtlas->getSize().width));
|
||||
|
||||
} else if (!properties.linePattern.value.from.empty()) {
|
||||
optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition(
|
||||
|
||||
@@ -101,7 +101,7 @@ void Painter::renderSymbol(PaintParameters& parameters,
|
||||
|
||||
auto values = layer.impl->textPropertyValues(layout);
|
||||
|
||||
const Size texsize = glyphAtlas->getSize()x§;
|
||||
const Size texsize = glyphAtlas->getSize();
|
||||
|
||||
if (values.hasHalo()) {
|
||||
draw(parameters.shaders.symbolGlyph,
|
||||
|
||||
@@ -40,7 +40,7 @@ Style::Style(FileSource& fileSource_, float pixelRatio)
|
||||
: fileSource(fileSource_),
|
||||
glyphAtlas(std::make_unique<GlyphAtlas>(Size{ 2048, 2048 }, fileSource)),
|
||||
spriteAtlas(std::make_unique<SpriteAtlas>(Size{ 1024, 1024 }, pixelRatio)),
|
||||
lineAtlas(std::make_unique<LineAtlas>(256, 512)),
|
||||
lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 })),
|
||||
observer(&nullObserver) {
|
||||
glyphAtlas->setObserver(this);
|
||||
spriteAtlas->setObserver(this);
|
||||
|
||||
Reference in New Issue
Block a user