From 358701f475b2c04c4681d70435bc76370b371285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Wed, 26 Oct 2016 17:19:19 -0700 Subject: [PATCH] [core] add ability to upload alpha-only textures + images --- include/mbgl/util/image.hpp | 9 ++++++--- src/mbgl/gl/context.cpp | 16 +++++++++++----- src/mbgl/gl/context.hpp | 16 ++++++++++------ src/mbgl/gl/types.hpp | 4 ++++ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index 3dbab27f4..1d84d4824 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -9,9 +9,10 @@ namespace mbgl { -enum ImageAlphaMode { +enum class ImageAlphaMode { Unassociated, - Premultiplied + Premultiplied, + Exclusive, // Alpha-channel only }; template @@ -47,15 +48,17 @@ public: return size && data.get() != nullptr; } - size_t stride() const { return static_cast(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 data; }; using UnassociatedImage = Image; using PremultipliedImage = Image; +using AlphaImage = Image; // TODO: don't use std::string for binary data. PremultipliedImage decodeImage(const std::string&); diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 7200b7505..41f02b636 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -26,6 +26,10 @@ static_assert(std::is_same::value, "OpenGL type mismatch" static_assert(std::is_same::value, "OpenGL type mismatch"); static_assert(std::is_same::value, "OpenGL type mismatch"); +static_assert(std::is_same, 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(format), size.width, + size.height, 0, static_cast(format), GL_UNSIGNED_BYTE, + data)); } void Context::bindTexture(Texture& obj, diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index ae2b71994..4e9320f7d 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -65,18 +65,22 @@ public: // Create a texture from an image with data. template 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 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); diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index 9a1eb365d..10cf0a973 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -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,