#include #include #include #include namespace mbgl { namespace gl { class OffscreenTextureResource final : public gl::RenderableResource { public: OffscreenTextureResource(gl::Context& context_, const Size size_, const gfx::TextureChannelDataType type_) : context(context_), size(size_), type(type_) { assert(!size.isEmpty()); texture = context.createTexture2D(); texture->setSize(size); texture->setFormat(gfx::TexturePixelType::RGBA, type); texture->setSamplerConfiguration({.filter = gfx::TextureFilterType::Linear, .wrapU = gfx::TextureWrapType::Clamp, .wrapV = gfx::TextureWrapType::Clamp}); } ~OffscreenTextureResource() noexcept override = default; void bind() override { if (!framebuffer) { assert(texture); texture->create(); framebuffer = context.createFramebuffer(*texture); } else { context.bindFramebuffer = framebuffer->framebuffer; } context.activeTextureUnit = 0; context.scissorTest = false; context.viewport = {.x = 0, .y = 0, .size = size}; } PremultipliedImage readStillImage() { assert(framebuffer); context.bindFramebuffer = framebuffer->framebuffer; return context.readFramebuffer(size); } gfx::Texture2DPtr& getTexture() { assert(texture); return texture; } private: gl::Context& context; const Size size; gfx::Texture2DPtr texture; const gfx::TextureChannelDataType type; std::optional framebuffer; }; OffscreenTexture::OffscreenTexture(gl::Context& context, const Size size_, const gfx::TextureChannelDataType type) : gfx::OffscreenTexture(size, std::make_unique(context, size_, type)) {} bool OffscreenTexture::isRenderable() { try { getResource().bind(); return true; } catch (const std::runtime_error&) { return false; } } PremultipliedImage OffscreenTexture::readStillImage() { return getResource().readStillImage(); } const gfx::Texture2DPtr& OffscreenTexture::getTexture() { return getResource().getTexture(); } } // namespace gl } // namespace mbgl