diff options
-rw-r--r-- | cmake/core-files.cmake | 4 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 38 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/gl/texture.hpp | 19 | ||||
-rw-r--r-- | src/mbgl/gl/types.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/raster_bucket.cpp | 21 | ||||
-rw-r--r-- | src/mbgl/renderer/raster_bucket.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/tile/raster_tile_worker.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/util/offscreen_texture.cpp | 18 | ||||
-rw-r--r-- | src/mbgl/util/offscreen_texture.hpp | 8 | ||||
-rw-r--r-- | src/mbgl/util/raster.cpp | 96 | ||||
-rw-r--r-- | src/mbgl/util/raster.hpp | 62 | ||||
-rw-r--r-- | test/util/offscreen_texture.test.cpp | 3 |
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)); |