mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[client] renderers: generalize software surface updates
This commit is contained in:
@@ -82,9 +82,9 @@ struct EGL_Desktop
|
||||
bool hdrPQ;
|
||||
LG_RendererRotate rotate;
|
||||
|
||||
bool useSpice;
|
||||
int spiceWidth, spiceHeight;
|
||||
EGL_Texture * spiceTexture;
|
||||
bool useSwSurface;
|
||||
int swSurfaceWidth, swSurfaceHeight;
|
||||
EGL_Texture * swSurfaceTexture;
|
||||
|
||||
// scale algorithm
|
||||
int scaleAlgo;
|
||||
@@ -251,7 +251,7 @@ void egl_desktopFree(EGL_Desktop ** desktop)
|
||||
return;
|
||||
|
||||
egl_textureFree (&(*desktop)->texture );
|
||||
egl_textureFree (&(*desktop)->spiceTexture );
|
||||
egl_textureFree (&(*desktop)->swSurfaceTexture);
|
||||
egl_shaderFree (&(*desktop)->shader .shader);
|
||||
egl_desktopRectsFree(&(*desktop)->mesh );
|
||||
egl_postProcessFree(&(*desktop)->pp);
|
||||
@@ -470,14 +470,15 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
EGL_Texture * tex;
|
||||
int width, height;
|
||||
|
||||
/* This also retires completed snapshots while the SPICE display is shown. */
|
||||
/* This also retires completed snapshots while the software surface is
|
||||
* shown. */
|
||||
egl_texturePoll(desktop->texture);
|
||||
|
||||
if (unlikely(desktop->useSpice))
|
||||
if (unlikely(desktop->useSwSurface))
|
||||
{
|
||||
tex = desktop->spiceTexture;
|
||||
width = desktop->spiceWidth;
|
||||
height = desktop->spiceHeight;
|
||||
tex = desktop->swSurfaceTexture;
|
||||
width = desktop->swSurfaceWidth;
|
||||
height = desktop->swSurfaceHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,7 +520,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
rects ? rects->rects : NULL, rects ? rects->count : -1,
|
||||
width, height);
|
||||
|
||||
const bool hdr = desktop->hdr && !desktop->useSpice;
|
||||
const bool hdr = desktop->hdr && !desktop->useSwSurface;
|
||||
uint32_t hdrPeak = 0;
|
||||
if (hdr)
|
||||
{
|
||||
@@ -579,7 +580,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
{
|
||||
if (bindStatus != EGL_TEX_STATUS_NOTREADY)
|
||||
DEBUG_ERROR("Failed to bind the desktop texture");
|
||||
if (!desktop->useSpice && desktop->useDMA && processFrame)
|
||||
if (!desktop->useSwSurface && desktop->useDMA && processFrame)
|
||||
egl_textureMarkUsed(desktop->texture);
|
||||
return false;
|
||||
}
|
||||
@@ -633,7 +634,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
desktop->linearComposition);
|
||||
egl_shaderUse(shader->shader);
|
||||
egl_desktopRectsRender(desktop->mesh);
|
||||
if (!desktop->useSpice && desktop->useDMA &&
|
||||
if (!desktop->useSwSurface && desktop->useDMA &&
|
||||
(processFrame || texture == tex))
|
||||
egl_textureMarkUsed(desktop->texture);
|
||||
return true;
|
||||
@@ -649,25 +650,26 @@ void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR,
|
||||
void egl_desktopGetHDRMapping(EGL_Desktop * desktop, bool * enabled,
|
||||
float * gain, float * contentPeak)
|
||||
{
|
||||
*enabled = desktop->hdr && !desktop->useSpice &&
|
||||
*enabled = desktop->hdr && !desktop->useSwSurface &&
|
||||
desktop->mapHDRtoSDR && !desktop->nativeHDR;
|
||||
*gain = (desktop->hdrPQ ? 10000.0f : 80.0f) /
|
||||
desktop->peakLuminance;
|
||||
*contentPeak = (float)desktop->maxCLL / desktop->peakLuminance;
|
||||
}
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
||||
void egl_desktopSwSurfaceConfigure(EGL_Desktop * desktop,
|
||||
int width, int height)
|
||||
{
|
||||
if (!desktop->spiceTexture)
|
||||
if (!egl_textureInit(&desktop->spiceTexture, desktop->display,
|
||||
if (!desktop->swSurfaceTexture)
|
||||
if (!egl_textureInit(&desktop->swSurfaceTexture, desktop->display,
|
||||
EGL_TEXTYPE_BUFFER_MAP))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the spice desktop texture");
|
||||
DEBUG_ERROR("Failed to initialize the software surface texture");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!egl_textureSetup(
|
||||
desktop->spiceTexture,
|
||||
desktop->swSurfaceTexture,
|
||||
EGL_PF_BGRA,
|
||||
width,
|
||||
height,
|
||||
@@ -675,40 +677,41 @@ void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
||||
width * 4
|
||||
))
|
||||
{
|
||||
DEBUG_ERROR("Failed to setup the spice desktop texture");
|
||||
DEBUG_ERROR("Failed to setup the software surface texture");
|
||||
return;
|
||||
}
|
||||
|
||||
desktop->spiceWidth = width;
|
||||
desktop->spiceHeight = height;
|
||||
desktop->swSurfaceWidth = width;
|
||||
desktop->swSurfaceHeight = height;
|
||||
}
|
||||
|
||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, uint32_t color)
|
||||
void egl_desktopSwSurfaceDrawFill(EGL_Desktop * desktop,
|
||||
int x, int y, int width, int height, uint32_t color)
|
||||
{
|
||||
if (!desktop->spiceTexture || width <= 0 || height <= 0)
|
||||
if (!desktop->swSurfaceTexture || width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
const int64_t right = (int64_t)x + width;
|
||||
const int64_t bottom = (int64_t)y + height;
|
||||
if (x >= desktop->spiceWidth || y >= desktop->spiceHeight ||
|
||||
if (x >= desktop->swSurfaceWidth ||
|
||||
y >= desktop->swSurfaceHeight ||
|
||||
right <= 0 || bottom <= 0)
|
||||
return;
|
||||
|
||||
x = x < 0 ? 0 : x;
|
||||
y = y < 0 ? 0 : y;
|
||||
width = (right > desktop->spiceWidth ?
|
||||
desktop->spiceWidth : (int)right ) - x;
|
||||
height = (bottom > desktop->spiceHeight ?
|
||||
desktop->spiceHeight : (int)bottom) - y;
|
||||
width = (right > desktop->swSurfaceWidth ?
|
||||
desktop->swSurfaceWidth : (int)right ) - x;
|
||||
height = (bottom > desktop->swSurfaceHeight ?
|
||||
desktop->swSurfaceHeight : (int)bottom) - y;
|
||||
|
||||
/* this is a fairly hacky way to do this, but since it's only for the fallback
|
||||
* spice display it's not really an issue */
|
||||
/* This is a fairly hacky way to update a software surface, but it preserves
|
||||
* the existing incremental fill behavior. */
|
||||
|
||||
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
||||
if (!line)
|
||||
{
|
||||
DEBUG_ERROR("Failed to allocate SPICE fill row");
|
||||
DEBUG_ERROR("Failed to allocate software surface fill row");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -716,7 +719,7 @@ void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
line[i] = color;
|
||||
|
||||
for(int dy = 0; dy < height; ++dy)
|
||||
egl_textureUpdateRect(desktop->spiceTexture,
|
||||
egl_textureUpdateRect(desktop->swSurfaceTexture,
|
||||
x, y + dy, width, 1, width, width * sizeof(*line),
|
||||
(uint8_t *)line, false);
|
||||
|
||||
@@ -724,17 +727,19 @@ void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
}
|
||||
|
||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown)
|
||||
void egl_desktopSwSurfaceDrawBitmap(EGL_Desktop * desktop,
|
||||
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||
bool topDown)
|
||||
{
|
||||
if (!desktop->spiceTexture || !data ||
|
||||
if (!desktop->swSurfaceTexture || !data ||
|
||||
width <= 0 || height <= 0 || stride <= 0 || width > stride / 4)
|
||||
return;
|
||||
|
||||
const int originalHeight = height;
|
||||
const int64_t right = (int64_t)x + width;
|
||||
const int64_t bottom = (int64_t)y + height;
|
||||
if (x >= desktop->spiceWidth || y >= desktop->spiceHeight ||
|
||||
if (x >= desktop->swSurfaceWidth ||
|
||||
y >= desktop->swSurfaceHeight ||
|
||||
right <= 0 || bottom <= 0)
|
||||
return;
|
||||
|
||||
@@ -742,22 +747,22 @@ void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
||||
const int sourceY = y < 0 ? -y : 0;
|
||||
x = x < 0 ? 0 : x;
|
||||
y = y < 0 ? 0 : y;
|
||||
width = (right > desktop->spiceWidth ?
|
||||
desktop->spiceWidth : (int)right ) - x;
|
||||
height = (bottom > desktop->spiceHeight ?
|
||||
desktop->spiceHeight : (int)bottom) - y;
|
||||
width = (right > desktop->swSurfaceWidth ?
|
||||
desktop->swSurfaceWidth : (int)right ) - x;
|
||||
height = (bottom > desktop->swSurfaceHeight ?
|
||||
desktop->swSurfaceHeight : (int)bottom) - y;
|
||||
|
||||
const int sourceRow = topDown ?
|
||||
sourceY : originalHeight - sourceY - height;
|
||||
data += (size_t)sourceRow * stride + (size_t)sourceX * 4;
|
||||
|
||||
egl_textureUpdateRect(desktop->spiceTexture,
|
||||
egl_textureUpdateRect(desktop->swSurfaceTexture,
|
||||
x, y, width, height, stride / 4, stride, data, topDown);
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
}
|
||||
|
||||
void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show)
|
||||
void egl_desktopSwSurfaceShow(EGL_Desktop * desktop, bool show)
|
||||
{
|
||||
desktop->useSpice = show;
|
||||
desktop->useSwSurface = show;
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
}
|
||||
|
||||
@@ -66,9 +66,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
LG_RendererFrameToken * renderedFrameToken,
|
||||
uint64_t * effectsTime, EGL_Framebuffer * target);
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height);
|
||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, uint32_t color);
|
||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown);
|
||||
void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show);
|
||||
void egl_desktopSwSurfaceConfigure(EGL_Desktop * desktop,
|
||||
int width, int height);
|
||||
void egl_desktopSwSurfaceDrawFill(EGL_Desktop * desktop,
|
||||
int x, int y, int width, int height, uint32_t color);
|
||||
void egl_desktopSwSurfaceDrawBitmap(EGL_Desktop * desktop,
|
||||
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||
bool topDown);
|
||||
void egl_desktopSwSurfaceShow(EGL_Desktop * desktop, bool show);
|
||||
|
||||
@@ -124,8 +124,8 @@ struct Inst
|
||||
int overlayHistoryCount[DESKTOP_DAMAGE_COUNT];
|
||||
unsigned int overlayHistoryIdx;
|
||||
|
||||
bool showSpice;
|
||||
int spiceWidth, spiceHeight;
|
||||
bool showSwSurface;
|
||||
int swSurfaceWidth, swSurfaceHeight;
|
||||
|
||||
bool surfaceSupportsPQ;
|
||||
bool surfaceSupportsSCRGB;
|
||||
@@ -391,13 +391,15 @@ static void egl_onRestart(LG_Renderer * renderer)
|
||||
|
||||
static void egl_calc_mouse_size(struct Inst * this)
|
||||
{
|
||||
if (this->showSpice)
|
||||
if (this->showSwSurface)
|
||||
{
|
||||
this->mouseScaleX = 2.0f / this->spiceWidth;
|
||||
this->mouseScaleY = 2.0f / this->spiceHeight;
|
||||
this->mouseScaleX = 2.0f / this->swSurfaceWidth;
|
||||
this->mouseScaleY = 2.0f / this->swSurfaceHeight;
|
||||
egl_cursorSetSize(this->cursor,
|
||||
(this->mouseWidth * (1.0f / this->spiceWidth )) * this->scaleX,
|
||||
(this->mouseHeight * (1.0f / this->spiceHeight)) * this->scaleY
|
||||
(this->mouseWidth *
|
||||
(1.0f / this->swSurfaceWidth )) * this->scaleX,
|
||||
(this->mouseHeight *
|
||||
(1.0f / this->swSurfaceHeight)) * this->scaleY
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -451,7 +453,7 @@ static void egl_calc_mouse_size(struct Inst * this)
|
||||
|
||||
static void egl_calc_mouse_state(struct Inst * this)
|
||||
{
|
||||
if (this->showSpice)
|
||||
if (this->showSwSurface)
|
||||
{
|
||||
egl_cursorSetState(
|
||||
this->cursor,
|
||||
@@ -648,7 +650,7 @@ static bool egl_updateHDRState(struct Inst * this, bool force)
|
||||
(this->surfaceSupportsPQ &&
|
||||
egl_hdrComposeIsConfigured(this->hdrCompose)) :
|
||||
this->surfaceSupportsSCRGB;
|
||||
const bool useNativeHDR = !this->showSpice && this->format.hdr &&
|
||||
const bool useNativeHDR = !this->showSwSurface && this->format.hdr &&
|
||||
surfaceCompatible && nativeHDR && !app_getHDRDescFailed();
|
||||
|
||||
LG_DSHDRWhiteLevels whiteLevels =
|
||||
@@ -1399,12 +1401,13 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
egl_desktopGetHDRMapping(this->desktop, &mapCursorHDR,
|
||||
&mapCursorGain, &mapCursorContentPeak);
|
||||
egl_cursorSetHDRState(this->cursor,
|
||||
this->format.hdr && !this->showSpice, this->nativeHDR, mapCursorHDR,
|
||||
this->format.hdr && !this->showSwSurface,
|
||||
this->nativeHDR, mapCursorHDR,
|
||||
this->format.hdrPQ, mapCursorGain, mapCursorContentPeak);
|
||||
bool renderAll = hdrStateChanged ||
|
||||
invalidateWindow || this->hadOverlay ||
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE ||
|
||||
this->showSpice;
|
||||
this->showSwSurface;
|
||||
|
||||
bool hasOverlay = false;
|
||||
struct CursorState cursorState = { .visible = false };
|
||||
@@ -1802,38 +1805,41 @@ static void egl_freeTexture(LG_Renderer * renderer, void * texture)
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
static void egl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
||||
static void egl_swSurfaceConfigure(LG_Renderer * renderer,
|
||||
int width, int height)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
this->spiceWidth = width;
|
||||
this->spiceHeight = height;
|
||||
egl_desktopSpiceConfigure(this->desktop, width, height);
|
||||
this->swSurfaceWidth = width;
|
||||
this->swSurfaceHeight = height;
|
||||
egl_desktopSwSurfaceConfigure(this->desktop, width, height);
|
||||
}
|
||||
|
||||
static void egl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, uint32_t color)
|
||||
static void egl_swSurfaceDrawFill(LG_Renderer * renderer,
|
||||
int x, int y, int width, int height, uint32_t color)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSpiceDrawFill(this->desktop, x, y, width, height, color);
|
||||
egl_desktopSwSurfaceDrawFill(
|
||||
this->desktop, x, y, width, height, color);
|
||||
}
|
||||
|
||||
static void egl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown)
|
||||
static void egl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||
bool topDown)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSpiceDrawBitmap(this->desktop, x, y, width, height, stride,
|
||||
data, topDown);
|
||||
egl_desktopSwSurfaceDrawBitmap(
|
||||
this->desktop, x, y, width, height, stride, data, topDown);
|
||||
}
|
||||
|
||||
static void egl_spiceShow(LG_Renderer * renderer, bool show)
|
||||
static void egl_swSurfaceShow(LG_Renderer * renderer, bool show)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
this->showSpice = show;
|
||||
this->showSwSurface = show;
|
||||
egl_calc_mouse_size(this);
|
||||
egl_desktopSpiceShow(this->desktop, show);
|
||||
egl_desktopSwSurfaceShow(this->desktop, show);
|
||||
}
|
||||
|
||||
struct LG_RendererOps LGR_EGL =
|
||||
@@ -1861,8 +1867,8 @@ struct LG_RendererOps LGR_EGL =
|
||||
.createTexture = egl_createTexture,
|
||||
.freeTexture = egl_freeTexture,
|
||||
|
||||
.spiceConfigure = egl_spiceConfigure,
|
||||
.spiceDrawFill = egl_spiceDrawFill,
|
||||
.spiceDrawBitmap = egl_spiceDrawBitmap,
|
||||
.spiceShow = egl_spiceShow
|
||||
.swSurfaceConfigure = egl_swSurfaceConfigure,
|
||||
.swSurfaceDrawFill = egl_swSurfaceDrawFill,
|
||||
.swSurfaceDrawBitmap = egl_swSurfaceDrawBitmap,
|
||||
.swSurfaceShow = egl_swSurfaceShow
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user