mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-08-07 03:04:05 +00:00
[client] egl: use eglSwapBuffersWithDamageKHR for cursor-only updates
Instead of damaging the entire surface when rendering a cursor move, we can use the EGL_KHR_swap_buffers_with_damage extension to only damage the part of the window covered by the cursor. This should reduce the cursor movement latency on Wayland.
This commit is contained in:
@@ -215,6 +215,16 @@ void egl_cursor_set_state(EGL_Cursor * cursor, const bool visible, const float x
|
||||
cursor->y = y;
|
||||
}
|
||||
|
||||
struct CursorState egl_cursor_get_state(EGL_Cursor * cursor, int width, int height) {
|
||||
return (struct CursorState) {
|
||||
.visible = cursor->visible,
|
||||
.rect.x = (cursor->x * width + width) / 2,
|
||||
.rect.y = (-cursor->y * height + height) / 2 - cursor->h * height,
|
||||
.rect.w = cursor->w * width + 2,
|
||||
.rect.h = cursor->h * height + 2,
|
||||
};
|
||||
}
|
||||
|
||||
void egl_cursor_render(EGL_Cursor * cursor, LG_RendererRotate rotate)
|
||||
{
|
||||
if (!cursor->visible)
|
||||
|
@@ -25,6 +25,11 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
typedef struct EGL_Cursor EGL_Cursor;
|
||||
|
||||
struct CursorState {
|
||||
bool visible;
|
||||
struct Rect rect;
|
||||
};
|
||||
|
||||
bool egl_cursor_init(EGL_Cursor ** cursor);
|
||||
void egl_cursor_free(EGL_Cursor ** cursor);
|
||||
|
||||
@@ -41,4 +46,6 @@ void egl_cursor_set_size(EGL_Cursor * cursor, const float x, const float y);
|
||||
void egl_cursor_set_state(EGL_Cursor * cursor, const bool visible,
|
||||
const float x, const float y);
|
||||
|
||||
struct CursorState egl_cursor_get_state(EGL_Cursor * cursor, int width, int height);
|
||||
|
||||
void egl_cursor_render(EGL_Cursor * cursor, LG_RendererRotate rotate);
|
||||
|
@@ -106,6 +106,9 @@ struct Inst
|
||||
unsigned fontSize;
|
||||
LG_FontObj helpFontObj;
|
||||
unsigned helpFontSize;
|
||||
|
||||
bool cursorLastValid;
|
||||
struct CursorState cursorLast;
|
||||
};
|
||||
|
||||
static struct Option egl_options[] =
|
||||
@@ -472,6 +475,8 @@ void egl_on_resize(void * opaque, const int width, const int height, const doubl
|
||||
egl_calc_mouse_state(this);
|
||||
egl_update_font(this);
|
||||
egl_update_help_font(this);
|
||||
|
||||
this->cursorLastValid = false;
|
||||
}
|
||||
|
||||
bool egl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor,
|
||||
@@ -545,6 +550,7 @@ bool egl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd)
|
||||
}
|
||||
|
||||
this->start = true;
|
||||
this->cursorLastValid = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -581,12 +587,14 @@ void egl_on_alert(void * opaque, const LG_MsgAlert alert, const char * message,
|
||||
}
|
||||
|
||||
this->showAlert = true;
|
||||
this->cursorLastValid = false;
|
||||
}
|
||||
|
||||
void egl_on_help(void * opaque, const char * message)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
egl_help_set_text(this->help, message);
|
||||
this->cursorLastValid = false;
|
||||
}
|
||||
|
||||
void egl_on_show_fps(void * opaque, bool showFPS)
|
||||
@@ -767,6 +775,10 @@ bool egl_render(void * opaque, LG_RendererRotate rotate)
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
bool hasLastCursor = this->cursorLastValid;
|
||||
bool cursorRendered = false;
|
||||
struct CursorState cursorState;
|
||||
|
||||
if (this->start && egl_desktop_render(this->desktop,
|
||||
this->translateX, this->translateY,
|
||||
this->scaleX , this->scaleY ,
|
||||
@@ -780,6 +792,8 @@ bool egl_render(void * opaque, LG_RendererRotate rotate)
|
||||
this->waitDone = true;
|
||||
}
|
||||
|
||||
cursorRendered = true;
|
||||
cursorState = egl_cursor_get_state(this->cursor, this->width, this->height);
|
||||
egl_cursor_render(this->cursor,
|
||||
(this->format.rotate + rotate) % LG_ROTATE_MAX);
|
||||
}
|
||||
@@ -819,14 +833,39 @@ bool egl_render(void * opaque, LG_RendererRotate rotate)
|
||||
close = true;
|
||||
|
||||
if (close)
|
||||
{
|
||||
this->showAlert = false;
|
||||
this->cursorLastValid = false;
|
||||
}
|
||||
else
|
||||
egl_alert_render(this->alert, this->screenScaleX, this->screenScaleY);
|
||||
}
|
||||
|
||||
struct Rect damage[2];
|
||||
int damageIdx = 0;
|
||||
|
||||
if (this->waitDone)
|
||||
{
|
||||
if (cursorRendered && hasLastCursor)
|
||||
{
|
||||
if (this->cursorLast.visible)
|
||||
damage[damageIdx++] = this->cursorLast.rect;
|
||||
|
||||
if (cursorState.visible)
|
||||
damage[damageIdx++] = cursorState.rect;
|
||||
|
||||
this->cursorLast = cursorState;
|
||||
}
|
||||
else if (cursorRendered)
|
||||
{
|
||||
this->cursorLast = cursorState;
|
||||
this->cursorLastValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
egl_fps_render(this->fps, this->screenScaleX, this->screenScaleY);
|
||||
egl_help_render(this->help, this->screenScaleX, this->screenScaleY);
|
||||
app_eglSwapBuffers(this->display, this->surface);
|
||||
app_eglSwapBuffers(this->display, this->surface, damage, damageIdx);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -834,6 +873,7 @@ void egl_update_fps(void * opaque, const float avgUPS, const float avgFPS)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
egl_fps_update(this->fps, avgUPS, avgFPS);
|
||||
this->cursorLastValid = false;
|
||||
}
|
||||
|
||||
struct LG_Renderer LGR_EGL =
|
||||
|
Reference in New Issue
Block a user