mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 21:47:23 +00:00
[client] egl: use queue of damages
This prevents damage from being overwritten when frames are received faster than could be rendered. This implementation cycles between two queues, removing all need for memory allocation.
This commit is contained in:
parent
2e0f765190
commit
b9a7ce17fe
@ -49,6 +49,7 @@
|
|||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
|
|
||||||
#define SPLASH_FADE_TIME 1000000
|
#define SPLASH_FADE_TIME 1000000
|
||||||
|
#define DESKTOP_DAMAGE_COUNT 2
|
||||||
|
|
||||||
struct Options
|
struct Options
|
||||||
{
|
{
|
||||||
@ -101,8 +102,9 @@ struct Inst
|
|||||||
|
|
||||||
struct CursorState cursorLast;
|
struct CursorState cursorLast;
|
||||||
|
|
||||||
bool hadOverlay;
|
bool hadOverlay;
|
||||||
_Atomic(struct DesktopDamage *) desktopDamage;
|
struct DesktopDamage desktopDamage[DESKTOP_DAMAGE_COUNT];
|
||||||
|
atomic_uint desktopDamageIdx;
|
||||||
|
|
||||||
RingBuffer importTimings;
|
RingBuffer importTimings;
|
||||||
GraphHandle importGraph;
|
GraphHandle importGraph;
|
||||||
@ -180,6 +182,16 @@ static void egl_setup(void)
|
|||||||
option_register(egl_options);
|
option_register(egl_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static struct DesktopDamage * currentDesktopDamage(struct Inst * this)
|
||||||
|
{
|
||||||
|
return this->desktopDamage + atomic_load(&this->desktopDamageIdx) % DESKTOP_DAMAGE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static struct DesktopDamage * finishDesktopDamage(struct Inst * this)
|
||||||
|
{
|
||||||
|
return this->desktopDamage + atomic_fetch_add(&this->desktopDamageIdx, 1) % DESKTOP_DAMAGE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
static bool egl_create(void ** opaque, const LG_RendererParams params, bool * needsOpenGL)
|
static bool egl_create(void ** opaque, const LG_RendererParams params, bool * needsOpenGL)
|
||||||
{
|
{
|
||||||
// check if EGL is even available
|
// check if EGL is even available
|
||||||
@ -209,7 +221,8 @@ static bool egl_create(void ** opaque, const LG_RendererParams params, bool * ne
|
|||||||
this->screenScaleY = 1.0f;
|
this->screenScaleY = 1.0f;
|
||||||
this->uiScale = 1.0;
|
this->uiScale = 1.0;
|
||||||
|
|
||||||
atomic_init(&this->desktopDamage, NULL);
|
atomic_init(&this->desktopDamageIdx, 0);
|
||||||
|
this->desktopDamage[0].count = -1;
|
||||||
|
|
||||||
this->importTimings = ringbuffer_new(256, sizeof(float));
|
this->importTimings = ringbuffer_new(256, sizeof(float));
|
||||||
this->importGraph = app_registerGraph("IMPORT", this->importTimings, 0.0f, 5.0f);
|
this->importGraph = app_registerGraph("IMPORT", this->importTimings, 0.0f, 5.0f);
|
||||||
@ -419,14 +432,7 @@ static void egl_on_resize(void * opaque, const int width, const int height, cons
|
|||||||
|
|
||||||
egl_calc_mouse_state(this);
|
egl_calc_mouse_state(this);
|
||||||
|
|
||||||
struct DesktopDamage * damage = malloc(sizeof(struct DesktopDamage));
|
currentDesktopDamage(this)->count = -1;
|
||||||
if (!damage)
|
|
||||||
{
|
|
||||||
DEBUG_FATAL("Out of memory");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
damage->count = 0;
|
|
||||||
free(atomic_exchange(&this->desktopDamage, damage));
|
|
||||||
|
|
||||||
// this is needed to refresh the font atlas texture
|
// this is needed to refresh the font atlas texture
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
@ -512,15 +518,14 @@ static bool egl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd,
|
|||||||
|
|
||||||
this->start = true;
|
this->start = true;
|
||||||
|
|
||||||
struct DesktopDamage * damage = malloc(sizeof(struct DesktopDamage));
|
struct DesktopDamage * damage = currentDesktopDamage(this);
|
||||||
if (!damage)
|
if (damage->count == -1 || damage->count + damageRectsCount >= KVMFR_MAX_DAMAGE_RECTS)
|
||||||
|
damage->count = -1;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
DEBUG_FATAL("Out of memory");
|
memcpy(damage->rects + damage->count, damageRects, damageRectsCount * sizeof(FrameDamageRect));
|
||||||
abort();
|
damage->count += damageRectsCount;
|
||||||
}
|
}
|
||||||
damage->count = damageRectsCount;
|
|
||||||
memcpy(damage->rects, damageRects, damageRectsCount * sizeof(FrameDamageRect));
|
|
||||||
free(atomic_exchange(&this->desktopDamage, damage));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -810,11 +815,10 @@ static bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFr
|
|||||||
|
|
||||||
bool hasOverlay = false;
|
bool hasOverlay = false;
|
||||||
struct CursorState cursorState = { .visible = false };
|
struct CursorState cursorState = { .visible = false };
|
||||||
struct DesktopDamage * desktopDamage = NULL;
|
struct DesktopDamage * desktopDamage = finishDesktopDamage(this);
|
||||||
|
|
||||||
if (this->start)
|
if (this->start)
|
||||||
{
|
{
|
||||||
desktopDamage = atomic_exchange(&this->desktopDamage, NULL);
|
|
||||||
if (egl_desktop_render(this->desktop,
|
if (egl_desktop_render(this->desktop,
|
||||||
this->translateX, this->translateY,
|
this->translateX, this->translateY,
|
||||||
this->scaleX , this->scaleY ,
|
this->scaleX , this->scaleY ,
|
||||||
@ -833,7 +837,7 @@ static bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFr
|
|||||||
this->width, this->height);
|
this->width, this->height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
desktopDamage->count = 0;
|
desktopDamage->count = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->waitDone)
|
if (!this->waitDone)
|
||||||
@ -865,7 +869,7 @@ static bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFr
|
|||||||
hasOverlay = true;
|
hasOverlay = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desktopDamage && rotate != LG_ROTATE_0)
|
if (desktopDamage->count > 0 && rotate != LG_ROTATE_0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < desktopDamage->count; ++i)
|
for (int i = 0; i < desktopDamage->count; ++i)
|
||||||
{
|
{
|
||||||
@ -958,34 +962,32 @@ static bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFr
|
|||||||
|
|
||||||
this->cursorLast = cursorState;
|
this->cursorLast = cursorState;
|
||||||
|
|
||||||
if (desktopDamage)
|
if (desktopDamage->count == -1)
|
||||||
|
// -1 damage count means invalidating entire window.
|
||||||
|
damageIdx = 0;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (desktopDamage->count == 0)
|
for (int i = 0; i < desktopDamage->count; ++i)
|
||||||
// Zero damage count means invalidating entire window.
|
|
||||||
damageIdx = 0;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < desktopDamage->count; ++i)
|
FrameDamageRect rect = desktopDamage->rects[i];
|
||||||
{
|
int x1 = (int) (rect.x * scaleX);
|
||||||
FrameDamageRect rect = desktopDamage->rects[i];
|
int y1 = (int) (rect.y * scaleY);
|
||||||
int x1 = (int) (rect.x * scaleX);
|
int x2 = (int) ceil((rect.x + rect.width) * scaleX);
|
||||||
int y1 = (int) (rect.y * scaleY);
|
int y2 = (int) ceil((rect.y + rect.height) * scaleY);
|
||||||
int x2 = (int) ceil((rect.x + rect.width) * scaleX);
|
damage[damageIdx++] = (struct Rect) {
|
||||||
int y2 = (int) ceil((rect.y + rect.height) * scaleY);
|
.x = this->destRect.x + x1,
|
||||||
damage[damageIdx++] = (struct Rect) {
|
.y = this->height - (this->destRect.y + y2),
|
||||||
.x = this->destRect.x + x1,
|
.w = x2 - x1,
|
||||||
.y = this->height - (this->destRect.y + y2),
|
.h = y2 - y1,
|
||||||
.w = x2 - x1,
|
};
|
||||||
.h = y2 - y1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
damageIdx = 0;
|
damageIdx = 0;
|
||||||
|
|
||||||
this->hadOverlay = hasOverlay;
|
this->hadOverlay = hasOverlay;
|
||||||
free(desktopDamage);
|
desktopDamage->count = 0;
|
||||||
|
|
||||||
app_eglSwapBuffers(this->display, this->surface, damage, damageIdx);
|
app_eglSwapBuffers(this->display, this->surface, damage, damageIdx);
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user