mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 22:01:46 +00:00
[client] imgui: track last rectangles for overlays
This is necessary in case overlays change size. When this happens, we must damage the larger of the overlays' rectangles this frame and last frame. This erases the overlay from where it is no longer appears. In order to do this, we must keep track of the rectangles for every overlay with no exception. We cannot short-circuit the generation of rectangles if we run out of buffer space, and we must allocate space for MAX_OVERLAY_RECTS rectangles for every frame. Otherwise, we will not know where to erase the overlay if it disappears.
This commit is contained in:
parent
334bfeecea
commit
df0397b10b
3 changed files with 42 additions and 19 deletions
|
@ -80,6 +80,7 @@ void app_glSetSwapInterval(int interval);
|
|||
void app_glSwapBuffers(void);
|
||||
#endif
|
||||
|
||||
#define MAX_OVERLAY_RECTS 10
|
||||
void app_registerOverlay(const struct LG_OverlayOps * ops, void * params);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1007,8 +1007,8 @@ bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame)
|
|||
hasOverlay |= egl_help_render(this->help, this->screenScaleX, this->screenScaleY);
|
||||
hasOverlay |= egl_damage_render(this->damage, newFrame ? desktopDamage : NULL);
|
||||
|
||||
struct Rect damage[KVMFR_MAX_DAMAGE_RECTS + 12];
|
||||
int damageIdx = app_renderOverlay(damage, 10);
|
||||
struct Rect damage[KVMFR_MAX_DAMAGE_RECTS + MAX_OVERLAY_RECTS + 2];
|
||||
int damageIdx = app_renderOverlay(damage, MAX_OVERLAY_RECTS);
|
||||
|
||||
switch (damageIdx)
|
||||
{
|
||||
|
|
|
@ -628,6 +628,8 @@ struct Overlay
|
|||
{
|
||||
const struct LG_OverlayOps * ops;
|
||||
void * udata;
|
||||
int lastRectCount;
|
||||
struct Rect lastRects[MAX_OVERLAY_RECTS];
|
||||
};
|
||||
|
||||
void app_registerOverlay(const struct LG_OverlayOps * ops, void * params)
|
||||
|
@ -642,16 +644,29 @@ void app_registerOverlay(const struct LG_OverlayOps * ops, void * params)
|
|||
}
|
||||
|
||||
struct Overlay * overlay = malloc(sizeof(struct Overlay));
|
||||
overlay->ops = ops;
|
||||
overlay->udata = udata;
|
||||
overlay->ops = ops;
|
||||
overlay->udata = udata;
|
||||
overlay->lastRectCount = 0;
|
||||
ll_push(g_state.overlays, overlay);
|
||||
}
|
||||
|
||||
static inline void mergeRect(struct Rect * dest, const struct Rect * a, const struct Rect * b)
|
||||
{
|
||||
int x2 = max(a->x + a->w, b->x + b->w);
|
||||
int y2 = max(a->y + a->h, b->y + b->h);
|
||||
|
||||
dest->x = min(a->x, b->x);
|
||||
dest->y = min(a->y, b->y);
|
||||
dest->w = x2 - dest->x;
|
||||
dest->h = y2 - dest->y;
|
||||
}
|
||||
|
||||
int app_renderOverlay(struct Rect * rects, int maxRects)
|
||||
{
|
||||
int totalRects = 0;
|
||||
bool totalDamage = false;
|
||||
struct Overlay * overlay;
|
||||
struct Rect buffer[MAX_OVERLAY_RECTS];
|
||||
|
||||
igNewFrame();
|
||||
|
||||
|
@ -660,25 +675,32 @@ int app_renderOverlay(struct Rect * rects, int maxRects)
|
|||
ll_walk(g_state.overlays, (void **)&overlay); )
|
||||
{
|
||||
const int written =
|
||||
overlay->ops->render(overlay->udata, false, rects, maxRects);
|
||||
overlay->ops->render(overlay->udata, false, buffer, MAX_OVERLAY_RECTS);
|
||||
|
||||
if (totalDamage)
|
||||
continue;
|
||||
// It is an error to run out of rectangles, because we will not be able to
|
||||
// correctly calculate the damage of the next frame.
|
||||
assert(written >= 0);
|
||||
|
||||
if (written == -1)
|
||||
const int toAdd = max(written, overlay->lastRectCount);
|
||||
totalDamage |= toAdd > maxRects;
|
||||
|
||||
if (!totalDamage && toAdd)
|
||||
{
|
||||
// out of rects, return that the entire surface is damaged
|
||||
totalDamage = true;
|
||||
rects = NULL;
|
||||
maxRects = 0;
|
||||
totalRects = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxRects -= written;
|
||||
rects += written;
|
||||
totalRects += written;
|
||||
int i = 0;
|
||||
for (; i < overlay->lastRectCount && i < written; ++i)
|
||||
mergeRect(rects + i, buffer + i, overlay->lastRects + i);
|
||||
|
||||
// only one of the following memcpys will copy non-zero bytes.
|
||||
memcpy(rects + i, buffer + i, (written - i) * sizeof(struct Rect));
|
||||
memcpy(rects + i, overlay->lastRects + i, (overlay->lastRectCount - i) * sizeof(struct Rect));
|
||||
|
||||
rects += toAdd;
|
||||
totalRects += toAdd;
|
||||
maxRects -= toAdd;
|
||||
}
|
||||
|
||||
memcpy(overlay->lastRects, buffer, sizeof(struct Rect) * written);
|
||||
overlay->lastRectCount = written;
|
||||
}
|
||||
|
||||
igRender();
|
||||
|
|
Loading…
Reference in a new issue