mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-20 14:22:00 +00:00
[client] add a MPV glsl style effect loader
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#define _H_LG_APP_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "common/ringbuffer.h"
|
||||
@@ -38,6 +39,19 @@ typedef enum LG_MsgAlert
|
||||
}
|
||||
LG_MsgAlert;
|
||||
|
||||
typedef struct LG_MouseState
|
||||
{
|
||||
/* Normalized guest cursor hotspot coordinates. */
|
||||
float x, y;
|
||||
|
||||
/* Bit 0: left, bit 1: middle, bit 2: right, etc. */
|
||||
uint32_t buttons;
|
||||
|
||||
/* True when the guest cursor position is known. */
|
||||
bool valid;
|
||||
}
|
||||
LG_MouseState;
|
||||
|
||||
bool app_isRunning(void);
|
||||
bool app_inputEnabled(void);
|
||||
bool app_isCaptureMode(void);
|
||||
@@ -45,6 +59,8 @@ bool app_isCaptureOnlyMode(void);
|
||||
bool app_isFormatValid(void);
|
||||
bool app_isOverlayMode(void);
|
||||
void app_updateCursorPos(double x, double y);
|
||||
void app_updateMouseState(void);
|
||||
void app_getMouseState(LG_MouseState * state);
|
||||
void app_updateWindowPos(int x, int y);
|
||||
void app_handleResizeEvent(int w, int h, double scale, const struct Border border);
|
||||
void app_invalidateWindow(bool full);
|
||||
|
||||
@@ -92,6 +92,7 @@ add_library(renderer_EGL STATIC
|
||||
effect.c
|
||||
postprocess.c
|
||||
ffx.c
|
||||
filter_glsl.c
|
||||
filter_24bit.c
|
||||
filter_ffx_cas.c
|
||||
filter_ffx_fsr1.c
|
||||
|
||||
@@ -205,6 +205,7 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
|
||||
egl_postProcessAdd(desktop->pp, &egl_filterDownscaleOps);
|
||||
egl_postProcessAdd(desktop->pp, &egl_filterFFXCASOps );
|
||||
egl_postProcessAdd(desktop->pp, &egl_filterFFXFSR1Ops );
|
||||
egl_postProcessAdd(desktop->pp, &egl_filterGLSLOps );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -424,7 +425,8 @@ void egl_desktopResize(EGL_Desktop * desktop, int width, int height)
|
||||
bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
unsigned int outputHeight, const float x, const float y,
|
||||
const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType,
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects)
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects,
|
||||
bool * fullFrame)
|
||||
{
|
||||
EGL_Texture * tex;
|
||||
int width, height;
|
||||
@@ -461,10 +463,19 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
width, height, x, y, scaleX, scaleY, rotate);
|
||||
egl_desktopRectsUpdate(desktop->mesh, rects, width, height);
|
||||
|
||||
if (atomic_exchange(&desktop->processFrame, false) ||
|
||||
egl_postProcessConfigModified(desktop->pp))
|
||||
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
|
||||
width, height, outputWidth, outputHeight, dma);
|
||||
*fullFrame = false;
|
||||
const bool processFrame = atomic_exchange(&desktop->processFrame, false) ||
|
||||
egl_postProcessConfigModified(desktop->pp);
|
||||
if (processFrame &&
|
||||
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
|
||||
width, height, outputWidth, outputHeight, dma) &&
|
||||
egl_postProcessNeedsFullFrame(desktop->pp))
|
||||
{
|
||||
/* The filter output may have changed everywhere, but this only applies to
|
||||
* the render that actually evaluated the filter. */
|
||||
egl_desktopRectsUpdate(desktop->mesh, NULL, width, height);
|
||||
*fullFrame = true;
|
||||
}
|
||||
|
||||
unsigned int finalSizeX, finalSizeY;
|
||||
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
|
||||
|
||||
@@ -50,7 +50,8 @@ void egl_desktopResize(EGL_Desktop * desktop, int width, int height);
|
||||
bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
unsigned int outputHeight, const float x, const float y,
|
||||
const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType,
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects);
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects,
|
||||
bool * fullFrame);
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height);
|
||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
|
||||
@@ -205,6 +205,35 @@ bool egl_effectPassSetup(EGL_EffectPass * pass, enum EGL_PixelFormat pixFmt,
|
||||
return true;
|
||||
}
|
||||
|
||||
EGL_Texture * egl_effectPassGetTexture(EGL_EffectPass * pass)
|
||||
{
|
||||
return pass->configured ? egl_framebufferGetTexture(pass->framebuffer) : NULL;
|
||||
}
|
||||
|
||||
EGL_Texture * egl_effectPassRun(EGL_EffectPass * pass, EGL_FilterRects * rects,
|
||||
EGL_Texture * const * textures, unsigned int textureCount)
|
||||
{
|
||||
if (!pass->configured || !pass->shader || !textureCount)
|
||||
{
|
||||
DEBUG_ERROR("Attempted to run an unconfigured EGL effect pass");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
egl_framebufferBind(pass->framebuffer);
|
||||
|
||||
for (unsigned int i = 0; i < textureCount; ++i)
|
||||
if (egl_textureBindUnitWithSampler(textures[i], i, pass->sampler) !=
|
||||
EGL_TEX_STATUS_OK)
|
||||
return NULL;
|
||||
|
||||
egl_uniformMatrix3x2fv(pass->uTransform, 1, GL_FALSE, rects->matrix);
|
||||
egl_uniform2f(pass->uDesktopSize, rects->width, rects->height);
|
||||
egl_shaderUse(pass->shader);
|
||||
egl_desktopRectsRender(rects->rects);
|
||||
|
||||
return egl_framebufferGetTexture(pass->framebuffer);
|
||||
}
|
||||
|
||||
EGL_Texture * egl_effectRun(EGL_Effect * effect, EGL_FilterRects * rects,
|
||||
EGL_Texture * texture)
|
||||
{
|
||||
@@ -213,22 +242,9 @@ EGL_Texture * egl_effectRun(EGL_Effect * effect, EGL_FilterRects * rects,
|
||||
if (!pass->enabled)
|
||||
continue;
|
||||
|
||||
if (!pass->configured || !pass->shader)
|
||||
{
|
||||
DEBUG_ERROR("Attempted to run an unconfigured EGL effect pass");
|
||||
texture = egl_effectPassRun(pass, rects, &texture, 1);
|
||||
if (!texture)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
egl_framebufferBind(pass->framebuffer);
|
||||
|
||||
egl_textureBindWithSampler(texture, pass->sampler);
|
||||
|
||||
egl_uniformMatrix3x2fv(pass->uTransform, 1, GL_FALSE, rects->matrix);
|
||||
egl_uniform2f(pass->uDesktopSize, rects->width, rects->height);
|
||||
egl_shaderUse(pass->shader);
|
||||
egl_desktopRectsRender(rects->rects);
|
||||
|
||||
texture = egl_framebufferGetTexture(pass->framebuffer);
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
@@ -48,6 +48,10 @@ void egl_effectPassSetWrap(EGL_EffectPass * pass, GLenum wrapS,
|
||||
|
||||
bool egl_effectPassSetup(EGL_EffectPass * pass, enum EGL_PixelFormat pixFmt,
|
||||
unsigned int width, unsigned int height);
|
||||
EGL_Texture * egl_effectPassGetTexture(EGL_EffectPass * pass);
|
||||
EGL_Texture * egl_effectPassRun(EGL_EffectPass * pass,
|
||||
struct EGL_FilterRects * rects, EGL_Texture * const * textures,
|
||||
unsigned int textureCount);
|
||||
|
||||
EGL_Texture * egl_effectRun(EGL_Effect * effect,
|
||||
struct EGL_FilterRects * rects, EGL_Texture * texture);
|
||||
|
||||
@@ -1218,13 +1218,15 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
}
|
||||
++this->overlayHistoryIdx;
|
||||
|
||||
bool fullFrame = false;
|
||||
if (likely(this->destRect.w > 0 && this->destRect.h > 0))
|
||||
{
|
||||
if (egl_desktopRender(this->desktop,
|
||||
this->destRect.w, this->destRect.h,
|
||||
this->translateX, this->translateY,
|
||||
this->scaleX , this->scaleY ,
|
||||
this->scaleType , rotate, renderAll ? NULL : accumulated))
|
||||
this->scaleType , rotate, renderAll ? NULL : accumulated,
|
||||
&fullFrame))
|
||||
{
|
||||
cursorState = egl_cursorRender(this->cursor,
|
||||
(this->format.rotate + rotate) % LG_ROTATE_MAX,
|
||||
@@ -1234,6 +1236,11 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
hasOverlay = true;
|
||||
}
|
||||
|
||||
/* Preserve the full update in the damage history so buffer-age repair still
|
||||
* redraws older swapchain buffers correctly. */
|
||||
if (fullFrame)
|
||||
desktopDamage->count = -1;
|
||||
|
||||
renderLetterBox(this);
|
||||
|
||||
hasOverlay |=
|
||||
|
||||
@@ -37,6 +37,8 @@ typedef struct EGL_FilterRects
|
||||
EGL_FilterRects;
|
||||
|
||||
typedef struct EGL_Filter EGL_Filter;
|
||||
/* Takes ownership of filter when it returns true. */
|
||||
typedef bool (*EGL_FilterAddFn)(void * opaque, EGL_Filter * filter);
|
||||
|
||||
typedef struct EGL_FilterOps
|
||||
{
|
||||
@@ -49,9 +51,16 @@ typedef struct EGL_FilterOps
|
||||
/* the type of this filter */
|
||||
EGL_FilterType type;
|
||||
|
||||
/* disable partial rendering and swap damage while this filter is active */
|
||||
bool fullFrame;
|
||||
|
||||
/* early initialization for registration of options */
|
||||
void (*earlyInit)(void);
|
||||
|
||||
/* create one or more filter instances
|
||||
* this is optional and used by runtime filter providers */
|
||||
bool (*create)(EGL_FilterAddFn add, void * opaque);
|
||||
|
||||
/* initialize the filter */
|
||||
bool (*init)(EGL_Filter ** filter);
|
||||
|
||||
|
||||
1260
client/renderers/EGL/filter_glsl.c
Normal file
1260
client/renderers/EGL/filter_glsl.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,3 +24,4 @@ extern EGL_FilterOps egl_filter24bitOps;
|
||||
extern EGL_FilterOps egl_filterDownscaleOps;
|
||||
extern EGL_FilterOps egl_filterFFXCASOps;
|
||||
extern EGL_FilterOps egl_filterFFXFSR1Ops;
|
||||
extern EGL_FilterOps egl_filterGLSLOps;
|
||||
|
||||
@@ -43,7 +43,8 @@ static const EGL_FilterOps * EGL_Filters[] =
|
||||
{
|
||||
&egl_filterDownscaleOps,
|
||||
&egl_filterFFXFSR1Ops,
|
||||
&egl_filterFFXCASOps
|
||||
&egl_filterFFXCASOps,
|
||||
&egl_filterGLSLOps
|
||||
};
|
||||
|
||||
struct EGL_PostProcess
|
||||
@@ -62,6 +63,7 @@ struct EGL_PostProcess
|
||||
unsigned int targetX, targetY;
|
||||
bool useDMA;
|
||||
unsigned int outputX, outputY;
|
||||
bool fullFrame;
|
||||
}
|
||||
config;
|
||||
|
||||
@@ -646,18 +648,36 @@ void egl_postProcessFree(EGL_PostProcess ** pp)
|
||||
*pp = NULL;
|
||||
}
|
||||
|
||||
bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops)
|
||||
static bool addFilter(void * opaque, EGL_Filter * filter)
|
||||
{
|
||||
EGL_Filter * filter;
|
||||
if (!egl_filterInit(ops, &filter))
|
||||
return false;
|
||||
EGL_PostProcess * this = opaque;
|
||||
|
||||
Vector * filters = ops->type == EGL_FILTER_TYPE_INTERNAL ?
|
||||
Vector * filters = filter->ops.type == EGL_FILTER_TYPE_INTERNAL ?
|
||||
&this->internalFilters : &this->filters;
|
||||
if (!vector_push(filters, &filter))
|
||||
{
|
||||
egl_filterFree(&filter);
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops)
|
||||
{
|
||||
if (ops->create)
|
||||
{
|
||||
if (!ops->create(addFilter, this))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EGL_Filter * filter;
|
||||
if (!egl_filterInit(ops, &filter))
|
||||
return false;
|
||||
|
||||
if (!addFilter(this, filter))
|
||||
{
|
||||
egl_filterFree(&filter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ops->type != EGL_FILTER_TYPE_INTERNAL)
|
||||
@@ -677,6 +697,11 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this)
|
||||
return atomic_load_explicit(&this->modified, memory_order_acquire);
|
||||
}
|
||||
|
||||
bool egl_postProcessNeedsFullFrame(EGL_PostProcess * this)
|
||||
{
|
||||
return this->config.valid && this->config.fullFrame;
|
||||
}
|
||||
|
||||
static bool configMatches(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||
unsigned int inputX, unsigned int inputY,
|
||||
int desktopWidth, int desktopHeight,
|
||||
@@ -706,6 +731,7 @@ static bool configureChain(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||
unsigned int outputY = inputY;
|
||||
EGL_PixelFormat outputFormat = pixFmt;
|
||||
bool inputDMA = useDMA;
|
||||
bool fullFrame = false;
|
||||
|
||||
EGL_Filter * filter;
|
||||
const Vector * lists[] =
|
||||
@@ -731,6 +757,8 @@ static bool configureChain(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||
return false;
|
||||
}
|
||||
|
||||
fullFrame |= filter->ops.fullFrame;
|
||||
|
||||
egl_filterGetOutputRes(filter, &outputX, &outputY, &outputFormat);
|
||||
|
||||
/* The first active filter converts external DMA textures into a normal
|
||||
@@ -751,6 +779,7 @@ static bool configureChain(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||
this->config.useDMA = useDMA;
|
||||
this->config.outputX = outputX;
|
||||
this->config.outputY = outputY;
|
||||
this->config.fullFrame = fullFrame;
|
||||
this->config.valid = true;
|
||||
return true;
|
||||
}
|
||||
@@ -792,6 +821,12 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
egl_desktopRectsUpdate(rects, NULL, desktopWidth, desktopHeight);
|
||||
}
|
||||
|
||||
if (this->config.fullFrame)
|
||||
{
|
||||
rects = this->rects;
|
||||
egl_desktopRectsUpdate(rects, NULL, desktopWidth, desktopHeight);
|
||||
}
|
||||
|
||||
EGL_FilterRects filterRects = {
|
||||
.rects = rects,
|
||||
.matrix = this->matrix,
|
||||
|
||||
@@ -40,6 +40,9 @@ void egl_postProcessInvalidate(EGL_PostProcess * this);
|
||||
/* returns true if the configuration was modified since the last run */
|
||||
bool egl_postProcessConfigModified(EGL_PostProcess * this);
|
||||
|
||||
/* true when an active filter requires full-frame rendering and damage */
|
||||
bool egl_postProcessNeedsFullFrame(EGL_PostProcess * this);
|
||||
|
||||
/* apply the filters to the supplied texture
|
||||
* targetX/Y is the final target output dimension hint if scalers are present */
|
||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
|
||||
@@ -215,6 +215,12 @@ enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||
enum EGL_TexStatus egl_textureBindWithSampler(EGL_Texture * this,
|
||||
GLuint sampler)
|
||||
{
|
||||
egl_stateBindSampler(0, sampler);
|
||||
return this->ops.bind(this);
|
||||
return egl_textureBindUnitWithSampler(this, 0, sampler);
|
||||
}
|
||||
|
||||
enum EGL_TexStatus egl_textureBindUnitWithSampler(EGL_Texture * this,
|
||||
GLuint unit, GLuint sampler)
|
||||
{
|
||||
egl_stateBindSampler(unit, sampler);
|
||||
return this->ops.bind(this, unit);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ typedef struct EGL_TextureOps
|
||||
EGL_PixelFormat * fmt);
|
||||
|
||||
/* bind the texture for use */
|
||||
enum EGL_TexStatus (*bind)(EGL_Texture * texture);
|
||||
enum EGL_TexStatus (*bind)(EGL_Texture * texture, GLuint unit);
|
||||
}
|
||||
EGL_TextureOps;
|
||||
|
||||
@@ -147,6 +147,8 @@ static inline EGL_TexStatus egl_textureGet(EGL_Texture * texture, GLuint * tex,
|
||||
enum EGL_TexStatus egl_textureBind(EGL_Texture * texture);
|
||||
enum EGL_TexStatus egl_textureBindWithSampler(EGL_Texture * texture,
|
||||
GLuint sampler);
|
||||
enum EGL_TexStatus egl_textureBindUnitWithSampler(EGL_Texture * texture,
|
||||
GLuint unit, GLuint sampler);
|
||||
|
||||
typedef void * PostProcessHandle;
|
||||
PostProcessHandle egl_textureAddFilter(EGL_Texture * texture,
|
||||
|
||||
@@ -340,7 +340,7 @@ EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex,
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture)
|
||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture, GLuint unit)
|
||||
{
|
||||
GLuint tex;
|
||||
EGL_TexStatus status;
|
||||
@@ -348,7 +348,7 @@ EGL_TexStatus egl_texBufferBind(EGL_Texture * texture)
|
||||
if ((status = texture->ops.get(texture, &tex, NULL)) != EGL_TEX_STATUS_OK)
|
||||
return status;
|
||||
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, tex);
|
||||
egl_stateBindTexture(unit, GL_TEXTURE_2D, tex);
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup);
|
||||
EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_);
|
||||
EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex,
|
||||
EGL_PixelFormat * fmt);
|
||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_);
|
||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_, GLuint unit);
|
||||
|
||||
bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type,
|
||||
EGLDisplay * display);
|
||||
|
||||
@@ -328,7 +328,7 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex,
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture)
|
||||
static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture, GLuint unit)
|
||||
{
|
||||
GLuint tex;
|
||||
EGL_TexStatus status;
|
||||
@@ -336,7 +336,7 @@ static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture)
|
||||
if ((status = egl_texDMABUFGet(texture, &tex, NULL)) != EGL_TEX_STATUS_OK)
|
||||
return status;
|
||||
|
||||
egl_stateBindTexture(0, GL_TEXTURE_EXTERNAL_OES, tex);
|
||||
egl_stateBindTexture(unit, GL_TEXTURE_EXTERNAL_OES, tex);
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define SHADER_MOUSE_VALID (UINT32_C(1) << 31)
|
||||
|
||||
bool app_isRunning(void)
|
||||
{
|
||||
return
|
||||
@@ -94,6 +96,74 @@ void app_updateCursorPos(double x, double y)
|
||||
g_state.io->MousePos = (ImVec2) { x, y };
|
||||
}
|
||||
|
||||
void app_updateMouseState(void)
|
||||
{
|
||||
LG_MouseState state = { 0 };
|
||||
|
||||
if (g_cursor.guest.valid &&
|
||||
g_state.srcSize.x > 0 && g_state.srcSize.y > 0)
|
||||
{
|
||||
state.x = (float)(g_cursor.guest.x + g_cursor.guest.hx) /
|
||||
g_state.srcSize.x;
|
||||
state.y = (float)(g_cursor.guest.y + g_cursor.guest.hy) /
|
||||
g_state.srcSize.y;
|
||||
state.valid = true;
|
||||
}
|
||||
|
||||
if (!state.valid)
|
||||
{
|
||||
atomic_fetch_and_explicit(&g_state.shaderMouseState,
|
||||
~SHADER_MOUSE_VALID, memory_order_release);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t position[2];
|
||||
memcpy(position + 0, &state.x, sizeof(state.x));
|
||||
memcpy(position + 1, &state.y, sizeof(state.y));
|
||||
const uint64_t packedPosition =
|
||||
(uint64_t)position[0] | (uint64_t)position[1] << 32;
|
||||
|
||||
atomic_store_explicit(&g_state.shaderMousePosition, packedPosition,
|
||||
memory_order_release);
|
||||
atomic_fetch_or_explicit(&g_state.shaderMouseState,
|
||||
SHADER_MOUSE_VALID, memory_order_release);
|
||||
}
|
||||
|
||||
static void app_updateMouseButtons(void)
|
||||
{
|
||||
const uint_least32_t buttons =
|
||||
(g_cursor.buttons >> 1) & ~SHADER_MOUSE_VALID;
|
||||
uint_least32_t current = atomic_load_explicit(&g_state.shaderMouseState,
|
||||
memory_order_relaxed);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const uint_least32_t updated =
|
||||
(current & SHADER_MOUSE_VALID) | buttons;
|
||||
if (atomic_compare_exchange_weak_explicit(&g_state.shaderMouseState,
|
||||
¤t, updated, memory_order_release, memory_order_relaxed))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void app_getMouseState(LG_MouseState * state)
|
||||
{
|
||||
const uint32_t packedState = atomic_load_explicit(
|
||||
&g_state.shaderMouseState, memory_order_acquire);
|
||||
const uint64_t packedPosition = atomic_load_explicit(
|
||||
&g_state.shaderMousePosition, memory_order_acquire);
|
||||
|
||||
const uint32_t position[2] = {
|
||||
packedPosition,
|
||||
packedPosition >> 32,
|
||||
};
|
||||
|
||||
memcpy(&state->x, position + 0, sizeof(state->x));
|
||||
memcpy(&state->y, position + 1, sizeof(state->y));
|
||||
state->buttons = packedState & ~SHADER_MOUSE_VALID;
|
||||
state->valid = !!(packedState & SHADER_MOUSE_VALID);
|
||||
}
|
||||
|
||||
void app_handleFocusEvent(bool focused)
|
||||
{
|
||||
if (g_state.focused == focused)
|
||||
@@ -271,6 +341,7 @@ static int mapSpiceToImGuiButton(uint32_t button)
|
||||
void app_handleButtonPress(int button)
|
||||
{
|
||||
g_cursor.buttons |= (1U << button);
|
||||
app_updateMouseButtons();
|
||||
|
||||
if (app_isOverlayMode())
|
||||
{
|
||||
@@ -290,6 +361,7 @@ void app_handleButtonPress(int button)
|
||||
void app_handleButtonRelease(int button)
|
||||
{
|
||||
g_cursor.buttons &= ~(1U << button);
|
||||
app_updateMouseButtons();
|
||||
|
||||
if (app_isOverlayMode())
|
||||
{
|
||||
|
||||
@@ -363,6 +363,7 @@ void core_updatePositionInfo(void)
|
||||
}
|
||||
|
||||
done:
|
||||
app_updateMouseState();
|
||||
atomic_fetch_add(&g_state.lgrResize, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -506,6 +506,7 @@ int main_cursorThread(void * unused)
|
||||
core_handleGuestMouseUpdate();
|
||||
}
|
||||
|
||||
app_updateMouseState();
|
||||
g_cursor.redraw = false;
|
||||
|
||||
RENDERER(onMouseEvent,
|
||||
|
||||
@@ -110,6 +110,9 @@ struct AppState
|
||||
bool alignToGuest;
|
||||
bool spiceClose;
|
||||
|
||||
atomic_uint_least64_t shaderMousePosition;
|
||||
atomic_uint_least32_t shaderMouseState;
|
||||
|
||||
LG_Renderer * lgr;
|
||||
atomic_int lgrResize;
|
||||
LG_Lock lgrLock;
|
||||
|
||||
@@ -48,13 +48,6 @@ bool util_fileGetContents(const char * filename, char ** buffer, size_t * length
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fseek(fh, 0, SEEK_SET) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to seek");
|
||||
fclose(fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
long fsize = ftell(fh);
|
||||
if (fsize < 0)
|
||||
{
|
||||
@@ -63,6 +56,13 @@ bool util_fileGetContents(const char * filename, char ** buffer, size_t * length
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fseek(fh, 0, SEEK_SET) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to seek");
|
||||
fclose(fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
*buffer = malloc(fsize + 1);
|
||||
if (!*buffer)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user