Introduce GLObjectStore

Make a class for keeping GL objects ids and attach it
to the ThreadContext instead of hanging it on the Environment.
This commit is contained in:
Thiago Marcos P. Santos
2015-06-25 00:10:34 +03:00
parent be4cb6786b
commit e32b0b7e20
12 changed files with 126 additions and 14 deletions

View File

@@ -3,8 +3,9 @@
#include <mbgl/platform/gl.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/map/environment.hpp>
#include <mbgl/util/thread_context.hpp>
#include <cstdlib>
#include <cassert>
@@ -23,7 +24,7 @@ public:
~Buffer() {
cleanup();
if (buffer != 0) {
Environment::Get().abandonBuffer(buffer);
util::ThreadContext::getGLObjectStore()->abandonBuffer(buffer);
buffer = 0;
}
}

View File

@@ -1,8 +1,9 @@
#include <mbgl/map/environment.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/platform/platform.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/thread_context.hpp>
#include <boost/functional/hash.hpp>
@@ -22,7 +23,7 @@ LineAtlas::~LineAtlas() {
std::lock_guard<std::recursive_mutex> lock(mtx);
if (texture) {
Environment::Get().abandonTexture(texture);
mbgl::util::ThreadContext::getGLObjectStore()->abandonTexture(texture);
texture = 0;
}
}

View File

@@ -3,6 +3,7 @@
#include <vector>
#include <map>
#include <memory>
#include <mutex>
#include <atomic>

View File

@@ -1,12 +1,13 @@
#include <mbgl/map/environment.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/platform/platform.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/scaling.hpp>
#include <mbgl/util/thread_context.hpp>
#include <mbgl/map/sprite.hpp>
@@ -300,7 +301,7 @@ void SpriteAtlas::bind(bool linear) {
SpriteAtlas::~SpriteAtlas() {
std::lock_guard<std::recursive_mutex> lock(mtx);
if (texture) {
Environment::Get().abandonTexture(texture);
mbgl::util::ThreadContext::getGLObjectStore()->abandonTexture(texture);
texture = 0;
}
}

View File

@@ -1,7 +1,8 @@
#include <mbgl/geometry/vao.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/map/environment.hpp>
#include <mbgl/util/thread_context.hpp>
namespace mbgl {
@@ -47,7 +48,7 @@ VertexArrayObject::~VertexArrayObject() {
if (!DeleteVertexArrays) return;
if (vao) {
Environment::Get().abandonVAO(vao);
util::ThreadContext::getGLObjectStore()->abandonVAO(vao);
}
}

View File

@@ -17,6 +17,7 @@
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/uv_detail.hpp>
#include <mbgl/util/worker.hpp>
#include <mbgl/util/texture_pool.hpp>
@@ -37,6 +38,7 @@ MapContext::MapContext(uv_loop_t* loop, View& view_, FileSource& fileSource, Map
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
util::ThreadContext::setFileSource(&fileSource);
util::ThreadContext::setGLObjectStore(&glObjectStore);
asyncUpdate->unref();
@@ -52,12 +54,12 @@ void MapContext::cleanup() {
view.notify();
// Explicit resets currently necessary because these abandon resources that need to be
// cleaned up by env.performCleanup();
// cleaned up by glObjectStore.performCleanup();
style.reset();
painter.reset();
texturePool.reset();
env.performCleanup();
glObjectStore.performCleanup();
view.deactivate();
}
@@ -310,7 +312,7 @@ void MapContext::render() {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
// Cleanup OpenGL objects that we abandoned since the last render call.
env.performCleanup();
glObjectStore.performCleanup();
if (data.mode == MapMode::Still && (!callback || !data.getFullyLoaded())) {
// We are either not waiting for a map to be rendered, or we don't have all resources yet.

View File

@@ -6,6 +6,7 @@
#include <mbgl/map/environment.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/ptr.hpp>
#include <vector>
@@ -76,6 +77,8 @@ private:
View& view;
MapData& data;
util::GLObjectStore glObjectStore;
Environment env;
EnvironmentScope envScope;

View File

@@ -0,0 +1,48 @@
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/platform/gl.hpp>
namespace mbgl {
namespace util {
void GLObjectStore::abandonVAO(uint32_t vao) {
assert(ThreadContext::currentlyOn(ThreadType::Map));
abandonedVAOs.emplace_back(vao);
}
void GLObjectStore::abandonBuffer(uint32_t buffer) {
assert(ThreadContext::currentlyOn(ThreadType::Map));
abandonedBuffers.emplace_back(buffer);
}
void GLObjectStore::abandonTexture(uint32_t texture) {
assert(ThreadContext::currentlyOn(ThreadType::Map));
abandonedTextures.emplace_back(texture);
}
void GLObjectStore::performCleanup() {
assert(ThreadContext::currentlyOn(ThreadType::Map));
if (!abandonedVAOs.empty()) {
MBGL_CHECK_ERROR(VertexArrayObject::Delete(static_cast<GLsizei>(abandonedVAOs.size()),
abandonedVAOs.data()));
abandonedVAOs.clear();
}
if (!abandonedTextures.empty()) {
MBGL_CHECK_ERROR(glDeleteTextures(static_cast<GLsizei>(abandonedTextures.size()),
abandonedTextures.data()));
abandonedTextures.clear();
}
if (!abandonedBuffers.empty()) {
MBGL_CHECK_ERROR(glDeleteBuffers(static_cast<GLsizei>(abandonedBuffers.size()),
abandonedBuffers.data()));
abandonedBuffers.clear();
}
}
}
}

View File

@@ -0,0 +1,34 @@
#ifndef MBGL_MAP_UTIL_GL_OBJECT_STORE
#define MBGL_MAP_UTIL_GL_OBJECT_STORE
#include <mbgl/util/noncopyable.hpp>
#include <cstdint>
#include <vector>
namespace mbgl {
namespace util {
class GLObjectStore : private util::noncopyable {
public:
GLObjectStore() = default;
// Mark OpenGL objects for deletion
void abandonVAO(uint32_t vao);
void abandonBuffer(uint32_t buffer);
void abandonTexture(uint32_t texture);
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
void performCleanup();
private:
std::vector<uint32_t> abandonedVAOs;
std::vector<uint32_t> abandonedBuffers;
std::vector<uint32_t> abandonedTextures;
};
}
}
#endif

View File

@@ -1,5 +1,7 @@
#include <mbgl/util/texture_pool.hpp>
#include <mbgl/map/environment.hpp>
#include <mbgl/util/gl_object_store.hpp>
#include <mbgl/util/thread_context.hpp>
#include <vector>
@@ -43,9 +45,9 @@ void TexturePool::removeTextureID(GLuint texture_id) {
}
void TexturePool::clearTextureIDs() {
auto& env = Environment::Get();
auto getGLObjectStore = util::ThreadContext::getGLObjectStore();
for (auto texture : texture_ids) {
env.abandonTexture(texture);
getGLObjectStore->abandonTexture(texture);
}
texture_ids.clear();
}

View File

@@ -13,6 +13,8 @@ class FileSource;
namespace util {
class GLObjectStore;
enum class ThreadPriority : bool {
Regular,
Low,
@@ -49,12 +51,21 @@ public:
current.get()->fileSource = fileSource;
}
static GLObjectStore* getGLObjectStore() {
return current.get()->glObjectStore;
}
static void setGLObjectStore(GLObjectStore* glObjectStore) {
current.get()->glObjectStore = glObjectStore;
}
private:
std::string name;
ThreadType type;
ThreadPriority priority;
FileSource* fileSource = nullptr;
GLObjectStore* glObjectStore = nullptr;
static uv::tls<ThreadContext> current;

View File

@@ -6,6 +6,13 @@
#include <uv.h>
// XXX: uv.h will include <bits/termios.h> that will
// polute the namespace by defining "B0" which
// will conflict with boost macros.
#ifdef B0
#undef B0
#endif
#include <functional>
#include <cassert>
#include <memory>