[core] add ability to upload alpha-only textures + images
This commit is contained in:
@@ -9,9 +9,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
enum ImageAlphaMode {
|
||||
enum class ImageAlphaMode {
|
||||
Unassociated,
|
||||
Premultiplied
|
||||
Premultiplied,
|
||||
Exclusive, // Alpha-channel only
|
||||
};
|
||||
|
||||
template <ImageAlphaMode Mode>
|
||||
@@ -47,15 +48,17 @@ public:
|
||||
return size && data.get() != nullptr;
|
||||
}
|
||||
|
||||
size_t stride() const { return static_cast<size_t>(size.width) * 4; }
|
||||
size_t stride() const { return channels * size.width; }
|
||||
size_t bytes() const { return stride() * size.height; }
|
||||
|
||||
Size size;
|
||||
static constexpr size_t channels = Mode == ImageAlphaMode::Exclusive ? 1 : 4;
|
||||
std::unique_ptr<uint8_t[]> data;
|
||||
};
|
||||
|
||||
using UnassociatedImage = Image<ImageAlphaMode::Unassociated>;
|
||||
using PremultipliedImage = Image<ImageAlphaMode::Premultiplied>;
|
||||
using AlphaImage = Image<ImageAlphaMode::Exclusive>;
|
||||
|
||||
// TODO: don't use std::string for binary data.
|
||||
PremultipliedImage decodeImage(const std::string&);
|
||||
|
||||
@@ -26,6 +26,10 @@ static_assert(std::is_same<VertexArrayID, GLuint>::value, "OpenGL type mismatch"
|
||||
static_assert(std::is_same<FramebufferID, GLuint>::value, "OpenGL type mismatch");
|
||||
static_assert(std::is_same<RenderbufferID, GLuint>::value, "OpenGL type mismatch");
|
||||
|
||||
static_assert(std::is_same<std::underlying_type_t<TextureFormat>, GLenum>::value, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch");
|
||||
|
||||
Context::~Context() {
|
||||
reset();
|
||||
}
|
||||
@@ -183,9 +187,9 @@ Framebuffer Context::createFramebuffer(const Texture& color) {
|
||||
}
|
||||
|
||||
UniqueTexture
|
||||
Context::createTexture(const Size size, const void* data, TextureUnit unit) {
|
||||
Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit) {
|
||||
auto obj = createTexture();
|
||||
updateTexture(obj, size, data, unit);
|
||||
updateTexture(obj, size, data, format, unit);
|
||||
// We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
|
||||
// We use those when the pixelRatio isn't a power of two, e.g. on iPhone 6 Plus.
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
@@ -195,11 +199,13 @@ Context::createTexture(const Size size, const void* data, TextureUnit unit) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
void Context::updateTexture(TextureID id, const Size size, const void* data, TextureUnit unit) {
|
||||
void Context::updateTexture(
|
||||
TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit) {
|
||||
activeTexture = unit;
|
||||
texture[unit] = id;
|
||||
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, data));
|
||||
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLenum>(format), size.width,
|
||||
size.height, 0, static_cast<GLenum>(format), GL_UNSIGNED_BYTE,
|
||||
data));
|
||||
}
|
||||
|
||||
void Context::bindTexture(Texture& obj,
|
||||
|
||||
@@ -65,18 +65,22 @@ public:
|
||||
// Create a texture from an image with data.
|
||||
template <typename Image>
|
||||
Texture createTexture(const Image& image, TextureUnit unit = 0) {
|
||||
return { image.size, createTexture(image.size, image.data.get(), unit) };
|
||||
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
|
||||
return { image.size, createTexture(image.size, image.data.get(), format, unit) };
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void updateTexture(Texture& obj, const Image& image, TextureUnit unit = 0) {
|
||||
updateTexture(obj.texture.get(), image.size, image.data.get(), unit);
|
||||
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
|
||||
updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit);
|
||||
obj.size = image.size;
|
||||
}
|
||||
|
||||
// Creates an empty texture with the specified dimensions.
|
||||
Texture createTexture(const Size size, TextureUnit unit = 0) {
|
||||
return { size, createTexture(size, nullptr, unit) };
|
||||
Texture createTexture(const Size size,
|
||||
TextureFormat format = TextureFormat::RGBA,
|
||||
TextureUnit unit = 0) {
|
||||
return { size, createTexture(size, nullptr, format, unit) };
|
||||
}
|
||||
|
||||
void bindTexture(Texture&,
|
||||
@@ -153,8 +157,8 @@ private:
|
||||
|
||||
UniqueBuffer createVertexBuffer(const void* data, std::size_t size);
|
||||
UniqueBuffer createIndexBuffer(const void* data, std::size_t size);
|
||||
UniqueTexture createTexture(Size size, const void* data, TextureUnit);
|
||||
void updateTexture(TextureID, Size size, const void* data, TextureUnit);
|
||||
UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit);
|
||||
void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
|
||||
UniqueFramebuffer createFramebuffer();
|
||||
UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ enum class RenderbufferType : uint32_t {
|
||||
|
||||
enum class TextureMipMap : bool { No = false, Yes = true };
|
||||
enum class TextureFilter : bool { Nearest = false, Linear = true };
|
||||
enum class TextureFormat : uint32_t {
|
||||
RGBA = 0x1908,
|
||||
Alpha = 0x1906,
|
||||
};
|
||||
|
||||
enum class PrimitiveType {
|
||||
Points = 0x0000,
|
||||
|
||||
Reference in New Issue
Block a user