summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2016-10-04 12:45:11 +0200
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-10-04 14:00:30 -0700
commit07315711d6b191a5812065bb76ab5beb33d995d9 (patch)
tree89afc1b90ac64660596ffb94512bbd23adbf80cc
parente103d92b1814fc3a735c05ce9be70be3409c201a (diff)
downloadqtlocation-mapboxgl-07315711d6b191a5812065bb76ab5beb33d995d9.tar.gz
[core] remove Raster object in favor of a more low-level Texture object
-rw-r--r--cmake/core-files.cmake4
-rw-r--r--src/mbgl/gl/context.cpp38
-rw-r--r--src/mbgl/gl/context.hpp21
-rw-r--r--src/mbgl/gl/texture.hpp19
-rw-r--r--src/mbgl/gl/types.hpp3
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp21
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp10
-rw-r--r--src/mbgl/tile/raster_tile_worker.cpp3
-rw-r--r--src/mbgl/util/offscreen_texture.cpp18
-rw-r--r--src/mbgl/util/offscreen_texture.hpp8
-rw-r--r--src/mbgl/util/raster.cpp96
-rw-r--r--src/mbgl/util/raster.hpp62
-rw-r--r--test/util/offscreen_texture.test.cpp3
13 files changed, 116 insertions, 190 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 2fc17af76d..32410927ad 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -87,6 +87,7 @@ set(MBGL_CORE_FILES
src/mbgl/gl/object.cpp
src/mbgl/gl/object.hpp
src/mbgl/gl/state.hpp
+ src/mbgl/gl/texture.hpp
src/mbgl/gl/types.hpp
src/mbgl/gl/value.cpp
src/mbgl/gl/value.hpp
@@ -229,6 +230,7 @@ set(MBGL_CORE_FILES
include/mbgl/storage/response.hpp
src/mbgl/storage/asset_file_source.hpp
src/mbgl/storage/http_file_source.hpp
+ src/mbgl/storage/local_file_source.hpp
src/mbgl/storage/network_status.cpp
src/mbgl/storage/resource.cpp
src/mbgl/storage/response.cpp
@@ -468,8 +470,6 @@ set(MBGL_CORE_FILES
src/mbgl/util/premultiply.cpp
src/mbgl/util/premultiply.hpp
src/mbgl/util/rapidjson.hpp
- src/mbgl/util/raster.cpp
- src/mbgl/util/raster.hpp
src/mbgl/util/rect.hpp
src/mbgl/util/std.hpp
src/mbgl/util/stopwatch.cpp
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index ae50e64cbc..ded7936feb 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -124,6 +124,44 @@ void Context::uploadBuffer(BufferType type, size_t size, void* data) {
MBGL_CHECK_ERROR(glBufferData(static_cast<GLenum>(type), size, data, GL_STATIC_DRAW));
}
+UniqueTexture
+Context::createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit unit) {
+ auto obj = createTexture();
+ activeTexture = unit;
+ texture[unit] = obj;
+ 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));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+ MBGL_CHECK_ERROR(
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
+ return obj;
+}
+
+void Context::bindTexture(Texture& obj,
+ TextureUnit unit,
+ TextureFilter filter,
+ TextureMipMap mipmap) {
+ if (filter != obj.filter || mipmap != obj.mipmap) {
+ 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;
+ } else if (texture[unit] != obj.texture) {
+ // We are checking first to avoid setting the active texture without a subsequent
+ // texture bind.
+ activeTexture = unit;
+ texture[unit] = obj.texture;
+ }
+}
+
void Context::reset() {
std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures));
pooledTextures.resize(0);
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 04089c2000..0ec846033a 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -3,6 +3,7 @@
#include <mbgl/gl/object.hpp>
#include <mbgl/gl/state.hpp>
#include <mbgl/gl/value.hpp>
+#include <mbgl/gl/texture.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <memory>
@@ -28,6 +29,23 @@ public:
void uploadBuffer(BufferType, size_t, void*);
+ // Create a texture from an image with data.
+ template <typename Image>
+ Texture createTexture(const Image& image, TextureUnit unit = 0) {
+ return { {{ image.width, image.height }},
+ createTexture(image.width, image.height, image.data.get(), unit) };
+ }
+
+ // Creates an empty texture with the specified dimensions.
+ Texture createTexture(const std::array<uint16_t, 2>& size, TextureUnit unit = 0) {
+ return { size, createTexture(size[0], size[1], nullptr, unit) };
+ }
+
+ void bindTexture(Texture&,
+ TextureUnit = 0,
+ TextureFilter = TextureFilter::Nearest,
+ TextureMipMap = TextureMipMap::No);
+
// 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();
@@ -80,6 +98,9 @@ public:
State<value::BindVertexArray> vertexArrayObject;
private:
+ UniqueTexture createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit);
+
+private:
friend detail::ProgramDeleter;
friend detail::ShaderDeleter;
friend detail::BufferDeleter;
diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp
new file mode 100644
index 0000000000..49e1323095
--- /dev/null
+++ b/src/mbgl/gl/texture.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <mbgl/gl/object.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace gl {
+
+class Texture {
+public:
+ std::array<uint16_t, 2> size;
+ UniqueTexture texture;
+ TextureFilter filter = TextureFilter::Nearest;
+ TextureMipMap mipmap = TextureMipMap::No;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index 8578a11f66..e9d14e4807 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -27,6 +27,9 @@ enum class BufferType : uint32_t {
Element = 0x8893
};
+enum class TextureMipMap : bool { No = false, Yes = true };
+enum class TextureFilter : bool { Nearest = false, Linear = true };
+
enum class StencilTestFunction : uint32_t {
Never = 0x0200,
Less = 0x0201,
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 0f902880de..3edbe3e042 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -9,11 +9,13 @@ namespace mbgl {
using namespace style;
+RasterBucket::RasterBucket(PremultipliedImage&& image_) : image(std::move(image_)) {
+}
+
void RasterBucket::upload(gl::Context& context) {
- if (hasData()) {
- raster.upload(context, 0);
- uploaded = true;
- }
+ texture = context.createTexture(image);
+ image = {};
+ uploaded = true;
}
void RasterBucket::render(Painter& painter,
@@ -23,22 +25,19 @@ void RasterBucket::render(Painter& painter,
painter.renderRaster(parameters, *this, *layer.as<RasterLayer>(), tile);
}
-void RasterBucket::setImage(PremultipliedImage image) {
- raster.load(std::move(image));
-}
-
void RasterBucket::drawRaster(RasterShader& shader,
StaticRasterVertexBuffer& vertices,
VertexArrayObject& array,
gl::Context& context) {
- raster.bind(context, 0, Raster::Scaling::Linear);
- raster.bind(context, 1, Raster::Scaling::Linear);
+ assert(texture);
+ context.bindTexture(*texture, 0, gl::TextureFilter::Linear);
+ context.bindTexture(*texture, 1, gl::TextureFilter::Linear);
array.bind(shader, vertices, BUFFER_OFFSET_0, context);
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)vertices.index()));
}
bool RasterBucket::hasData() const {
- return raster.isLoaded();
+ return true;
}
bool RasterBucket::needsClipping() const {
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index 24f3f8864a..db8138b875 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/util/raster.hpp>
+#include <mbgl/util/image.hpp>
#include <mbgl/gl/context.hpp>
namespace mbgl {
@@ -12,16 +12,18 @@ class VertexArrayObject;
class RasterBucket : public Bucket {
public:
+ RasterBucket(PremultipliedImage&&);
+
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
bool needsClipping() const override;
- void setImage(PremultipliedImage);
-
void drawRaster(RasterShader&, StaticRasterVertexBuffer&, VertexArrayObject&, gl::Context&);
- Raster raster;
+private:
+ PremultipliedImage image;
+ optional<gl::Texture> texture;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp
index 838737d5b8..d7621e35b8 100644
--- a/src/mbgl/tile/raster_tile_worker.cpp
+++ b/src/mbgl/tile/raster_tile_worker.cpp
@@ -16,8 +16,7 @@ void RasterTileWorker::parse(std::shared_ptr<const std::string> data) {
}
try {
- auto bucket = std::make_unique<RasterBucket>();
- bucket->setImage(decodeImage(*data));
+ auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
parent.invoke(&RasterTile::onParsed, std::move(bucket));
} catch (...) {
parent.invoke(&RasterTile::setError, std::current_exception());
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 194527d1b0..51049f8282 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -10,16 +10,15 @@ void OffscreenTexture::bind(gl::Context& context,
std::array<uint16_t, 2> size) {
assert(size[0] > 0 && size[1] > 0);
- if (raster.getSize() != size) {
- raster.load(PremultipliedImage(size[0], size[1], nullptr));
- raster.upload(context, 0);
+ if (!texture || texture->size != size) {
+ texture = context.createTexture(size);
}
if (!framebuffer) {
framebuffer = context.createFramebuffer();
context.bindFramebuffer = *framebuffer;
MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- raster.getID(), 0));
+ texture->texture, 0));
GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
if (status != GL_FRAMEBUFFER_COMPLETE) {
@@ -55,12 +54,17 @@ void OffscreenTexture::bind(gl::Context& context,
context.viewport = { 0, 0, size[0], size[1] };
}
-Raster& OffscreenTexture::getTexture() {
- return raster;
+gl::Texture& OffscreenTexture::getTexture() {
+ return *texture;
}
std::array<uint16_t, 2> OffscreenTexture::getSize() const {
- return raster.getSize();
+ if (texture) {
+ // Use explicit dereference instead of -> due to clang 3.5 bug
+ return (*texture).size;
+ } else {
+ return {{ 0, 0 }};
+ }
}
} // namespace mbgl
diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp
index 2f5fa75d6c..c71c0e51d9 100644
--- a/src/mbgl/util/offscreen_texture.hpp
+++ b/src/mbgl/util/offscreen_texture.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/util/raster.hpp>
+#include <mbgl/gl/texture.hpp>
namespace mbgl {
@@ -12,12 +12,12 @@ class OffscreenTexture {
public:
void bind(gl::Context&, std::array<uint16_t, 2> size);
- Raster& getTexture();
+ gl::Texture& getTexture();
std::array<uint16_t, 2> getSize() const;
private:
- mbgl::optional<gl::UniqueFramebuffer> framebuffer;
- Raster raster;
+ optional<gl::UniqueFramebuffer> framebuffer;
+ optional<gl::Texture> texture;
};
} // namespace mbgl
diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp
deleted file mode 100644
index 885230c7ec..0000000000
--- a/src/mbgl/util/raster.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/log.hpp>
-
-#include <mbgl/util/raster.hpp>
-
-#include <cassert>
-#include <cstring>
-
-namespace mbgl {
-
-bool Raster::isLoaded() const {
- return loaded;
-}
-
-gl::TextureID Raster::getID() const {
- return texture ? *texture : 0;
-}
-
-std::array<uint16_t, 2> Raster::getSize() const {
- return size;
-}
-
-void Raster::load(PremultipliedImage image, uint32_t mipmapLevel) {
- if (images.size() <= mipmapLevel) {
- images.resize(mipmapLevel + 1);
- }
- images.at(mipmapLevel) = std::move(image);
-
- loaded = true;
-}
-
-void Raster::bind(gl::Context& context,
- uint32_t unit,
- Scaling newFilter,
- MipMap newMipMap) {
- bool filterNeedsUpdate = false;
-
- if (!texture) {
- if (images.empty()) {
- Log::Error(Event::OpenGL, "trying to bind texture without images");
- return;
- } else {
- upload(context, unit);
- filterNeedsUpdate = true;
- }
- } else {
- if (context.texture[unit] != *texture) {
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- }
- filterNeedsUpdate = (filter != newFilter || mipmap != newMipMap);
- }
-
- if (filterNeedsUpdate) {
- filter = newFilter;
- mipmap = newMipMap;
- updateFilter();
- }
-}
-
-void Raster::updateFilter() {
- MBGL_CHECK_ERROR(glTexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- filter == Scaling::Linear
- ? (mipmap == MipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
- : (mipmap == MipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- filter == Scaling::Linear ? GL_LINEAR : GL_NEAREST));
-}
-
-void Raster::upload(gl::Context& context, uint32_t unit) {
- if (!images.empty() && !texture) {
- texture = context.createTexture();
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- updateFilter();
-#if not MBGL_USE_GLES2
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, images.size()));
-#endif // MBGL_USE_GLES2
- 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));
- GLint level = 0;
- for (auto& img : images) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, level++, GL_RGBA, static_cast<GLsizei>(img.width),
- static_cast<GLsizei>(img.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data.get()));
- }
- size = { { images.front().width, images.front().height } };
- images.clear();
- images.shrink_to_fit();
- }
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp
deleted file mode 100644
index 606839050d..0000000000
--- a/src/mbgl/util/raster.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/object.hpp>
-#include <mbgl/util/image.hpp>
-#include <mbgl/util/optional.hpp>
-
-#include <atomic>
-#include <array>
-#include <vector>
-
-namespace mbgl {
-
-namespace gl {
-class Context;
-} // namespace gl
-
-class Raster {
-public:
- enum class MipMap : bool { No = false, Yes = true };
- enum class Scaling : bool { Nearest = false, Linear = true };
-
- // load image data
- void load(PremultipliedImage, uint32_t mipmapLevel = 0);
-
- // bind current texture
- void bind(gl::Context&,
- uint32_t unit,
- Scaling = Scaling::Nearest,
- MipMap = MipMap::No);
-
- // uploads the texture if it hasn't been uploaded yet.
- void upload(gl::Context&, uint32_t unit);
-
- // loaded status
- bool isLoaded() const;
-
- // returns the OpenGL texture ID
- gl::TextureID getID() const;
-
- // size of uploaded image.
- std::array<uint16_t, 2> getSize() const;
-
-private:
- void updateFilter();
-
-private:
- // raw pixels have been loaded
- std::atomic<bool> loaded { false };
- std::array<uint16_t, 2> size = {{ 0, 0 }};
-
- // filters
- Scaling filter = Scaling::Nearest;
- MipMap mipmap = MipMap::No;
-
- // the raw pixels
- std::vector<PremultipliedImage> images;
-
- // GL buffer object handle.
- mbgl::optional<gl::UniqueTexture> texture;
-};
-
-} // namespace mbgl
diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp
index 2c80c04c41..301fc2c250 100644
--- a/test/util/offscreen_texture.test.cpp
+++ b/test/util/offscreen_texture.test.cpp
@@ -4,7 +4,6 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/util/offscreen_texture.hpp>
-#include <mbgl/util/raster.hpp>
using namespace mbgl;
@@ -137,7 +136,7 @@ void main() {
// Now, composite the Framebuffer texture we've rendered to onto the main FBO.
context.program = compositeShader.program;
- texture.getTexture().bind(context, 0, Raster::Scaling::Linear);
+ context.bindTexture(texture.getTexture(), 0, gl::TextureFilter::Linear);
MBGL_CHECK_ERROR(glUniform1i(u_texture, 0));
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, viewportBuffer.buffer));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(compositeShader.a_pos));