Drawable Renderer (#1570), Texture2D storage allocation fixes, async image transfer
This commit is contained in:
@@ -50,6 +50,10 @@ public:
|
||||
/// @return this
|
||||
virtual Texture2D& setSize(Size size_) noexcept = 0;
|
||||
|
||||
/// @brief Sets the internal image
|
||||
/// @param image_ Image data to transfer
|
||||
virtual Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept = 0;
|
||||
|
||||
/// @brief Get the size of the texture
|
||||
/// @return Size of the texture
|
||||
virtual Size getSize() const noexcept = 0;
|
||||
@@ -68,6 +72,7 @@ public:
|
||||
virtual size_t numChannels() const noexcept = 0;
|
||||
|
||||
/// @brief Create the texture with default initialized memory.
|
||||
/// @note Be sure to configure a valid size and format.
|
||||
virtual void create() noexcept = 0;
|
||||
|
||||
/// @brief Upload image data to the texture resource
|
||||
@@ -93,10 +98,17 @@ public:
|
||||
uploadSubRegion(&img.data[0], img.size, xOffset, yOffset);
|
||||
}
|
||||
|
||||
/// @brief Upload staged image data if present and required.
|
||||
/// @see needsUpload
|
||||
virtual void upload() 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;
|
||||
|
||||
/// @brief Check whether the texture needs upload
|
||||
virtual bool needsUpload() const noexcept = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -24,6 +24,8 @@ public: // gfx::Texture2D
|
||||
|
||||
Texture2D& setSize(Size size_) noexcept override;
|
||||
|
||||
Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept override;
|
||||
|
||||
Size getSize() const noexcept override { return size; }
|
||||
|
||||
size_t getDataSize() const noexcept override;
|
||||
@@ -36,12 +38,15 @@ public: // gfx::Texture2D
|
||||
|
||||
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;
|
||||
void upload() noexcept override;
|
||||
|
||||
gfx::TextureResource& getResource() override {
|
||||
assert(textureResource);
|
||||
return *textureResource;
|
||||
}
|
||||
|
||||
bool needsUpload() const noexcept override { return !!image; };
|
||||
|
||||
public:
|
||||
/// @brief Get the OpenGL handle ID for the underlying resource
|
||||
/// @return GLuint
|
||||
@@ -58,14 +63,19 @@ public:
|
||||
/// @brief Unbind the texture, if it was bound
|
||||
void unbind() noexcept;
|
||||
|
||||
private:
|
||||
void createObject() noexcept;
|
||||
void createStorage(const void* data = nullptr) noexcept;
|
||||
|
||||
private:
|
||||
gl::Context& context;
|
||||
std::unique_ptr<gfx::TextureResource> textureResource{nullptr};
|
||||
|
||||
SamplerState samplerState{};
|
||||
gfx::TexturePixelType pixelFormat;
|
||||
gfx::TextureChannelDataType channelType;
|
||||
gfx::TexturePixelType pixelFormat{gfx::TexturePixelType::RGBA};
|
||||
gfx::TextureChannelDataType channelType{gfx::TextureChannelDataType::UnsignedByte};
|
||||
|
||||
std::shared_ptr<PremultipliedImage> image{nullptr};
|
||||
Size size{0, 0};
|
||||
bool samplerStateDirty{false};
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ Texture2D& Texture2D::setSize(mbgl::Size size_) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Texture2D& Texture2D::setImage(std::shared_ptr<PremultipliedImage> image_) noexcept {
|
||||
image = std::move(image_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t Texture2D::getDataSize() const noexcept {
|
||||
return size.width * size.height * getPixelStride();
|
||||
}
|
||||
@@ -64,9 +69,9 @@ size_t Texture2D::numChannels() const noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::create() noexcept {
|
||||
void Texture2D::createObject() noexcept {
|
||||
// Create a new texture object
|
||||
assert(!textureResource);
|
||||
|
||||
auto obj = context.createUniqueTexture();
|
||||
const auto storageSize = gl::TextureResource::getStorageSize(size, pixelFormat, channelType);
|
||||
context.renderingStats().memTextures += storageSize;
|
||||
@@ -75,6 +80,32 @@ void Texture2D::create() noexcept {
|
||||
textureResource = std::make_unique<gl::TextureResource>(std::move(obj), storageSize);
|
||||
}
|
||||
|
||||
void Texture2D::createStorage(const void* data) noexcept {
|
||||
assert(textureResource);
|
||||
|
||||
// Create backing storage for our texture object
|
||||
using namespace platform;
|
||||
|
||||
// Bind to TU 0 and upload
|
||||
context.activeTextureUnit = 0;
|
||||
context.texture[0] = getTextureID();
|
||||
updateSamplerConfiguration();
|
||||
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),
|
||||
data));
|
||||
}
|
||||
|
||||
void Texture2D::create() noexcept {
|
||||
createObject();
|
||||
createStorage();
|
||||
}
|
||||
|
||||
platform::GLuint Texture2D::getTextureID() const noexcept {
|
||||
return static_cast<gl::TextureResource&>(*textureResource).texture;
|
||||
}
|
||||
@@ -139,28 +170,18 @@ void Texture2D::unbind() noexcept {
|
||||
|
||||
void Texture2D::upload(const void* pixelData, const Size& size_) noexcept {
|
||||
using namespace platform;
|
||||
if (!textureResource) {
|
||||
create();
|
||||
}
|
||||
assert(textureResource);
|
||||
|
||||
// Bind to TU 0 and upload
|
||||
context.activeTextureUnit = 0;
|
||||
context.texture[0] = getTextureID();
|
||||
updateSamplerConfiguration();
|
||||
if (!textureResource || size_ == Size{0, 0} || size_ != size) {
|
||||
// Create the texture object if we don't already have one
|
||||
if (!textureResource) {
|
||||
createObject();
|
||||
}
|
||||
|
||||
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));
|
||||
createStorage(pixelData);
|
||||
|
||||
} else {
|
||||
// Upload to existing memory
|
||||
uploadSubRegion(pixelData, size, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +195,6 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
|
||||
// Bind to TU 0 and upload
|
||||
context.activeTextureUnit = 0;
|
||||
context.texture[0] = getTextureID();
|
||||
|
||||
MBGL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
xOffset,
|
||||
@@ -186,5 +206,14 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
|
||||
pixelData));
|
||||
}
|
||||
|
||||
void Texture2D::upload() noexcept {
|
||||
if (image && image->valid()) {
|
||||
setFormat(gfx::TexturePixelType::RGBA,
|
||||
gfx::TextureChannelDataType::UnsignedByte);
|
||||
upload(&(*image).data[0], image->size);
|
||||
image.reset();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user