From a14de25661ce50fcbbd0c8b000f1d97c90beb716 Mon Sep 17 00:00:00 2001 From: Quantum Date: Sun, 18 Jul 2021 03:33:53 -0400 Subject: [PATCH] [client] egl: only copy damaged areas when using dmabuf This speeds up the copy significantly when the frame only has small amount of damage. --- client/include/util.h | 2 +- client/renderers/EGL/desktop.c | 10 ++++++++-- client/renderers/EGL/desktop.h | 4 +++- client/renderers/EGL/egl.c | 2 +- client/renderers/EGL/texture.c | 13 +++++++++++-- client/renderers/EGL/texture.h | 3 ++- client/src/util.c | 19 +++++++++---------- 7 files changed, 35 insertions(+), 18 deletions(-) diff --git a/client/include/util.h b/client/include/util.h index f1124a54..2444de1e 100644 --- a/client/include/util.h +++ b/client/include/util.h @@ -37,7 +37,7 @@ bool util_guestCurToLocal(struct DoublePoint *local); void util_localCurToGuest(struct DoublePoint *guest); void util_rotatePoint(struct DoublePoint *point); bool util_hasGLExt(const char * exts, const char * ext); -int util_mergeOverlappingRects(FrameDamageRect * out, const FrameDamageRect * rects, int count); +int util_mergeOverlappingRects(FrameDamageRect * rects, int count); static inline double util_clamp(double x, double min, double max) { diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index 7cef18f0..a7c1f6c1 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -27,6 +27,7 @@ #include "texture.h" #include "shader.h" #include "model.h" +#include "util.h" #include #include @@ -259,11 +260,16 @@ bool egl_desktop_setup(EGL_Desktop * desktop, const LG_RendererFormat format, bo return true; } -bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd) +bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd, + const FrameDamageRect * origRects, int rectsCount) { + FrameDamageRect rects[KVMFR_MAX_DAMAGE_RECTS]; + memcpy(rects, origRects, rectsCount * sizeof(FrameDamageRect)); + rectsCount = util_mergeOverlappingRects(rects, rectsCount); + if (dmaFd >= 0) { - if (!egl_texture_update_from_dma(desktop->texture, frame, dmaFd)) + if (!egl_texture_update_from_dma(desktop->texture, frame, dmaFd, rects, rectsCount)) return false; } else diff --git a/client/renderers/EGL/desktop.h b/client/renderers/EGL/desktop.h index 0e6e8fd5..d8c17887 100644 --- a/client/renderers/EGL/desktop.h +++ b/client/renderers/EGL/desktop.h @@ -22,6 +22,7 @@ #include +#include "common/types.h" #include "interface/renderer.h" typedef struct EGL_Desktop EGL_Desktop; @@ -40,7 +41,8 @@ bool egl_desktop_init(EGL_Desktop ** desktop, EGLDisplay * display); void egl_desktop_free(EGL_Desktop ** desktop); bool egl_desktop_setup (EGL_Desktop * desktop, const LG_RendererFormat format, bool useDMA); -bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd); +bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd, + const FrameDamageRect * rects, int rectsCount); bool egl_desktop_render(EGL_Desktop * desktop, const float x, const float y, const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType, LG_RendererRotate rotate); diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index 79d7183c..b2bf3dcb 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -583,7 +583,7 @@ bool egl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd, { struct Inst * this = (struct Inst *)opaque; - if (!egl_desktop_update(this->desktop, frame, dmaFd)) + if (!egl_desktop_update(this->desktop, frame, dmaFd, damageRects, damageRectsCount)) { DEBUG_INFO("Failed to to update the desktop"); return false; diff --git a/client/renderers/EGL/texture.c b/client/renderers/EGL/texture.c index ea426f72..c52941d6 100644 --- a/client/renderers/EGL/texture.c +++ b/client/renderers/EGL/texture.c @@ -388,7 +388,8 @@ bool egl_texture_update_from_frame(EGL_Texture * texture, const FrameBuffer * fr return true; } -bool egl_texture_update_from_dma(EGL_Texture * texture, const FrameBuffer * frame, const int dmaFd) +bool egl_texture_update_from_dma(EGL_Texture * texture, const FrameBuffer * frame, const int dmaFd, + const FrameDamageRect * rects, int rectsCount) { if (!texture->streaming) return false; @@ -470,7 +471,15 @@ bool egl_texture_update_from_dma(EGL_Texture * texture, const FrameBuffer * fram glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->dmaTex, 0); glBindTexture(GL_TEXTURE_2D, texture->tex[0]); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texture->width, texture->height); + + if (!texture->ready || rectsCount == 0) + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texture->width, texture->height); + else + { + for (int i = 0; i < rectsCount; ++i) + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, rects[i].x, rects[i].y, rects[i].x, rects[i].y, + rects[i].width, rects[i].height); + } GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); diff --git a/client/renderers/EGL/texture.h b/client/renderers/EGL/texture.h index cd2905f9..d0586563 100644 --- a/client/renderers/EGL/texture.h +++ b/client/renderers/EGL/texture.h @@ -23,6 +23,7 @@ #include #include "shader.h" #include "common/framebuffer.h" +#include "common/types.h" #include #include @@ -52,7 +53,7 @@ void egl_texture_free(EGL_Texture ** tex); bool egl_texture_setup (EGL_Texture * texture, enum EGL_PixelFormat pixfmt, size_t width, size_t height, size_t stride, bool streaming, bool useDMA); bool egl_texture_update (EGL_Texture * texture, const uint8_t * buffer); bool egl_texture_update_from_frame(EGL_Texture * texture, const FrameBuffer * frame); -bool egl_texture_update_from_dma (EGL_Texture * texture, const FrameBuffer * frmame, const int dmaFd); +bool egl_texture_update_from_dma (EGL_Texture * texture, const FrameBuffer * frmame, const int dmaFd, const FrameDamageRect * rects, int rectsCount); enum EGL_TexStatus egl_texture_process(EGL_Texture * texture); enum EGL_TexStatus egl_texture_bind (EGL_Texture * texture); int egl_texture_count (EGL_Texture * texture); diff --git a/client/src/util.c b/client/src/util.c index b6293ea1..142db478 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -224,13 +224,12 @@ static bool rectIntersects(const FrameDamageRect * r1, const FrameDamageRect * r r2->y + r1->height > r2->y; } -int util_mergeOverlappingRects(FrameDamageRect * out, const FrameDamageRect * rects, int count) +int util_mergeOverlappingRects(FrameDamageRect * rects, int count) { bool removed[count]; bool changed; memset(removed, 0, sizeof(removed)); - memcpy(out, rects, count * sizeof(FrameDamageRect)); do { @@ -238,14 +237,14 @@ int util_mergeOverlappingRects(FrameDamageRect * out, const FrameDamageRect * re for (int i = 0; i < count; ++i) if (!removed[i]) for (int j = i + 1; j < count; ++j) - if (!removed[j] && rectIntersects(out + i, out + j)) + if (!removed[j] && rectIntersects(rects + i, rects + j)) { - uint32_t x2 = max(out[i].x + out[i].width, out[j].x + out[j].width); - uint32_t y2 = max(out[i].y + out[i].height, out[j].y + out[j].height); - out[i].x = min(out[i].x, out[j].x); - out[i].y = min(out[i].y, out[j].y); - out[i].width = x2 - out[i].x; - out[i].height = y2 - out[i].y; + uint32_t x2 = max(rects[i].x + rects[i].width, rects[j].x + rects[j].width); + uint32_t y2 = max(rects[i].y + rects[i].height, rects[j].y + rects[j].height); + rects[i].x = min(rects[i].x, rects[j].x); + rects[i].y = min(rects[i].y, rects[j].y); + rects[i].width = x2 - rects[i].x; + rects[i].height = y2 - rects[i].y; removed[j] = true; changed = true; } @@ -255,6 +254,6 @@ int util_mergeOverlappingRects(FrameDamageRect * out, const FrameDamageRect * re int o = 0; for (int i = 0; i < count; ++i) if (!removed[i]) - out[o++] = out[i]; + rects[o++] = rects[i]; return o; }