diff options
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/context.cpp | 58 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 18 | ||||
-rw-r--r-- | src/mbgl/gl/texture.cpp | 54 | ||||
-rw-r--r-- | src/mbgl/gl/texture.hpp | 52 | ||||
-rw-r--r-- | src/mbgl/gl/texture_resource.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.hpp | 2 |
8 files changed, 137 insertions, 67 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 2758e236e4..ca06ab660d 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -3,6 +3,7 @@ #include <mbgl/gl/vertex_buffer_resource.hpp> #include <mbgl/gl/index_buffer_resource.hpp> #include <mbgl/gl/texture_resource.hpp> +#include <mbgl/gl/texture.hpp> #include <mbgl/gl/debugging_extension.hpp> #include <mbgl/gl/vertex_array_extension.hpp> #include <mbgl/gl/program_binary_extension.hpp> @@ -511,16 +512,15 @@ Context::createFramebuffer(const gfx::Texture& color, return { depthTarget.size, std::move(fbo) }; } -std::unique_ptr<const gfx::TextureResource> +std::unique_ptr<gfx::TextureResource> Context::createTextureResource(const Size size, const void* data, gfx::TexturePixelType format, - uint8_t unit, gfx::TextureChannelDataType type) { auto obj = createUniqueTexture(); - std::unique_ptr<const gfx::TextureResource> resource = std::make_unique<gl::TextureResource>(std::move(obj)); + std::unique_ptr<gfx::TextureResource> resource = std::make_unique<gl::TextureResource>(std::move(obj)); pixelStoreUnpack = { 1 }; - updateTextureResource(*resource, size, data, format, unit, type); + updateTextureResource(*resource, size, data, format, type); // 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)); @@ -534,60 +534,16 @@ void Context::updateTextureResource(const gfx::TextureResource& resource, const Size size, const void* data, gfx::TexturePixelType format, - uint8_t unit, gfx::TextureChannelDataType type) { - activeTextureUnit = unit; - texture[unit] = reinterpret_cast<const gl::TextureResource&>(resource).texture; + // Always use texture unit 0 for manipulating it. + activeTextureUnit = 0; + texture[0] = reinterpret_cast<const gl::TextureResource&>(resource).texture; MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, Enum<gfx::TexturePixelType>::to(format), size.width, size.height, 0, Enum<gfx::TexturePixelType>::to(format), Enum<gfx::TextureChannelDataType>::to(type), data)); } -void Context::bindTexture(gfx::Texture& obj, - uint8_t unit, - gfx::TextureFilterType filter, - gfx::TextureMipMapType mipmap, - gfx::TextureWrapType wrapX, - gfx::TextureWrapType wrapY) { - TextureID id = reinterpret_cast<const gl::TextureResource&>(*obj.resource).texture; - if (filter != obj.filter || mipmap != obj.mipmap || wrapX != obj.wrapX || wrapY != obj.wrapY) { - activeTextureUnit = unit; - texture[unit] = id; - - if (filter != obj.filter || mipmap != obj.mipmap) { - MBGL_CHECK_ERROR(glTexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - filter == gfx::TextureFilterType::Linear - ? (mipmap == gfx::TextureMipMapType::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR) - : (mipmap == gfx::TextureMipMapType::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST))); - MBGL_CHECK_ERROR( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - filter == gfx::TextureFilterType::Linear ? GL_LINEAR : GL_NEAREST)); - obj.filter = filter; - obj.mipmap = mipmap; - } - if (wrapX != obj.wrapX) { - - MBGL_CHECK_ERROR( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - wrapX == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - obj.wrapX = wrapX; - } - if (wrapY != obj.wrapY) { - MBGL_CHECK_ERROR( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - wrapY == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - obj.wrapY = wrapY; - } - } else if (texture[unit] != id) { - // We are checking first to avoid setting the active texture without a subsequent - // texture bind. - activeTextureUnit = unit; - texture[unit] = id; - } -} - void Context::reset() { std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures)); pooledTextures.resize(0); diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 1200e3b49a..51b79200ba 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -88,13 +88,6 @@ public: return { size, readFramebuffer(size, format, flip) }; } - void bindTexture(gfx::Texture&, - uint8_t unit = 0, - gfx::TextureFilterType = gfx::TextureFilterType::Nearest, - gfx::TextureMipMapType = gfx::TextureMipMapType::No, - gfx::TextureWrapType wrapX = gfx::TextureWrapType::Clamp, - gfx::TextureWrapType wrapY = gfx::TextureWrapType::Clamp) override; - #if not MBGL_USE_GLES2 template <typename Image> void drawPixels(const Image& image) { @@ -220,8 +213,8 @@ private: std::unique_ptr<const gfx::IndexBufferResource> createIndexBufferResource(const void* data, std::size_t size, const gfx::BufferUsageType) override; void updateIndexBufferResource(const gfx::IndexBufferResource&, const void* data, std::size_t size) override; - std::unique_ptr<const gfx::TextureResource> createTextureResource(Size, const void* data, gfx::TexturePixelType, uint8_t, gfx::TextureChannelDataType) override; - void updateTextureResource(const gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, uint8_t, gfx::TextureChannelDataType) override; + std::unique_ptr<gfx::TextureResource> createTextureResource(Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override; + void updateTextureResource(const gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override; UniqueFramebuffer createFramebuffer(); UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size); diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index 050ec6c268..ffa3e07391 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -8,6 +8,7 @@ #include <mbgl/gl/vertex_array.hpp> #include <mbgl/gl/attribute.hpp> #include <mbgl/gl/uniform.hpp> +#include <mbgl/gl/texture.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/logging.hpp> @@ -20,7 +21,7 @@ namespace mbgl { namespace gl { -template <class P, class As, class Us, class TBs> +template <class P, class As, class Us, class TextureList> class Program { public: using Primitive = P; @@ -29,7 +30,7 @@ public: using UniformValues = typename Uniforms::Values; using AttributeBindings = typename Attributes::Bindings; - using TextureBindings = TBs; + using TextureBindings = gfx::TextureBindings<TextureList>; Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource) : program( @@ -37,13 +38,15 @@ public: context.createShader(ShaderType::Fragment, fragmentSource))), uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))), attributeLocations(Attributes::bindLocations(context, program)) { - // Re-link program after manually binding only active attributes in Attributes::bindLocations context.linkProgram(program); // We have to re-initialize the uniforms state from the bindings as the uniform locations // get shifted on some implementations uniformsState = Uniforms::bindLocations(program); + + // Texture units are specified via uniforms as well, so we need query their locations + textures.queryLocations(program); } template <class BinaryProgram> @@ -51,6 +54,7 @@ public: : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), uniformsState(Uniforms::loadNamedLocations(binaryProgram)), attributeLocations(Attributes::loadNamedLocations(binaryProgram)) { + textures.loadNamedLocations(binaryProgram); } static Program createProgram(gl::Context& context, @@ -108,7 +112,8 @@ public: if (auto binaryProgram = context.getBinaryProgram(program)) { return BinaryProgram{ binaryProgram->first, std::move(binaryProgram->second), identifier, Attributes::getNamedLocations(attributeLocations), - Uniforms::getNamedLocations(uniformsState) }; + Uniforms::getNamedLocations(uniformsState), + textures.getNamedLocations() }; } return {}; } @@ -129,8 +134,6 @@ public: std::size_t indexLength) { static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode"); - (void)textureBindings; - context.setDrawMode(drawMode); context.setDepthMode(depthMode); context.setStencilMode(stencilMode); @@ -141,6 +144,8 @@ public: Uniforms::bind(uniformsState, uniformValues); + textures.bind(context, textureBindings); + vertexArray.bind(context, indexBuffer, Attributes::toBindingArray(attributeLocations, attributeBindings)); @@ -155,6 +160,7 @@ private: typename Uniforms::State uniformsState; typename Attributes::Locations attributeLocations; + gl::Textures<TextureList> textures; }; } // namespace gl diff --git a/src/mbgl/gl/texture.cpp b/src/mbgl/gl/texture.cpp new file mode 100644 index 0000000000..2b41e7ae8e --- /dev/null +++ b/src/mbgl/gl/texture.cpp @@ -0,0 +1,54 @@ +#include <mbgl/gl/texture.hpp> +#include <mbgl/gl/context.hpp> +#include <mbgl/gl/texture_resource.hpp> +#include <mbgl/gl/defines.hpp> + +namespace mbgl { +namespace gl { + +using namespace platform; + +void bindTexture(gl::Context& context, const uint8_t unit, const gfx::TextureBinding& binding) { + auto& resource = reinterpret_cast<gl::TextureResource&>(*binding.resource); + if (binding.filter != resource.filter || binding.mipmap != resource.mipmap || + binding.wrapX != resource.wrapX || binding.wrapY != resource.wrapY) { + context.activeTextureUnit = unit; + context.texture[unit] = resource.texture; + + if (binding.filter != resource.filter || binding.mipmap != resource.mipmap) { + MBGL_CHECK_ERROR(glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + binding.filter == gfx::TextureFilterType::Linear + ? (binding.mipmap == gfx::TextureMipMapType::Yes ? GL_LINEAR_MIPMAP_NEAREST + : GL_LINEAR) + : (binding.mipmap == gfx::TextureMipMapType::Yes ? GL_NEAREST_MIPMAP_NEAREST + : GL_NEAREST))); + MBGL_CHECK_ERROR(glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + binding.filter == gfx::TextureFilterType::Linear ? GL_LINEAR : GL_NEAREST)); + resource.filter = binding.filter; + resource.mipmap = binding.mipmap; + } + if (binding.wrapX != resource.wrapX) { + + MBGL_CHECK_ERROR(glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + binding.wrapX == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + resource.wrapX = binding.wrapX; + } + if (binding.wrapY != resource.wrapY) { + MBGL_CHECK_ERROR(glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + binding.wrapY == gfx::TextureWrapType::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + resource.wrapY = binding.wrapY; + } + } else if (context.texture[unit] != resource.texture) { + // We are checking first to avoid setting the active texture without a subsequent + // texture bind. + context.activeTextureUnit = unit; + context.texture[unit] = resource.texture; + } +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp new file mode 100644 index 0000000000..8230be1652 --- /dev/null +++ b/src/mbgl/gl/texture.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include <mbgl/gfx/texture.hpp> +#include <mbgl/gl/uniform.hpp> +#include <mbgl/util/ignore.hpp> + +#include <vector> +#include <string> + +namespace mbgl { +namespace gl { + +class Context; + +void bindTexture(gl::Context&, uint8_t unit, const gfx::TextureBinding&); + +template <class> +class Textures; + +template <class... Ts> +class Textures<TypeList<Ts...>> { + using State = + IndexedTuple<TypeList<Ts...>, TypeList<ExpandToType<Ts, gl::UniformState<uint8_t>>...>>; + using NamedLocations = std::vector<std::pair<const std::string, gl::UniformLocation>>; + +public: + void queryLocations(const ProgramID& id) { + state = State{ gl::uniformLocation(id, Ts::name())... }; + } + + template <class BinaryProgram> + void loadNamedLocations(const BinaryProgram& program) { + state = State{ program.textureLocation(Ts::name())... }; + } + + NamedLocations getNamedLocations() const { + return NamedLocations{ { Ts::name(), state.template get<Ts>().location }... }; + } + + void bind(gl::Context& context, const gfx::TextureBindings<TypeList<Ts...>>& bindings) { + util::ignore( + { (state.template get<Ts>() = TypeIndex<Ts, Ts...>::value, + gl::bindTexture(context, TypeIndex<Ts, Ts...>::value, bindings.template get<Ts>()), + 0)... }); + } + +private: + State state; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/texture_resource.hpp b/src/mbgl/gl/texture_resource.hpp index 4803f9b7f4..ed742e75b7 100644 --- a/src/mbgl/gl/texture_resource.hpp +++ b/src/mbgl/gl/texture_resource.hpp @@ -12,6 +12,10 @@ public: } UniqueTexture texture; + gfx::TextureFilterType filter = gfx::TextureFilterType::Nearest; + gfx::TextureMipMapType mipmap = gfx::TextureMipMapType::No; + gfx::TextureWrapType wrapX = gfx::TextureWrapType::Clamp; + gfx::TextureWrapType wrapY = gfx::TextureWrapType::Clamp; }; } // namespace gl diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp index 21017d6436..8d99d4b467 100644 --- a/src/mbgl/gl/uniform.cpp +++ b/src/mbgl/gl/uniform.cpp @@ -68,6 +68,11 @@ void bindUniform<uint32_t>(UniformLocation location, const uint32_t& t) { } template <> +void bindUniform<uint8_t>(UniformLocation location, const uint8_t& t) { + bindUniform(location, int32_t(t)); +} + +template <> void bindUniform<Color>(UniformLocation location, const Color& t) { bindUniform(location, std::array<float, 4> {{ t.r, t.g, t.b, t.a }}); } diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index c5aa2d6c39..3827015bb3 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -35,7 +35,7 @@ ActiveUniforms activeUniforms(ProgramID); template <class Value> class UniformState { public: - UniformState(UniformLocation location_) : location(std::move(location_)) { + UniformState(UniformLocation location_ = -1) : location(std::move(location_)) { } void operator=(const Value& value) { |