[core] add gfx::Renderable and gfx::OffscreenTexture

This commit is contained in:
Konstantin Käfer
2019-04-01 13:48:20 +02:00
parent ebd8508032
commit 865f8a6c03
17 changed files with 260 additions and 164 deletions

View File

@@ -0,0 +1,44 @@
#pragma once
#include <mbgl/util/size.hpp>
#include <memory>
#include <cassert>
namespace mbgl {
namespace gfx {
class RenderableResource {
protected:
explicit RenderableResource() = default;
public:
virtual ~RenderableResource() = default;
RenderableResource(const RenderableResource&) = delete;
RenderableResource& operator=(const RenderableResource&) = delete;
};
class Renderable {
protected:
Renderable(const Size size_, std::unique_ptr<RenderableResource> resource_)
: size(size_), resource(std::move(resource_)) {
}
public:
Size getSize() const {
return size;
}
template <typename T>
T& getResource() const {
assert(resource);
return static_cast<T&>(*resource);
}
protected:
Size size;
std::unique_ptr<RenderableResource> resource;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -0,0 +1,17 @@
#pragma once
#include <mbgl/gfx/renderable.hpp>
namespace mbgl {
namespace gl {
class RenderableResource : public gfx::RenderableResource {
protected:
explicit RenderableResource() = default;
public:
virtual void bind() = 0;
};
} // namespace gl
} // namespace mbgl

View File

@@ -24,6 +24,7 @@
"src/mbgl/gl/debugging_extension.cpp",
"src/mbgl/gl/enum.cpp",
"src/mbgl/gl/object.cpp",
"src/mbgl/gl/offscreen_texture.cpp",
"src/mbgl/gl/texture.cpp",
"src/mbgl/gl/uniform.cpp",
"src/mbgl/gl/value.cpp",
@@ -299,7 +300,6 @@
"src/mbgl/util/mat2.cpp",
"src/mbgl/util/mat3.cpp",
"src/mbgl/util/mat4.cpp",
"src/mbgl/util/offscreen_texture.cpp",
"src/mbgl/util/premultiply.cpp",
"src/mbgl/util/rapidjson.cpp",
"src/mbgl/util/stopwatch.cpp",
@@ -321,6 +321,8 @@
"mbgl/actor/message.hpp": "include/mbgl/actor/message.hpp",
"mbgl/actor/scheduler.hpp": "include/mbgl/actor/scheduler.hpp",
"mbgl/annotation/annotation.hpp": "include/mbgl/annotation/annotation.hpp",
"mbgl/gfx/renderable.hpp": "include/mbgl/gfx/renderable.hpp",
"mbgl/gl/renderable_resource.hpp": "include/mbgl/gl/renderable_resource.hpp",
"mbgl/layermanager/background_layer_factory.hpp": "include/mbgl/layermanager/background_layer_factory.hpp",
"mbgl/layermanager/circle_layer_factory.hpp": "include/mbgl/layermanager/circle_layer_factory.hpp",
"mbgl/layermanager/custom_layer_factory.hpp": "include/mbgl/layermanager/custom_layer_factory.hpp",
@@ -520,6 +522,7 @@
"mbgl/gfx/draw_scope.hpp": "src/mbgl/gfx/draw_scope.hpp",
"mbgl/gfx/index_buffer.hpp": "src/mbgl/gfx/index_buffer.hpp",
"mbgl/gfx/index_vector.hpp": "src/mbgl/gfx/index_vector.hpp",
"mbgl/gfx/offscreen_texture.hpp": "src/mbgl/gfx/offscreen_texture.hpp",
"mbgl/gfx/program.hpp": "src/mbgl/gfx/program.hpp",
"mbgl/gfx/renderbuffer.hpp": "src/mbgl/gfx/renderbuffer.hpp",
"mbgl/gfx/stencil_mode.hpp": "src/mbgl/gfx/stencil_mode.hpp",
@@ -541,6 +544,7 @@
"mbgl/gl/framebuffer.hpp": "src/mbgl/gl/framebuffer.hpp",
"mbgl/gl/index_buffer_resource.hpp": "src/mbgl/gl/index_buffer_resource.hpp",
"mbgl/gl/object.hpp": "src/mbgl/gl/object.hpp",
"mbgl/gl/offscreen_texture.hpp": "src/mbgl/gl/offscreen_texture.hpp",
"mbgl/gl/program.hpp": "src/mbgl/gl/program.hpp",
"mbgl/gl/program_binary_extension.hpp": "src/mbgl/gl/program_binary_extension.hpp",
"mbgl/gl/renderbuffer_resource.hpp": "src/mbgl/gl/renderbuffer_resource.hpp",
@@ -757,7 +761,6 @@
"mbgl/util/mat3.hpp": "src/mbgl/util/mat3.hpp",
"mbgl/util/mat4.hpp": "src/mbgl/util/mat4.hpp",
"mbgl/util/math.hpp": "src/mbgl/util/math.hpp",
"mbgl/util/offscreen_texture.hpp": "src/mbgl/util/offscreen_texture.hpp",
"mbgl/util/rapidjson.hpp": "src/mbgl/util/rapidjson.hpp",
"mbgl/util/rect.hpp": "src/mbgl/util/rect.hpp",
"mbgl/util/std.hpp": "src/mbgl/util/std.hpp",

View File

@@ -17,6 +17,8 @@ class ProgramParameters;
namespace gfx {
class OffscreenTexture;
class Context {
protected:
Context(ContextType type_, uint32_t maximumVertexBindingCount_)
@@ -123,6 +125,14 @@ protected:
virtual void updateTextureResourceSub(TextureResource&, uint16_t xOffset, uint16_t yOffset, Size, const void* data,
TexturePixelType, TextureChannelDataType) = 0;
public:
virtual std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(
Size, gfx::TextureChannelDataType = gfx::TextureChannelDataType::UnsignedByte) = 0;
virtual std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(
Size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>&,
gfx::TextureChannelDataType = gfx::TextureChannelDataType::UnsignedByte) = 0;
public:
template <RenderbufferPixelType pixelType>
Renderbuffer<pixelType>

View File

@@ -0,0 +1,25 @@
#pragma once
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/util/image.hpp>
namespace mbgl {
namespace gfx {
class Texture;
class OffscreenTexture : public gfx::Renderable {
protected:
OffscreenTexture(const Size size_, std::unique_ptr<RenderableResource> resource_)
: gfx::Renderable(size_, std::move(resource_)) {
}
public:
virtual ~OffscreenTexture() = default;
virtual PremultipliedImage readStillImage() = 0;
virtual gfx::Texture& getTexture() = 0;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -6,6 +6,7 @@
#include <mbgl/gl/renderbuffer_resource.hpp>
#include <mbgl/gl/draw_scope_resource.hpp>
#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/offscreen_texture.hpp>
#include <mbgl/gl/command_encoder.hpp>
#include <mbgl/gl/debugging_extension.hpp>
#include <mbgl/gl/vertex_array_extension.hpp>
@@ -553,6 +554,17 @@ void Context::updateTextureResourceSub(gfx::TextureResource& resource,
Enum<gfx::TextureChannelDataType>::to(type), data));
}
std::unique_ptr<gfx::OffscreenTexture>
Context::createOffscreenTexture(const Size size, const gfx::TextureChannelDataType type) {
return std::make_unique<gl::OffscreenTexture>(*this, size, type);
}
std::unique_ptr<gfx::OffscreenTexture>
Context::createOffscreenTexture(const Size size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& depth,
gfx::TextureChannelDataType type) {
return std::make_unique<gl::OffscreenTexture>(*this, size, depth, type);
}
std::unique_ptr<gfx::DrawScopeResource> Context::createDrawScopeResource() {
return std::make_unique<gl::DrawScopeResource>(createVertexArray());

View File

@@ -201,6 +201,13 @@ private:
void updateTextureResource(gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
void updateTextureResourceSub(gfx::TextureResource&, const uint16_t xOffset, const uint16_t yOffset, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(
Size, gfx::TextureChannelDataType = gfx::TextureChannelDataType::UnsignedByte) override;
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(
Size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>&,
gfx::TextureChannelDataType = gfx::TextureChannelDataType::UnsignedByte) override;
std::unique_ptr<gfx::RenderbufferResource> createRenderbufferResource(gfx::RenderbufferPixelType, Size size) override;
std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override;

View File

@@ -0,0 +1,87 @@
#include <mbgl/gl/offscreen_texture.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/framebuffer.hpp>
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());
}
OffscreenTextureResource(gl::Context& context_,
const Size size_,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& depth_,
const gfx::TextureChannelDataType type_)
: context(context_), size(size_), depth(&depth_), type(type_) {
assert(!size.isEmpty());
}
void bind() override {
if (!framebuffer) {
texture = context.createTexture(size, gfx::TexturePixelType::RGBA, type);
if (depth) {
framebuffer = context.createFramebuffer(*texture, *depth);
} else {
framebuffer = context.createFramebuffer(*texture);
}
} else {
context.bindFramebuffer = framebuffer->framebuffer;
}
context.activeTextureUnit = 0;
context.scissorTest = false;
context.viewport = { 0, 0, size };
}
PremultipliedImage readStillImage() {
assert(framebuffer);
context.bindFramebuffer = framebuffer->framebuffer;
return context.readFramebuffer<PremultipliedImage>(size);
}
gfx::Texture& getTexture() {
assert(texture);
return *texture;
}
private:
gl::Context& context;
const Size size;
optional<gfx::Texture> texture;
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>* depth = nullptr;
const gfx::TextureChannelDataType type;
optional<gl::Framebuffer> framebuffer;
};
OffscreenTexture::OffscreenTexture(gl::Context& context,
const Size size_,
const gfx::TextureChannelDataType type)
: gfx::OffscreenTexture(size, std::make_unique<OffscreenTextureResource>(context, size_, type)) {
}
OffscreenTexture::OffscreenTexture(
gl::Context& context,
const Size size_,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& renderbuffer,
const gfx::TextureChannelDataType type)
: gfx::OffscreenTexture(
size, std::make_unique<OffscreenTextureResource>(context, size_, renderbuffer, type)) {
}
PremultipliedImage OffscreenTexture::readStillImage() {
return getResource<OffscreenTextureResource>().readStillImage();
}
gfx::Texture& OffscreenTexture::getTexture() {
return getResource<OffscreenTextureResource>().getTexture();
}
} // namespace gl
} // namespace mbgl

View File

@@ -0,0 +1,26 @@
#pragma once
#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/gfx/renderbuffer.hpp>
namespace mbgl {
namespace gl {
class Context;
class OffscreenTexture final : public gfx::OffscreenTexture {
public:
OffscreenTexture(gl::Context&,
Size size,
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
OffscreenTexture(gl::Context&,
Size size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>&,
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
PremultipliedImage readStillImage() override;
gfx::Texture& getTexture() override;
};
} // namespace gl
} // namespace mbgl

View File

@@ -15,6 +15,7 @@
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
namespace mbgl {
@@ -62,10 +63,11 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
const auto& size = parameters.staticData.backendSize;
if (!renderTexture || renderTexture->getSize() != size) {
renderTexture = OffscreenTexture(parameters.context, size, *parameters.staticData.depthRenderbuffer);
renderTexture.reset();
renderTexture = parameters.context.createOffscreenTexture(size, *parameters.staticData.depthRenderbuffer);
}
renderTexture->bind();
renderTexture->getResource<gl::RenderableResource>().bind();
optional<float> depthClearValue = {};
if (parameters.staticData.depthRenderbuffer->needsClearing()) depthClearValue = 1.0;

View File

@@ -3,8 +3,7 @@
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/offscreen_texture.hpp>
#include <mbgl/gfx/offscreen_texture.hpp>
namespace mbgl {
@@ -41,7 +40,7 @@ public:
const style::FillExtrusionLayer::Impl& impl() const;
optional<OffscreenTexture> renderTexture;
std::unique_ptr<gfx::OffscreenTexture> renderTexture;
private:
CrossfadeParameters crossfade;
};

View File

@@ -11,6 +11,7 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
@@ -57,27 +58,27 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto size = Size{viewportSize.width / 4, viewportSize.height / 4};
if (!renderTexture || renderTexture->getSize() != size) {
renderTexture.reset();
if (parameters.context.supportsHalfFloatTextures) {
renderTexture = OffscreenTexture(parameters.context, size, gfx::TextureChannelDataType::HalfFloat);
renderTexture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::HalfFloat);
// TODO: try binding in the offscreen texture constructor
try {
renderTexture->bind();
renderTexture->getResource<gl::RenderableResource>().bind();
} catch (const std::runtime_error& ex) {
// can't render to a half-float texture; falling back to unsigned byte one
renderTexture = nullopt;
renderTexture.reset();
parameters.context.supportsHalfFloatTextures = false;
}
}
if (!parameters.context.supportsHalfFloatTextures || !renderTexture) {
renderTexture = OffscreenTexture(parameters.context, size, gfx::TextureChannelDataType::UnsignedByte);
renderTexture->bind();
if (!renderTexture) {
renderTexture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::UnsignedByte);
}
} else {
renderTexture->bind();
}
renderTexture->getResource<gl::RenderableResource>().bind();
if (!colorRampTexture) {
colorRampTexture = parameters.context.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte);
}

View File

@@ -4,8 +4,8 @@
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
#include <mbgl/gfx/texture.hpp>
#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/offscreen_texture.hpp>
namespace mbgl {
@@ -36,7 +36,7 @@ public:
const style::HeatmapLayer::Impl& impl() const;
PremultipliedImage colorRamp;
optional<OffscreenTexture> renderTexture;
std::unique_ptr<gfx::OffscreenTexture> renderTexture;
optional<gfx::Texture> colorRampTexture;
private:

View File

@@ -10,8 +10,9 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/offscreen_texture.hpp>
namespace mbgl {
@@ -130,8 +131,8 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
assert(bucket.dem);
const uint16_t stride = bucket.getDEMData().stride;
const uint16_t tilesize = bucket.getDEMData().dim;
OffscreenTexture view(parameters.context, { tilesize, tilesize });
view.bind();
auto view = parameters.context.createOffscreenTexture({ tilesize, tilesize });
view->getResource<gl::RenderableResource>().bind();
const Properties<>::PossiblyEvaluated properties;
const HillshadePrepareProgram::Binders paintAttributeData{ properties, 0 };
@@ -173,7 +174,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
},
getID()
);
bucket.texture = std::move(view.getTexture());
bucket.texture = std::move(view->getTexture());
bucket.setPrepared(true);
} else if (parameters.pass == RenderPass::Translucent) {
assert(bucket.texture);

View File

@@ -1,100 +0,0 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/util/offscreen_texture.hpp>
#include <cassert>
#include <cstring>
namespace mbgl {
OffscreenTexture::OffscreenTexture(OffscreenTexture&&) = default;
OffscreenTexture& OffscreenTexture::operator=(OffscreenTexture&&) = default;
class OffscreenTexture::Impl {
public:
Impl(gl::Context& context_, const Size size_, const gfx::TextureChannelDataType type_)
: context(context_), size(std::move(size_)), type(type_) {
assert(!size.isEmpty());
}
Impl(gl::Context& context_,
const Size size_,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& depth_,
const gfx::TextureChannelDataType type_)
: context(context_), size(std::move(size_)), depth(&depth_), type(type_) {
assert(!size.isEmpty());
}
void bind() {
if (!framebuffer) {
texture = context.createTexture(size, gfx::TexturePixelType::RGBA, type);
if (depth) {
framebuffer = context.createFramebuffer(*texture, *depth);
} else {
framebuffer = context.createFramebuffer(*texture);
}
} else {
context.bindFramebuffer = framebuffer->framebuffer;
}
context.activeTextureUnit = 0;
context.scissorTest = false;
context.viewport = { 0, 0, size };
}
PremultipliedImage readStillImage() {
return context.readFramebuffer<PremultipliedImage>(size);
}
gfx::Texture& getTexture() {
assert(texture);
return *texture;
}
const Size& getSize() const {
return size;
}
private:
gl::Context& context;
const Size size;
optional<gl::Framebuffer> framebuffer;
optional<gfx::Texture> texture;
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>* depth = nullptr;
const gfx::TextureChannelDataType type;
};
OffscreenTexture::OffscreenTexture(gfx::Context& context,
const Size size,
const gfx::TextureChannelDataType type)
// TODO: remove cast
: impl(std::make_unique<Impl>(static_cast<gl::Context&>(context), std::move(size), type)) {
assert(!size.isEmpty());
}
OffscreenTexture::OffscreenTexture(gfx::Context& context,
const Size size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& renderbuffer,
const gfx::TextureChannelDataType type)
// TODO: remove cast
: impl(std::make_unique<Impl>(static_cast<gl::Context&>(context), std::move(size), renderbuffer, type)) {
assert(!size.isEmpty());
}
OffscreenTexture::~OffscreenTexture() = default;
void OffscreenTexture::bind() {
impl->bind();
}
PremultipliedImage OffscreenTexture::readStillImage() {
return impl->readStillImage();
}
gfx::Texture& OffscreenTexture::getTexture() {
return impl->getTexture();
}
const Size& OffscreenTexture::getSize() const {
return impl->getSize();
}
} // namespace mbgl

View File

@@ -1,39 +0,0 @@
#pragma once
#include <mbgl/gfx/renderbuffer.hpp>
#include <mbgl/util/image.hpp>
namespace mbgl {
namespace gfx {
class Context;
class Texture;
} // namespace gfx
class OffscreenTexture {
public:
OffscreenTexture(gfx::Context&,
Size size = { 256, 256 },
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
OffscreenTexture(gfx::Context&,
Size size,
gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>&,
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
~OffscreenTexture();
OffscreenTexture(OffscreenTexture&&);
OffscreenTexture& operator=(OffscreenTexture&&);
void bind();
PremultipliedImage readStillImage();
gfx::Texture& getTexture();
const Size& getSize() const;
private:
class Impl;
std::unique_ptr<Impl> impl;
};
} // namespace mbgl

View File

@@ -4,10 +4,11 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/gl/offscreen_texture.hpp>
#include <mbgl/util/offscreen_texture.hpp>
using namespace mbgl;
using namespace mbgl::platform;
@@ -132,13 +133,13 @@ void main() {
// Then, create a texture, bind it, and render yellow to that texture. This should not
// affect the originally bound FBO.
OffscreenTexture texture(context, { 128, 128 });
gl::OffscreenTexture texture(context, { 128, 128 });
// Scissor test shouldn't leak after OffscreenTexture::bind().
MBGL_CHECK_ERROR(glScissor(32, 32, 64, 64));
context.scissorTest.setCurrentValue(true);
texture.bind();
texture.getResource<gl::RenderableResource>().bind();
context.clear(Color(), {}, {});