Keep image on vram if at all possible with wlroots based compositors
This commit is contained in:
@@ -50,6 +50,17 @@ public:
|
|||||||
|
|
||||||
static frame_buf_t make(std::size_t count);
|
static frame_buf_t make(std::size_t count);
|
||||||
|
|
||||||
|
inline void bind(std::nullptr_t, std::nullptr_t) {
|
||||||
|
int x = 0;
|
||||||
|
for(auto fb : (*this)) {
|
||||||
|
ctx.BindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||||
|
ctx.FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + x, 0, 0);
|
||||||
|
|
||||||
|
++x;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
void bind(It it_begin, It it_end) {
|
void bind(It it_begin, It it_end) {
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
@@ -230,6 +241,22 @@ public:
|
|||||||
std::vector<std::uint8_t> buffer;
|
std::vector<std::uint8_t> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Allow cursor and the underlying image to be kept together
|
||||||
|
class img_descriptor_t : public cursor_t {
|
||||||
|
public:
|
||||||
|
std::uint32_t format;
|
||||||
|
std::uint32_t img_width, img_height;
|
||||||
|
std::uint32_t obj_count;
|
||||||
|
std::uint32_t strides[4];
|
||||||
|
// std::uint32_t sizes[4];
|
||||||
|
std::int32_t fds[4];
|
||||||
|
std::uint32_t offsets[4];
|
||||||
|
// std::uint32_t plane_indices[4];
|
||||||
|
|
||||||
|
// Increment sequence when new rgb_t needs to be created
|
||||||
|
std::uint64_t sequence;
|
||||||
|
};
|
||||||
|
|
||||||
class sws_t {
|
class sws_t {
|
||||||
public:
|
public:
|
||||||
static std::optional<sws_t> make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex);
|
static std::optional<sws_t> make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex);
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the framebuffer is reinitialized, this id can no longer be found
|
// Keep track of what framebuffer we're using.
|
||||||
std::uint32_t framebuffer_index;
|
std::uint32_t framebuffer_index;
|
||||||
|
|
||||||
capture_e status;
|
capture_e status;
|
||||||
@@ -500,7 +500,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
||||||
if(mem_type == mem_type_e::vaapi) {
|
if(mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_hwdevice(width, height);
|
return va::make_hwdevice(width, height, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<hwdevice_t>();
|
return std::make_shared<hwdevice_t>();
|
||||||
@@ -546,14 +546,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
||||||
if(mem_type == mem_type_e::vaapi) {
|
if(mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_hwdevice(width, height, dup(card.fd.el), offset_x, offset_y,
|
return va::make_hwdevice(width, height, dup(card.fd.el), offset_x, offset_y, true);
|
||||||
{
|
|
||||||
fb_fd.el,
|
|
||||||
img_width,
|
|
||||||
img_height,
|
|
||||||
0,
|
|
||||||
pitch,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG(error) << "Unsupported pixel format for egl::display_vram_t: "sv << platf::from_pix_fmt(pix_fmt);
|
BOOST_LOG(error) << "Unsupported pixel format for egl::display_vram_t: "sv << platf::from_pix_fmt(pix_fmt);
|
||||||
@@ -561,12 +554,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<img_t> alloc_img() override {
|
std::shared_ptr<img_t> alloc_img() override {
|
||||||
auto img = std::make_shared<egl::cursor_t>();
|
auto img = std::make_shared<egl::img_descriptor_t>();
|
||||||
|
|
||||||
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
||||||
img->data = nullptr;
|
img->data = nullptr;
|
||||||
img->pixel_pitch = 4;
|
img->pixel_pitch = 4;
|
||||||
|
|
||||||
|
img->sequence = 1;
|
||||||
|
|
||||||
|
img->obj_count = 1;
|
||||||
|
img->img_width = img_width;
|
||||||
|
img->img_height = img_height;
|
||||||
|
img->fds[0] = fb_fd.el;
|
||||||
|
img->offsets[0] = 0;
|
||||||
|
img->strides[0] = pitch;
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -412,26 +412,45 @@ public:
|
|||||||
class va_vram_t : public va_t {
|
class va_vram_t : public va_t {
|
||||||
public:
|
public:
|
||||||
int convert(platf::img_t &img) override {
|
int convert(platf::img_t &img) override {
|
||||||
sws.load_vram((egl::cursor_t &)img, offset_x, offset_y, framebuffer[0]);
|
auto &descriptor = (egl::img_descriptor_t &)img;
|
||||||
|
|
||||||
|
if(descriptor.sequence > sequence) {
|
||||||
|
sequence = descriptor.sequence;
|
||||||
|
|
||||||
|
framebuffer.bind(nullptr, nullptr);
|
||||||
|
|
||||||
|
auto rgb_opt = egl::import_source(display.get(),
|
||||||
|
{
|
||||||
|
descriptor.fds[0],
|
||||||
|
(int)descriptor.img_width,
|
||||||
|
(int)descriptor.img_height,
|
||||||
|
(int)descriptor.offsets[0],
|
||||||
|
(int)descriptor.strides[0],
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!rgb_opt) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = std::move(*rgb_opt);
|
||||||
|
|
||||||
|
framebuffer.bind(std::begin(rgb->tex), std::end(rgb->tex));
|
||||||
|
}
|
||||||
|
|
||||||
|
sws.load_vram(descriptor, offset_x, offset_y, framebuffer[0]);
|
||||||
|
|
||||||
sws.convert(nv12);
|
sws.convert(nv12);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init(int in_width, int in_height, file_t &&render_device, int offset_x, int offset_y, const egl::surface_descriptor_t &sd) {
|
int init(int in_width, int in_height, file_t &&render_device, int offset_x, int offset_y) {
|
||||||
if(va_t::init(in_width, in_height, std::move(render_device))) {
|
if(va_t::init(in_width, in_height, std::move(render_device))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rgb_opt = egl::import_source(display.get(), sd);
|
|
||||||
if(!rgb_opt) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rgb = std::move(*rgb_opt);
|
|
||||||
|
|
||||||
framebuffer = gl::frame_buf_t::make(1);
|
framebuffer = gl::frame_buf_t::make(1);
|
||||||
framebuffer.bind(std::begin(rgb->tex), std::end(rgb->tex));
|
|
||||||
|
sequence = 0;
|
||||||
|
|
||||||
this->offset_x = offset_x;
|
this->offset_x = offset_x;
|
||||||
this->offset_y = offset_y;
|
this->offset_y = offset_y;
|
||||||
@@ -439,8 +458,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_t fb_fd;
|
std::uint64_t sequence;
|
||||||
|
|
||||||
egl::rgb_t rgb;
|
egl::rgb_t rgb;
|
||||||
gl::frame_buf_t framebuffer;
|
gl::frame_buf_t framebuffer;
|
||||||
|
|
||||||
@@ -607,7 +625,27 @@ bool validate(int fd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height) {
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram) {
|
||||||
|
if(vram) {
|
||||||
|
auto egl = std::make_shared<va::va_vram_t>();
|
||||||
|
if(egl->init(width, height, std::move(card), offset_x, offset_y)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return egl;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
auto egl = std::make_shared<va::va_ram_t>();
|
||||||
|
if(egl->init(width, height, std::move(card))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return egl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram) {
|
||||||
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
|
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
|
||||||
|
|
||||||
file_t file = open(render_device, O_RDWR);
|
file_t file = open(render_device, O_RDWR);
|
||||||
@@ -618,20 +656,10 @@ std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto egl = std::make_shared<va::va_ram_t>();
|
return make_hwdevice(width, height, std::move(file), offset_x, offset_y, vram);
|
||||||
if(egl->init(width, height, std::move(file))) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return egl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, const egl::surface_descriptor_t &sd) {
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram) {
|
||||||
auto egl = std::make_shared<va::va_vram_t>();
|
return make_hwdevice(width, height, 0, 0, vram);
|
||||||
if(egl->init(width, height, std::move(card), offset_x, offset_y, sd)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return egl;
|
|
||||||
}
|
}
|
||||||
} // namespace va
|
} // namespace va
|
||||||
@@ -8,10 +8,18 @@ namespace egl {
|
|||||||
struct surface_descriptor_t;
|
struct surface_descriptor_t;
|
||||||
}
|
}
|
||||||
namespace va {
|
namespace va {
|
||||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height);
|
/**
|
||||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, const egl::surface_descriptor_t &sd);
|
* Width --> Width of the image
|
||||||
|
* Height --> Height of the image
|
||||||
|
* offset_x --> Horizontal offset of the image in the texture
|
||||||
|
* offset_y --> Vertical offset of the image in the texture
|
||||||
|
* file_t card --> The file descriptor of the render device used for encoding
|
||||||
|
*/
|
||||||
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram);
|
||||||
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram);
|
||||||
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram);
|
||||||
|
|
||||||
// Ensure the render device pointed to by fd is capable of encoding h264
|
// Ensure the render device pointed to by fd is capable of encoding h264 with the hevc_mode configured
|
||||||
bool validate(int fd);
|
bool validate(int fd);
|
||||||
|
|
||||||
int init();
|
int init();
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ void interface_t::del_interface(wl_registry *registry, uint32_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dmabuf_t::dmabuf_t()
|
dmabuf_t::dmabuf_t()
|
||||||
: status { REINIT }, frames {}, current_frame { &frames[0] }, listener {
|
: status { READY }, frames {}, current_frame { &frames[0] }, listener {
|
||||||
(decltype(zwlr_export_dmabuf_frame_v1_listener::frame))&dmabuf_t::frame,
|
(decltype(zwlr_export_dmabuf_frame_v1_listener::frame))&dmabuf_t::frame,
|
||||||
(decltype(zwlr_export_dmabuf_frame_v1_listener::object))&dmabuf_t::object,
|
(decltype(zwlr_export_dmabuf_frame_v1_listener::object))&dmabuf_t::object,
|
||||||
(decltype(zwlr_export_dmabuf_frame_v1_listener::ready))&dmabuf_t::ready,
|
(decltype(zwlr_export_dmabuf_frame_v1_listener::ready))&dmabuf_t::ready,
|
||||||
@@ -141,26 +141,6 @@ dmabuf_t::dmabuf_t()
|
|||||||
} {
|
} {
|
||||||
}
|
}
|
||||||
|
|
||||||
int dmabuf_t::init(wl_display *display_p) {
|
|
||||||
display = egl::make_display(display_p);
|
|
||||||
|
|
||||||
if(!display) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ctx_opt = egl::make_ctx(display.get());
|
|
||||||
|
|
||||||
if(!ctx_opt) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = std::move(*ctx_opt);
|
|
||||||
|
|
||||||
status = READY;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dmabuf_t::listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor) {
|
void dmabuf_t::listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor) {
|
||||||
auto frame = zwlr_export_dmabuf_manager_v1_capture_output(dmabuf_manager, blend_cursor, output);
|
auto frame = zwlr_export_dmabuf_manager_v1_capture_output(dmabuf_manager, blend_cursor, output);
|
||||||
zwlr_export_dmabuf_frame_v1_add_listener(frame, &listener, this);
|
zwlr_export_dmabuf_frame_v1_add_listener(frame, &listener, this);
|
||||||
@@ -211,27 +191,9 @@ void dmabuf_t::object(
|
|||||||
void dmabuf_t::ready(
|
void dmabuf_t::ready(
|
||||||
zwlr_export_dmabuf_frame_v1 *frame,
|
zwlr_export_dmabuf_frame_v1 *frame,
|
||||||
std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec) {
|
std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec) {
|
||||||
auto next_frame = get_next_frame();
|
|
||||||
|
|
||||||
auto rgb_opt = egl::import_source(display.get(),
|
|
||||||
{
|
|
||||||
next_frame->fds[0],
|
|
||||||
(int)next_frame->width,
|
|
||||||
(int)next_frame->height,
|
|
||||||
(int)next_frame->offsets[0],
|
|
||||||
(int)next_frame->strides[0],
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!rgb_opt) {
|
|
||||||
status = REINIT;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_frame->rgb = std::move(*rgb_opt);
|
|
||||||
|
|
||||||
current_frame->destroy();
|
current_frame->destroy();
|
||||||
current_frame = next_frame;
|
current_frame = get_next_frame();
|
||||||
|
|
||||||
status = READY;
|
status = READY;
|
||||||
}
|
}
|
||||||
@@ -254,8 +216,6 @@ void frame_t::destroy() {
|
|||||||
close(fds[x]);
|
close(fds[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb = egl::rgb_t {};
|
|
||||||
|
|
||||||
frame = nullptr;
|
frame = nullptr;
|
||||||
obj_count = 0;
|
obj_count = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ public:
|
|||||||
std::uint32_t offsets[4];
|
std::uint32_t offsets[4];
|
||||||
std::uint32_t plane_indices[4];
|
std::uint32_t plane_indices[4];
|
||||||
|
|
||||||
egl::rgb_t rgb;
|
|
||||||
|
|
||||||
zwlr_export_dmabuf_frame_v1 *frame;
|
zwlr_export_dmabuf_frame_v1 *frame;
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
@@ -45,7 +43,6 @@ public:
|
|||||||
|
|
||||||
dmabuf_t();
|
dmabuf_t();
|
||||||
|
|
||||||
int init(wl_display *display);
|
|
||||||
void listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor = false);
|
void listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor = false);
|
||||||
|
|
||||||
~dmabuf_t();
|
~dmabuf_t();
|
||||||
@@ -82,9 +79,6 @@ public:
|
|||||||
|
|
||||||
status_e status;
|
status_e status;
|
||||||
|
|
||||||
egl::display_t display;
|
|
||||||
egl::ctx_t ctx;
|
|
||||||
|
|
||||||
std::array<frame_t, 2> frames;
|
std::array<frame_t, 2> frames;
|
||||||
frame_t *current_frame;
|
frame_t *current_frame;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
delay = std::chrono::nanoseconds { 1s } / framerate;
|
delay = std::chrono::nanoseconds { 1s } / framerate;
|
||||||
mem_type = hwdevice_type;
|
mem_type = hwdevice_type;
|
||||||
|
|
||||||
if(display.init() || dmabuf.init(display.get())) {
|
if(display.init()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +72,48 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dummy_img(platf::img_t *img) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
|
||||||
|
auto to = std::chrono::steady_clock::now() + timeout;
|
||||||
|
|
||||||
|
dmabuf.listen(interface.dmabuf_manager, output, cursor);
|
||||||
|
do {
|
||||||
|
display.roundtrip();
|
||||||
|
|
||||||
|
if(to < std::chrono::steady_clock::now()) {
|
||||||
|
return platf::capture_e::timeout;
|
||||||
|
}
|
||||||
|
} while(dmabuf.status == dmabuf_t::WAITING);
|
||||||
|
|
||||||
|
auto current_frame = dmabuf.current_frame;
|
||||||
|
|
||||||
|
if(
|
||||||
|
dmabuf.status == dmabuf_t::REINIT ||
|
||||||
|
current_frame->width != width ||
|
||||||
|
current_frame->height != height) {
|
||||||
|
|
||||||
|
return platf::capture_e::reinit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return platf::capture_e::ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
platf::mem_type_e mem_type;
|
||||||
|
|
||||||
|
std::chrono::nanoseconds delay;
|
||||||
|
|
||||||
|
wl::display_t display;
|
||||||
|
interface_t interface;
|
||||||
|
dmabuf_t dmabuf;
|
||||||
|
|
||||||
|
wl_output *output;
|
||||||
|
};
|
||||||
|
|
||||||
|
class wlr_ram_t : public wlr_t {
|
||||||
|
public:
|
||||||
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
|
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
|
||||||
auto next_frame = std::chrono::steady_clock::now();
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
@@ -106,36 +148,61 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
|
platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
|
||||||
auto to = std::chrono::steady_clock::now() + timeout;
|
auto status = wlr_t::snapshot(img_out_base, timeout, cursor);
|
||||||
|
if(status != platf::capture_e::ok) {
|
||||||
dmabuf.listen(interface.dmabuf_manager, output, cursor);
|
return status;
|
||||||
do {
|
}
|
||||||
display.roundtrip();
|
|
||||||
|
|
||||||
if(to < std::chrono::steady_clock::now()) {
|
|
||||||
return platf::capture_e::timeout;
|
|
||||||
}
|
|
||||||
} while(dmabuf.status == dmabuf_t::WAITING);
|
|
||||||
|
|
||||||
auto current_frame = dmabuf.current_frame;
|
auto current_frame = dmabuf.current_frame;
|
||||||
|
|
||||||
if(
|
auto rgb_opt = egl::import_source(egl_display.get(),
|
||||||
dmabuf.status == dmabuf_t::REINIT ||
|
{
|
||||||
current_frame->width != width ||
|
current_frame->fds[0],
|
||||||
current_frame->height != height) {
|
(int)current_frame->width,
|
||||||
|
(int)current_frame->height,
|
||||||
|
(int)current_frame->offsets[0],
|
||||||
|
(int)current_frame->strides[0],
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!rgb_opt) {
|
||||||
return platf::capture_e::reinit;
|
return platf::capture_e::reinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &rgb = current_frame->rgb;
|
gl::ctx.BindTexture(GL_TEXTURE_2D, (*rgb_opt)->tex[0]);
|
||||||
|
gl::ctx.GetTextureSubImage((*rgb_opt)->tex[0], 0, 0, 0, 0, width, height, 1, GL_BGRA, GL_UNSIGNED_BYTE, img_out_base->height * img_out_base->row_pitch, img_out_base->data);
|
||||||
gl::ctx.BindTexture(GL_TEXTURE_2D, rgb->tex[0]);
|
|
||||||
gl::ctx.GetTextureSubImage(rgb->tex[0], 0, 0, 0, 0, width, height, 1, GL_BGRA, GL_UNSIGNED_BYTE, img_out_base->height * img_out_base->row_pitch, img_out_base->data);
|
|
||||||
gl::ctx.BindTexture(GL_TEXTURE_2D, 0);
|
gl::ctx.BindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
return platf::capture_e::ok;
|
return platf::capture_e::ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int init(platf::mem_type_e hwdevice_type, const std::string &display_name, int framerate) {
|
||||||
|
if(wlr_t::init(hwdevice_type, display_name, framerate)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_display = egl::make_display(display.get());
|
||||||
|
if(!egl_display) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ctx_opt = egl::make_ctx(egl_display.get());
|
||||||
|
if(!ctx_opt) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = std::move(*ctx_opt);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override {
|
||||||
|
if(mem_type == platf::mem_type_e::vaapi) {
|
||||||
|
return va::make_hwdevice(width, height, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<platf::hwdevice_t>();
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<platf::img_t> alloc_img() override {
|
std::shared_ptr<platf::img_t> alloc_img() override {
|
||||||
auto img = std::make_shared<img_t>();
|
auto img = std::make_shared<img_t>();
|
||||||
img->width = width;
|
img->width = width;
|
||||||
@@ -147,27 +214,91 @@ public:
|
|||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dummy_img(platf::img_t *img) override {
|
egl::display_t egl_display;
|
||||||
return 0;
|
egl::ctx_t ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
class wlr_vram_t : public wlr_t {
|
||||||
|
public:
|
||||||
|
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
|
||||||
|
auto next_frame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
while(img) {
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
if(next_frame > now) {
|
||||||
|
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
|
||||||
|
}
|
||||||
|
while(next_frame > now) {
|
||||||
|
now = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
next_frame = now + delay;
|
||||||
|
|
||||||
|
auto status = snapshot(img.get(), 1000ms, *cursor);
|
||||||
|
switch(status) {
|
||||||
|
case platf::capture_e::reinit:
|
||||||
|
case platf::capture_e::error:
|
||||||
|
return status;
|
||||||
|
case platf::capture_e::timeout:
|
||||||
|
continue;
|
||||||
|
case platf::capture_e::ok:
|
||||||
|
img = snapshot_cb(img);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']';
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return platf::capture_e::ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
|
||||||
|
auto status = wlr_t::snapshot(img_out_base, timeout, cursor);
|
||||||
|
if(status != platf::capture_e::ok) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto img = (egl::img_descriptor_t *)img_out_base;
|
||||||
|
|
||||||
|
auto current_frame = dmabuf.current_frame;
|
||||||
|
|
||||||
|
++sequence;
|
||||||
|
img->sequence = sequence;
|
||||||
|
|
||||||
|
img->obj_count = 1;
|
||||||
|
img->img_width = current_frame->width;
|
||||||
|
img->img_height = current_frame->height;
|
||||||
|
img->obj_count = current_frame->obj_count;
|
||||||
|
|
||||||
|
std::copy_n(std::begin(current_frame->fds), current_frame->obj_count, img->fds);
|
||||||
|
std::copy_n(std::begin(current_frame->offsets), current_frame->obj_count, img->offsets);
|
||||||
|
std::copy_n(std::begin(current_frame->strides), current_frame->obj_count, img->strides);
|
||||||
|
|
||||||
|
return platf::capture_e::ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<platf::img_t> alloc_img() override {
|
||||||
|
auto img = std::make_shared<egl::img_descriptor_t>();
|
||||||
|
|
||||||
|
img->img_width = width;
|
||||||
|
img->img_height = height;
|
||||||
|
img->sequence = 0;
|
||||||
|
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
||||||
|
img->data = nullptr;
|
||||||
|
|
||||||
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override {
|
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override {
|
||||||
if(mem_type == platf::mem_type_e::vaapi) {
|
if(mem_type == platf::mem_type_e::vaapi) {
|
||||||
return va::make_hwdevice(width, height);
|
return va::make_hwdevice(width, height, 0, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<platf::hwdevice_t>();
|
return std::make_shared<platf::hwdevice_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
platf::mem_type_e mem_type;
|
std::uint64_t sequence {};
|
||||||
|
|
||||||
std::chrono::nanoseconds delay;
|
|
||||||
|
|
||||||
wl::display_t display;
|
|
||||||
interface_t interface;
|
|
||||||
dmabuf_t dmabuf;
|
|
||||||
|
|
||||||
wl_output *output;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wl
|
} // namespace wl
|
||||||
@@ -179,7 +310,16 @@ std::shared_ptr<display_t> wl_display(mem_type_e hwdevice_type, const std::strin
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto wlr = std::make_shared<wl::wlr_t>();
|
if(hwdevice_type == platf::mem_type_e::vaapi) {
|
||||||
|
auto wlr = std::make_shared<wl::wlr_vram_t>();
|
||||||
|
if(wlr->init(hwdevice_type, display_name, framerate)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wlr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wlr = std::make_shared<wl::wlr_ram_t>();
|
||||||
if(wlr->init(hwdevice_type, display_name, framerate)) {
|
if(wlr->init(hwdevice_type, display_name, framerate)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ struct x11_attr_t : public display_t {
|
|||||||
|
|
||||||
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override {
|
||||||
if(mem_type == mem_type_e::vaapi) {
|
if(mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_hwdevice(width, height);
|
return va::make_hwdevice(width, height, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<hwdevice_t>();
|
return std::make_shared<hwdevice_t>();
|
||||||
|
|||||||
Reference in New Issue
Block a user