summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2016-07-07 19:13:16 +0200
committerKonstantin Käfer <mail@kkaefer.com>2016-07-08 13:11:25 +0200
commit4f26c8122a57cd5fe35a10dc2e125500179a75a5 (patch)
tree02381c3db2adedcc6afa721137a6fb318ec915dd /src
parentaaa30c8a19bd608baf4c190f794258919365c36d (diff)
downloadqtlocation-mapboxgl-4f26c8122a57cd5fe35a10dc2e125500179a75a5.tar.gz
[core] track texture state to avoid redundand binds
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/geometry/glyph_atlas.cpp16
-rw-r--r--src/mbgl/geometry/glyph_atlas.hpp8
-rw-r--r--src/mbgl/geometry/line_atlas.cpp24
-rw-r--r--src/mbgl/geometry/line_atlas.hpp12
-rw-r--r--src/mbgl/gl/gl_config.cpp3
-rw-r--r--src/mbgl/gl/gl_config.hpp11
-rw-r--r--src/mbgl/renderer/bucket.hpp3
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp2
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp2
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp2
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp2
-rw-r--r--src/mbgl/renderer/frame_history.cpp16
-rw-r--r--src/mbgl/renderer/frame_history.hpp8
-rw-r--r--src/mbgl/renderer/line_bucket.cpp2
-rw-r--r--src/mbgl/renderer/line_bucket.hpp2
-rw-r--r--src/mbgl/renderer/painter.cpp18
-rw-r--r--src/mbgl/renderer/painter_background.cpp2
-rw-r--r--src/mbgl/renderer/painter_fill.cpp6
-rw-r--r--src/mbgl/renderer/painter_line.cpp10
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp14
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp10
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp2
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp2
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp2
-rw-r--r--src/mbgl/sprite/sprite_atlas.cpp17
-rw-r--r--src/mbgl/sprite/sprite_atlas.hpp8
-rw-r--r--src/mbgl/util/raster.cpp20
-rw-r--r--src/mbgl/util/raster.hpp12
28 files changed, 141 insertions, 95 deletions
diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp
index c45a93d24e..cfc5962eb3 100644
--- a/src/mbgl/geometry/glyph_atlas.cpp
+++ b/src/mbgl/geometry/glyph_atlas.cpp
@@ -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;
}
}
diff --git a/src/mbgl/geometry/glyph_atlas.hpp b/src/mbgl/geometry/glyph_atlas.hpp
index b1fc9d5747..5252963f51 100644
--- a/src/mbgl/geometry/glyph_atlas.hpp
+++ b/src/mbgl/geometry/glyph_atlas.hpp
@@ -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;
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
index d7ae5b4a60..f08ea1e5fc 100644
--- a/src/mbgl/geometry/line_atlas.cpp
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -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
diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp
index 0ca5e95a23..1e6c0ac84e 100644
--- a/src/mbgl/geometry/line_atlas.hpp
+++ b/src/mbgl/geometry/line_atlas.hpp
@@ -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;
diff --git a/src/mbgl/gl/gl_config.cpp b/src/mbgl/gl/gl_config.cpp
index 97d2f26f6c..9031c3d34f 100644
--- a/src/mbgl/gl/gl_config.cpp
+++ b/src/mbgl/gl/gl_config.cpp
@@ -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 };
diff --git a/src/mbgl/gl/gl_config.hpp b/src/mbgl/gl/gl_config.hpp
index 9d7dfb3b6c..41bee8fab7 100644
--- a/src/mbgl/gl/gl_config.hpp
+++ b/src/mbgl/gl/gl_config.hpp
@@ -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
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index 6792c162a5..4fcfb7b24e 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -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).
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index d86fbda489..3a6181b003 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -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;
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index 041207a6ca..695abe53b6 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -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;
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index c927071850..e79dfd316b 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -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);
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index 7508445579..69d4331486 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -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;
diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp
index 68b6bf863e..fc9d9b6616 100644
--- a/src/mbgl/renderer/frame_history.cpp
+++ b/src/mbgl/renderer/frame_history.cpp
@@ -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
diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp
index 04ebe23276..ec43e2beb5 100644
--- a/src/mbgl/renderer/frame_history.hpp
+++ b/src/mbgl/renderer/frame_history.hpp
@@ -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;
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index e9a8e78618..381356b801 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -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);
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 5ece05b03b..f09341e7a5 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -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;
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index d6f14708aa..46207fbcfe 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -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());
}
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index 6c47bb08fb..68463f3154 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -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 {
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 2b90f6d351..1a7b758000 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -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);
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index ab552d7ef9..ce1c6758fc 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -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);
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 8b4138819c..df29d16b9d 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -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
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 1cf6f2c413..c4e11198d3 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -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()));
}
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index 35b1bc2b51..ec24cff400 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -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;
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 66d2f04700..78b90dea19 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -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);
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index b899d52767..9a023a6010 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -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;
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp
index 581bc01ed8..05b713f454 100644
--- a/src/mbgl/sprite/sprite_atlas.cpp
+++ b/src/mbgl/sprite/sprite_atlas.cpp
@@ -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
diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp
index 4d1ee1c38c..4f44eb9ac9 100644
--- a/src/mbgl/sprite/sprite_atlas.hpp
+++ b/src/mbgl/sprite/sprite_atlas.hpp
@@ -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; }
diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp
index 7417c8bcd5..3f9cb467b9 100644
--- a/src/mbgl/util/raster.cpp
+++ b/src/mbgl/util/raster.cpp
@@ -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
diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp
index 6223440bd6..a30c086323 100644
--- a/src/mbgl/util/raster.hpp
+++ b/src/mbgl/util/raster.hpp
@@ -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;