mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[client] egl: track software surface damage
This commit is contained in:
@@ -389,6 +389,94 @@ static void egl_onRestart(LG_Renderer * renderer)
|
||||
});
|
||||
}
|
||||
|
||||
static void egl_getDesktopSize(
|
||||
const struct Inst * this, int * width, int * height)
|
||||
{
|
||||
if (this->showSwSurface)
|
||||
{
|
||||
*width = this->swSurfaceWidth;
|
||||
*height = this->swSurfaceHeight;
|
||||
return;
|
||||
}
|
||||
|
||||
*width = this->formatValid ? this->format.frameWidth : 0;
|
||||
*height = this->formatValid ? this->format.frameHeight : 0;
|
||||
}
|
||||
|
||||
static void egl_invalidateDesktopDamage(struct Inst * this)
|
||||
{
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
struct DesktopDamage * damage =
|
||||
this->desktopDamage + this->desktopDamageIdx;
|
||||
damage->frameToken = LG_RENDERER_FRAME_TOKEN_NONE;
|
||||
damage->count = -1;
|
||||
});
|
||||
}
|
||||
|
||||
static void egl_update_pointer_scale(struct Inst * this)
|
||||
{
|
||||
if (!this->scalePointer || this->width <= 0 || this->height <= 0)
|
||||
return;
|
||||
|
||||
int width, height;
|
||||
if (this->showSwSurface)
|
||||
{
|
||||
width = this->swSurfaceWidth;
|
||||
height = this->swSurfaceHeight;
|
||||
}
|
||||
else if (this->formatValid)
|
||||
{
|
||||
width = this->format.screenWidth;
|
||||
height = this->format.screenHeight;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
egl_cursorSetScale(this->cursor, max(1.0f, max(
|
||||
(float)width / this->width,
|
||||
(float)height / this->height)));
|
||||
}
|
||||
|
||||
static void egl_addSwSurfaceDamage(
|
||||
struct Inst * this, int x, int y, int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0 ||
|
||||
this->swSurfaceWidth <= 0 || this->swSurfaceHeight <= 0)
|
||||
return;
|
||||
|
||||
const int64_t right = min(
|
||||
(int64_t)x + width, (int64_t)this->swSurfaceWidth);
|
||||
const int64_t bottom = min(
|
||||
(int64_t)y + height, (int64_t)this->swSurfaceHeight);
|
||||
x = max(x, 0);
|
||||
y = max(y, 0);
|
||||
if (right <= x || bottom <= y)
|
||||
return;
|
||||
|
||||
const FrameDamageRect rect = {
|
||||
.x = (uint32_t)x,
|
||||
.y = (uint32_t)y,
|
||||
.width = (uint32_t)(right - x),
|
||||
.height = (uint32_t)(bottom - y),
|
||||
};
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
if (this->showSwSurface)
|
||||
{
|
||||
struct DesktopDamage * damage =
|
||||
this->desktopDamage + this->desktopDamageIdx;
|
||||
damage->frameToken = LG_RENDERER_FRAME_TOKEN_NONE;
|
||||
if (damage->count >= 0)
|
||||
{
|
||||
if (damage->count + 1 >= LG_MAX_FRAME_DAMAGE_RECTS)
|
||||
damage->count = -1;
|
||||
else
|
||||
damage->rects[damage->count++] = rect;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void egl_calc_mouse_size(struct Inst * this)
|
||||
{
|
||||
if (this->showSwSurface)
|
||||
@@ -499,22 +587,24 @@ static void egl_calc_mouse_state(struct Inst * this)
|
||||
|
||||
static void egl_update_scale_type(struct Inst * this)
|
||||
{
|
||||
int width = 0, height = 0;
|
||||
int width, height;
|
||||
egl_getDesktopSize(this, &width, &height);
|
||||
|
||||
switch (this->rotate)
|
||||
{
|
||||
case LG_ROTATE_0:
|
||||
case LG_ROTATE_180:
|
||||
width = this->format.frameWidth;
|
||||
height = this->format.frameHeight;
|
||||
break;
|
||||
|
||||
case LG_ROTATE_90:
|
||||
case LG_ROTATE_270:
|
||||
width = this->format.frameHeight;
|
||||
height = this->format.frameWidth;
|
||||
{
|
||||
const int swap = width;
|
||||
width = height;
|
||||
height = swap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (width == this->viewportWidth || height == this->viewportHeight)
|
||||
this->scaleType = EGL_DESKTOP_NOSCALE;
|
||||
@@ -565,16 +655,7 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig
|
||||
this->screenScaleY = 1.0f / this->height;
|
||||
|
||||
egl_calc_mouse_state(this);
|
||||
if (this->scalePointer)
|
||||
{
|
||||
float scale = max(1.0f,
|
||||
this->formatValid ?
|
||||
max(
|
||||
(float)this->format.screenWidth / this->width,
|
||||
(float)this->format.screenHeight / this->height)
|
||||
: 1.0f);
|
||||
egl_cursorSetScale(this->cursor, scale);
|
||||
}
|
||||
egl_update_pointer_scale(this);
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
this->desktopDamage[this->desktopDamageIdx].count = -1;
|
||||
@@ -717,11 +798,7 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
||||
|
||||
egl_stateCheckShared();
|
||||
|
||||
if (likely(this->scalePointer))
|
||||
{
|
||||
float scale = max(1.0f, (float)format.screenWidth / this->width);
|
||||
egl_cursorSetScale(this->cursor, scale);
|
||||
}
|
||||
egl_update_pointer_scale(this);
|
||||
|
||||
// Track HDR state and warn if HDR frames arrive without any HDR path
|
||||
this->hdr = format.hdr;
|
||||
@@ -741,12 +818,16 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
||||
egl_updateHDRState(this, true);
|
||||
|
||||
egl_update_scale_type(this);
|
||||
|
||||
if (!this->showSwSurface)
|
||||
{
|
||||
egl_damageSetup(this->damage, format.frameWidth, format.frameHeight);
|
||||
|
||||
/* we need full screen damage when the format changes */
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
this->desktopDamage[this->desktopDamageIdx].count = -1;
|
||||
});
|
||||
}
|
||||
|
||||
return egl_desktopSetup(this->desktop, format);
|
||||
}
|
||||
@@ -778,6 +859,8 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame,
|
||||
elapsed > waitTimeNs ? elapsed - waitTimeNs : 0, waitTimeNs);
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
if (!this->showSwSurface)
|
||||
{
|
||||
struct DesktopDamage * damage =
|
||||
this->desktopDamage + this->desktopDamageIdx;
|
||||
if (unlikely(
|
||||
@@ -794,6 +877,7 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame,
|
||||
damage->count += damageRectsCount;
|
||||
}
|
||||
damage->frameToken = frameToken;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -1246,13 +1330,16 @@ inline static EGLint egl_bufferAge(struct Inst * this)
|
||||
static FrameDamageRect egl_expandDesktopDamage(
|
||||
const struct Inst * this, const FrameDamageRect * rect)
|
||||
{
|
||||
int width, height;
|
||||
egl_getDesktopSize(this, &width, &height);
|
||||
|
||||
const uint32_t x = rect->x > DESKTOP_DAMAGE_MARGIN ?
|
||||
rect->x - DESKTOP_DAMAGE_MARGIN : 0;
|
||||
const uint32_t y = rect->y > DESKTOP_DAMAGE_MARGIN ?
|
||||
rect->y - DESKTOP_DAMAGE_MARGIN : 0;
|
||||
const uint32_t right = (uint32_t)min((uint64_t)this->format.frameWidth,
|
||||
const uint32_t right = (uint32_t)min((uint64_t)width,
|
||||
(uint64_t)rect->x + rect->width + DESKTOP_DAMAGE_MARGIN);
|
||||
const uint32_t bottom = (uint32_t)min((uint64_t)this->format.frameHeight,
|
||||
const uint32_t bottom = (uint32_t)min((uint64_t)height,
|
||||
(uint64_t)rect->y + rect->height + DESKTOP_DAMAGE_MARGIN);
|
||||
|
||||
return (FrameDamageRect) {
|
||||
@@ -1406,8 +1493,10 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
this->format.hdrPQ, mapCursorGain, mapCursorContentPeak);
|
||||
bool renderAll = hdrStateChanged ||
|
||||
invalidateWindow || this->hadOverlay ||
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE ||
|
||||
this->showSwSurface;
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE;
|
||||
|
||||
int desktopWidth, desktopHeight;
|
||||
egl_getDesktopSize(this, &desktopWidth, &desktopHeight);
|
||||
|
||||
bool hasOverlay = false;
|
||||
struct CursorState cursorState = { .visible = false };
|
||||
@@ -1472,7 +1561,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
{
|
||||
double matrix[6];
|
||||
egl_screenToDesktopMatrix(matrix,
|
||||
this->format.frameWidth, this->format.frameHeight,
|
||||
desktopWidth, desktopHeight,
|
||||
this->translateX, this->translateY, this->scaleX, this->scaleY, rotate,
|
||||
this->width, this->height);
|
||||
|
||||
@@ -1491,7 +1580,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
for (int j = 0; j < count; ++j)
|
||||
accumulated->count += egl_screenToDesktop(
|
||||
accumulated->rects + accumulated->count, matrix, damage + j,
|
||||
this->format.frameWidth, this->format.frameHeight
|
||||
desktopWidth, desktopHeight
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1545,7 +1634,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
if (desktopRendered)
|
||||
{
|
||||
cursorState = egl_cursorRender(this->cursor,
|
||||
(this->format.rotate + rotate) % LG_ROTATE_MAX,
|
||||
((this->showSwSurface ? LG_ROTATE_0 : this->format.rotate) + rotate) %
|
||||
LG_ROTATE_MAX,
|
||||
this->width, this->height,
|
||||
linearHDRComposition, &deferredLogicalCursor);
|
||||
}
|
||||
@@ -1574,7 +1664,9 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
|
||||
hasOverlay |=
|
||||
egl_damageRender(
|
||||
this->damage, rotate, frameConsumed ? desktopDamage : NULL) |
|
||||
this->damage, rotate,
|
||||
frameConsumed || (this->showSwSurface && damageRendered) ?
|
||||
desktopDamage : NULL) |
|
||||
invalidateWindow;
|
||||
|
||||
/* The diagnostics being displayed must not contribute to Compose. */
|
||||
@@ -1634,7 +1726,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
{
|
||||
double matrix[6];
|
||||
egl_desktopToScreenMatrix(matrix,
|
||||
this->format.frameWidth, this->format.frameHeight,
|
||||
desktopWidth, desktopHeight,
|
||||
this->translateX, this->translateY, this->scaleX, this->scaleY, rotate,
|
||||
this->width, this->height);
|
||||
|
||||
@@ -1666,7 +1758,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
|
||||
double matrix[6];
|
||||
egl_desktopToScreenMatrix(matrix,
|
||||
this->format.frameWidth, this->format.frameHeight,
|
||||
desktopWidth, desktopHeight,
|
||||
this->translateX, this->translateY, this->scaleX, this->scaleY, rotate,
|
||||
this->width, this->height);
|
||||
for (int i = 0; i < accumulated->count; ++i)
|
||||
@@ -1682,7 +1774,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
egl_hdrComposeEnd(this->hdrCompose, encodeDamage, encodeDamageCount);
|
||||
if (deferredLogicalCursor && cursorState.visible)
|
||||
egl_cursorRender(this->cursor,
|
||||
(this->format.rotate + rotate) % LG_ROTATE_MAX,
|
||||
((this->showSwSurface ? LG_ROTATE_0 : this->format.rotate) + rotate) %
|
||||
LG_ROTATE_MAX,
|
||||
this->width, this->height, false, NULL);
|
||||
this->hadOverlay = hasOverlay;
|
||||
this->cursorLast = cursorState;
|
||||
@@ -1813,6 +1906,16 @@ static void egl_swSurfaceConfigure(LG_Renderer * renderer,
|
||||
this->swSurfaceWidth = width;
|
||||
this->swSurfaceHeight = height;
|
||||
egl_desktopSwSurfaceConfigure(this->desktop, width, height);
|
||||
|
||||
if (this->showSwSurface && width > 0 && height > 0)
|
||||
{
|
||||
egl_update_scale_type(this);
|
||||
egl_calc_mouse_size(this);
|
||||
egl_calc_mouse_state(this);
|
||||
egl_update_pointer_scale(this);
|
||||
egl_damageSetup(this->damage, width, height);
|
||||
egl_invalidateDesktopDamage(this);
|
||||
}
|
||||
}
|
||||
|
||||
static void egl_swSurfaceDrawFill(LG_Renderer * renderer,
|
||||
@@ -1822,6 +1925,7 @@ static void egl_swSurfaceDrawFill(LG_Renderer * renderer,
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSwSurfaceDrawFill(
|
||||
this->desktop, x, y, width, height, color);
|
||||
egl_addSwSurfaceDamage(this, x, y, width, height);
|
||||
}
|
||||
|
||||
static void egl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||
@@ -1832,13 +1936,29 @@ static void egl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSwSurfaceDrawBitmap(
|
||||
this->desktop, x, y, width, height, stride, data, topDown);
|
||||
egl_addSwSurfaceDamage(this, x, y, width, height);
|
||||
}
|
||||
|
||||
static void egl_swSurfaceShow(LG_Renderer * renderer, bool show)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
this->showSwSurface = show;
|
||||
struct DesktopDamage * damage =
|
||||
this->desktopDamage + this->desktopDamageIdx;
|
||||
damage->frameToken = LG_RENDERER_FRAME_TOKEN_NONE;
|
||||
damage->count = -1;
|
||||
});
|
||||
|
||||
int width, height;
|
||||
egl_getDesktopSize(this, &width, &height);
|
||||
if (width > 0 && height > 0)
|
||||
egl_damageSetup(this->damage, width, height);
|
||||
|
||||
egl_update_scale_type(this);
|
||||
egl_calc_mouse_size(this);
|
||||
egl_calc_mouse_state(this);
|
||||
egl_update_pointer_scale(this);
|
||||
egl_desktopSwSurfaceShow(this->desktop, show);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user