diff --git a/sunshine/platform/linux/graphics.cpp b/sunshine/platform/linux/graphics.cpp index 0dd53f0c..a0b8d3af 100644 --- a/sunshine/platform/linux/graphics.cpp +++ b/sunshine/platform/linux/graphics.cpp @@ -69,6 +69,13 @@ frame_buf_t frame_buf_t::make(std::size_t count) { return frame_buf; } +void frame_buf_t::copy(int id, int texture, int offset_x, int offset_y, int width, int height) { + gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, (*this)[id]); + gl::ctx.ReadBuffer(GL_COLOR_ATTACHMENT0 + id); + gl::ctx.BindTexture(GL_TEXTURE_2D, texture); + gl::ctx.CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offset_x, offset_y, width, height); +} + std::string shader_t::err_str() { int length; ctx.GetShaderiv(handle(), GL_INFO_LOG_LENGTH, &length); @@ -730,18 +737,36 @@ 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 texture) { +void sws_t::load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture) { + // When only a sub-part of the image must be encoded... + const bool copy = offset_x || offset_y || img.sd.width != in_width || img.sd.height != in_height; + if(copy) { + auto framebuf = gl::frame_buf_t::make(1); + framebuf.bind(&texture, &texture + 1); + + loaded_texture = tex[0]; + framebuf.copy(0, loaded_texture, offset_x, offset_y, in_width, in_height); + } + else { + loaded_texture = 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); + + // When a copy has already been made... + if(!copy) { + gl::ctx.BindTexture(GL_TEXTURE_2D, texture); + gl::ctx.DrawBuffers(1, &attachment); + + gl::ctx.Viewport(0, 0, in_width, in_height); + gl::ctx.DrawArrays(GL_TRIANGLES, 0, 3); + + loaded_texture = tex[0]; + } gl::ctx.BindTexture(GL_TEXTURE_2D, tex[1]); if(serial != img.serial) { @@ -770,9 +795,6 @@ void sws_t::load_vram(cursor_t &img, int offset_x, int offset_y, int texture) { gl::ctx.BindTexture(GL_TEXTURE_2D, 0); gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, 0); } - else { - loaded_texture = texture; - } } int sws_t::convert(nv12_t &nv12) { diff --git a/sunshine/platform/linux/graphics.h b/sunshine/platform/linux/graphics.h index 78c66708..127077e4 100644 --- a/sunshine/platform/linux/graphics.h +++ b/sunshine/platform/linux/graphics.h @@ -80,6 +80,11 @@ public: ++x; }); } + + /** + * Copies a part of the framebuffer to texture + */ + void copy(int id, int texture, int offset_x, int offset_y, int width, int height); }; class shader_t { @@ -275,7 +280,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 texture); + void load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture); void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range); @@ -285,6 +290,7 @@ public: // The cursor image will be blended into this framebuffer gl::frame_buf_t cursor_framebuffer; + gl::frame_buf_t copy_framebuffer; // Y - shader, UV - shader, Cursor - shader gl::program_t program[3]; diff --git a/sunshine/platform/linux/kmsgrab.cpp b/sunshine/platform/linux/kmsgrab.cpp index d0d2bdbb..fab989a7 100644 --- a/sunshine/platform/linux/kmsgrab.cpp +++ b/sunshine/platform/linux/kmsgrab.cpp @@ -673,6 +673,7 @@ public: std::this_thread::sleep_for((next_frame - now) / 3 * 2); } while(next_frame > now) { + std::this_thread::sleep_for(1ns); now = std::chrono::steady_clock::now(); } next_frame = now + delay; @@ -793,6 +794,7 @@ public: std::this_thread::sleep_for((next_frame - now) / 3 * 2); } while(next_frame > now) { + std::this_thread::sleep_for(1ns); now = std::chrono::steady_clock::now(); } next_frame = now + delay; diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index 3ae10cd9..dd14e829 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -763,7 +763,7 @@ void controlBroadcastThread(control_server_t *server) { break; } - server->iterate(50ms); + server->iterate(150ms); } // Let all remaining connections know the server is shutting down