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:
@@ -41,10 +41,10 @@
|
|||||||
(x)->render && \
|
(x)->render && \
|
||||||
(x)->createTexture && \
|
(x)->createTexture && \
|
||||||
(x)->freeTexture && \
|
(x)->freeTexture && \
|
||||||
(x)->spiceConfigure && \
|
(x)->swSurfaceConfigure && \
|
||||||
(x)->spiceDrawFill && \
|
(x)->swSurfaceDrawFill && \
|
||||||
(x)->spiceDrawBitmap && \
|
(x)->swSurfaceDrawBitmap && \
|
||||||
(x)->spiceShow)
|
(x)->swSurfaceShow)
|
||||||
|
|
||||||
typedef struct LG_RendererParams
|
typedef struct LG_RendererParams
|
||||||
{
|
{
|
||||||
@@ -300,19 +300,21 @@ typedef struct LG_RendererOps
|
|||||||
* Context: renderThread */
|
* Context: renderThread */
|
||||||
void (*freeTexture)(LG_Renderer * renderer, void * texture);
|
void (*freeTexture)(LG_Renderer * renderer, void * texture);
|
||||||
|
|
||||||
/* setup the spice display */
|
/* setup the incremental software surface */
|
||||||
void (*spiceConfigure)(LG_Renderer * renderer, int width, int height);
|
void (*swSurfaceConfigure)(LG_Renderer * renderer,
|
||||||
|
int width, int height);
|
||||||
|
|
||||||
/* draw a filled rect on the spice display with the specified color */
|
/* draw a filled rect on the software surface with the specified color */
|
||||||
void (*spiceDrawFill)(LG_Renderer * renderer, int x, int y, int width,
|
void (*swSurfaceDrawFill)(LG_Renderer * renderer,
|
||||||
int height, uint32_t color);
|
int x, int y, int width, int height, uint32_t color);
|
||||||
|
|
||||||
/* draw an image on the spice display, data is RGBA32 */
|
/* draw an image on the software surface, data is RGBA32 */
|
||||||
void (*spiceDrawBitmap)(LG_Renderer * renderer, int x, int y, int width,
|
void (*swSurfaceDrawBitmap)(LG_Renderer * renderer,
|
||||||
int height, int stride, uint8_t * data, bool topDown);
|
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||||
|
bool topDown);
|
||||||
|
|
||||||
/* show the spice display */
|
/* show the incremental software surface */
|
||||||
void (*spiceShow)(LG_Renderer * renderer, bool show);
|
void (*swSurfaceShow)(LG_Renderer * renderer, bool show);
|
||||||
}
|
}
|
||||||
LG_RendererOps;
|
LG_RendererOps;
|
||||||
|
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ struct EGL_Desktop
|
|||||||
bool hdrPQ;
|
bool hdrPQ;
|
||||||
LG_RendererRotate rotate;
|
LG_RendererRotate rotate;
|
||||||
|
|
||||||
bool useSpice;
|
bool useSwSurface;
|
||||||
int spiceWidth, spiceHeight;
|
int swSurfaceWidth, swSurfaceHeight;
|
||||||
EGL_Texture * spiceTexture;
|
EGL_Texture * swSurfaceTexture;
|
||||||
|
|
||||||
// scale algorithm
|
// scale algorithm
|
||||||
int scaleAlgo;
|
int scaleAlgo;
|
||||||
@@ -251,7 +251,7 @@ void egl_desktopFree(EGL_Desktop ** desktop)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
egl_textureFree (&(*desktop)->texture );
|
egl_textureFree (&(*desktop)->texture );
|
||||||
egl_textureFree (&(*desktop)->spiceTexture );
|
egl_textureFree (&(*desktop)->swSurfaceTexture);
|
||||||
egl_shaderFree (&(*desktop)->shader .shader);
|
egl_shaderFree (&(*desktop)->shader .shader);
|
||||||
egl_desktopRectsFree(&(*desktop)->mesh );
|
egl_desktopRectsFree(&(*desktop)->mesh );
|
||||||
egl_postProcessFree(&(*desktop)->pp);
|
egl_postProcessFree(&(*desktop)->pp);
|
||||||
@@ -470,14 +470,15 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
EGL_Texture * tex;
|
EGL_Texture * tex;
|
||||||
int width, height;
|
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);
|
egl_texturePoll(desktop->texture);
|
||||||
|
|
||||||
if (unlikely(desktop->useSpice))
|
if (unlikely(desktop->useSwSurface))
|
||||||
{
|
{
|
||||||
tex = desktop->spiceTexture;
|
tex = desktop->swSurfaceTexture;
|
||||||
width = desktop->spiceWidth;
|
width = desktop->swSurfaceWidth;
|
||||||
height = desktop->spiceHeight;
|
height = desktop->swSurfaceHeight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -519,7 +520,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
rects ? rects->rects : NULL, rects ? rects->count : -1,
|
rects ? rects->rects : NULL, rects ? rects->count : -1,
|
||||||
width, height);
|
width, height);
|
||||||
|
|
||||||
const bool hdr = desktop->hdr && !desktop->useSpice;
|
const bool hdr = desktop->hdr && !desktop->useSwSurface;
|
||||||
uint32_t hdrPeak = 0;
|
uint32_t hdrPeak = 0;
|
||||||
if (hdr)
|
if (hdr)
|
||||||
{
|
{
|
||||||
@@ -579,7 +580,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
{
|
{
|
||||||
if (bindStatus != EGL_TEX_STATUS_NOTREADY)
|
if (bindStatus != EGL_TEX_STATUS_NOTREADY)
|
||||||
DEBUG_ERROR("Failed to bind the desktop texture");
|
DEBUG_ERROR("Failed to bind the desktop texture");
|
||||||
if (!desktop->useSpice && desktop->useDMA && processFrame)
|
if (!desktop->useSwSurface && desktop->useDMA && processFrame)
|
||||||
egl_textureMarkUsed(desktop->texture);
|
egl_textureMarkUsed(desktop->texture);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -633,7 +634,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
desktop->linearComposition);
|
desktop->linearComposition);
|
||||||
egl_shaderUse(shader->shader);
|
egl_shaderUse(shader->shader);
|
||||||
egl_desktopRectsRender(desktop->mesh);
|
egl_desktopRectsRender(desktop->mesh);
|
||||||
if (!desktop->useSpice && desktop->useDMA &&
|
if (!desktop->useSwSurface && desktop->useDMA &&
|
||||||
(processFrame || texture == tex))
|
(processFrame || texture == tex))
|
||||||
egl_textureMarkUsed(desktop->texture);
|
egl_textureMarkUsed(desktop->texture);
|
||||||
return true;
|
return true;
|
||||||
@@ -649,25 +650,26 @@ void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR,
|
|||||||
void egl_desktopGetHDRMapping(EGL_Desktop * desktop, bool * enabled,
|
void egl_desktopGetHDRMapping(EGL_Desktop * desktop, bool * enabled,
|
||||||
float * gain, float * contentPeak)
|
float * gain, float * contentPeak)
|
||||||
{
|
{
|
||||||
*enabled = desktop->hdr && !desktop->useSpice &&
|
*enabled = desktop->hdr && !desktop->useSwSurface &&
|
||||||
desktop->mapHDRtoSDR && !desktop->nativeHDR;
|
desktop->mapHDRtoSDR && !desktop->nativeHDR;
|
||||||
*gain = (desktop->hdrPQ ? 10000.0f : 80.0f) /
|
*gain = (desktop->hdrPQ ? 10000.0f : 80.0f) /
|
||||||
desktop->peakLuminance;
|
desktop->peakLuminance;
|
||||||
*contentPeak = (float)desktop->maxCLL / 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 (!desktop->swSurfaceTexture)
|
||||||
if (!egl_textureInit(&desktop->spiceTexture, desktop->display,
|
if (!egl_textureInit(&desktop->swSurfaceTexture, desktop->display,
|
||||||
EGL_TEXTYPE_BUFFER_MAP))
|
EGL_TEXTYPE_BUFFER_MAP))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the spice desktop texture");
|
DEBUG_ERROR("Failed to initialize the software surface texture");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_textureSetup(
|
if (!egl_textureSetup(
|
||||||
desktop->spiceTexture,
|
desktop->swSurfaceTexture,
|
||||||
EGL_PF_BGRA,
|
EGL_PF_BGRA,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@@ -675,40 +677,41 @@ void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
|||||||
width * 4
|
width * 4
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to setup the spice desktop texture");
|
DEBUG_ERROR("Failed to setup the software surface texture");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop->spiceWidth = width;
|
desktop->swSurfaceWidth = width;
|
||||||
desktop->spiceHeight = height;
|
desktop->swSurfaceHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
void egl_desktopSwSurfaceDrawFill(EGL_Desktop * desktop,
|
||||||
int height, uint32_t color)
|
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;
|
return;
|
||||||
|
|
||||||
const int64_t right = (int64_t)x + width;
|
const int64_t right = (int64_t)x + width;
|
||||||
const int64_t bottom = (int64_t)y + height;
|
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)
|
right <= 0 || bottom <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
x = x < 0 ? 0 : x;
|
x = x < 0 ? 0 : x;
|
||||||
y = y < 0 ? 0 : y;
|
y = y < 0 ? 0 : y;
|
||||||
width = (right > desktop->spiceWidth ?
|
width = (right > desktop->swSurfaceWidth ?
|
||||||
desktop->spiceWidth : (int)right ) - x;
|
desktop->swSurfaceWidth : (int)right ) - x;
|
||||||
height = (bottom > desktop->spiceHeight ?
|
height = (bottom > desktop->swSurfaceHeight ?
|
||||||
desktop->spiceHeight : (int)bottom) - y;
|
desktop->swSurfaceHeight : (int)bottom) - y;
|
||||||
|
|
||||||
/* this is a fairly hacky way to do this, but since it's only for the fallback
|
/* This is a fairly hacky way to update a software surface, but it preserves
|
||||||
* spice display it's not really an issue */
|
* the existing incremental fill behavior. */
|
||||||
|
|
||||||
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate SPICE fill row");
|
DEBUG_ERROR("Failed to allocate software surface fill row");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,7 +719,7 @@ void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
|||||||
line[i] = color;
|
line[i] = color;
|
||||||
|
|
||||||
for(int dy = 0; dy < height; ++dy)
|
for(int dy = 0; dy < height; ++dy)
|
||||||
egl_textureUpdateRect(desktop->spiceTexture,
|
egl_textureUpdateRect(desktop->swSurfaceTexture,
|
||||||
x, y + dy, width, 1, width, width * sizeof(*line),
|
x, y + dy, width, 1, width, width * sizeof(*line),
|
||||||
(uint8_t *)line, false);
|
(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);
|
atomic_store(&desktop->processFrame, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
void egl_desktopSwSurfaceDrawBitmap(EGL_Desktop * desktop,
|
||||||
int height, int stride, uint8_t * data, bool topDown)
|
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)
|
width <= 0 || height <= 0 || stride <= 0 || width > stride / 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int originalHeight = height;
|
const int originalHeight = height;
|
||||||
const int64_t right = (int64_t)x + width;
|
const int64_t right = (int64_t)x + width;
|
||||||
const int64_t bottom = (int64_t)y + height;
|
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)
|
right <= 0 || bottom <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -742,22 +747,22 @@ void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
|||||||
const int sourceY = y < 0 ? -y : 0;
|
const int sourceY = y < 0 ? -y : 0;
|
||||||
x = x < 0 ? 0 : x;
|
x = x < 0 ? 0 : x;
|
||||||
y = y < 0 ? 0 : y;
|
y = y < 0 ? 0 : y;
|
||||||
width = (right > desktop->spiceWidth ?
|
width = (right > desktop->swSurfaceWidth ?
|
||||||
desktop->spiceWidth : (int)right ) - x;
|
desktop->swSurfaceWidth : (int)right ) - x;
|
||||||
height = (bottom > desktop->spiceHeight ?
|
height = (bottom > desktop->swSurfaceHeight ?
|
||||||
desktop->spiceHeight : (int)bottom) - y;
|
desktop->swSurfaceHeight : (int)bottom) - y;
|
||||||
|
|
||||||
const int sourceRow = topDown ?
|
const int sourceRow = topDown ?
|
||||||
sourceY : originalHeight - sourceY - height;
|
sourceY : originalHeight - sourceY - height;
|
||||||
data += (size_t)sourceRow * stride + (size_t)sourceX * 4;
|
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);
|
x, y, width, height, stride / 4, stride, data, topDown);
|
||||||
atomic_store(&desktop->processFrame, true);
|
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);
|
atomic_store(&desktop->processFrame, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,9 +66,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
LG_RendererFrameToken * renderedFrameToken,
|
LG_RendererFrameToken * renderedFrameToken,
|
||||||
uint64_t * effectsTime, EGL_Framebuffer * target);
|
uint64_t * effectsTime, EGL_Framebuffer * target);
|
||||||
|
|
||||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height);
|
void egl_desktopSwSurfaceConfigure(EGL_Desktop * desktop,
|
||||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
int width, int height);
|
||||||
int height, uint32_t color);
|
void egl_desktopSwSurfaceDrawFill(EGL_Desktop * desktop,
|
||||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
int x, int y, int width, int height, uint32_t color);
|
||||||
int height, int stride, uint8_t * data, bool topDown);
|
void egl_desktopSwSurfaceDrawBitmap(EGL_Desktop * desktop,
|
||||||
void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show);
|
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];
|
int overlayHistoryCount[DESKTOP_DAMAGE_COUNT];
|
||||||
unsigned int overlayHistoryIdx;
|
unsigned int overlayHistoryIdx;
|
||||||
|
|
||||||
bool showSpice;
|
bool showSwSurface;
|
||||||
int spiceWidth, spiceHeight;
|
int swSurfaceWidth, swSurfaceHeight;
|
||||||
|
|
||||||
bool surfaceSupportsPQ;
|
bool surfaceSupportsPQ;
|
||||||
bool surfaceSupportsSCRGB;
|
bool surfaceSupportsSCRGB;
|
||||||
@@ -391,13 +391,15 @@ static void egl_onRestart(LG_Renderer * renderer)
|
|||||||
|
|
||||||
static void egl_calc_mouse_size(struct Inst * this)
|
static void egl_calc_mouse_size(struct Inst * this)
|
||||||
{
|
{
|
||||||
if (this->showSpice)
|
if (this->showSwSurface)
|
||||||
{
|
{
|
||||||
this->mouseScaleX = 2.0f / this->spiceWidth;
|
this->mouseScaleX = 2.0f / this->swSurfaceWidth;
|
||||||
this->mouseScaleY = 2.0f / this->spiceHeight;
|
this->mouseScaleY = 2.0f / this->swSurfaceHeight;
|
||||||
egl_cursorSetSize(this->cursor,
|
egl_cursorSetSize(this->cursor,
|
||||||
(this->mouseWidth * (1.0f / this->spiceWidth )) * this->scaleX,
|
(this->mouseWidth *
|
||||||
(this->mouseHeight * (1.0f / this->spiceHeight)) * this->scaleY
|
(1.0f / this->swSurfaceWidth )) * this->scaleX,
|
||||||
|
(this->mouseHeight *
|
||||||
|
(1.0f / this->swSurfaceHeight)) * this->scaleY
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -451,7 +453,7 @@ static void egl_calc_mouse_size(struct Inst * this)
|
|||||||
|
|
||||||
static void egl_calc_mouse_state(struct Inst * this)
|
static void egl_calc_mouse_state(struct Inst * this)
|
||||||
{
|
{
|
||||||
if (this->showSpice)
|
if (this->showSwSurface)
|
||||||
{
|
{
|
||||||
egl_cursorSetState(
|
egl_cursorSetState(
|
||||||
this->cursor,
|
this->cursor,
|
||||||
@@ -648,7 +650,7 @@ static bool egl_updateHDRState(struct Inst * this, bool force)
|
|||||||
(this->surfaceSupportsPQ &&
|
(this->surfaceSupportsPQ &&
|
||||||
egl_hdrComposeIsConfigured(this->hdrCompose)) :
|
egl_hdrComposeIsConfigured(this->hdrCompose)) :
|
||||||
this->surfaceSupportsSCRGB;
|
this->surfaceSupportsSCRGB;
|
||||||
const bool useNativeHDR = !this->showSpice && this->format.hdr &&
|
const bool useNativeHDR = !this->showSwSurface && this->format.hdr &&
|
||||||
surfaceCompatible && nativeHDR && !app_getHDRDescFailed();
|
surfaceCompatible && nativeHDR && !app_getHDRDescFailed();
|
||||||
|
|
||||||
LG_DSHDRWhiteLevels whiteLevels =
|
LG_DSHDRWhiteLevels whiteLevels =
|
||||||
@@ -1399,12 +1401,13 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
|||||||
egl_desktopGetHDRMapping(this->desktop, &mapCursorHDR,
|
egl_desktopGetHDRMapping(this->desktop, &mapCursorHDR,
|
||||||
&mapCursorGain, &mapCursorContentPeak);
|
&mapCursorGain, &mapCursorContentPeak);
|
||||||
egl_cursorSetHDRState(this->cursor,
|
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);
|
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->showSpice;
|
this->showSwSurface;
|
||||||
|
|
||||||
bool hasOverlay = false;
|
bool hasOverlay = false;
|
||||||
struct CursorState cursorState = { .visible = false };
|
struct CursorState cursorState = { .visible = false };
|
||||||
@@ -1802,38 +1805,41 @@ static void egl_freeTexture(LG_Renderer * renderer, void * texture)
|
|||||||
egl_stateInvalidateShared();
|
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);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
egl_stateCheckShared();
|
egl_stateCheckShared();
|
||||||
this->spiceWidth = width;
|
this->swSurfaceWidth = width;
|
||||||
this->spiceHeight = height;
|
this->swSurfaceHeight = height;
|
||||||
egl_desktopSpiceConfigure(this->desktop, width, height);
|
egl_desktopSwSurfaceConfigure(this->desktop, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void egl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
static void egl_swSurfaceDrawFill(LG_Renderer * renderer,
|
||||||
int height, uint32_t color)
|
int x, int y, int width, int height, uint32_t color)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
egl_stateCheckShared();
|
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,
|
static void egl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||||
int height, int stride, uint8_t * data, bool topDown)
|
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||||
|
bool topDown)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
egl_stateCheckShared();
|
egl_stateCheckShared();
|
||||||
egl_desktopSpiceDrawBitmap(this->desktop, x, y, width, height, stride,
|
egl_desktopSwSurfaceDrawBitmap(
|
||||||
data, topDown);
|
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);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
this->showSpice = show;
|
this->showSwSurface = show;
|
||||||
egl_calc_mouse_size(this);
|
egl_calc_mouse_size(this);
|
||||||
egl_desktopSpiceShow(this->desktop, show);
|
egl_desktopSwSurfaceShow(this->desktop, show);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LG_RendererOps LGR_EGL =
|
struct LG_RendererOps LGR_EGL =
|
||||||
@@ -1861,8 +1867,8 @@ struct LG_RendererOps LGR_EGL =
|
|||||||
.createTexture = egl_createTexture,
|
.createTexture = egl_createTexture,
|
||||||
.freeTexture = egl_freeTexture,
|
.freeTexture = egl_freeTexture,
|
||||||
|
|
||||||
.spiceConfigure = egl_spiceConfigure,
|
.swSurfaceConfigure = egl_swSurfaceConfigure,
|
||||||
.spiceDrawFill = egl_spiceDrawFill,
|
.swSurfaceDrawFill = egl_swSurfaceDrawFill,
|
||||||
.spiceDrawBitmap = egl_spiceDrawBitmap,
|
.swSurfaceDrawBitmap = egl_swSurfaceDrawBitmap,
|
||||||
.spiceShow = egl_spiceShow
|
.swSurfaceShow = egl_swSurfaceShow
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
#define FPS_TEXTURE 0
|
#define FPS_TEXTURE 0
|
||||||
#define MOUSE_TEXTURE 1
|
#define MOUSE_TEXTURE 1
|
||||||
#define SPICE_TEXTURE 2
|
#define SW_SURFACE_TEXTURE 2
|
||||||
#define TEXTURE_COUNT 3
|
#define TEXTURE_COUNT 3
|
||||||
|
|
||||||
static struct Option opengl_options[] =
|
static struct Option opengl_options[] =
|
||||||
@@ -137,10 +137,10 @@ struct Inst
|
|||||||
int texWIndex, texRIndex;
|
int texWIndex, texRIndex;
|
||||||
int texList;
|
int texList;
|
||||||
int mouseList;
|
int mouseList;
|
||||||
int spiceList;
|
int swSurfaceList;
|
||||||
LG_RendererRect destRect;
|
LG_RendererRect destRect;
|
||||||
struct IntPoint spiceSize;
|
struct IntPoint swSurfaceSize;
|
||||||
bool spiceShow;
|
bool showSwSurface;
|
||||||
|
|
||||||
bool hasTextures, hasFrames;
|
bool hasTextures, hasFrames;
|
||||||
GLuint frames[BUFFER_COUNT];
|
GLuint frames[BUFFER_COUNT];
|
||||||
@@ -235,8 +235,8 @@ void opengl_deinitialize(LG_Renderer * renderer)
|
|||||||
ImGui_ImplOpenGL2_Shutdown();
|
ImGui_ImplOpenGL2_Shutdown();
|
||||||
|
|
||||||
glDeleteLists(this->texList , BUFFER_COUNT);
|
glDeleteLists(this->texList , BUFFER_COUNT);
|
||||||
glDeleteLists(this->mouseList, 1);
|
glDeleteLists(this->mouseList , 1);
|
||||||
glDeleteLists(this->spiceList, 1);
|
glDeleteLists(this->swSurfaceList, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
deconfigure(this);
|
deconfigure(this);
|
||||||
@@ -277,10 +277,10 @@ static void setupModelView(struct Inst * this)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int fw, fh;
|
int fw, fh;
|
||||||
if (this->spiceShow)
|
if (this->showSwSurface)
|
||||||
{
|
{
|
||||||
fw = this->spiceSize.x;
|
fw = this->swSurfaceSize.x;
|
||||||
fh = this->spiceSize.y;
|
fh = this->swSurfaceSize.y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -478,7 +478,7 @@ bool opengl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
|||||||
// generate lists for drawing
|
// generate lists for drawing
|
||||||
this->texList = glGenLists(BUFFER_COUNT);
|
this->texList = glGenLists(BUFFER_COUNT);
|
||||||
this->mouseList = glGenLists(1);
|
this->mouseList = glGenLists(1);
|
||||||
this->spiceList = glGenLists(1);
|
this->swSurfaceList = glGenLists(1);
|
||||||
|
|
||||||
// create the overlay textures
|
// create the overlay textures
|
||||||
glGenTextures(TEXTURE_COUNT, this->textures);
|
glGenTextures(TEXTURE_COUNT, this->textures);
|
||||||
@@ -527,8 +527,8 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
updateMouseShape(this);
|
updateMouseShape(this);
|
||||||
if (this->spiceShow)
|
if (this->showSwSurface)
|
||||||
glCallList(this->spiceList);
|
glCallList(this->swSurfaceList);
|
||||||
else
|
else
|
||||||
glCallList(this->texList + this->texRIndex);
|
glCallList(this->texList + this->texRIndex);
|
||||||
drawMouse(this);
|
drawMouse(this);
|
||||||
@@ -587,13 +587,14 @@ static void opengl_freeTexture(LG_Renderer * renderer, void * texture)
|
|||||||
glDeleteTextures(1, &tex);
|
glDeleteTextures(1, &tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opengl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
static void opengl_swSurfaceConfigure(LG_Renderer * renderer,
|
||||||
|
int width, int height)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
this->spiceSize.x = width;
|
this->swSurfaceSize.x = width;
|
||||||
this->spiceSize.y = height;
|
this->swSurfaceSize.y = height;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glTexImage2D
|
glTexImage2D
|
||||||
(
|
(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
@@ -614,22 +615,26 @@ static void opengl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// create the display lists
|
// create the display lists
|
||||||
glNewList(this->spiceList, GL_COMPILE);
|
glNewList(this->swSurfaceList, GL_COMPILE);
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D,
|
||||||
|
this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
|
glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
|
||||||
glTexCoord2f(1.0f, 0.0f); glVertex2i(this->spiceSize.x, 0);
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
glTexCoord2f(0.0f, 1.0f); glVertex2i(0, this->spiceSize.y);
|
glVertex2i(this->swSurfaceSize.x, 0);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex2i(0, this->swSurfaceSize.y);
|
||||||
glTexCoord2f(1.0f, 1.0f);
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
glVertex2i(this->spiceSize.x, this->spiceSize.y);
|
glVertex2i(
|
||||||
|
this->swSurfaceSize.x, this->swSurfaceSize.y);
|
||||||
glEnd();
|
glEnd();
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glEndList();
|
glEndList();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opengl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
static void opengl_swSurfaceDrawFill(LG_Renderer * renderer,
|
||||||
int height, uint32_t color)
|
int x, int y, int width, int height, uint32_t color)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
@@ -638,31 +643,32 @@ static void opengl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width
|
|||||||
|
|
||||||
const int64_t right = (int64_t)x + width;
|
const int64_t right = (int64_t)x + width;
|
||||||
const int64_t bottom = (int64_t)y + height;
|
const int64_t bottom = (int64_t)y + height;
|
||||||
if (x >= this->spiceSize.x || y >= this->spiceSize.y ||
|
if (x >= this->swSurfaceSize.x ||
|
||||||
|
y >= this->swSurfaceSize.y ||
|
||||||
right <= 0 || bottom <= 0)
|
right <= 0 || bottom <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
x = x < 0 ? 0 : x;
|
x = x < 0 ? 0 : x;
|
||||||
y = y < 0 ? 0 : y;
|
y = y < 0 ? 0 : y;
|
||||||
width = (right > this->spiceSize.x ?
|
width = (right > this->swSurfaceSize.x ?
|
||||||
this->spiceSize.x : (int)right ) - x;
|
this->swSurfaceSize.x : (int)right ) - x;
|
||||||
height = (bottom > this->spiceSize.y ?
|
height = (bottom > this->swSurfaceSize.y ?
|
||||||
this->spiceSize.y : (int)bottom) - y;
|
this->swSurfaceSize.y : (int)bottom) - y;
|
||||||
|
|
||||||
/* this is a fairly hacky way to do this, but since it's only for the fallback
|
/* This is a fairly hacky way to update a software surface, but it preserves
|
||||||
* spice display it's not really an issue */
|
* the existing incremental fill behavior. */
|
||||||
|
|
||||||
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate SPICE fill row");
|
DEBUG_ERROR("Failed to allocate software surface fill row");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < width; ++i)
|
for(int i = 0; i < width; ++i)
|
||||||
line[i] = color;
|
line[i] = color;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
for(int dy = 0; dy < height; ++dy)
|
for(int dy = 0; dy < height; ++dy)
|
||||||
@@ -682,8 +688,9 @@ static void opengl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width
|
|||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opengl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int width,
|
static void opengl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||||
int height, int stride, uint8_t * data, bool topDown)
|
int x, int y, int width, int height, int stride, uint8_t * data,
|
||||||
|
bool topDown)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
@@ -693,11 +700,11 @@ static void opengl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int wid
|
|||||||
|
|
||||||
if (!topDown)
|
if (!topDown)
|
||||||
{
|
{
|
||||||
// this is non-optimal but as spice is a fallback it's not too critical
|
// This is non-optimal, but the incremental surface is a fallback.
|
||||||
uint8_t * line = malloc((size_t)stride);
|
uint8_t * line = malloc((size_t)stride);
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate SPICE bitmap row");
|
DEBUG_ERROR("Failed to allocate software surface bitmap row");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +721,8 @@ static void opengl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int wid
|
|||||||
|
|
||||||
const int64_t right = (int64_t)x + width;
|
const int64_t right = (int64_t)x + width;
|
||||||
const int64_t bottom = (int64_t)y + height;
|
const int64_t bottom = (int64_t)y + height;
|
||||||
if (x >= this->spiceSize.x || y >= this->spiceSize.y ||
|
if (x >= this->swSurfaceSize.x ||
|
||||||
|
y >= this->swSurfaceSize.y ||
|
||||||
right <= 0 || bottom <= 0)
|
right <= 0 || bottom <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -722,13 +730,13 @@ static void opengl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int wid
|
|||||||
const int sourceY = y < 0 ? -y : 0;
|
const int sourceY = y < 0 ? -y : 0;
|
||||||
x = x < 0 ? 0 : x;
|
x = x < 0 ? 0 : x;
|
||||||
y = y < 0 ? 0 : y;
|
y = y < 0 ? 0 : y;
|
||||||
width = (right > this->spiceSize.x ?
|
width = (right > this->swSurfaceSize.x ?
|
||||||
this->spiceSize.x : (int)right ) - x;
|
this->swSurfaceSize.x : (int)right ) - x;
|
||||||
height = (bottom > this->spiceSize.y ?
|
height = (bottom > this->swSurfaceSize.y ?
|
||||||
this->spiceSize.y : (int)bottom) - y;
|
this->swSurfaceSize.y : (int)bottom) - y;
|
||||||
data += (size_t)sourceY * stride + (size_t)sourceX * 4;
|
data += (size_t)sourceY * stride + (size_t)sourceX * 4;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4);
|
||||||
glTexSubImage2D
|
glTexSubImage2D
|
||||||
@@ -746,10 +754,10 @@ static void opengl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int wid
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opengl_spiceShow(LG_Renderer * renderer, bool show)
|
static void opengl_swSurfaceShow(LG_Renderer * renderer, bool show)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
this->spiceShow = show;
|
this->showSwSurface = show;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LG_RendererOps LGR_OpenGL =
|
const LG_RendererOps LGR_OpenGL =
|
||||||
@@ -772,10 +780,10 @@ const LG_RendererOps LGR_OpenGL =
|
|||||||
.createTexture = opengl_createTexture,
|
.createTexture = opengl_createTexture,
|
||||||
.freeTexture = opengl_freeTexture,
|
.freeTexture = opengl_freeTexture,
|
||||||
|
|
||||||
.spiceConfigure = opengl_spiceConfigure,
|
.swSurfaceConfigure = opengl_swSurfaceConfigure,
|
||||||
.spiceDrawFill = opengl_spiceDrawFill,
|
.swSurfaceDrawFill = opengl_swSurfaceDrawFill,
|
||||||
.spiceDrawBitmap = opengl_spiceDrawBitmap,
|
.swSurfaceDrawBitmap = opengl_swSurfaceDrawBitmap,
|
||||||
.spiceShow = opengl_spiceShow
|
.swSurfaceShow = opengl_swSurfaceShow
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _checkGLError(unsigned int line, const char * name)
|
static bool _checkGLError(unsigned int line, const char * name)
|
||||||
|
|||||||
@@ -1202,7 +1202,7 @@ bool app_useSpiceDisplay(bool enable)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderQueue_spiceShow(true);
|
renderQueue_swSurfaceShow(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1215,7 +1215,7 @@ bool app_useSpiceDisplay(bool enable)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderQueue_spiceShow(false);
|
renderQueue_swSurfaceShow(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
active = enable;
|
active = enable;
|
||||||
|
|||||||
@@ -1608,8 +1608,8 @@ static void spice_surfaceCreate(unsigned int surfaceId, PSSurfaceFormat format,
|
|||||||
g_state.haveSrcSize = true;
|
g_state.haveSrcSize = true;
|
||||||
core_updatePositionInfo();
|
core_updatePositionInfo();
|
||||||
|
|
||||||
renderQueue_spiceConfigure(width, height);
|
renderQueue_swSurfaceConfigure(width, height);
|
||||||
renderQueue_spiceDrawFill(0, 0, width, height, 0x0);
|
renderQueue_swSurfaceDrawFill(0, 0, width, height, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spice_surfaceDestroy(unsigned int surfaceId)
|
static void spice_surfaceDestroy(unsigned int surfaceId)
|
||||||
@@ -1632,7 +1632,7 @@ static void spice_drawFill(unsigned int surfaceId, int x, int y, int width,
|
|||||||
if (!g_state.spicePrimarySurfaceValid || surfaceId != 0)
|
if (!g_state.spicePrimarySurfaceValid || surfaceId != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
renderQueue_spiceDrawFill(x, y, width, height, color);
|
renderQueue_swSurfaceDrawFill(x, y, width, height, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spice_drawBitmap(unsigned int surfaceId, PSBitmapFormat format,
|
static void spice_drawBitmap(unsigned int surfaceId, PSBitmapFormat format,
|
||||||
@@ -1652,7 +1652,7 @@ static void spice_drawBitmap(unsigned int surfaceId, PSBitmapFormat format,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderQueue_spiceDrawBitmap(x, y, width, height, stride, data, topDown);
|
renderQueue_swSurfaceDrawBitmap(x, y, width, height, stride, data, topDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spice_setCursorRGBAImage(int width, int height, int hx, int hy,
|
static void spice_setCursorRGBAImage(int width, int height, int hx, int hy,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "overlays.h"
|
#include "overlays.h"
|
||||||
|
|
||||||
struct ll * l_renderQueue = NULL;
|
struct ll * l_renderQueue = NULL;
|
||||||
static bool l_showSpice;
|
static bool l_showSwSurface;
|
||||||
static bool l_surfaceFormatValid;
|
static bool l_surfaceFormatValid;
|
||||||
static bool l_rendererSupportsNativeHDR;
|
static bool l_rendererSupportsNativeHDR;
|
||||||
static LG_RendererFormat l_surfaceFormat;
|
static LG_RendererFormat l_surfaceFormat;
|
||||||
@@ -43,10 +43,10 @@ static void updateSurfaceFormat(void)
|
|||||||
if (l_surfaceFormatValid)
|
if (l_surfaceFormatValid)
|
||||||
format = l_surfaceFormat;
|
format = l_surfaceFormat;
|
||||||
|
|
||||||
if (l_showSpice)
|
if (l_showSwSurface)
|
||||||
{
|
{
|
||||||
// The SPICE display is always 8-bit SDR, regardless of the last format
|
// The software surface is always 8-bit SDR, regardless of the last frame
|
||||||
// received from the Looking Glass host.
|
// format received from the active frame provider.
|
||||||
format.hdr = false;
|
format.hdr = false;
|
||||||
format.hdrPQ = false;
|
format.hdrPQ = false;
|
||||||
format.hdrMetadata = false;
|
format.hdrMetadata = false;
|
||||||
@@ -80,7 +80,7 @@ static void updateSurfaceFormat(void)
|
|||||||
void renderQueue_init(void)
|
void renderQueue_init(void)
|
||||||
{
|
{
|
||||||
l_renderQueue = ll_new();
|
l_renderQueue = ll_new();
|
||||||
l_showSpice = false;
|
l_showSwSurface = false;
|
||||||
l_surfaceFormatValid = false;
|
l_surfaceFormatValid = false;
|
||||||
l_rendererSupportsNativeHDR = false;
|
l_rendererSupportsNativeHDR = false;
|
||||||
memset(&l_surfaceFormat, 0, sizeof(l_surfaceFormat));
|
memset(&l_surfaceFormat, 0, sizeof(l_surfaceFormat));
|
||||||
@@ -100,56 +100,58 @@ void renderQueue_clear(void)
|
|||||||
RenderCommand * cmd;
|
RenderCommand * cmd;
|
||||||
while(ll_shift(l_renderQueue, (void **)&cmd))
|
while(ll_shift(l_renderQueue, (void **)&cmd))
|
||||||
{
|
{
|
||||||
if (cmd->op == SPICE_OP_DRAW_BITMAP)
|
if (cmd->op == SW_SURFACE_OP_DRAW_BITMAP)
|
||||||
free(cmd->spiceDrawBitmap.data);
|
free(cmd->swSurfaceDrawBitmap.data);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_spiceConfigure(int width, int height)
|
void renderQueue_swSurfaceConfigure(int width, int height)
|
||||||
{
|
{
|
||||||
RenderCommand * cmd = malloc(sizeof(*cmd));
|
RenderCommand * cmd = malloc(sizeof(*cmd));
|
||||||
cmd->op = SPICE_OP_CONFIGURE;
|
cmd->op = SW_SURFACE_OP_CONFIGURE;
|
||||||
cmd->spiceConfigure.width = width;
|
cmd->swSurfaceConfigure.width = width;
|
||||||
cmd->spiceConfigure.height = height;
|
cmd->swSurfaceConfigure.height = height;
|
||||||
ll_push(l_renderQueue, cmd);
|
ll_push(l_renderQueue, cmd);
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_spiceDrawFill(int x, int y, int width, int height,
|
void renderQueue_swSurfaceDrawFill(int x, int y, int width, int height,
|
||||||
uint32_t color)
|
uint32_t color)
|
||||||
{
|
{
|
||||||
RenderCommand * cmd = malloc(sizeof(*cmd));
|
RenderCommand * cmd = malloc(sizeof(*cmd));
|
||||||
cmd->op = SPICE_OP_DRAW_FILL;
|
cmd->op = SW_SURFACE_OP_DRAW_FILL;
|
||||||
cmd->spiceFillRect.x = x;
|
cmd->swSurfaceDrawFill.x = x;
|
||||||
cmd->spiceFillRect.y = y;
|
cmd->swSurfaceDrawFill.y = y;
|
||||||
cmd->spiceFillRect.width = width;
|
cmd->swSurfaceDrawFill.width = width;
|
||||||
cmd->spiceFillRect.height = height;
|
cmd->swSurfaceDrawFill.height = height;
|
||||||
cmd->spiceFillRect.color = color;
|
cmd->swSurfaceDrawFill.color = color;
|
||||||
ll_push(l_renderQueue, cmd);
|
ll_push(l_renderQueue, cmd);
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride,
|
void renderQueue_swSurfaceDrawBitmap(int x, int y, int width, int height,
|
||||||
void * data, bool topDown)
|
int stride, void * data, bool topDown)
|
||||||
{
|
{
|
||||||
if (width <= 0 || height <= 0 || stride <= 0)
|
if (width <= 0 || height <= 0 || stride <= 0)
|
||||||
{
|
{
|
||||||
if (width < 0 || height < 0 || stride < 0)
|
if (width < 0 || height < 0 || stride < 0)
|
||||||
DEBUG_ERROR("Invalid SPICE bitmap dimensions: %dx%d, stride: %d",
|
DEBUG_ERROR("Invalid software surface bitmap dimensions: "
|
||||||
|
"%dx%d, stride: %d",
|
||||||
width, height, stride);
|
width, height, stride);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("SPICE bitmap data is NULL");
|
DEBUG_ERROR("Software surface bitmap data is NULL");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size_t)height > SIZE_MAX / (size_t)stride)
|
if ((size_t)height > SIZE_MAX / (size_t)stride)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("SPICE bitmap size overflows: height: %d, stride: %d",
|
DEBUG_ERROR("Software surface bitmap size overflows: "
|
||||||
|
"height: %d, stride: %d",
|
||||||
height, stride);
|
height, stride);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -158,28 +160,29 @@ void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride
|
|||||||
RenderCommand * cmd = malloc(sizeof(*cmd));
|
RenderCommand * cmd = malloc(sizeof(*cmd));
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate SPICE bitmap command");
|
DEBUG_ERROR("Failed to allocate software surface bitmap command");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * copy = malloc(size);
|
uint8_t * copy = malloc(size);
|
||||||
if (!copy)
|
if (!copy)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate %zu bytes for SPICE bitmap", size);
|
DEBUG_ERROR("Failed to allocate %zu bytes for software surface bitmap",
|
||||||
|
size);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(copy, data, size);
|
memcpy(copy, data, size);
|
||||||
|
|
||||||
cmd->op = SPICE_OP_DRAW_BITMAP;
|
cmd->op = SW_SURFACE_OP_DRAW_BITMAP;
|
||||||
cmd->spiceDrawBitmap.x = x;
|
cmd->swSurfaceDrawBitmap.x = x;
|
||||||
cmd->spiceDrawBitmap.y = y;
|
cmd->swSurfaceDrawBitmap.y = y;
|
||||||
cmd->spiceDrawBitmap.width = width;
|
cmd->swSurfaceDrawBitmap.width = width;
|
||||||
cmd->spiceDrawBitmap.height = height;
|
cmd->swSurfaceDrawBitmap.height = height;
|
||||||
cmd->spiceDrawBitmap.stride = stride;
|
cmd->swSurfaceDrawBitmap.stride = stride;
|
||||||
cmd->spiceDrawBitmap.data = copy;
|
cmd->swSurfaceDrawBitmap.data = copy;
|
||||||
cmd->spiceDrawBitmap.topDown = topDown;
|
cmd->swSurfaceDrawBitmap.topDown = topDown;
|
||||||
|
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
if (!ll_push(l_renderQueue, cmd))
|
||||||
{
|
{
|
||||||
@@ -191,11 +194,11 @@ void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride
|
|||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_spiceShow(bool show)
|
void renderQueue_swSurfaceShow(bool show)
|
||||||
{
|
{
|
||||||
RenderCommand * cmd = malloc(sizeof(*cmd));
|
RenderCommand * cmd = malloc(sizeof(*cmd));
|
||||||
cmd->op = SPICE_OP_SHOW;
|
cmd->op = SW_SURFACE_OP_SHOW;
|
||||||
cmd->spiceShow.show = show;
|
cmd->swSurfaceShow.show = show;
|
||||||
ll_push(l_renderQueue, cmd);
|
ll_push(l_renderQueue, cmd);
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
}
|
}
|
||||||
@@ -244,32 +247,33 @@ void renderQueue_process(void)
|
|||||||
{
|
{
|
||||||
switch(cmd->op)
|
switch(cmd->op)
|
||||||
{
|
{
|
||||||
case SPICE_OP_CONFIGURE:
|
case SW_SURFACE_OP_CONFIGURE:
|
||||||
RENDERER(spiceConfigure,
|
RENDERER(swSurfaceConfigure,
|
||||||
cmd->spiceConfigure.width, cmd->spiceConfigure.height);
|
cmd->swSurfaceConfigure.width,
|
||||||
|
cmd->swSurfaceConfigure.height);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICE_OP_DRAW_FILL:
|
case SW_SURFACE_OP_DRAW_FILL:
|
||||||
RENDERER(spiceDrawFill,
|
RENDERER(swSurfaceDrawFill,
|
||||||
cmd->spiceFillRect.x , cmd->spiceFillRect.y,
|
cmd->swSurfaceDrawFill.x , cmd->swSurfaceDrawFill.y,
|
||||||
cmd->spiceFillRect.width, cmd->spiceFillRect.height,
|
cmd->swSurfaceDrawFill.width, cmd->swSurfaceDrawFill.height,
|
||||||
cmd->spiceFillRect.color);
|
cmd->swSurfaceDrawFill.color);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICE_OP_DRAW_BITMAP:
|
case SW_SURFACE_OP_DRAW_BITMAP:
|
||||||
RENDERER(spiceDrawBitmap,
|
RENDERER(swSurfaceDrawBitmap,
|
||||||
cmd->spiceDrawBitmap.x , cmd->spiceDrawBitmap.y,
|
cmd->swSurfaceDrawBitmap.x , cmd->swSurfaceDrawBitmap.y,
|
||||||
cmd->spiceDrawBitmap.width , cmd->spiceDrawBitmap.height,
|
cmd->swSurfaceDrawBitmap.width , cmd->swSurfaceDrawBitmap.height,
|
||||||
cmd->spiceDrawBitmap.stride, cmd->spiceDrawBitmap.data,
|
cmd->swSurfaceDrawBitmap.stride, cmd->swSurfaceDrawBitmap.data,
|
||||||
cmd->spiceDrawBitmap.topDown);
|
cmd->swSurfaceDrawBitmap.topDown);
|
||||||
free(cmd->spiceDrawBitmap.data);
|
free(cmd->swSurfaceDrawBitmap.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICE_OP_SHOW:
|
case SW_SURFACE_OP_SHOW:
|
||||||
l_showSpice = cmd->spiceShow.show;
|
l_showSwSurface = cmd->swSurfaceShow.show;
|
||||||
RENDERER(spiceShow, cmd->spiceShow.show);
|
RENDERER(swSurfaceShow, cmd->swSurfaceShow.show);
|
||||||
updateSurfaceFormat();
|
updateSurfaceFormat();
|
||||||
if (cmd->spiceShow.show)
|
if (cmd->swSurfaceShow.show)
|
||||||
overlaySplash_show(false);
|
overlaySplash_show(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ typedef struct
|
|||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SPICE_OP_CONFIGURE,
|
SW_SURFACE_OP_CONFIGURE,
|
||||||
SPICE_OP_DRAW_FILL,
|
SW_SURFACE_OP_DRAW_FILL,
|
||||||
SPICE_OP_DRAW_BITMAP,
|
SW_SURFACE_OP_DRAW_BITMAP,
|
||||||
SPICE_OP_SHOW,
|
SW_SURFACE_OP_SHOW,
|
||||||
SURFACE_OP_FORMAT,
|
SURFACE_OP_FORMAT,
|
||||||
CURSOR_OP_STATE,
|
CURSOR_OP_STATE,
|
||||||
CURSOR_OP_IMAGE,
|
CURSOR_OP_IMAGE,
|
||||||
@@ -41,7 +41,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
}
|
}
|
||||||
spiceConfigure;
|
swSurfaceConfigure;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -49,7 +49,7 @@ typedef struct
|
|||||||
int width, height;
|
int width, height;
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
}
|
}
|
||||||
spiceFillRect;
|
swSurfaceDrawFill;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -59,13 +59,13 @@ typedef struct
|
|||||||
uint8_t * data;
|
uint8_t * data;
|
||||||
bool topDown;
|
bool topDown;
|
||||||
}
|
}
|
||||||
spiceDrawBitmap;
|
swSurfaceDrawBitmap;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool show;
|
bool show;
|
||||||
}
|
}
|
||||||
spiceShow;
|
swSurfaceShow;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -102,15 +102,15 @@ void renderQueue_free(void);
|
|||||||
void renderQueue_clear(void);
|
void renderQueue_clear(void);
|
||||||
void renderQueue_process(void);
|
void renderQueue_process(void);
|
||||||
|
|
||||||
void renderQueue_spiceConfigure(int width, int height);
|
void renderQueue_swSurfaceConfigure(int width, int height);
|
||||||
|
|
||||||
void renderQueue_spiceDrawFill(int x, int y, int width, int height,
|
void renderQueue_swSurfaceDrawFill(int x, int y, int width, int height,
|
||||||
uint32_t color);
|
uint32_t color);
|
||||||
|
|
||||||
void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride,
|
void renderQueue_swSurfaceDrawBitmap(int x, int y, int width, int height,
|
||||||
void * data, bool topDown);
|
int stride, void * data, bool topDown);
|
||||||
|
|
||||||
void renderQueue_spiceShow(bool show);
|
void renderQueue_swSurfaceShow(bool show);
|
||||||
|
|
||||||
void renderQueue_surfaceFormat(const LG_RendererFormat format,
|
void renderQueue_surfaceFormat(const LG_RendererFormat format,
|
||||||
bool rendererSupportsNativeHDR);
|
bool rendererSupportsNativeHDR);
|
||||||
|
|||||||
Reference in New Issue
Block a user