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