From a745329eb152763ce567ed7a44007e1731d0e66f Mon Sep 17 00:00:00 2001 From: mwilsnd <53413200+mwilsnd@users.noreply.github.com> Date: Tue, 30 May 2023 11:30:18 -0500 Subject: [PATCH] Add Texture2D and use it in PatternAtlas (#1183) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CMakeLists.txt | 5 +- include/mbgl/gfx/drawable.hpp | 33 ++++++ include/mbgl/gfx/drawable_builder.hpp | 6 + include/mbgl/gfx/texture2d.hpp | 85 +++++++++++++++ {src => include}/mbgl/gfx/types.hpp | 0 include/mbgl/gl/drawable_gl.hpp | 4 + include/mbgl/gl/texture2d.hpp | 70 ++++++++++++ src/mbgl/gfx/drawable.cpp | 19 ++++ src/mbgl/gfx/drawable_builder.cpp | 11 ++ src/mbgl/gfx/upload_pass.hpp | 6 +- src/mbgl/gl/context.cpp | 1 + src/mbgl/gl/context.hpp | 5 +- src/mbgl/gl/drawable_gl.cpp | 17 ++- src/mbgl/gl/texture2d.cpp | 151 ++++++++++++++++++++++++++ src/mbgl/gl/upload_pass.cpp | 11 ++ src/mbgl/gl/upload_pass.hpp | 3 + src/mbgl/renderer/pattern_atlas.cpp | 21 +++- src/mbgl/renderer/pattern_atlas.hpp | 6 +- 18 files changed, 443 insertions(+), 11 deletions(-) create mode 100644 include/mbgl/gfx/texture2d.hpp rename {src => include}/mbgl/gfx/types.hpp (100%) create mode 100644 include/mbgl/gl/texture2d.hpp create mode 100644 src/mbgl/gl/texture2d.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 908c50a17..930d81932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,6 +153,8 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/texture2d.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/types.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/background_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/circle_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp @@ -394,7 +396,6 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/shader_registry.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/stencil_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/texture.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/types.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform_block.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform_buffer.cpp @@ -929,6 +930,7 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_block_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gl/texture2d.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/location_indicator_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/platform/gl_functions.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/change_request.hpp @@ -1010,6 +1012,7 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/state.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture2d.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture_resource.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture_resource.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/types.hpp diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index b78c64ed0..84a269ad5 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,20 @@ using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; class Drawable { +public: + struct TextureAttachment { + /// @brief A Texture2D instance + std::shared_ptr texture{nullptr}; + /// @brief A sampler location to bind the texture to + int32_t location{0}; + + TextureAttachment() = delete; + TextureAttachment(std::shared_ptr tex, int32_t loc) + : texture(std::move(tex)), + location(loc) {} + }; + using Textures = std::vector; + protected: Drawable(std::string name); @@ -73,6 +88,23 @@ public: int32_t getLineWidth() const { return lineWidth; } void setLineWidth(int32_t value) { lineWidth = value; } + /// @brief Remove an attached texture from this drawable at the given sampler location + /// @param location Texture sampler location + void removeTexture(int32_t location); + + /// @brief Return the textures attached to this drawable + /// @return Texture and sampler location pairs + const Textures& getTextures() const { return textures; }; + + /// @brief Set the collection of textures bound to this drawable + /// @param textures_ A Textures collection to set + void setTextures(const Textures& textures_) noexcept { textures = textures_; } + + /// @brief Attach the given texture to this drawable at the given sampler location. + /// @param texture Texture2D instance + /// @param location A sampler location in the shader being used with this drawable. + void setTexture(std::shared_ptr& texture, int32_t location); + /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } @@ -141,6 +173,7 @@ protected: struct Impl; std::unique_ptr impl; + Textures textures; std::vector tweakers; }; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 4f68cf0e7..d13584afc 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -108,6 +108,11 @@ public: void setVertexAttrName(std::string value) { vertexAttrName = std::move(value); } void setColorAttrName(std::string value) { colorAttrName = std::move(value); } + /// @brief Attach the given texture at the given sampler location. + /// @param texture Texture2D instance + /// @param location A sampler location in the shader being used. + void setTexture(const std::shared_ptr& texture, int32_t location); + /// Set the matrix applied to new drawables void setMatrix(mat4 value) { matrix = value; } @@ -169,6 +174,7 @@ protected: std::vector drawables; ColorAttrMode colorAttrMode = ColorAttrMode::PerVertex; VertexAttributeArray vertexAttrs; + gfx::Drawable::Textures textures; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/texture2d.hpp b/include/mbgl/gfx/texture2d.hpp new file mode 100644 index 000000000..9b25386e6 --- /dev/null +++ b/include/mbgl/gfx/texture2d.hpp @@ -0,0 +1,85 @@ +#pragma once +#include +#include + +#include +#include + +namespace mbgl { + +class Size; + +namespace gfx { + +constexpr int32_t MaxActiveTextureUnits = 8; + +class Context; +class UploadPass; +class TextureResource; + +class Texture2D { +public: + struct SamplerState { + /// Minification filter within a single mip level + TextureFilterType minification{TextureFilterType::Nearest}; + /// Magnification filter within a single mip level + TextureFilterType magnification{TextureFilterType::Nearest}; + /// Wrapping behavior along U coordinate + TextureWrapType wrapU{TextureWrapType::Clamp}; + /// Wrapping behavior along V coordinate + TextureWrapType wrapV{TextureWrapType::Clamp}; + }; + +public: + virtual ~Texture2D() = default; + + /// @brief Set the sampler configuration to be used for shader access of this + /// texture. + /// @param samplerState Sampler state configuration + /// @return this + virtual Texture2D& setSamplerConfiguration(const SamplerState& samplerState) noexcept = 0; + + /// @brief Set the texture pixel and data format + /// @param pixelFormat Pixel format to use + /// @param channelType Data type of each color channel + /// @return this + virtual Texture2D& setFormat(TexturePixelType pixelFormat, TextureChannelDataType channelType) noexcept = 0; + + /// @brief Set the size of the texture + /// @param size_ Size of the texture + /// @return this + virtual Texture2D& setSize(Size size_) noexcept = 0; + + /// @brief Determine the size of the buffer backing this texture + /// as configured, in bytes. + /// @return Size in bytes + virtual size_t getDataSize() const noexcept = 0; + + /// @brief Returns the size, in bytes, of a pixel in the texture. + /// @return Size of a pixel, in bytes + virtual size_t getPixelStride() const noexcept = 0; + + /// @brief Returns the number of color channels in the texture. + /// @return Channel count + virtual size_t numChannels() const noexcept = 0; + + /// @brief Create the texture using the provided buffer. + /// @param pixelData Buffer of bytes to initialize the texture with + virtual void create(const std::vector& pixelData, gfx::UploadPass& uploadPass) noexcept = 0; + + /// @brief Create the texture with default initialized memory. + virtual void create() noexcept = 0; + + /// @brief Upload image data to the texture resource + /// @param image Image data to transfer + /// @param uploadPass Upload pass to orchestrate upload + virtual void upload(const PremultipliedImage& image, gfx::UploadPass& uploadPass) const noexcept = 0; + + /// @brief Get the underlying GL texture resource + /// @note: Compat with legacy textures, to be refactored + /// @return gfx::TextureResource + virtual gfx::TextureResource& getResource() = 0; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/types.hpp b/include/mbgl/gfx/types.hpp similarity index 100% rename from src/mbgl/gfx/types.hpp rename to include/mbgl/gfx/types.hpp diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 45f8414e8..69315da80 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -26,6 +26,7 @@ using UniqueVertexBufferResource = std::unique_ptr; namespace gl { +class Texture2D; class VertexArray; class DrawableGL : public gfx::Drawable { @@ -62,6 +63,9 @@ protected: private: void bindUniformBuffers() const; void unbindUniformBuffers() const; + + void bindTextures() const; + void unbindTextures() const; }; } // namespace gl diff --git a/include/mbgl/gl/texture2d.hpp b/include/mbgl/gl/texture2d.hpp new file mode 100644 index 000000000..f75921886 --- /dev/null +++ b/include/mbgl/gl/texture2d.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include + +namespace mbgl { + +namespace gl { + +class Context; + +class Texture2D : public gfx::Texture2D { +public: + Texture2D(gl::Context& context_); + ~Texture2D() override; + +public: // gfx::Texture2D + Texture2D& setSamplerConfiguration(const SamplerState& samplerState) noexcept override; + + Texture2D& setFormat(gfx::TexturePixelType pixelFormat, gfx::TextureChannelDataType channelType) noexcept override; + + Texture2D& setSize(Size size_) noexcept override; + + size_t getDataSize() const noexcept override; + + size_t getPixelStride() const noexcept override; + + size_t numChannels() const noexcept override; + + void create(const std::vector& pixelData, gfx::UploadPass& uploadPass) noexcept override; + void create() noexcept override; + + void upload(const PremultipliedImage& image, gfx::UploadPass& uploadPass) const noexcept override; + + gfx::TextureResource& getResource() override { return *textureResource; } + +public: + /// @brief Get the OpenGL handle ID for the underlying resource + /// @return GLuint + platform::GLuint getTextureID() const noexcept; + + /// @brief Bind this texture to the specified texture unit + /// @param location Location index of texture sampler in a shader + /// @param textureUnit Unit to bind to. A maximum of gl::MaxActiveTextureUnits + /// texture units are available for binding. + void bind(int32_t location, int32_t textureUnit) noexcept; + + /// @brief Unbind the texture, if it was bound + void unbind() noexcept; + +private: + gl::Context& context; + std::unique_ptr textureResource{nullptr}; + + SamplerState samplerState{}; + gfx::TexturePixelType pixelFormat; + gfx::TextureChannelDataType channelType; + + Size size{0, 0}; + mutable bool samplerStateDirty{false}; + + int32_t boundTextureUnit{-1}; + int32_t boundLocation{-1}; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index 3a239fc09..3929fedc6 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -29,5 +29,24 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& value) { impl->cullFaceMode = value; } +void Drawable::setTexture(std::shared_ptr& texture, int32_t location) { + for (auto& tex : textures) { + if (tex.location == location) { + tex.texture = texture; + return; + } + } + textures.emplace_back(texture, location); +} + +void Drawable::removeTexture(int32_t location) { + for (auto it = textures.begin(); it != textures.end(); ++it) { + if (it->location == location) { + textures.erase(it); + return; + } + } +} + } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 43c08a2db..6590e6cec 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -50,6 +50,7 @@ void DrawableBuilder::flush() { draw->setCullFaceMode(impl->cullFaceMode); draw->setShader(shader); draw->setMatrix(matrix); + draw->setTextures(textures); if (auto drawAttrs = getVertexAttributes().clone()) { vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) { @@ -102,6 +103,16 @@ void DrawableBuilder::resetDrawPriority(DrawPriority value) { } } +void DrawableBuilder::setTexture(const std::shared_ptr& texture, int32_t location) { + for (auto& tex : textures) { + if (tex.location == location) { + tex.texture = texture; + return; + } + } + textures.emplace_back(texture, location); +} + void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { const auto n = static_cast(impl->vertices.elements()); impl->vertices.emplace_back(Impl::VT({{{x0, y0}}})); diff --git a/src/mbgl/gfx/upload_pass.hpp b/src/mbgl/gfx/upload_pass.hpp index f000d1969..1f759f4e7 100644 --- a/src/mbgl/gfx/upload_pass.hpp +++ b/src/mbgl/gfx/upload_pass.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ namespace mbgl { namespace gfx { +class Texture2D; class VertexAttributeArray; using AttributeBindingArray = std::vector>; @@ -107,7 +109,7 @@ public: updateTextureResourceSub(texture.getResource(), offsetX, offsetY, image.size, image.data.get(), format, type); } -protected: +public: virtual std::unique_ptr createTextureResource(Size, const void* data, TexturePixelType, @@ -121,6 +123,8 @@ protected: const void* data, TexturePixelType, TextureChannelDataType) = 0; + + virtual std::shared_ptr createTexture2D(const PremultipliedImage& image) = 0; }; } // namespace gfx diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index ee62527db..09749f051 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index a800c381e..fc60a7e5f 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -122,7 +123,7 @@ public: State bindFramebuffer; State viewport; State scissorTest; - std::array, 2> texture; + std::array, gfx::MaxActiveTextureUnits> texture; State program; State vertexBuffer; @@ -157,10 +158,12 @@ private: std::unique_ptr createOffscreenTexture(Size, gfx::TextureChannelDataType) override; +public: std::unique_ptr createTextureResource(Size, gfx::TexturePixelType, gfx::TextureChannelDataType) override; +private: std::unique_ptr createRenderbufferResource(gfx::RenderbufferPixelType, Size size) override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index c8fab8bbe..315ac41fc 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -1,6 +1,6 @@ #include - #include +#include #include #include #include @@ -49,6 +49,7 @@ void DrawableGL::draw(const PaintParameters& parameters) const { context.setCullFaceMode(gfx::CullFaceMode::disabled()); bindUniformBuffers(); + bindTextures(); auto& glContext = static_cast(parameters.context); const auto saveVertexArray = glContext.bindVertexArray.getCurrentValue(); @@ -64,6 +65,7 @@ void DrawableGL::draw(const PaintParameters& parameters) const { glContext.bindVertexArray = saveVertexArray; + unbindTextures(); unbindUniformBuffers(); } @@ -173,5 +175,18 @@ void DrawableGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) { } } +void DrawableGL::bindTextures() const { + int32_t unit = 0; + for (const auto& tex : textures) { + std::static_pointer_cast(tex.texture)->bind(tex.location, unit++); + } +} + +void DrawableGL::unbindTextures() const { + for (const auto& tex : textures) { + std::static_pointer_cast(tex.texture)->unbind(); + } +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/texture2d.cpp b/src/mbgl/gl/texture2d.cpp new file mode 100644 index 000000000..184b5814d --- /dev/null +++ b/src/mbgl/gl/texture2d.cpp @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mbgl { +namespace gl { + +Texture2D::Texture2D(gl::Context& context_) + : context(context_) {} + +Texture2D::~Texture2D() {} + +Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_) noexcept { + samplerState = samplerState_; + samplerStateDirty = textureResource != nullptr; + return *this; +} + +Texture2D& Texture2D::setFormat(gfx::TexturePixelType pixelFormat_, gfx::TextureChannelDataType channelType_) noexcept { + pixelFormat = pixelFormat_; + channelType = channelType_; + return *this; +} + +Texture2D& Texture2D::setSize(mbgl::Size size_) noexcept { + size = size_; + return *this; +} + +size_t Texture2D::getDataSize() const noexcept { + return size.width * size.height * getPixelStride(); +} + +size_t Texture2D::getPixelStride() const noexcept { + switch (channelType) { + case gfx::TextureChannelDataType::UnsignedByte: + return 1 * numChannels(); + case gfx::TextureChannelDataType::HalfFloat: + return 2 * numChannels(); + default: + return 0; + } +} + +size_t Texture2D::numChannels() const noexcept { + switch (pixelFormat) { + case gfx::TexturePixelType::RGBA: + return 4; + default: + return 0; + } +} + +void Texture2D::create(const std::vector& pixelData, gfx::UploadPass& uploadPass) noexcept { + assert(!textureResource); + textureResource = uploadPass.createTextureResource(size, pixelData.data(), pixelFormat, channelType); +} + +void Texture2D::create() noexcept { + assert(!textureResource); + textureResource = context.createTextureResource(size, pixelFormat, channelType); +} + +platform::GLuint Texture2D::getTextureID() const noexcept { + return static_cast(*textureResource).texture; +} + +void Texture2D::bind(int32_t location, int32_t textureUnit) noexcept { + using namespace platform; + + assert(gfx::MaxActiveTextureUnits > textureUnit); + if (gfx::MaxActiveTextureUnits > textureUnit) return; + + context.activeTextureUnit = static_cast(textureUnit); + context.texture[static_cast(textureUnit)] = getTextureID(); + + boundTextureUnit = textureUnit; + + // Update the sampler state if it was changed after resource creation + if (samplerStateDirty) { + samplerStateDirty = false; + + MBGL_CHECK_ERROR( + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + samplerState.minification == gfx::TextureFilterType::Nearest ? GL_NEAREST : GL_LINEAR)); + MBGL_CHECK_ERROR( + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + samplerState.magnification == gfx::TextureFilterType::Nearest ? GL_NEAREST : GL_LINEAR)); + MBGL_CHECK_ERROR( + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + samplerState.wrapU == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + MBGL_CHECK_ERROR( + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + samplerState.wrapV == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + } + + // Link the bound texture unit with the requested sampler in the active shader + glUniform1i(location, textureUnit); +} + +void Texture2D::unbind() noexcept { + using namespace platform; + + // Unlink the texture from the last used texture unit + if (boundTextureUnit != -1) { + context.activeTextureUnit = boundTextureUnit; + context.texture[static_cast(boundTextureUnit)] = 0; + boundTextureUnit = -1; + } + + // And clear the uniform value linking a sampler to the texture unit + // Default back to GL_TEXTURE0 + if (boundLocation != -1) { + glUniform1i(boundLocation, 0); + boundLocation = -1; + } +} + +void Texture2D::upload(const PremultipliedImage& image, gfx::UploadPass& uploadPass) const noexcept { + assert(textureResource); + assert(image.size == size); + if (image.size != size) { + return; + } + + assert(image.channels == numChannels()); + if (image.channels != numChannels()) { + return; + } + + // note: images are always unsigned bytes + assert(image.channels == getPixelStride()); + if (image.channels != getPixelStride()) { + return; + } + + uploadPass.updateTextureResource(*textureResource, size, &image.data[0], pixelFormat, channelType); +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 36259e546..8fee70773 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -209,6 +210,16 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( return {}; } +std::shared_ptr UploadPass::createTexture2D(const PremultipliedImage& image) { + auto tex = std::make_shared(commandEncoder.context); + tex->setSize(image.size) + .setFormat(image.channels == 4 ? gfx::TexturePixelType::RGBA : gfx::TexturePixelType::Alpha, + gfx::TextureChannelDataType::UnsignedByte) + .create(); + tex->upload(image, *this); + return tex; +} + void UploadPass::pushDebugGroup(const char* name) { commandEncoder.pushDebugGroup(name); } diff --git a/src/mbgl/gl/upload_pass.hpp b/src/mbgl/gl/upload_pass.hpp index 07e0ddc14..d1395abb3 100644 --- a/src/mbgl/gl/upload_pass.hpp +++ b/src/mbgl/gl/upload_pass.hpp @@ -15,6 +15,7 @@ namespace gl { class CommandEncoder; class Context; class VertexArray; +class Texture2D; class UploadPass final : public gfx::UploadPass { public: @@ -56,6 +57,8 @@ public: gfx::TexturePixelType, gfx::TextureChannelDataType) override; + std::shared_ptr createTexture2D(const PremultipliedImage& image) override; + private: gl::CommandEncoder& commandEncoder; const gfx::DebugGroup debugGroup; diff --git a/src/mbgl/renderer/pattern_atlas.cpp b/src/mbgl/renderer/pattern_atlas.cpp index 4a3c881c0..e5ba696af 100644 --- a/src/mbgl/renderer/pattern_atlas.cpp +++ b/src/mbgl/renderer/pattern_atlas.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace mbgl { @@ -87,19 +88,29 @@ Size PatternAtlas::getPixelSize() const { } void PatternAtlas::upload(gfx::UploadPass& uploadPass) { - if (!atlasTexture) { - atlasTexture = uploadPass.createTexture(atlasImage); + // @note: This is what we should be doing, but will fail a ton of render tests until we update them all + // if (atlasImage.size.isEmpty()) { + // return; + // } + + if (!atlasTexture2D) { + atlasTexture2D = uploadPass.createTexture2D(atlasImage); } else if (dirty) { - uploadPass.updateTexture(*atlasTexture, atlasImage); + atlasTexture2D->upload(atlasImage, uploadPass); } dirty = false; } +// @note: Deprecated gfx::TextureBinding PatternAtlas::textureBinding() const { - assert(atlasTexture); + assert(atlasTexture2D); assert(!dirty); - return {atlasTexture->getResource(), gfx::TextureFilterType::Linear}; + return {atlasTexture2D->getResource(), gfx::TextureFilterType::Linear}; +} + +const std::shared_ptr& PatternAtlas::texture() const { + return atlasTexture2D; } } // namespace mbgl diff --git a/src/mbgl/renderer/pattern_atlas.hpp b/src/mbgl/renderer/pattern_atlas.hpp index de225eb0c..ab0e65b05 100644 --- a/src/mbgl/renderer/pattern_atlas.hpp +++ b/src/mbgl/renderer/pattern_atlas.hpp @@ -15,6 +15,7 @@ template class Actor; namespace gfx { +class Texture2D; class UploadPass; } // namespace gfx @@ -29,7 +30,8 @@ public: std::optional addPattern(const style::Image::Impl&); void removePattern(const std::string&); - gfx::TextureBinding textureBinding() const; + gfx::TextureBinding textureBinding() const; // @TODO: Migrate + const std::shared_ptr& texture() const; void upload(gfx::UploadPass&); Size getPixelSize() const; @@ -46,7 +48,7 @@ private: mapbox::ShelfPack shelfPack; std::unordered_map patterns; PremultipliedImage atlasImage; - std::optional atlasTexture; + std::shared_ptr atlasTexture2D{nullptr}; bool dirty = true; };