Skip to content

Commit

Permalink
Add the plumbing needed to enable bypass
Browse files Browse the repository at this point in the history
`drmModeAddFB2` returns -2, which is `ENOENT` for some reason...
  • Loading branch information
tarek-y-ismail committed Sep 13, 2024
1 parent 5e799d8 commit bf4dd70
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 7 deletions.
4 changes: 2 additions & 2 deletions include/platform/mir/graphics/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ class GBMDisplayAllocator : public DisplayAllocator
virtual auto make_surface(DRMFormat format, std::span<uint64_t> modifiers) -> std::unique_ptr<GBMSurface> = 0;
};

class DmaBufBuffer;
class DMABufBuffer;

class DmaBufDisplayAllocator : public DisplayAllocator
{
Expand All @@ -396,7 +396,7 @@ class DmaBufDisplayAllocator : public DisplayAllocator
{
};

virtual auto framebuffer_for(std::shared_ptr<DmaBufBuffer> buffer)
virtual auto framebuffer_for(std::shared_ptr<DMABufBuffer> buffer)
-> std::unique_ptr<Framebuffer> = 0;
};

Expand Down
86 changes: 85 additions & 1 deletion src/platforms/atomic-kms/server/kms/display_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <cstdint>
#include <drm_fourcc.h>

#include <memory>
#include <stdexcept>
#include <chrono>
#include <xf86drmMode.h>

namespace mg = mir::graphics;
namespace mga = mir::graphics::atomic;
Expand All @@ -56,7 +59,8 @@ mga::DisplaySink::DisplaySink(
std::vector<std::shared_ptr<KMSOutput>> const& outputs,
geom::Rectangle const& area,
glm::mat2 const& transformation)
: gbm{std::move(gbm)},
: DmaBufDisplayAllocator(drm_fd),
gbm{std::move(gbm)},
listener(listener),
outputs(outputs),
event_handler{std::move(event_handler)},
Expand Down Expand Up @@ -335,6 +339,78 @@ void mga::DisplaySink::set_next_image(std::unique_ptr<Framebuffer> content)
}
}

auto mga::DmaBufDisplayAllocator::framebuffer_for(std::shared_ptr<DMABufBuffer> buffer) -> std::unique_ptr<Framebuffer>
{
auto plane_descriptors = buffer->planes();

assert(plane_descriptors.size() <= 4);

auto width = buffer->size().width;
auto height = buffer->size().height;
auto pixel_format = buffer->format();

uint32_t bo_handles[4] = {0};
uint32_t pitches[4] = {0};
uint32_t offsets[4] = {0};

for (std::size_t i = 0; i < std::min(4zu, plane_descriptors.size()); i++)
{
bo_handles[i] = plane_descriptors[i].dma_buf;
pitches[i] = plane_descriptors[i].stride;
offsets[i] = plane_descriptors[i].offset;
}

auto fb_id = std::shared_ptr<uint32_t>{
new uint32_t{0},
[drm_fd = drm_fd()](uint32_t* fb_id)
{
if (*fb_id)
{
drmModeRmFB(drm_fd, *fb_id);
}
delete fb_id;
}};

int ret = drmModeAddFB2(
drm_fd(),
width.as_uint32_t(),
height.as_uint32_t(),
pixel_format,
bo_handles,
pitches,
offsets,
fb_id.get(),
0);

if (ret)
return {};

struct AtomicKmsFbHandle : public mg::FBHandle
{
AtomicKmsFbHandle(std::shared_ptr<uint32_t> fb_handle, geometry::Size size) :
kms_fb_id{fb_handle},
size_{size}
{
}

virtual auto size() const -> geometry::Size override
{
return size_;
}

virtual operator uint32_t() const override
{
return *kms_fb_id;
}

private:
std::shared_ptr<uint32_t> kms_fb_id;
geometry::Size size_;
};

return std::make_unique<AtomicKmsFbHandle>(fb_id, buffer->size());
}

auto mga::DisplaySink::maybe_create_allocator(DisplayAllocator::Tag const& type_tag)
-> DisplayAllocator*
{
Expand All @@ -354,5 +430,13 @@ auto mga::DisplaySink::maybe_create_allocator(DisplayAllocator::Tag const& type_
}
return gbm_allocator.get();
}
if(dynamic_cast<DmaBufDisplayAllocator::Tag const*>(&type_tag))
{
if (!bypass_allocator)
{
bypass_allocator = std::make_shared<DmaBufDisplayAllocator>(drm_fd());
}
return bypass_allocator.get();
}
return nullptr;
}
26 changes: 24 additions & 2 deletions src/platforms/atomic-kms/server/kms/display_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "platform_common.h"
#include "kms_framebuffer.h"

#include <boost/iostreams/detail/buffer.hpp>
#include <future>
#include <vector>
#include <memory>
Expand All @@ -50,8 +51,28 @@ namespace atomic
class Platform;
class KMSOutput;

class DisplaySink : public graphics::DisplaySink,
public graphics::DisplaySyncGroup
class DmaBufDisplayAllocator : public graphics::DmaBufDisplayAllocator
{
public:
DmaBufDisplayAllocator(mir::Fd drm_fd) : drm_fd_{drm_fd}
{
}

virtual auto framebuffer_for(std::shared_ptr<DMABufBuffer> buffer) -> std::unique_ptr<Framebuffer> override;

auto drm_fd() -> mir::Fd const
{
return drm_fd_;
}

private:
mir::Fd const drm_fd_;
};

class DisplaySink :
public graphics::DisplaySink,
public graphics::DisplaySyncGroup,
public DmaBufDisplayAllocator
{
public:
DisplaySink(
Expand Down Expand Up @@ -103,6 +124,7 @@ class DisplaySink : public graphics::DisplaySink,

std::shared_ptr<kms::DRMEventHandler> const event_handler;

std::shared_ptr<DmaBufDisplayAllocator> bypass_allocator;
std::shared_ptr<CPUAddressableDisplayAllocator> kms_allocator;
std::unique_ptr<GBMDisplayAllocator> gbm_allocator;

Expand Down
29 changes: 28 additions & 1 deletion src/platforms/gbm-kms/server/buffer_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <memory>
#include <optional>
#include <stdexcept>
#include <cassert>
Expand Down Expand Up @@ -552,9 +553,35 @@ auto mgg::GLRenderingProvider::surface_for_sink(
config);
}

auto mgg::GLRenderingProvider::make_framebuffer_provider(DisplaySink& /*sink*/)
auto mgg::GLRenderingProvider::make_framebuffer_provider(DisplaySink& sink)
-> std::unique_ptr<FramebufferProvider>
{
if(auto* allocator = sink.acquire_compatible_allocator<DmaBufDisplayAllocator>())
{
struct FooFramebufferProvider: public FramebufferProvider
{
public:
FooFramebufferProvider(DmaBufDisplayAllocator* allocator) : allocator{allocator}
{
}

auto buffer_to_framebuffer(std::shared_ptr<Buffer> buffer) -> std::unique_ptr<Framebuffer> override
{
if(auto dma_buf = std::dynamic_pointer_cast<mir::graphics::DMABufBuffer>(buffer))
{
return allocator->framebuffer_for(dma_buf);
}

return {};
}

private:
DmaBufDisplayAllocator* allocator;
};

return std::make_unique<FooFramebufferProvider>(allocator);
}

// TODO: Make this not a null implementation, so bypass/overlays can work again
class NullFramebufferProvider : public FramebufferProvider
{
Expand Down
7 changes: 7 additions & 0 deletions src/server/compositor/default_display_buffer_compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@
#include "mir/renderer/renderer.h"
#include "occlusion.h"

#define MIR_LOG_COMPONENT "compositor"
#include "mir/log.h"

namespace mc = mir::compositor;
namespace mg = mir::graphics;


mc::DefaultDisplayBufferCompositor::DefaultDisplayBufferCompositor(
mg::DisplaySink& display_sink,
graphics::GLRenderingProvider& gl_provider,
Expand Down Expand Up @@ -110,11 +114,14 @@ bool mc::DefaultDisplayBufferCompositor::composite(mc::SceneElementSequence&& sc

if (framebuffers.size() == renderable_list.size() && display_sink.overlay(framebuffers))
{
mir::log_debug("Bypass path\n");
report->renderables_in_frame(this, renderable_list);
renderer->suspend();
}
else
{
mir::log_debug("composite path\n");

renderer->set_output_transform(display_sink.transformation());
renderer->set_viewport(view_area);

Expand Down
2 changes: 1 addition & 1 deletion src/server/compositor/multi_threaded_compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class CompositingFunctor
void wait_until_stopped()
{
stop();
if (stopped_future.wait_for(10s) != std::future_status::ready)
if (stopped_future.wait_for(10h) != std::future_status::ready)
BOOST_THROW_EXCEPTION(std::runtime_error("Compositor thread failed to stop"));

stopped_future.get();
Expand Down

0 comments on commit bf4dd70

Please sign in to comment.