committed by
Bart Louwers
parent
e771363d4b
commit
4cac8a8dfb
@@ -940,6 +940,7 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/prelude.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_background.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_background_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_circle.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline.hpp
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
/// @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<gfx::Texture2D>& texture, int32_t location);
|
||||
void setTexture(std::shared_ptr<gfx::Texture2D> texture, int32_t location);
|
||||
|
||||
/// not used for anything yet
|
||||
DrawPriority getDrawPriority() const { return drawPriority; }
|
||||
|
||||
@@ -11,6 +11,8 @@ struct Drawable::DrawSegment {
|
||||
segment(std::move(segment_)) {}
|
||||
|
||||
const gfx::DrawMode& getMode() const { return mode; }
|
||||
|
||||
Segment<void>& getSegment() { return segment; }
|
||||
const Segment<void>& getSegment() const { return segment; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -50,6 +50,10 @@ public:
|
||||
/// @return this
|
||||
virtual Texture2D& setSize(Size size_) noexcept = 0;
|
||||
|
||||
/// @brief Get the size of the texture
|
||||
/// @return Size of the texture
|
||||
virtual Size getSize() const noexcept = 0;
|
||||
|
||||
/// @brief Determine the size of the buffer backing this texture
|
||||
/// as configured, in bytes.
|
||||
/// @return Size in bytes
|
||||
@@ -63,17 +67,31 @@ public:
|
||||
/// @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<uint8_t>& 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;
|
||||
/// @param pixelData Image data to transfer
|
||||
virtual void upload(const void* pixelData, const Size& size_) noexcept = 0;
|
||||
template <typename Image>
|
||||
void upload(const Image& img) noexcept {
|
||||
setFormat(Image::channels == 1 ? gfx::TexturePixelType::Alpha : gfx::TexturePixelType::RGBA,
|
||||
gfx::TextureChannelDataType::UnsignedByte);
|
||||
upload(&img.data[0], img.size);
|
||||
}
|
||||
|
||||
virtual void uploadSubRegion(const void* pixelData,
|
||||
const Size& size,
|
||||
uint16_t xOffset,
|
||||
uint16_t yOffset) noexcept = 0;
|
||||
template <typename Image>
|
||||
void uploadSubRegion(const Image& img, uint16_t xOffset, uint16_t yOffset) noexcept {
|
||||
assert(Image::channels == numChannels());
|
||||
assert(Image::channels == getPixelStride());
|
||||
assert(img.size.width + xOffset <= getSize().width);
|
||||
assert(img.size.height + yOffset <= getSize().height);
|
||||
uploadSubRegion(&img.data[0], img.size, xOffset, yOffset);
|
||||
}
|
||||
|
||||
/// @brief Get the underlying GL texture resource
|
||||
/// @note: Compat with legacy textures, to be refactored
|
||||
|
||||
@@ -51,8 +51,7 @@ public:
|
||||
const std::shared_ptr<UniformBuffer>& get(const std::string& name) const;
|
||||
|
||||
/// Add a new uniform buffer element or replace the existing one.
|
||||
const std::shared_ptr<UniformBuffer>& addOrReplace(std::string name,
|
||||
const std::shared_ptr<UniformBuffer>& uniformBuffer);
|
||||
const std::shared_ptr<UniformBuffer>& addOrReplace(std::string name, std::shared_ptr<UniformBuffer> uniformBuffer);
|
||||
|
||||
UniformBufferArray& operator=(UniformBufferArray&&);
|
||||
UniformBufferArray& operator=(const UniformBufferArray&);
|
||||
|
||||
@@ -15,7 +15,6 @@ class Segment;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class Context;
|
||||
class IndexBuffer;
|
||||
class UploadPass;
|
||||
class VertexBufferResource;
|
||||
@@ -51,7 +50,7 @@ public:
|
||||
/// Reset a single color attribute for all vertexes
|
||||
void resetColor(const Color&) override;
|
||||
|
||||
void upload(gfx::Context&, gfx::UploadPass&);
|
||||
void upload(gfx::UploadPass&);
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
TileLayerGroupGL(int32_t layerIndex, std::size_t initialCapacity);
|
||||
~TileLayerGroupGL() override {}
|
||||
|
||||
void upload(gfx::Context&, gfx::UploadPass&) override;
|
||||
void upload(gfx::UploadPass&) override;
|
||||
void render(RenderOrchestrator&, PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -24,24 +24,31 @@ public: // gfx::Texture2D
|
||||
|
||||
Texture2D& setSize(Size size_) noexcept override;
|
||||
|
||||
Size getSize() const noexcept override { return size; }
|
||||
|
||||
size_t getDataSize() const noexcept override;
|
||||
|
||||
size_t getPixelStride() const noexcept override;
|
||||
|
||||
size_t numChannels() const noexcept override;
|
||||
|
||||
void create(const std::vector<uint8_t>& pixelData, gfx::UploadPass& uploadPass) noexcept override;
|
||||
void create() noexcept override;
|
||||
|
||||
void upload(const PremultipliedImage& image, gfx::UploadPass& uploadPass) const noexcept override;
|
||||
void upload(const void* pixelData, const Size& size_) noexcept override;
|
||||
void uploadSubRegion(const void* pixelData, const Size& size, uint16_t xOffset, uint16_t yOffset) noexcept override;
|
||||
|
||||
gfx::TextureResource& getResource() override { return *textureResource; }
|
||||
gfx::TextureResource& getResource() override {
|
||||
assert(textureResource);
|
||||
return *textureResource;
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief Get the OpenGL handle ID for the underlying resource
|
||||
/// @return GLuint
|
||||
platform::GLuint getTextureID() const noexcept;
|
||||
|
||||
void updateSamplerConfiguration() 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
|
||||
@@ -60,7 +67,7 @@ private:
|
||||
gfx::TextureChannelDataType channelType;
|
||||
|
||||
Size size{0, 0};
|
||||
mutable bool samplerStateDirty{false};
|
||||
bool samplerStateDirty{false};
|
||||
|
||||
int32_t boundTextureUnit{-1};
|
||||
int32_t boundLocation{-1};
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
/// Called before starting each frame
|
||||
virtual void preRender(RenderOrchestrator&, PaintParameters&) {}
|
||||
/// Called during the upload pass
|
||||
virtual void upload(gfx::Context&, gfx::UploadPass&) {}
|
||||
virtual void upload(gfx::UploadPass&) {}
|
||||
/// Called during each render pass
|
||||
virtual void render(RenderOrchestrator&, PaintParameters&) {}
|
||||
/// Called at the end of each frame
|
||||
|
||||
85
include/mbgl/shaders/gl/drawable_background_pattern.hpp
Normal file
85
include/mbgl/shaders/gl/drawable_background_pattern.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "BackgroundPatternShader";
|
||||
static constexpr const char* vertex = R"(layout (std140) uniform BackgroundDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
};
|
||||
layout (std140) uniform BackgroundLayerUBO {
|
||||
highp vec2 u_pattern_tl_a;
|
||||
highp vec2 u_pattern_br_a;
|
||||
highp vec2 u_pattern_tl_b;
|
||||
highp vec2 u_pattern_br_b;
|
||||
highp vec2 u_texsize;
|
||||
highp vec2 u_pattern_size_a;
|
||||
highp vec2 u_pattern_size_b;
|
||||
highp vec2 u_pixel_coord_upper;
|
||||
highp vec2 u_pixel_coord_lower;
|
||||
highp float u_tile_units_to_pixels;
|
||||
highp float u_scale_a;
|
||||
highp float u_scale_b;
|
||||
highp float u_mix;
|
||||
highp float u_opacity;
|
||||
highp float pad;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
out mediump vec2 v_pos_a;
|
||||
out mediump vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
|
||||
v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);
|
||||
v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(layout (std140) uniform BackgroundLayerUBO {
|
||||
highp vec2 u_pattern_tl_a;
|
||||
highp vec2 u_pattern_br_a;
|
||||
highp vec2 u_pattern_tl_b;
|
||||
highp vec2 u_pattern_br_b;
|
||||
highp vec2 u_texsize;
|
||||
highp vec2 u_pattern_size_a;
|
||||
highp vec2 u_pattern_size_b;
|
||||
highp vec2 u_pixel_coord_upper;
|
||||
highp vec2 u_pixel_coord_lower;
|
||||
highp float u_tile_units_to_pixels;
|
||||
highp float u_scale_a;
|
||||
highp float u_scale_b;
|
||||
highp float u_mix;
|
||||
highp float u_opacity;
|
||||
highp float pad;
|
||||
};
|
||||
|
||||
uniform sampler2D u_image;
|
||||
|
||||
in mediump vec2 v_pos_a;
|
||||
in mediump vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
vec2 imagecoord = mod(v_pos_a, 1.0);
|
||||
vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);
|
||||
vec4 color1 = texture(u_image, pos);
|
||||
|
||||
vec2 imagecoord_b = mod(v_pos_b, 1.0);
|
||||
vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);
|
||||
vec4 color2 = texture(u_image, pos2);
|
||||
|
||||
fragColor = mix(color1, color2, u_mix) * u_opacity;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#ifdef MBGL_RENDER_BACKEND_OPENGL
|
||||
#include <mbgl/shaders/gl/drawable_background.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_background_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_circle.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill_outline.hpp>
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace shaders {
|
||||
enum class BuiltIn {
|
||||
None,
|
||||
BackgroundShader,
|
||||
BackgroundPatternShader,
|
||||
CircleShader,
|
||||
FillShader,
|
||||
FillOutlineShader,
|
||||
|
||||
38
shaders/drawable.background_pattern.fragment.glsl
Normal file
38
shaders/drawable.background_pattern.fragment.glsl
Normal file
@@ -0,0 +1,38 @@
|
||||
layout (std140) uniform BackgroundLayerUBO {
|
||||
highp vec2 u_pattern_tl_a;
|
||||
highp vec2 u_pattern_br_a;
|
||||
highp vec2 u_pattern_tl_b;
|
||||
highp vec2 u_pattern_br_b;
|
||||
highp vec2 u_texsize;
|
||||
highp vec2 u_pattern_size_a;
|
||||
highp vec2 u_pattern_size_b;
|
||||
highp vec2 u_pixel_coord_upper;
|
||||
highp vec2 u_pixel_coord_lower;
|
||||
highp float u_tile_units_to_pixels;
|
||||
highp float u_scale_a;
|
||||
highp float u_scale_b;
|
||||
highp float u_mix;
|
||||
highp float u_opacity;
|
||||
highp float pad;
|
||||
};
|
||||
|
||||
uniform sampler2D u_image;
|
||||
|
||||
in mediump vec2 v_pos_a;
|
||||
in mediump vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
vec2 imagecoord = mod(v_pos_a, 1.0);
|
||||
vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);
|
||||
vec4 color1 = texture(u_image, pos);
|
||||
|
||||
vec2 imagecoord_b = mod(v_pos_b, 1.0);
|
||||
vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);
|
||||
vec4 color2 = texture(u_image, pos2);
|
||||
|
||||
fragColor = mix(color1, color2, u_mix) * u_opacity;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
31
shaders/drawable.background_pattern.vertex.glsl
Normal file
31
shaders/drawable.background_pattern.vertex.glsl
Normal file
@@ -0,0 +1,31 @@
|
||||
layout (std140) uniform BackgroundDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
};
|
||||
layout (std140) uniform BackgroundLayerUBO {
|
||||
highp vec2 u_pattern_tl_a;
|
||||
highp vec2 u_pattern_br_a;
|
||||
highp vec2 u_pattern_tl_b;
|
||||
highp vec2 u_pattern_br_b;
|
||||
highp vec2 u_texsize;
|
||||
highp vec2 u_pattern_size_a;
|
||||
highp vec2 u_pattern_size_b;
|
||||
highp vec2 u_pixel_coord_upper;
|
||||
highp vec2 u_pixel_coord_lower;
|
||||
highp float u_tile_units_to_pixels;
|
||||
highp float u_scale_a;
|
||||
highp float u_scale_b;
|
||||
highp float u_mix;
|
||||
highp float u_opacity;
|
||||
highp float pad;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
out mediump vec2 v_pos_a;
|
||||
out mediump vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
|
||||
v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);
|
||||
v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);
|
||||
}
|
||||
@@ -6,6 +6,13 @@
|
||||
"glsl_frag": "drawable.background.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "BackgroundPatternShader",
|
||||
"header": "drawable_background_pattern",
|
||||
"glsl_vert": "drawable.background_pattern.vertex.glsl",
|
||||
"glsl_frag": "drawable.background_pattern.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "CircleShader",
|
||||
"header": "drawable_circle",
|
||||
|
||||
@@ -28,12 +28,14 @@ class DrawableTweaker;
|
||||
class OffscreenTexture;
|
||||
class ShaderProgramBase;
|
||||
class ShaderRegistry;
|
||||
class Texture2D;
|
||||
|
||||
using DrawablePtr = std::shared_ptr<Drawable>;
|
||||
using UniqueDrawableBuilder = std::unique_ptr<DrawableBuilder>;
|
||||
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
|
||||
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
|
||||
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
|
||||
class Context {
|
||||
protected:
|
||||
@@ -115,6 +117,9 @@ public:
|
||||
|
||||
/// Create a layer group implementation
|
||||
virtual TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity) = 0;
|
||||
|
||||
/// Create a texture
|
||||
virtual Texture2DPtr createTexture2D() = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -27,14 +27,14 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& value) {
|
||||
impl->cullFaceMode = value;
|
||||
}
|
||||
|
||||
void Drawable::setTexture(std::shared_ptr<gfx::Texture2D>& texture, int32_t location) {
|
||||
void Drawable::setTexture(std::shared_ptr<gfx::Texture2D> texture, int32_t location) {
|
||||
for (auto& tex : textures) {
|
||||
if (tex.location == location) {
|
||||
tex.texture = texture;
|
||||
tex.texture = std::move(texture);
|
||||
return;
|
||||
}
|
||||
}
|
||||
textures.emplace_back(texture, location);
|
||||
textures.emplace_back(std::move(texture), location);
|
||||
}
|
||||
|
||||
void Drawable::removeTexture(int32_t location) {
|
||||
|
||||
@@ -120,6 +120,13 @@ void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1
|
||||
if (colorAttrMode == ColorAttrMode::PerVertex) {
|
||||
impl->colors.insert(impl->colors.end(), 3, impl->currentColor);
|
||||
}
|
||||
|
||||
if (impl->segments.empty()) {
|
||||
impl->segments.emplace_back(createSegment(gfx::Triangles(), {0, 0}));
|
||||
}
|
||||
auto& segment = impl->segments.back();
|
||||
segment->getSegment().vertexLength += 3;
|
||||
segment->getSegment().indexLength += 3;
|
||||
}
|
||||
|
||||
void DrawableBuilder::appendTriangle(int16_t x0, int16_t y0) {
|
||||
@@ -129,6 +136,11 @@ void DrawableBuilder::appendTriangle(int16_t x0, int16_t y0) {
|
||||
if (colorAttrMode == ColorAttrMode::PerVertex) {
|
||||
impl->colors.emplace_back(impl->currentColor);
|
||||
}
|
||||
|
||||
assert(!impl->segments.empty());
|
||||
auto& segment = impl->segments.back();
|
||||
segment->getSegment().vertexLength += 1;
|
||||
segment->getSegment().indexLength += 3;
|
||||
}
|
||||
|
||||
void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
|
||||
|
||||
@@ -29,8 +29,8 @@ const std::shared_ptr<UniformBuffer>& UniformBufferArray::get(const std::string&
|
||||
return (result != uniformBufferMap.end()) ? result->second : nullref;
|
||||
}
|
||||
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::addOrReplace(
|
||||
std::string name, const std::shared_ptr<UniformBuffer>& uniformBuffer) {
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::addOrReplace(std::string name,
|
||||
std::shared_ptr<UniformBuffer> uniformBuffer) {
|
||||
const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr<UniformBuffer>()));
|
||||
result.first->second = std::move(uniformBuffer);
|
||||
return result.first->second;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <mbgl/gfx/index_vector.hpp>
|
||||
#include <mbgl/gfx/index_buffer.hpp>
|
||||
#include <mbgl/gfx/texture.hpp>
|
||||
#include <mbgl/gfx/texture2d.hpp>
|
||||
#include <mbgl/util/size.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
|
||||
@@ -20,6 +21,7 @@ class Texture2D;
|
||||
class VertexAttributeArray;
|
||||
|
||||
using AttributeBindingArray = std::vector<std::optional<gfx::AttributeBinding>>;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
|
||||
class UploadPass {
|
||||
protected:
|
||||
@@ -36,6 +38,9 @@ public:
|
||||
|
||||
DebugGroup<UploadPass> createDebugGroup(const char* name) { return {*this, name}; }
|
||||
|
||||
virtual Context& getContext() = 0;
|
||||
virtual const Context& getContext() const = 0;
|
||||
|
||||
public:
|
||||
template <class Vertex>
|
||||
VertexBuffer<Vertex> createVertexBuffer(VertexVector<Vertex>&& v,
|
||||
@@ -92,7 +97,7 @@ public:
|
||||
void updateTexture(Texture& texture,
|
||||
const Image& image,
|
||||
TextureChannelDataType type = TextureChannelDataType::UnsignedByte) {
|
||||
auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
const auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
updateTextureResource(texture.getResource(), image.size, image.data.get(), format, type);
|
||||
texture.size = image.size;
|
||||
}
|
||||
@@ -105,7 +110,27 @@ public:
|
||||
TextureChannelDataType type = TextureChannelDataType::UnsignedByte) {
|
||||
assert(image.size.width + offsetX <= texture.size.width);
|
||||
assert(image.size.height + offsetY <= texture.size.height);
|
||||
auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
const auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
updateTextureResourceSub(texture.getResource(), offsetX, offsetY, image.size, image.data.get(), format, type);
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void updateTexture(Texture2D& texture,
|
||||
const Image& image,
|
||||
TextureChannelDataType type = TextureChannelDataType::UnsignedByte) {
|
||||
const auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
updateTexture2D(texture, image.size, image.data.get(), format, type);
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void updateTextureSub(Texture2D& texture,
|
||||
const Image& image,
|
||||
const uint16_t offsetX,
|
||||
const uint16_t offsetY,
|
||||
TextureChannelDataType type = TextureChannelDataType::UnsignedByte) {
|
||||
assert(image.size.width + offsetX <= texture.getSize().width);
|
||||
assert(image.size.height + offsetY <= texture.getSize().height);
|
||||
const auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
|
||||
updateTextureResourceSub(texture.getResource(), offsetX, offsetY, image.size, image.data.get(), format, type);
|
||||
}
|
||||
|
||||
@@ -116,6 +141,7 @@ public:
|
||||
TextureChannelDataType) = 0;
|
||||
virtual void updateTextureResource(
|
||||
TextureResource&, Size, const void* data, TexturePixelType, TextureChannelDataType) = 0;
|
||||
|
||||
virtual void updateTextureResourceSub(TextureResource&,
|
||||
uint16_t xOffset,
|
||||
uint16_t yOffset,
|
||||
@@ -123,8 +149,6 @@ public:
|
||||
const void* data,
|
||||
TexturePixelType,
|
||||
TextureChannelDataType) = 0;
|
||||
|
||||
virtual std::shared_ptr<gfx::Texture2D> createTexture2D(const PremultipliedImage& image) = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -475,6 +475,10 @@ TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t
|
||||
return std::make_shared<TileLayerGroupGL>(layerIndex, initialCapacity);
|
||||
}
|
||||
|
||||
gfx::Texture2DPtr Context::createTexture2D() {
|
||||
return std::make_shared<gl::Texture2D>(*this);
|
||||
}
|
||||
|
||||
void Context::clear(std::optional<mbgl::Color> color, std::optional<float> depth, std::optional<int32_t> stencil) {
|
||||
GLbitfield mask = 0;
|
||||
|
||||
@@ -603,10 +607,10 @@ void Context::performCleanup() {
|
||||
// TODO: Find a better way to unbind VAOs after we're done with them without
|
||||
// introducing unnecessary bind(0)/bind(N) sequences.
|
||||
{
|
||||
activeTextureUnit = 1;
|
||||
texture[1] = 0;
|
||||
activeTextureUnit = 0;
|
||||
texture[0] = 0;
|
||||
for (auto i = 0; i < gfx::MaxActiveTextureUnits; i++) {
|
||||
activeTextureUnit = i;
|
||||
texture[i] = 0;
|
||||
}
|
||||
|
||||
bindVertexArray = 0;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,8 @@ public:
|
||||
|
||||
TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity) override;
|
||||
|
||||
gfx::Texture2DPtr createTexture2D() override;
|
||||
|
||||
private:
|
||||
RendererBackend& backend;
|
||||
bool cleanupOnDestruction = true;
|
||||
|
||||
@@ -126,7 +126,7 @@ void DrawableGL::unbindUniformBuffers() const {
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) {
|
||||
void DrawableGL::upload(gfx::UploadPass& uploadPass) {
|
||||
if (!shader) {
|
||||
return;
|
||||
}
|
||||
@@ -137,6 +137,7 @@ void DrawableGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) {
|
||||
});
|
||||
|
||||
if (build) {
|
||||
auto& context = uploadPass.getContext();
|
||||
auto& glContext = static_cast<gl::Context&>(context);
|
||||
constexpr auto usage = gfx::BufferUsageType::StaticDraw;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace gl {
|
||||
TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity)
|
||||
: TileLayerGroup(layerIndex_, initialCapacity) {}
|
||||
|
||||
void TileLayerGroupGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass) {
|
||||
void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) {
|
||||
observeDrawables([&](gfx::Drawable& drawable) {
|
||||
auto& drawableGL = static_cast<gl::DrawableGL&>(drawable);
|
||||
|
||||
@@ -28,7 +28,7 @@ void TileLayerGroupGL::upload(gfx::Context& context, gfx::UploadPass& uploadPass
|
||||
const auto debugGroup = uploadPass.createDebugGroup(labelPtr);
|
||||
#endif
|
||||
|
||||
drawableGL.upload(context, uploadPass);
|
||||
drawableGL.upload(uploadPass);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ void registerTypes(gfx::ShaderRegistry& registry, gl::Context& glContext, const
|
||||
|
||||
void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramParameters& programParameters) {
|
||||
registerTypes<shaders::BuiltIn::BackgroundShader,
|
||||
shaders::BuiltIn::BackgroundPatternShader,
|
||||
shaders::BuiltIn::CircleShader,
|
||||
shaders::BuiltIn::FillShader,
|
||||
shaders::BuiltIn::FillOutlineShader,
|
||||
|
||||
@@ -23,6 +23,11 @@ Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_)
|
||||
}
|
||||
|
||||
Texture2D& Texture2D::setFormat(gfx::TexturePixelType pixelFormat_, gfx::TextureChannelDataType channelType_) noexcept {
|
||||
if (pixelFormat_ == pixelFormat && channelType_ == channelType) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
assert(!textureResource);
|
||||
pixelFormat = pixelFormat_;
|
||||
channelType = channelType_;
|
||||
return *this;
|
||||
@@ -52,56 +57,61 @@ size_t Texture2D::numChannels() const noexcept {
|
||||
switch (pixelFormat) {
|
||||
case gfx::TexturePixelType::RGBA:
|
||||
return 4;
|
||||
case gfx::TexturePixelType::Alpha:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::create(const std::vector<uint8_t>& 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);
|
||||
|
||||
auto obj = context.createUniqueTexture();
|
||||
const auto storageSize = gl::TextureResource::getStorageSize(size, pixelFormat, channelType);
|
||||
context.renderingStats().memTextures += storageSize;
|
||||
|
||||
// @TODO: TextureResource is still needed while we have legacy rendering pathways
|
||||
textureResource = std::make_unique<gl::TextureResource>(std::move(obj), storageSize);
|
||||
}
|
||||
|
||||
platform::GLuint Texture2D::getTextureID() const noexcept {
|
||||
return static_cast<gl::TextureResource&>(*textureResource).texture;
|
||||
}
|
||||
|
||||
void Texture2D::updateSamplerConfiguration() noexcept {
|
||||
using namespace platform;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void Texture2D::bind(int32_t location, int32_t textureUnit) noexcept {
|
||||
using namespace platform;
|
||||
|
||||
assert(gfx::MaxActiveTextureUnits > textureUnit);
|
||||
if (gfx::MaxActiveTextureUnits > textureUnit) return;
|
||||
if (gfx::MaxActiveTextureUnits <= textureUnit) return;
|
||||
|
||||
// Bind to the texture unit
|
||||
context.activeTextureUnit = static_cast<uint8_t>(textureUnit);
|
||||
context.texture[static_cast<size_t>(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));
|
||||
updateSamplerConfiguration();
|
||||
}
|
||||
|
||||
// Link the bound texture unit with the requested sampler in the active shader
|
||||
@@ -126,18 +136,55 @@ void Texture2D::unbind() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::upload(const PremultipliedImage& image, gfx::UploadPass& uploadPass) const noexcept {
|
||||
void Texture2D::upload(const void* pixelData, const Size& size_) noexcept {
|
||||
using namespace platform;
|
||||
if (!textureResource) {
|
||||
create();
|
||||
}
|
||||
assert(textureResource);
|
||||
assert(image.size == size);
|
||||
if (image.size != size) {
|
||||
return;
|
||||
|
||||
// Bind to TU 0 and upload
|
||||
context.activeTextureUnit = 0;
|
||||
context.texture[0] = getTextureID();
|
||||
if (samplerStateDirty) {
|
||||
updateSamplerConfiguration();
|
||||
}
|
||||
|
||||
assert(PremultipliedImage::channels == numChannels());
|
||||
// note: images are always unsigned bytes
|
||||
assert(PremultipliedImage::channels == getPixelStride());
|
||||
if (size_ == Size{0, 0} || size_ != size) {
|
||||
size = size_;
|
||||
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
Enum<gfx::TexturePixelType>::to(pixelFormat),
|
||||
size.width,
|
||||
size.height,
|
||||
0,
|
||||
Enum<gfx::TexturePixelType>::to(pixelFormat),
|
||||
Enum<gfx::TextureChannelDataType>::to(channelType),
|
||||
pixelData));
|
||||
} else {
|
||||
uploadSubRegion(pixelData, size, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uploadPass.updateTextureResource(*textureResource, size, &image.data[0], pixelFormat, channelType);
|
||||
void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16_t xOffset, uint16_t yOffset) noexcept {
|
||||
using namespace platform;
|
||||
|
||||
assert(textureResource);
|
||||
assert(!samplerStateDirty);
|
||||
|
||||
// Bind to TU 0 and upload
|
||||
context.activeTextureUnit = 0;
|
||||
context.texture[0] = getTextureID();
|
||||
|
||||
MBGL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
xOffset,
|
||||
yOffset,
|
||||
size_.width,
|
||||
size_.height,
|
||||
Enum<gfx::TexturePixelType>::to(pixelFormat),
|
||||
Enum<gfx::TextureChannelDataType>::to(channelType),
|
||||
pixelData));
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -68,10 +68,9 @@ std::unique_ptr<gfx::TextureResource> UploadPass::createTextureResource(const Si
|
||||
gfx::TexturePixelType format,
|
||||
gfx::TextureChannelDataType type) {
|
||||
auto obj = commandEncoder.context.createUniqueTexture();
|
||||
int textureByteSize = gl::TextureResource::getStorageSize(size, format, type);
|
||||
const int textureByteSize = gl::TextureResource::getStorageSize(size, format, type);
|
||||
commandEncoder.context.renderingStats().memTextures += textureByteSize;
|
||||
std::unique_ptr<gfx::TextureResource> resource = std::make_unique<gl::TextureResource>(std::move(obj),
|
||||
textureByteSize);
|
||||
auto resource = std::make_unique<gl::TextureResource>(std::move(obj), textureByteSize);
|
||||
commandEncoder.context.pixelStoreUnpack = {1};
|
||||
updateTextureResource(*resource, size, data, format, type);
|
||||
// We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT
|
||||
@@ -210,13 +209,6 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<gfx::Texture2D> UploadPass::createTexture2D(const PremultipliedImage& image) {
|
||||
auto tex = std::make_shared<gl::Texture2D>(commandEncoder.context);
|
||||
tex->setSize(image.size).setFormat(gfx::TexturePixelType::RGBA, gfx::TextureChannelDataType::UnsignedByte).create();
|
||||
tex->upload(image, *this);
|
||||
return tex;
|
||||
}
|
||||
|
||||
void UploadPass::pushDebugGroup(const char* name) {
|
||||
commandEncoder.pushDebugGroup(name);
|
||||
}
|
||||
@@ -225,5 +217,13 @@ void UploadPass::popDebugGroup() {
|
||||
commandEncoder.popDebugGroup();
|
||||
}
|
||||
|
||||
gfx::Context& UploadPass::getContext() {
|
||||
return commandEncoder.context;
|
||||
}
|
||||
|
||||
const gfx::Context& UploadPass::getContext() const {
|
||||
return commandEncoder.context;
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -26,6 +26,9 @@ private:
|
||||
void popDebugGroup() override;
|
||||
|
||||
public:
|
||||
gfx::Context& getContext() override;
|
||||
const gfx::Context& getContext() const override;
|
||||
|
||||
std::unique_ptr<gfx::VertexBufferResource> createVertexBufferResource(const void* data,
|
||||
std::size_t size,
|
||||
gfx::BufferUsageType) override;
|
||||
@@ -49,6 +52,7 @@ public:
|
||||
gfx::TextureChannelDataType) override;
|
||||
void updateTextureResource(
|
||||
gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
|
||||
|
||||
void updateTextureResourceSub(gfx::TextureResource&,
|
||||
uint16_t xOffset,
|
||||
uint16_t yOffset,
|
||||
@@ -57,8 +61,6 @@ public:
|
||||
gfx::TexturePixelType,
|
||||
gfx::TextureChannelDataType) override;
|
||||
|
||||
std::shared_ptr<gfx::Texture2D> createTexture2D(const PremultipliedImage& image) override;
|
||||
|
||||
private:
|
||||
gl::CommandEncoder& commandEncoder;
|
||||
const gfx::DebugGroup<gfx::CommandEncoder> debugGroup;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <mbgl/renderer/layers/background_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/style/layers/background_layer_properties.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/pattern_atlas.hpp>
|
||||
#include <mbgl/style/layers/background_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -16,53 +18,116 @@ struct alignas(16) BackgroundDrawableUBO {
|
||||
static_assert(sizeof(BackgroundDrawableUBO) % 16 == 0);
|
||||
|
||||
struct alignas(16) BackgroundLayerUBO {
|
||||
Color color;
|
||||
float opacity;
|
||||
float padding[3];
|
||||
/* 0 */ Color color;
|
||||
/* 16 */ float opacity;
|
||||
/* 20 */ std::array<float, 3> pad;
|
||||
/* 32 */
|
||||
};
|
||||
static_assert(sizeof(BackgroundLayerUBO) % 16 == 0);
|
||||
static_assert(sizeof(BackgroundLayerUBO) == 32);
|
||||
|
||||
struct alignas(16) BackgroundPatternLayerUBO {
|
||||
std::array<float, 2> pattern_tl_a;
|
||||
std::array<float, 2> pattern_br_a;
|
||||
std::array<float, 2> pattern_tl_b;
|
||||
std::array<float, 2> pattern_br_b;
|
||||
std::array<float, 2> texsize;
|
||||
std::array<float, 2> pattern_size_a;
|
||||
std::array<float, 2> pattern_size_b;
|
||||
std::array<float, 2> pixel_coord_upper;
|
||||
std::array<float, 2> pixel_coord_lower;
|
||||
float tile_units_to_pixels;
|
||||
float scale_a;
|
||||
float scale_b;
|
||||
float mix;
|
||||
float opacity;
|
||||
/* 0 */ std::array<float, 2> pattern_tl_a;
|
||||
/* 8 */ std::array<float, 2> pattern_br_a;
|
||||
/* 16 */ std::array<float, 2> pattern_tl_b;
|
||||
/* 24 */ std::array<float, 2> pattern_br_b;
|
||||
/* 32 */ std::array<float, 2> texsize;
|
||||
/* 40 */ std::array<float, 2> pattern_size_a;
|
||||
/* 48 */ std::array<float, 2> pattern_size_b;
|
||||
/* 56 */ std::array<float, 2> pixel_coord_upper;
|
||||
/* 64 */ std::array<float, 2> pixel_coord_lower;
|
||||
/* 72 */ float tile_units_to_pixels;
|
||||
/* 76 */ float scale_a;
|
||||
/* 80 */ float scale_b;
|
||||
/* 84 */ float mix;
|
||||
/* 88 */ float opacity;
|
||||
/* 92 */ std::array<float, 1> pad;
|
||||
/* 96 */
|
||||
};
|
||||
static_assert(sizeof(BackgroundPatternLayerUBO) % 16 == 0);
|
||||
static_assert(sizeof(BackgroundPatternLayerUBO) == 96);
|
||||
|
||||
void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, const PaintParameters& parameters) {
|
||||
const auto& state = parameters.state;
|
||||
const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
const auto& crossfade = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).crossfade;
|
||||
|
||||
if (!layerUniformBuffer) {
|
||||
BackgroundLayerUBO layerUBO;
|
||||
layerUBO.color = evaluated.get<BackgroundColor>();
|
||||
layerUBO.opacity = evaluated.get<BackgroundOpacity>();
|
||||
layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO));
|
||||
const bool hasPattern = !evaluated.get<BackgroundPattern>().to.empty();
|
||||
const std::optional<ImagePosition> imagePosA = hasPattern ? parameters.patternAtlas.getPattern(
|
||||
evaluated.get<BackgroundPattern>().from.id())
|
||||
: std::nullopt;
|
||||
const std::optional<ImagePosition> imagePosB = hasPattern ? parameters.patternAtlas.getPattern(
|
||||
evaluated.get<BackgroundPattern>().to.id())
|
||||
: std::nullopt;
|
||||
|
||||
if (hasPattern && (!imagePosA || !imagePosB)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shader) {
|
||||
shader = parameters.context.getGenericShader(parameters.shaders, "BackgroundShader");
|
||||
}
|
||||
if (!patternShader) {
|
||||
patternShader = parameters.context.getGenericShader(parameters.shaders, "BackgroundPatternShader");
|
||||
}
|
||||
const auto& curShader = hasPattern ? patternShader : shader;
|
||||
if (!curShader) {
|
||||
return;
|
||||
}
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
drawable.mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", layerUniformBuffer);
|
||||
|
||||
if (!drawable.getTileID()) {
|
||||
return;
|
||||
}
|
||||
assert(drawable.getTileID());
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto matrix = parameters.matrixForTile(tileID);
|
||||
|
||||
drawable.setShader(curShader);
|
||||
|
||||
BackgroundDrawableUBO drawableUBO;
|
||||
drawableUBO.matrix = util::cast<float>(matrix);
|
||||
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
|
||||
drawable.mutableUniformBuffers().addOrReplace("BackgroundDrawableUBO", drawableUniformBuffer);
|
||||
drawable.mutableUniformBuffers().addOrReplace("BackgroundDrawableUBO", std::move(drawableUniformBuffer));
|
||||
|
||||
gfx::UniformBufferPtr layerUniformBuffer;
|
||||
if (hasPattern) {
|
||||
// TODO: add when raster is merged
|
||||
// curShader->getSamplerLocation("u_image");
|
||||
drawable.setTexture(parameters.patternAtlas.texture(), 0);
|
||||
|
||||
// from BackgroundPatternProgram::layoutUniformValues
|
||||
const int32_t tileSizeAtNearestZoom = static_cast<int32_t>(
|
||||
util::tileSize_D * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z));
|
||||
const int32_t pixelX = static_cast<int32_t>(
|
||||
tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z)));
|
||||
const int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
|
||||
const Size atlasSize = parameters.patternAtlas.getPixelSize();
|
||||
const auto pixToTile = tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
|
||||
|
||||
const BackgroundPatternLayerUBO layerUBO = {
|
||||
/* .pattern_tl_a = */ util::cast<float>(imagePosA->tl()),
|
||||
/* .pattern_br_a = */ util::cast<float>(imagePosA->br()),
|
||||
/* .pattern_tl_b = */ util::cast<float>(imagePosB->tl()),
|
||||
/* .pattern_br_b = */ util::cast<float>(imagePosB->br()),
|
||||
/* .texsize = */ {static_cast<float>(atlasSize.width), static_cast<float>(atlasSize.height)},
|
||||
/* .pattern_size_a = */ imagePosA->displaySize(),
|
||||
/* .pattern_size_b = */ imagePosB->displaySize(),
|
||||
/* .pixel_coord_upper = */ {static_cast<float>(pixelX >> 16), static_cast<float>(pixelY >> 16)},
|
||||
/* .pixel_coord_lower = */ {static_cast<float>(pixelX & 0xFFFF), static_cast<float>(pixelY & 0xFFFF)},
|
||||
/* .tile_units_to_pixels = */ (pixToTile != 0) ? 1.0f / pixToTile : 0.0f,
|
||||
/* .scale_a = */ crossfade.fromScale,
|
||||
/* .scale_b = */ crossfade.toScale,
|
||||
/* .mix = */ crossfade.t,
|
||||
/* .opacity = */ evaluated.get<BackgroundOpacity>(),
|
||||
/* .pad = */ {0},
|
||||
};
|
||||
// TODO: Update UBOs in-place
|
||||
layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO));
|
||||
} else {
|
||||
const BackgroundLayerUBO layerUBO = {
|
||||
/* .color = */ evaluated.get<BackgroundColor>(),
|
||||
/* .opacity = */ evaluated.get<BackgroundOpacity>(),
|
||||
/* .pad = */ {0, 0, 0},
|
||||
};
|
||||
layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO));
|
||||
}
|
||||
drawable.mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", std::move(layerUniformBuffer));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
class ShaderProgramBase;
|
||||
class UniformBuffer;
|
||||
|
||||
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
|
||||
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
|
||||
} // namespace gfx
|
||||
|
||||
@@ -23,7 +28,8 @@ public:
|
||||
void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr layerUniformBuffer = nullptr;
|
||||
gfx::ShaderProgramBasePtr shader;
|
||||
gfx::ShaderProgramBasePtr patternShader;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <mbgl/renderer/layers/background_layer_tweaker.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
@@ -206,17 +205,13 @@ void RenderBackgroundLayer::layerRemoved(UniqueChangeRequestVec& changes) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
void RenderBackgroundLayer::update(gfx::ShaderRegistry& /*shaders*/,
|
||||
gfx::Context& context,
|
||||
const TransformState& state,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
[[maybe_unused]] UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if (!shader) {
|
||||
shader = context.getGenericShader(shaders, "BackgroundShader");
|
||||
}
|
||||
|
||||
const auto removeAll = [&]() {
|
||||
if (tileLayerGroup) {
|
||||
stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount();
|
||||
@@ -228,7 +223,6 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
const auto tileCover = util::tileCover(state, zoom);
|
||||
|
||||
// renderTiles is always empty, we use tileCover instead
|
||||
// if (!renderTiles || renderTiles->empty()) {
|
||||
if (tileCover.empty()) {
|
||||
removeAll();
|
||||
return;
|
||||
@@ -245,9 +239,6 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
: RenderPass::Opaque |
|
||||
RenderPass::Translucent; // evaluated based on opaquePassCutoff in render()
|
||||
|
||||
// unevaluated.hasTransition();
|
||||
// getCrossfade<BackgroundLayerProperties>(evaluatedProperties).t != 1;
|
||||
|
||||
// If the result is transparent or missing, just remove any existing drawables and stop
|
||||
if (drawPasses == RenderPass::None) {
|
||||
removeAll();
|
||||
@@ -284,7 +275,6 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
});
|
||||
|
||||
// For each tile in the cover set, add a tile drawable if one doesn't already exist.
|
||||
// We currently assume only one drawable per tile.
|
||||
for (const auto& tileID : tileCover) {
|
||||
// If we already have drawables for this tile, skip.
|
||||
// If a drawable needs to be updated, that's handled in the layer tweaker.
|
||||
@@ -296,7 +286,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (!builder) {
|
||||
builder = context.createDrawableBuilder("background");
|
||||
builder->setRenderPass(drawPasses);
|
||||
builder->setShader(shader);
|
||||
// builder->setShader(shader);
|
||||
builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::PerDrawable);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
}
|
||||
@@ -306,9 +296,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
|
||||
builder->flush();
|
||||
|
||||
auto newDrawables = builder->clearDrawables();
|
||||
if (!newDrawables.empty()) {
|
||||
auto& drawable = newDrawables[0];
|
||||
for (auto& drawable : builder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
|
||||
@@ -48,8 +48,6 @@ private:
|
||||
// Programs
|
||||
std::shared_ptr<BackgroundProgram> backgroundProgram;
|
||||
std::shared_ptr<BackgroundPatternProgram> backgroundPatternProgram;
|
||||
|
||||
gfx::ShaderProgramBasePtr shader;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -189,7 +189,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
|
||||
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
|
||||
evaluated.get<FillExtrusionTranslateAnchor>(),
|
||||
parameters.state),
|
||||
tile.getIconAtlasTexture().size,
|
||||
tile.getIconAtlasTexture()->getSize(),
|
||||
crossfade,
|
||||
tile.id,
|
||||
parameters.state,
|
||||
@@ -201,8 +201,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
|
||||
patternPosA,
|
||||
patternPosB,
|
||||
FillExtrusionPatternProgram::TextureBindings{
|
||||
textures::image::Value{tile.getIconAtlasTexture().getResource(),
|
||||
gfx::TextureFilterType::Linear},
|
||||
textures::image::Value{tile.getIconAtlasTextureBinding(gfx::TextureFilterType::Linear)},
|
||||
},
|
||||
name);
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ void RenderFillLayer::render(PaintParameters& parameters) {
|
||||
tile.translatedMatrix(
|
||||
evaluated.get<FillTranslate>(), evaluated.get<FillTranslateAnchor>(), parameters.state),
|
||||
parameters.backend.getDefaultRenderable().getSize(),
|
||||
tile.getIconAtlasTexture().size,
|
||||
tile.getIconAtlasTexture()->getSize(),
|
||||
crossfade,
|
||||
tile.id,
|
||||
parameters.state,
|
||||
@@ -230,8 +230,7 @@ void RenderFillLayer::render(PaintParameters& parameters) {
|
||||
*bucket.triangleIndexBuffer,
|
||||
bucket.triangleSegments,
|
||||
FillPatternProgram::TextureBindings{
|
||||
textures::image::Value{tile.getIconAtlasTexture().getResource(),
|
||||
gfx::TextureFilterType::Linear},
|
||||
tile.getIconAtlasTextureBinding(gfx::TextureFilterType::Linear),
|
||||
});
|
||||
}
|
||||
if (evaluated.get<FillAntialias>() && unevaluated.get<FillOutlineColor>().isUndefined()) {
|
||||
@@ -241,8 +240,7 @@ void RenderFillLayer::render(PaintParameters& parameters) {
|
||||
*bucket.lineIndexBuffer,
|
||||
bucket.lineSegments,
|
||||
FillOutlinePatternProgram::TextureBindings{
|
||||
textures::image::Value{tile.getIconAtlasTexture().getResource(),
|
||||
gfx::TextureFilterType::Linear},
|
||||
tile.getIconAtlasTextureBinding(gfx::TextureFilterType::Linear),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -519,6 +517,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
patternBuilder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
patternBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
patternBuilder->setSubLayerIndex(1);
|
||||
// patternBuilder->setTexture(tile.getIconAtlasTexture(), 0);
|
||||
}
|
||||
if (doOutline && !outlinePatternBuilder && outlinePatternShader) {
|
||||
outlinePatternBuilder = context.createDrawableBuilder("fill-outline-pattern");
|
||||
@@ -528,6 +527,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
outlinePatternBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
outlinePatternBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
outlinePatternBuilder->setSubLayerIndex(2);
|
||||
// outlinePatternBuilder->setTexture(tile.getIconAtlasTexture(), 0);
|
||||
}
|
||||
|
||||
// parameters.stencilModeForClipping(tile.id),
|
||||
|
||||
@@ -169,7 +169,7 @@ void RenderLineLayer::render(PaintParameters& parameters) {
|
||||
|
||||
} else if (!unevaluated.get<LinePattern>().isUndefined()) {
|
||||
const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<expression::Image>{"", ""});
|
||||
const Size& texsize = tile.getIconAtlasTexture().size;
|
||||
const Size& texsize = tile.getIconAtlasTexture()->getSize();
|
||||
|
||||
std::optional<ImagePosition> posA = tile.getPattern(linePatternValue.from.id());
|
||||
std::optional<ImagePosition> posB = tile.getPattern(linePatternValue.to.id());
|
||||
@@ -185,7 +185,7 @@ void RenderLineLayer::render(PaintParameters& parameters) {
|
||||
posA,
|
||||
posB,
|
||||
LinePatternProgram::TextureBindings{
|
||||
textures::image::Value{tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear},
|
||||
tile.getIconAtlasTextureBinding(gfx::TextureFilterType::Linear),
|
||||
});
|
||||
} else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
|
||||
assert(colorRampTexture);
|
||||
|
||||
@@ -120,12 +120,11 @@ void drawIcon(const RenderSymbolLayer::Programs& programs,
|
||||
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
|
||||
const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || parameters.state.getPitch() != 0;
|
||||
|
||||
const gfx::TextureBinding textureBinding{tile.getIconAtlasTexture().getResource(),
|
||||
sdfIcons || parameters.state.isChanging() || iconScaled || iconTransformed
|
||||
? gfx::TextureFilterType::Linear
|
||||
: gfx::TextureFilterType::Nearest};
|
||||
const bool linear = sdfIcons || parameters.state.isChanging() || iconScaled || iconTransformed;
|
||||
const auto filterType = linear ? gfx::TextureFilterType::Linear : gfx::TextureFilterType::Nearest;
|
||||
const gfx::TextureBinding textureBinding = tile.getIconAtlasTextureBinding(filterType);
|
||||
|
||||
const Size& iconSize = tile.getIconAtlasTexture().size;
|
||||
const Size& iconSize = tile.getIconAtlasTexture()->getSize();
|
||||
const bool variablePlacedIcon = bucket.hasVariablePlacement && layout.get<IconTextFit>() != IconTextFitType::None;
|
||||
|
||||
if (sdfIcons) {
|
||||
@@ -211,9 +210,8 @@ void drawText(const RenderSymbolLayer::Programs& programs,
|
||||
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point &&
|
||||
layout.get<TextRotationAlignment>() == AlignmentType::Map;
|
||||
|
||||
const Size& glyphTexSize = tile.getGlyphAtlasTexture().size;
|
||||
const gfx::TextureBinding glyphTextureBinding{tile.getGlyphAtlasTexture().getResource(),
|
||||
gfx::TextureFilterType::Linear};
|
||||
const Size& glyphTexSize = tile.getGlyphAtlasTexture()->getSize();
|
||||
const gfx::TextureBinding glyphTextureBinding = tile.getGlyphAtlasTextureBinding(gfx::TextureFilterType::Linear);
|
||||
|
||||
const auto drawGlyphs = [&](auto& program, const auto& uniforms, const auto& textures, SymbolSDFPart part) {
|
||||
draw(program,
|
||||
@@ -231,12 +229,10 @@ void drawText(const RenderSymbolLayer::Programs& programs,
|
||||
const ZoomEvaluatedSize partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(
|
||||
static_cast<float>(parameters.state.getZoom()));
|
||||
const bool transformed = values.rotationAlignment == AlignmentType::Map || parameters.state.getPitch() != 0;
|
||||
const Size& iconTexSize = tile.getIconAtlasTexture().size;
|
||||
const gfx::TextureBinding iconTextureBinding{
|
||||
tile.getIconAtlasTexture().getResource(),
|
||||
parameters.state.isChanging() || transformed || !partiallyEvaluatedTextSize.isZoomConstant
|
||||
? gfx::TextureFilterType::Linear
|
||||
: gfx::TextureFilterType::Nearest};
|
||||
const Size& iconTexSize = tile.getIconAtlasTexture()->getSize();
|
||||
const bool linear = parameters.state.isChanging() || transformed || !partiallyEvaluatedTextSize.isZoomConstant;
|
||||
const auto filterType = linear ? gfx::TextureFilterType::Linear : gfx::TextureFilterType::Nearest;
|
||||
const gfx::TextureBinding iconTextureBinding = tile.getIconAtlasTextureBinding(filterType);
|
||||
if (values.hasHalo) {
|
||||
drawGlyphs(*programs.symbolTextAndIconProgram,
|
||||
SymbolTextAndIconProgram::layoutUniformValues(bucket.hasVariablePlacement,
|
||||
|
||||
@@ -87,16 +87,12 @@ Size PatternAtlas::getPixelSize() const {
|
||||
return {static_cast<uint32_t>(shelfPack.width()), static_cast<uint32_t>(shelfPack.height())};
|
||||
}
|
||||
|
||||
void PatternAtlas::upload(gfx::UploadPass& uploadPass) {
|
||||
// @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;
|
||||
// }
|
||||
|
||||
void PatternAtlas::upload([[maybe_unused]] gfx::UploadPass& uploadPass) {
|
||||
if (!atlasTexture2D) {
|
||||
atlasTexture2D = uploadPass.createTexture2D(atlasImage);
|
||||
atlasTexture2D = uploadPass.getContext().createTexture2D();
|
||||
atlasTexture2D->upload(atlasImage);
|
||||
} else if (dirty) {
|
||||
atlasTexture2D->upload(atlasImage, uploadPass);
|
||||
atlasTexture2D->upload(atlasImage);
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
|
||||
@@ -96,14 +96,32 @@ std::optional<ImagePosition> RenderTile::getPattern(const std::string& pattern)
|
||||
return renderData->getPattern(pattern);
|
||||
}
|
||||
|
||||
const gfx::Texture& RenderTile::getGlyphAtlasTexture() const {
|
||||
assert(renderData);
|
||||
return renderData->getGlyphAtlasTexture();
|
||||
static const gfx::Texture2DPtr noTexture;
|
||||
|
||||
bool RenderTile::hasGlyphAtlasTexture() const {
|
||||
return renderData && renderData->getGlyphAtlasTexture();
|
||||
}
|
||||
|
||||
const gfx::Texture& RenderTile::getIconAtlasTexture() const {
|
||||
assert(renderData);
|
||||
return renderData->getIconAtlasTexture();
|
||||
const gfx::Texture2DPtr& RenderTile::getGlyphAtlasTexture() const {
|
||||
return renderData ? renderData->getGlyphAtlasTexture() : noTexture;
|
||||
}
|
||||
|
||||
gfx::TextureBinding RenderTile::getGlyphAtlasTextureBinding(gfx::TextureFilterType filter) const {
|
||||
assert(renderData && renderData->getGlyphAtlasTexture());
|
||||
return {getGlyphAtlasTexture()->getResource(), filter};
|
||||
}
|
||||
|
||||
bool RenderTile::hasIconAtlasTexture() const {
|
||||
return renderData && renderData->getIconAtlasTexture();
|
||||
}
|
||||
|
||||
const gfx::Texture2DPtr& RenderTile::getIconAtlasTexture() const {
|
||||
return renderData ? renderData->getIconAtlasTexture() : noTexture;
|
||||
}
|
||||
|
||||
gfx::TextureBinding RenderTile::getIconAtlasTextureBinding(gfx::TextureFilterType filter) const {
|
||||
assert(renderData && renderData->getIconAtlasTexture());
|
||||
return {getIconAtlasTexture()->getResource(), filter};
|
||||
}
|
||||
|
||||
void RenderTile::upload(gfx::UploadPass& uploadPass) const {
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
class Texture2D;
|
||||
class UploadPass;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
} // namespace gfx
|
||||
|
||||
class Bucket;
|
||||
@@ -55,8 +57,14 @@ public:
|
||||
Bucket* getBucket(const style::Layer::Impl&) const;
|
||||
const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const;
|
||||
std::optional<ImagePosition> getPattern(const std::string& pattern) const;
|
||||
const gfx::Texture& getGlyphAtlasTexture() const;
|
||||
const gfx::Texture& getIconAtlasTexture() const;
|
||||
|
||||
bool hasGlyphAtlasTexture() const;
|
||||
const gfx::Texture2DPtr& getGlyphAtlasTexture() const;
|
||||
gfx::TextureBinding getGlyphAtlasTextureBinding(gfx::TextureFilterType) const;
|
||||
|
||||
bool hasIconAtlasTexture() const;
|
||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
||||
gfx::TextureBinding getIconAtlasTextureBinding(gfx::TextureFilterType) const;
|
||||
|
||||
void upload(gfx::UploadPass&) const;
|
||||
void prepare(const SourcePrepareParameters&);
|
||||
|
||||
@@ -130,7 +130,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
|
||||
renderTree.getPatternAtlas().upload(*uploadPass);
|
||||
|
||||
// Give the layers a chance to upload
|
||||
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.upload(context, *uploadPass); });
|
||||
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.upload(*uploadPass); });
|
||||
}
|
||||
|
||||
// - 3D PASS
|
||||
|
||||
@@ -9,16 +9,14 @@ TileRenderData::TileRenderData(std::shared_ptr<TileAtlasTextures> atlasTextures_
|
||||
|
||||
TileRenderData::~TileRenderData() = default;
|
||||
|
||||
const gfx::Texture& TileRenderData::getGlyphAtlasTexture() const {
|
||||
assert(atlasTextures);
|
||||
assert(atlasTextures->glyph);
|
||||
return *atlasTextures->glyph;
|
||||
static gfx::Texture2DPtr noTexture;
|
||||
|
||||
const gfx::Texture2DPtr& TileRenderData::getGlyphAtlasTexture() const {
|
||||
return atlasTextures ? atlasTextures->glyph : noTexture;
|
||||
}
|
||||
|
||||
const gfx::Texture& TileRenderData::getIconAtlasTexture() const {
|
||||
assert(atlasTextures);
|
||||
assert(atlasTextures->icon);
|
||||
return *atlasTextures->icon;
|
||||
const gfx::Texture2DPtr& TileRenderData::getIconAtlasTexture() const {
|
||||
return atlasTextures ? atlasTextures->icon : noTexture;
|
||||
}
|
||||
|
||||
std::optional<ImagePosition> TileRenderData::getPattern(const std::string&) const {
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
class Texture2D;
|
||||
class UploadPass;
|
||||
using Texture2DPtr = std::shared_ptr<gfx::Texture2D>;
|
||||
} // namespace gfx
|
||||
|
||||
class Bucket;
|
||||
@@ -19,15 +21,15 @@ class SourcePrepareParameters;
|
||||
|
||||
class TileAtlasTextures {
|
||||
public:
|
||||
std::optional<gfx::Texture> glyph;
|
||||
std::optional<gfx::Texture> icon;
|
||||
gfx::Texture2DPtr glyph;
|
||||
gfx::Texture2DPtr icon;
|
||||
};
|
||||
|
||||
class TileRenderData {
|
||||
public:
|
||||
virtual ~TileRenderData();
|
||||
const gfx::Texture& getGlyphAtlasTexture() const;
|
||||
const gfx::Texture& getIconAtlasTexture() const;
|
||||
const gfx::Texture2DPtr& getGlyphAtlasTexture() const;
|
||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
||||
// To be implemented for concrete tile types.
|
||||
virtual std::optional<ImagePosition> getPattern(const std::string&) const;
|
||||
virtual const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const;
|
||||
|
||||
@@ -87,21 +87,22 @@ void GeometryTileRenderData::upload(gfx::UploadPass& uploadPass) {
|
||||
assert(atlasTextures);
|
||||
|
||||
if (layoutResult->glyphAtlasImage) {
|
||||
atlasTextures->glyph = uploadPass.createTexture(*layoutResult->glyphAtlasImage);
|
||||
atlasTextures->glyph = uploadPass.getContext().createTexture2D();
|
||||
atlasTextures->glyph->upload(*layoutResult->glyphAtlasImage);
|
||||
layoutResult->glyphAtlasImage = {};
|
||||
}
|
||||
|
||||
if (layoutResult->iconAtlas.image.valid()) {
|
||||
atlasTextures->icon = uploadPass.createTexture(layoutResult->iconAtlas.image);
|
||||
atlasTextures->icon = uploadPass.getContext().createTexture2D();
|
||||
atlasTextures->icon->upload(layoutResult->iconAtlas.image);
|
||||
layoutResult->iconAtlas.image = {};
|
||||
}
|
||||
|
||||
if (atlasTextures->icon && !imagePatches.empty()) {
|
||||
for (const auto& imagePatch : imagePatches) { // patch updated images.
|
||||
uploadPass.updateTextureSub(*atlasTextures->icon,
|
||||
imagePatch.image->image,
|
||||
imagePatch.paddedRect.x + ImagePosition::padding,
|
||||
imagePatch.paddedRect.y + ImagePosition::padding);
|
||||
atlasTextures->icon->uploadSubRegion(imagePatch.image->image,
|
||||
imagePatch.paddedRect.x + ImagePosition::padding,
|
||||
imagePatch.paddedRect.y + ImagePosition::padding);
|
||||
}
|
||||
imagePatches.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user