[core] add gfx::Renderable and gfx::OffscreenTexture
This commit is contained in:
44
include/mbgl/gfx/renderable.hpp
Normal file
44
include/mbgl/gfx/renderable.hpp
Normal 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
|
||||
17
include/mbgl/gl/renderable_resource.hpp
Normal file
17
include/mbgl/gl/renderable_resource.hpp
Normal 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
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
25
src/mbgl/gfx/offscreen_texture.hpp
Normal file
25
src/mbgl/gfx/offscreen_texture.hpp
Normal 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
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
87
src/mbgl/gl/offscreen_texture.cpp
Normal file
87
src/mbgl/gl/offscreen_texture.cpp
Normal 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
|
||||
26
src/mbgl/gl/offscreen_texture.hpp
Normal file
26
src/mbgl/gl/offscreen_texture.hpp
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(), {}, {});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user