From 00de30d336896c6e461f0691c244cc711baa33cd Mon Sep 17 00:00:00 2001 From: Loki Date: Thu, 26 Aug 2021 23:59:32 +0200 Subject: [PATCH] Omit single copy of frame with VAAPI if possible --- sunshine/platform/linux/graphics.cpp | 32 +++++++++++++++++----------- sunshine/platform/linux/graphics.h | 5 ++++- sunshine/platform/linux/kmsgrab.cpp | 31 +++++++++++---------------- sunshine/platform/linux/vaapi.cpp | 9 +------- sunshine/platform/linux/wlgrab.cpp | 4 ++++ 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/sunshine/platform/linux/graphics.cpp b/sunshine/platform/linux/graphics.cpp index 0d122150..732b43ca 100644 --- a/sunshine/platform/linux/graphics.cpp +++ b/sunshine/platform/linux/graphics.cpp @@ -644,13 +644,19 @@ void sws_t::load_ram(platf::img_t &img) { gl::ctx.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, img.width, img.height, GL_BGRA, GL_UNSIGNED_BYTE, img.data); } -void sws_t::load_vram(cursor_t &img, int offset_x, int offset_y, int framebuffer) { - gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, framebuffer); - gl::ctx.ReadBuffer(GL_COLOR_ATTACHMENT0); - gl::ctx.BindTexture(GL_TEXTURE_2D, tex[0]); - gl::ctx.CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offset_x, offset_y, in_width, in_height); - +void sws_t::load_vram(cursor_t &img, int offset_x, int offset_y, int texture) { if(img.data) { + loaded_texture = tex[0]; + GLenum attachment = GL_COLOR_ATTACHMENT0; + + gl::ctx.BindTexture(GL_TEXTURE_2D, texture); + gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, cursor_framebuffer[0]); + gl::ctx.DrawBuffers(1, &attachment); + + gl::ctx.UseProgram(program[2].handle()); + gl::ctx.Viewport(offset_x, offset_y, in_width, in_height); + gl::ctx.DrawArrays(GL_TRIANGLES, 0, 3); + gl::ctx.BindTexture(GL_TEXTURE_2D, tex[1]); if(serial != img.serial) { serial = img.serial; @@ -660,8 +666,7 @@ void sws_t::load_vram(cursor_t &img, int offset_x, int offset_y, int framebuffer } gl::ctx.Enable(GL_BLEND); - GLenum attachment = GL_COLOR_ATTACHMENT0; - gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, cursor_framebuffer[0]); + gl::ctx.DrawBuffers(1, &attachment); #ifndef NDEBUG @@ -672,18 +677,21 @@ void sws_t::load_vram(cursor_t &img, int offset_x, int offset_y, int framebuffer } #endif - gl::ctx.UseProgram(program[2].handle()); gl::ctx.Viewport(img.x, img.y, img.width, img.height); gl::ctx.DrawArrays(GL_TRIANGLES, 0, 3); gl::ctx.Disable(GL_BLEND); - } - gl::ctx.BindTexture(GL_TEXTURE_2D, 0); + gl::ctx.BindTexture(GL_TEXTURE_2D, 0); + gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, 0); + } + else { + loaded_texture = texture; + } } int sws_t::convert(nv12_t &nv12) { - gl::ctx.BindTexture(GL_TEXTURE_2D, tex[0]); + gl::ctx.BindTexture(GL_TEXTURE_2D, loaded_texture); GLenum attachments[] { GL_COLOR_ATTACHMENT0, diff --git a/sunshine/platform/linux/graphics.h b/sunshine/platform/linux/graphics.h index 7e1ba805..98d55a50 100644 --- a/sunshine/platform/linux/graphics.h +++ b/sunshine/platform/linux/graphics.h @@ -265,7 +265,7 @@ public: int convert(nv12_t &nv12); void load_ram(platf::img_t &img); - void load_vram(cursor_t &img, int offset_x, int offset_y, int framebuffer); + void load_vram(cursor_t &img, int offset_x, int offset_y, int texture); void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range); @@ -284,6 +284,9 @@ public: int in_width, in_height; int offsetX, offsetY; + // Pointer to the texture to be converted to nv12 + int loaded_texture; + // Store latest cursor for load_vram std::uint64_t serial; }; diff --git a/sunshine/platform/linux/kmsgrab.cpp b/sunshine/platform/linux/kmsgrab.cpp index c059342b..f512bb2b 100644 --- a/sunshine/platform/linux/kmsgrab.cpp +++ b/sunshine/platform/linux/kmsgrab.cpp @@ -200,7 +200,7 @@ struct kms_img_t : public img_t { } }; -void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) { +void print(plane_t::pointer plane, fb2_t::pointer fb, crtc_t::pointer crtc) { if(crtc) { BOOST_LOG(debug) << "crtc("sv << crtc->x << ", "sv << crtc->y << ')'; BOOST_LOG(debug) << "crtc("sv << crtc->width << ", "sv << crtc->height << ')'; @@ -217,9 +217,8 @@ void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) { BOOST_LOG(debug) << "Resolution: "sv << fb->width << 'x' << fb->height - << ": Pitch: "sv << fb->pitch - << ": bpp: "sv << fb->bpp - << ": depth: "sv << fb->depth; + << ": Pitch: "sv << fb->pitches[0] + << ": Offset: "sv << fb->offsets[0]; std::stringstream ss; @@ -334,19 +333,19 @@ public: continue; } - auto fb = card.fb(plane.get()); + auto fb = card.fb2(plane.get()); if(!fb) { BOOST_LOG(error) << "Couldn't get drm fb for plane ["sv << plane->fb_id << "]: "sv << strerror(errno); return -1; } - if(!fb->handle) { + if(!fb->handles[0]) { BOOST_LOG(error) << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+ep sunshine]"sv; return -1; } - fb_fd = card.handleFD(fb->handle); + fb_fd = card.handleFD(fb->handles[0]); if(fb_fd.el < 0) { BOOST_LOG(error) << "Couldn't get primary file descriptor for Framebuffer ["sv << fb->fb_id << "]: "sv << strerror(errno); continue; @@ -363,7 +362,8 @@ public: width = crct->width; height = crct->height; - pitch = fb->pitch; + pitch = fb->pitches[0]; + offset = fb->offsets[0]; this->env_width = ::platf::kms::env_width; this->env_height = ::platf::kms::env_height; @@ -404,6 +404,7 @@ public: int img_width, img_height; int pitch; + int offset; card_t card; file_t fb_fd; @@ -566,7 +567,7 @@ public: img->img_width = img_width; img->img_height = img_height; img->fds[0] = fb_fd.el; - img->offsets[0] = 0; + img->offsets[0] = offset; img->strides[0] = pitch; return img; @@ -613,7 +614,7 @@ public: capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds /* timeout */, bool cursor) { if(!cursor || !cursor_opt) { img_out_base->data = nullptr; - return capture_e::ok; + return status; } auto img = (egl::cursor_t *)img_out_base; @@ -690,13 +691,13 @@ std::vector kms_display_names() { auto end = std::end(card); for(auto plane = std::begin(card); plane != end; ++plane) { - auto fb = card.fb(plane.get()); + auto fb = card.fb2(plane.get()); if(!fb) { BOOST_LOG(error) << "Couldn't get drm fb for plane ["sv << plane->fb_id << "]: "sv << strerror(errno); continue; } - if(!fb->handle) { + if(!fb->handles[0]) { BOOST_LOG(error) << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+ep sunshine]"sv; break; @@ -738,12 +739,6 @@ std::vector kms_display_names() { kms::env_width = std::max(kms::env_width, (int)(crtc->x + crtc->width)); kms::env_height = std::max(kms::env_height, (int)(crtc->y + crtc->height)); - auto fb_2 = card.fb2(plane.get()); - for(int x = 0; x < 4 && fb_2->handles[x]; ++x) { - BOOST_LOG(debug) << "handles::"sv << x << '(' << fb_2->handles[x] << ')'; - BOOST_LOG(debug) << "pixel_format::"sv << util::view(fb_2->pixel_format); - } - kms::print(plane.get(), fb.get(), crtc.get()); if(!cursor) { diff --git a/sunshine/platform/linux/vaapi.cpp b/sunshine/platform/linux/vaapi.cpp index d3fe74b1..a6b0a84b 100644 --- a/sunshine/platform/linux/vaapi.cpp +++ b/sunshine/platform/linux/vaapi.cpp @@ -417,8 +417,6 @@ public: if(descriptor.sequence > sequence) { sequence = descriptor.sequence; - framebuffer.bind(nullptr, nullptr); - auto rgb_opt = egl::import_source(display.get(), { descriptor.fds[0], @@ -433,11 +431,9 @@ public: } 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.load_vram(descriptor, offset_x, offset_y, rgb->tex[0]); sws.convert(nv12); return 0; @@ -448,8 +444,6 @@ public: return -1; } - framebuffer = gl::frame_buf_t::make(1); - sequence = 0; this->offset_x = offset_x; @@ -460,7 +454,6 @@ public: std::uint64_t sequence; egl::rgb_t rgb; - gl::frame_buf_t framebuffer; int offset_x, offset_y; }; diff --git a/sunshine/platform/linux/wlgrab.cpp b/sunshine/platform/linux/wlgrab.cpp index ae5f4815..1fee24a2 100644 --- a/sunshine/platform/linux/wlgrab.cpp +++ b/sunshine/platform/linux/wlgrab.cpp @@ -298,6 +298,10 @@ public: return std::make_shared(); } + int dummy_img(platf::img_t *img) override { + return snapshot(img, 1000ms, false) != platf::capture_e::ok; + } + std::uint64_t sequence {}; };