[core] track texture state to avoid redundand binds
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/util/color.hpp>
|
||||
@@ -258,15 +259,15 @@ struct LineWidth {
|
||||
};
|
||||
|
||||
struct ActiveTexture {
|
||||
using Type = GLint;
|
||||
using Type = uint8_t;
|
||||
static const Type Default;
|
||||
static void Set(const Type& value) {
|
||||
MBGL_CHECK_ERROR(glActiveTexture(value));
|
||||
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0 + value));
|
||||
}
|
||||
static Type Get() {
|
||||
Type activeTexture;
|
||||
GLint activeTexture;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture));
|
||||
return activeTexture;
|
||||
return activeTexture - GL_TEXTURE0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -305,5 +306,18 @@ struct RasterPos {
|
||||
|
||||
#endif // GL_ES_VERSION_2_0
|
||||
|
||||
struct BindTexture {
|
||||
using Type = GLuint;
|
||||
static const Type Default;
|
||||
static void Set(const Type& value) {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, value));
|
||||
}
|
||||
static Type Get() {
|
||||
GLint texture;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture));
|
||||
return texture;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/object_store.hpp>
|
||||
#include <mbgl/gl/gl_config.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
@@ -141,13 +142,14 @@ void GlyphAtlas::removeGlyphs(uintptr_t tileUID) {
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphAtlas::upload(gl::ObjectStore& store) {
|
||||
void GlyphAtlas::upload(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
if (dirty) {
|
||||
const bool first = !texture;
|
||||
bind(store);
|
||||
bind(store, config, unit);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
|
||||
config.activeTexture = unit;
|
||||
if (first) {
|
||||
MBGL_CHECK_ERROR(glTexImage2D(
|
||||
GL_TEXTURE_2D, // GLenum target
|
||||
@@ -182,10 +184,11 @@ void GlyphAtlas::upload(gl::ObjectStore& store) {
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphAtlas::bind(gl::ObjectStore& store) {
|
||||
void GlyphAtlas::bind(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
if (!texture) {
|
||||
texture = store.createTexture();
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
|
||||
#endif
|
||||
@@ -193,8 +196,9 @@ void GlyphAtlas::bind(gl::ObjectStore& store) {
|
||||
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_CLAMP_TO_EDGE));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
} else {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
} else if (config.texture[unit] != *texture) {
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gl {
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
class GlyphAtlas : public util::noncopyable {
|
||||
public:
|
||||
GlyphAtlas(uint16_t width, uint16_t height);
|
||||
@@ -28,11 +32,11 @@ public:
|
||||
void removeGlyphs(uintptr_t tileUID);
|
||||
|
||||
// Binds the atlas texture to the GPU, and uploads data if it is out of date.
|
||||
void bind(gl::ObjectStore&);
|
||||
void bind(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
// Uploads the texture to the GPU to be available when we need it. This is a lazy operation;
|
||||
// the texture is only bound when the data is out of date (=dirty).
|
||||
void upload(gl::ObjectStore&);
|
||||
void upload(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
const GLsizei width;
|
||||
const GLsizei height;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/geometry/line_atlas.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/object_store.hpp>
|
||||
#include <mbgl/gl/gl_config.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
@@ -20,7 +21,7 @@ LineAtlas::LineAtlas(GLsizei w, GLsizei h)
|
||||
|
||||
LineAtlas::~LineAtlas() = default;
|
||||
|
||||
LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round, gl::ObjectStore& store) {
|
||||
LinePatternPos LineAtlas::getDashPosition(const std::vector<float>& dasharray, bool round) {
|
||||
size_t key = round ? std::numeric_limits<size_t>::min() : std::numeric_limits<size_t>::max();
|
||||
for (const float part : dasharray) {
|
||||
boost::hash_combine<float>(key, part);
|
||||
@@ -29,7 +30,7 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, b
|
||||
// Note: We're not handling hash collisions here.
|
||||
const auto it = positions.find(key);
|
||||
if (it == positions.end()) {
|
||||
auto inserted = positions.emplace(key, addDash(dasharray, round, store));
|
||||
auto inserted = positions.emplace(key, addDash(dasharray, round));
|
||||
assert(inserted.second);
|
||||
return inserted.first->second;
|
||||
} else {
|
||||
@@ -37,8 +38,7 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, b
|
||||
}
|
||||
}
|
||||
|
||||
LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round, gl::ObjectStore& store) {
|
||||
|
||||
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;
|
||||
@@ -115,32 +115,34 @@ LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool roun
|
||||
nextRow += dashheight;
|
||||
|
||||
dirty = true;
|
||||
bind(store);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
void LineAtlas::upload(gl::ObjectStore& store) {
|
||||
void LineAtlas::upload(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
if (dirty) {
|
||||
bind(store);
|
||||
bind(store, config, unit);
|
||||
}
|
||||
}
|
||||
|
||||
void LineAtlas::bind(gl::ObjectStore& store) {
|
||||
void LineAtlas::bind(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
bool first = false;
|
||||
if (!texture) {
|
||||
texture = store.createTexture();
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
config.activeTexture = unit;
|
||||
config.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 {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
} else if (config.texture[unit] != *texture) {
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
config.activeTexture = unit;
|
||||
if (first) {
|
||||
MBGL_CHECK_ERROR(glTexImage2D(
|
||||
GL_TEXTURE_2D, // GLenum target
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gl {
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
typedef struct {
|
||||
float width;
|
||||
float height;
|
||||
@@ -21,14 +25,14 @@ public:
|
||||
~LineAtlas();
|
||||
|
||||
// Binds the atlas texture to the GPU, and uploads data if it is out of date.
|
||||
void bind(gl::ObjectStore&);
|
||||
void bind(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
// Uploads the texture to the GPU to be available when we need it. This is a lazy operation;
|
||||
// the texture is only bound when the data is out of date (=dirty).
|
||||
void upload(gl::ObjectStore&);
|
||||
void upload(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
LinePatternPos getDashPosition(const std::vector<float>&, bool, gl::ObjectStore&);
|
||||
LinePatternPos addDash(const std::vector<float> &dasharray, bool round, gl::ObjectStore&);
|
||||
LinePatternPos getDashPosition(const std::vector<float>&, bool);
|
||||
LinePatternPos addDash(const std::vector<float>& dasharray, bool round);
|
||||
|
||||
const GLsizei width;
|
||||
const GLsizei height;
|
||||
|
||||
@@ -20,7 +20,8 @@ const ClearColor::Type ClearColor::Default = { 0, 0, 0, 0 };
|
||||
const ClearStencil::Type ClearStencil::Default = 0;
|
||||
const Program::Type Program::Default = 0;
|
||||
const LineWidth::Type LineWidth::Default = 1;
|
||||
const ActiveTexture::Type ActiveTexture::Default = GL_TEXTURE0;
|
||||
const ActiveTexture::Type ActiveTexture::Default = 0;
|
||||
const BindTexture::Type BindTexture::Default = 0;
|
||||
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
const PixelZoom::Type PixelZoom::Default = { 1, 1 };
|
||||
|
||||
@@ -13,13 +13,17 @@ template <typename T>
|
||||
class Value {
|
||||
public:
|
||||
void operator=(const typename T::Type& value) {
|
||||
if (dirty || current != value) {
|
||||
if (*this != value) {
|
||||
dirty = false;
|
||||
current = value;
|
||||
T::Set(current);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const typename T::Type& value) const {
|
||||
return dirty || current != value;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
*this = T::Default;
|
||||
}
|
||||
@@ -28,11 +32,11 @@ public:
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
typename T::Type getCurrent() {
|
||||
typename T::Type getCurrent() const {
|
||||
return current;
|
||||
}
|
||||
|
||||
bool getDirty() {
|
||||
bool getDirty() const {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
@@ -115,6 +119,7 @@ public:
|
||||
Value<PixelZoom> pixelZoom;
|
||||
Value<RasterPos> rasterPos;
|
||||
#endif // GL_ES_VERSION_2_0
|
||||
std::array<Value<BindTexture>, 2> texture;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -17,6 +17,7 @@ class CollisionTile;
|
||||
|
||||
namespace gl {
|
||||
class ObjectStore;
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
namespace style {
|
||||
@@ -29,7 +30,7 @@ public:
|
||||
|
||||
// As long as this bucket has a Prepare render pass, this function is getting called. Typically,
|
||||
// this only happens once when the bucket is being rendered for the first time.
|
||||
virtual void upload(gl::ObjectStore&) = 0;
|
||||
virtual void upload(gl::ObjectStore&, gl::Config&) = 0;
|
||||
|
||||
// Every time this bucket is getting rendered, this function is called. This happens either
|
||||
// once or twice (for Opaque and Transparent render passes).
|
||||
|
||||
@@ -16,7 +16,7 @@ CircleBucket::~CircleBucket() {
|
||||
// Do not remove. header file only contains forward definitions to unique pointers.
|
||||
}
|
||||
|
||||
void CircleBucket::upload(gl::ObjectStore& store) {
|
||||
void CircleBucket::upload(gl::ObjectStore& store, gl::Config&) {
|
||||
vertexBuffer_.upload(store);
|
||||
elementsBuffer_.upload(store);
|
||||
uploaded = true;
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
CircleBucket(const MapMode);
|
||||
~CircleBucket() override;
|
||||
|
||||
void upload(gl::ObjectStore&) override;
|
||||
void upload(gl::ObjectStore&, gl::Config&) override;
|
||||
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
|
||||
|
||||
bool hasData() const override;
|
||||
|
||||
@@ -95,7 +95,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
|
||||
}
|
||||
}
|
||||
|
||||
void FillBucket::upload(gl::ObjectStore& store) {
|
||||
void FillBucket::upload(gl::ObjectStore& store, gl::Config&) {
|
||||
vertexBuffer.upload(store);
|
||||
triangleElementsBuffer.upload(store);
|
||||
lineElementsBuffer.upload(store);
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
FillBucket();
|
||||
~FillBucket() override;
|
||||
|
||||
void upload(gl::ObjectStore&) override;
|
||||
void upload(gl::ObjectStore&, gl::Config&) override;
|
||||
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/renderer/frame_history.hpp>
|
||||
#include <mbgl/math/minmax.hpp>
|
||||
#include <mbgl/gl/gl_config.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -57,11 +58,11 @@ bool FrameHistory::needsAnimation(const Duration& duration) const {
|
||||
return (time - previousTime) < duration;
|
||||
}
|
||||
|
||||
void FrameHistory::upload(gl::ObjectStore& store) {
|
||||
void FrameHistory::upload(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
|
||||
if (changed) {
|
||||
const bool first = !texture;
|
||||
bind(store);
|
||||
bind(store, config, unit);
|
||||
|
||||
if (first) {
|
||||
MBGL_CHECK_ERROR(glTexImage2D(
|
||||
@@ -94,10 +95,11 @@ void FrameHistory::upload(gl::ObjectStore& store) {
|
||||
}
|
||||
}
|
||||
|
||||
void FrameHistory::bind(gl::ObjectStore& store) {
|
||||
void FrameHistory::bind(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
if (!texture) {
|
||||
texture = store.createTexture();
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
|
||||
#endif
|
||||
@@ -105,10 +107,10 @@ void FrameHistory::bind(gl::ObjectStore& store) {
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
} else {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
} else if (config.texture[unit] != *texture) {
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gl {
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
class FrameHistory {
|
||||
public:
|
||||
FrameHistory();
|
||||
void record(const TimePoint&, float zoom, const Duration&);
|
||||
|
||||
bool needsAnimation(const Duration&) const;
|
||||
void bind(gl::ObjectStore&);
|
||||
void upload(gl::ObjectStore&);
|
||||
void bind(gl::ObjectStore&, gl::Config&, uint32_t);
|
||||
void upload(gl::ObjectStore&, gl::Config&, uint32_t);
|
||||
|
||||
private:
|
||||
const int width = 256;
|
||||
|
||||
@@ -437,7 +437,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
|
||||
}
|
||||
}
|
||||
|
||||
void LineBucket::upload(gl::ObjectStore& store) {
|
||||
void LineBucket::upload(gl::ObjectStore& store, gl::Config&) {
|
||||
vertexBuffer.upload(store);
|
||||
triangleElementsBuffer.upload(store);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
LineBucket(uint32_t overscaling);
|
||||
~LineBucket() override;
|
||||
|
||||
void upload(gl::ObjectStore&) override;
|
||||
void upload(gl::ObjectStore&, gl::Config&) override;
|
||||
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
@@ -135,15 +135,15 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
tileStencilBuffer.upload(store);
|
||||
rasterBoundsBuffer.upload(store);
|
||||
tileBorderBuffer.upload(store);
|
||||
spriteAtlas->upload(store);
|
||||
lineAtlas->upload(store);
|
||||
glyphAtlas->upload(store);
|
||||
frameHistory.upload(store);
|
||||
annotationSpriteAtlas.upload(store);
|
||||
spriteAtlas->upload(store, config, 0);
|
||||
lineAtlas->upload(store, config, 0);
|
||||
glyphAtlas->upload(store, config, 0);
|
||||
frameHistory.upload(store, config, 0);
|
||||
annotationSpriteAtlas.upload(store, config, 0);
|
||||
|
||||
for (const auto& item : order) {
|
||||
if (item.bucket && item.bucket->needsUpload()) {
|
||||
item.bucket->upload(store);
|
||||
item.bucket->upload(store, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,7 +232,11 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
{
|
||||
MBGL_DEBUG_GROUP("cleanup");
|
||||
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
config.activeTexture = 1;
|
||||
config.texture[1] = 0;
|
||||
config.activeTexture = 0;
|
||||
config.texture[0] = 0;
|
||||
|
||||
MBGL_CHECK_ERROR(VertexArrayObject::Unbind());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
|
||||
patternShader.u_mix = properties.backgroundPattern.value.t;
|
||||
patternShader.u_opacity = properties.backgroundOpacity;
|
||||
|
||||
spriteAtlas->bind(true, store);
|
||||
spriteAtlas->bind(true, store, config, 0);
|
||||
arrayBackgroundPattern.bind(patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -103,8 +103,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
|
||||
patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
|
||||
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
spriteAtlas->bind(true, store);
|
||||
spriteAtlas->bind(true, store, config, 0);
|
||||
|
||||
// Draw the actual triangles into the color & stencil buffer.
|
||||
setDepthSublayer(0);
|
||||
@@ -132,8 +131,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
// Draw the entire line
|
||||
outlinePatternShader.u_world = worldSize;
|
||||
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
spriteAtlas->bind(true, store);
|
||||
spriteAtlas->bind(true, store, config, 0);
|
||||
|
||||
setDepthSublayer(2);
|
||||
bucket.drawVertices(outlinePatternShader, store, overdraw);
|
||||
|
||||
@@ -72,8 +72,8 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
linesdfShader.u_color = color;
|
||||
linesdfShader.u_opacity = opacity;
|
||||
|
||||
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, layout.lineCap == LineCapType::Round, store);
|
||||
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, layout.lineCap == LineCapType::Round, store);
|
||||
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, layout.lineCap == LineCapType::Round);
|
||||
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, layout.lineCap == LineCapType::Round);
|
||||
|
||||
const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.impl->dashLineWidth;
|
||||
const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.impl->dashLineWidth;
|
||||
@@ -94,8 +94,7 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
linesdfShader.u_antialiasingmatrix = antialiasingMatrix;
|
||||
|
||||
linesdfShader.u_image = 0;
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
lineAtlas->bind(store);
|
||||
lineAtlas->bind(store, config, 0);
|
||||
|
||||
bucket.drawLineSDF(linesdfShader, store, overdraw);
|
||||
|
||||
@@ -136,8 +135,7 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
linepatternShader.u_antialiasingmatrix = antialiasingMatrix;
|
||||
|
||||
linepatternShader.u_image = 0;
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
spriteAtlas->bind(true, store);
|
||||
spriteAtlas->bind(true, store, config, 0);
|
||||
|
||||
bucket.drawLinePatterns(linepatternShader, store, overdraw);
|
||||
|
||||
|
||||
@@ -77,8 +77,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
|
||||
sdfShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
config.activeTexture = GL_TEXTURE1;
|
||||
frameHistory.bind(store);
|
||||
frameHistory.bind(store, config, 1);
|
||||
sdfShader.u_fadetexture = 1;
|
||||
|
||||
// The default gamma value has to be adjust for the current pixelratio so that we're not
|
||||
@@ -164,8 +163,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas;
|
||||
const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear;
|
||||
const bool iconTransformed = layout.iconRotationAlignment == AlignmentType::Map || angleOffset != 0 || state.getPitch() != 0;
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, store);
|
||||
activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, store, config, 0);
|
||||
|
||||
if (sdf) {
|
||||
renderSDF(bucket,
|
||||
@@ -219,8 +217,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
iconShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
|
||||
iconShader.u_opacity = paint.iconOpacity;
|
||||
|
||||
config.activeTexture = GL_TEXTURE1;
|
||||
frameHistory.bind(store);
|
||||
frameHistory.bind(store, config, 1);
|
||||
iconShader.u_fadetexture = 1;
|
||||
|
||||
setDepthSublayer(0);
|
||||
@@ -236,8 +233,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
config.depthTest = GL_FALSE;
|
||||
}
|
||||
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
glyphAtlas->bind(store);
|
||||
glyphAtlas->bind(store, config, 0);
|
||||
|
||||
renderSDF(bucket,
|
||||
tileID,
|
||||
@@ -276,8 +272,6 @@ void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
bucket.drawCollisionBoxes(collisionBoxShader, store);
|
||||
|
||||
}
|
||||
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
void RasterBucket::upload(gl::ObjectStore& store) {
|
||||
void RasterBucket::upload(gl::ObjectStore& store, gl::Config& config) {
|
||||
if (hasData()) {
|
||||
raster.upload(store);
|
||||
raster.upload(store, config, 0);
|
||||
uploaded = true;
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,8 @@ void RasterBucket::drawRaster(RasterShader& shader,
|
||||
VertexArrayObject& array,
|
||||
gl::Config& config,
|
||||
gl::ObjectStore& store) {
|
||||
config.activeTexture = GL_TEXTURE0;
|
||||
raster.bind(store, Raster::Scaling::Linear);
|
||||
config.activeTexture = GL_TEXTURE1;
|
||||
raster.bind(store, Raster::Scaling::Linear);
|
||||
raster.bind(store, config, 0, Raster::Scaling::Linear);
|
||||
raster.bind(store, config, 1, Raster::Scaling::Linear);
|
||||
array.bind(shader, vertices, BUFFER_OFFSET_0, store);
|
||||
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)vertices.index()));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class VertexArrayObject;
|
||||
|
||||
class RasterBucket : public Bucket {
|
||||
public:
|
||||
void upload(gl::ObjectStore&) override;
|
||||
void upload(gl::ObjectStore&, gl::Config&) override;
|
||||
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
@@ -73,7 +73,7 @@ SymbolBucket::~SymbolBucket() {
|
||||
// Do not remove. header file only contains forward definitions to unique pointers.
|
||||
}
|
||||
|
||||
void SymbolBucket::upload(gl::ObjectStore& store) {
|
||||
void SymbolBucket::upload(gl::ObjectStore& store, gl::Config&) {
|
||||
if (hasTextData()) {
|
||||
renderData->text.vertices.upload(store);
|
||||
renderData->text.triangles.upload(store);
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
SymbolBucket(uint32_t overscaling, float zoom, const MapMode, std::string bucketName_, std::string sourceLayerName_);
|
||||
~SymbolBucket() override;
|
||||
|
||||
void upload(gl::ObjectStore&) override;
|
||||
void upload(gl::ObjectStore&, gl::Config&) override;
|
||||
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool hasTextData() const;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/sprite/sprite_atlas.hpp>
|
||||
#include <mbgl/sprite/sprite_store.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/gl_config.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
@@ -142,9 +143,9 @@ void SpriteAtlas::copy(const Holder& holder, const bool wrap) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void SpriteAtlas::upload(gl::ObjectStore& objectStore) {
|
||||
void SpriteAtlas::upload(gl::ObjectStore& objectStore, gl::Config& config, uint32_t unit) {
|
||||
if (dirty) {
|
||||
bind(false, objectStore);
|
||||
bind(false, objectStore, config, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,14 +180,15 @@ void SpriteAtlas::updateDirty() {
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore) {
|
||||
void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore, gl::Config& config, uint32_t unit) {
|
||||
if (!data) {
|
||||
return; // Empty atlas
|
||||
}
|
||||
|
||||
if (!texture) {
|
||||
texture = objectStore.createTexture();
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
|
||||
#endif
|
||||
@@ -195,12 +197,14 @@ void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore) {
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
fullUploadRequired = true;
|
||||
} else {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
} else if (config.texture[unit] != *texture) {
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
}
|
||||
|
||||
GLuint filter_val = linear ? GL_LINEAR : GL_NEAREST;
|
||||
if (filter_val != filter) {
|
||||
config.activeTexture = unit;
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_val));
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_val));
|
||||
filter = filter_val;
|
||||
@@ -209,6 +213,7 @@ void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore) {
|
||||
if (dirty) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
config.activeTexture = unit;
|
||||
if (fullUploadRequired) {
|
||||
MBGL_CHECK_ERROR(glTexImage2D(
|
||||
GL_TEXTURE_2D, // GLenum target
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gl {
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
class SpriteStore;
|
||||
class SpriteImage;
|
||||
class SpritePosition;
|
||||
@@ -47,14 +51,14 @@ public:
|
||||
optional<SpriteAtlasPosition> getPosition(const std::string& name, bool repeating = false);
|
||||
|
||||
// Binds the atlas texture to the GPU, and uploads data if it is out of date.
|
||||
void bind(bool linear, gl::ObjectStore&);
|
||||
void bind(bool linear, gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
// Updates sprites in the atlas texture that may have changed in the source SpriteStore object.
|
||||
void updateDirty();
|
||||
|
||||
// Uploads the texture to the GPU to be available when we need it. This is a lazy operation;
|
||||
// the texture is only bound when the data is out of date (=dirty).
|
||||
void upload(gl::ObjectStore&);
|
||||
void upload(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
dimension getWidth() const { return width; }
|
||||
dimension getHeight() const { return height; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/gl_config.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <mbgl/util/raster.hpp>
|
||||
@@ -24,7 +25,11 @@ void Raster::load(PremultipliedImage image, uint32_t mipmapLevel) {
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
void Raster::bind(gl::ObjectStore& store, Scaling newFilter, MipMap newMipMap) {
|
||||
void Raster::bind(gl::ObjectStore& store,
|
||||
gl::Config& config,
|
||||
uint32_t unit,
|
||||
Scaling newFilter,
|
||||
MipMap newMipMap) {
|
||||
bool updateFilter = false;
|
||||
|
||||
if (!texture) {
|
||||
@@ -32,17 +37,21 @@ void Raster::bind(gl::ObjectStore& store, Scaling newFilter, MipMap newMipMap) {
|
||||
Log::Error(Event::OpenGL, "trying to bind texture without images");
|
||||
return;
|
||||
} else {
|
||||
upload(store);
|
||||
upload(store, config, unit);
|
||||
updateFilter = true;
|
||||
}
|
||||
} else {
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
if (config.texture[unit] != *texture) {
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
}
|
||||
updateFilter = (filter != newFilter || mipmap != newMipMap);
|
||||
}
|
||||
|
||||
if (updateFilter) {
|
||||
filter = newFilter;
|
||||
mipmap = newMipMap;
|
||||
config.activeTexture = unit;
|
||||
MBGL_CHECK_ERROR(glTexParameteri(
|
||||
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
filter == Scaling::Linear
|
||||
@@ -53,10 +62,11 @@ void Raster::bind(gl::ObjectStore& store, Scaling newFilter, MipMap newMipMap) {
|
||||
}
|
||||
}
|
||||
|
||||
void Raster::upload(gl::ObjectStore& store) {
|
||||
void Raster::upload(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
|
||||
if (!images.empty() && !texture) {
|
||||
texture = store.createTexture();
|
||||
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
|
||||
config.activeTexture = unit;
|
||||
config.texture[unit] = *texture;
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, images.size()));
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gl {
|
||||
class Config;
|
||||
} // namespace gl
|
||||
|
||||
class Raster {
|
||||
public:
|
||||
enum class MipMap : bool { No = false, Yes = true };
|
||||
@@ -16,10 +20,14 @@ public:
|
||||
void load(PremultipliedImage, uint32_t mipmapLevel = 0);
|
||||
|
||||
// bind current texture
|
||||
void bind(gl::ObjectStore&, Scaling = Scaling::Nearest, MipMap = MipMap::No);
|
||||
void bind(gl::ObjectStore&,
|
||||
gl::Config&,
|
||||
uint32_t unit,
|
||||
Scaling = Scaling::Nearest,
|
||||
MipMap = MipMap::No);
|
||||
|
||||
// uploads the texture if it hasn't been uploaded yet.
|
||||
void upload(gl::ObjectStore&);
|
||||
void upload(gl::ObjectStore&, gl::Config&, uint32_t unit);
|
||||
|
||||
// loaded status
|
||||
bool isLoaded() const;
|
||||
|
||||
Reference in New Issue
Block a user