mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-04-28 09:36:28 +00:00
[client] egl: keep the mouse cursor 1:1 when downscaling
This keeps the cursor a usable size when the guest is running a high resolution and downscaling (ie, 4K -> FHD).
This commit is contained in:
parent
74444f8eed
commit
d69069fb09
@ -139,8 +139,8 @@ typedef struct LG_RendererOps
|
|||||||
|
|
||||||
/* called when the mouse has moved or changed visibillity
|
/* called when the mouse has moved or changed visibillity
|
||||||
* Context: cursorThread */
|
* Context: cursorThread */
|
||||||
bool (*onMouseEvent)(LG_Renderer * renderer, const bool visible, const int x,
|
bool (*onMouseEvent)(LG_Renderer * renderer, const bool visible, int x, int y,
|
||||||
const int y);
|
const int hx, const int hy);
|
||||||
|
|
||||||
/* called when the frame format has changed
|
/* called when the frame format has changed
|
||||||
* Context: frameThread */
|
* Context: frameThread */
|
||||||
|
@ -42,6 +42,7 @@ struct CursorTex
|
|||||||
struct EGL_Texture * texture;
|
struct EGL_Texture * texture;
|
||||||
struct EGL_Shader * shader;
|
struct EGL_Shader * shader;
|
||||||
GLuint uMousePos;
|
GLuint uMousePos;
|
||||||
|
GLuint uScale;
|
||||||
GLuint uRotate;
|
GLuint uRotate;
|
||||||
GLuint uCBMode;
|
GLuint uCBMode;
|
||||||
};
|
};
|
||||||
@ -73,7 +74,9 @@ struct EGL_Cursor
|
|||||||
int cbMode;
|
int cbMode;
|
||||||
|
|
||||||
_Atomic(struct CursorPos) pos;
|
_Atomic(struct CursorPos) pos;
|
||||||
|
_Atomic(struct CursorPos) hs;
|
||||||
_Atomic(struct CursorSize) size;
|
_Atomic(struct CursorSize) size;
|
||||||
|
_Atomic(float) scale;
|
||||||
|
|
||||||
struct CursorTex norm;
|
struct CursorTex norm;
|
||||||
struct CursorTex mono;
|
struct CursorTex mono;
|
||||||
@ -103,28 +106,22 @@ static bool cursorTexInit(struct CursorTex * t,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->uMousePos = egl_shaderGetUniform(t->shader, "mouse" );
|
t->uMousePos = egl_shaderGetUniform(t->shader, "mouse" );
|
||||||
t->uRotate = egl_shaderGetUniform(t->shader, "rotate");
|
t->uScale = egl_shaderGetUniform(t->shader, "scale" );
|
||||||
t->uCBMode = egl_shaderGetUniform(t->shader, "cbMode");
|
t->uRotate = egl_shaderGetUniform(t->shader, "rotate" );
|
||||||
|
t->uCBMode = egl_shaderGetUniform(t->shader, "cbMode" );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setCursorTexUniforms(EGL_Cursor * cursor,
|
static inline void setCursorTexUniforms(EGL_Cursor * cursor,
|
||||||
struct CursorTex * t, bool mono, float x, float y, float w, float h)
|
struct CursorTex * t, bool mono, float x, float y,
|
||||||
|
float w, float h, float scale)
|
||||||
{
|
{
|
||||||
if (mono)
|
glUniform4f(t->uMousePos, x, y, w, mono ? h / 2 : h);
|
||||||
{
|
glUniform1f(t->uScale , scale);
|
||||||
glUniform4f(t->uMousePos, x, y, w, h / 2);
|
glUniform1i(t->uRotate , cursor->rotate);
|
||||||
glUniform1i(t->uRotate , cursor->rotate);
|
glUniform1i(t->uCBMode , cursor->cbMode);
|
||||||
glUniform1i(t->uCBMode , cursor->cbMode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glUniform4f(t->uMousePos, x, y, w, h);
|
|
||||||
glUniform1i(t->uRotate , cursor->rotate);
|
|
||||||
glUniform1i(t->uCBMode , cursor->cbMode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursorTexFree(struct CursorTex * t)
|
static void cursorTexFree(struct CursorTex * t)
|
||||||
@ -166,9 +163,12 @@ bool egl_cursorInit(EGL_Cursor ** cursor)
|
|||||||
(*cursor)->cbMode = option_get_int("egl", "cbMode");
|
(*cursor)->cbMode = option_get_int("egl", "cbMode");
|
||||||
|
|
||||||
struct CursorPos pos = { .x = 0, .y = 0 };
|
struct CursorPos pos = { .x = 0, .y = 0 };
|
||||||
|
struct CursorPos hs = { .x = 0, .y = 0 };
|
||||||
struct CursorSize size = { .w = 0, .h = 0 };
|
struct CursorSize size = { .w = 0, .h = 0 };
|
||||||
atomic_init(&(*cursor)->pos, pos);
|
atomic_init(&(*cursor)->pos , pos );
|
||||||
atomic_init(&(*cursor)->size, size);
|
atomic_init(&(*cursor)->hs , hs );
|
||||||
|
atomic_init(&(*cursor)->size , size);
|
||||||
|
atomic_init(&(*cursor)->scale, 1.0f);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -229,11 +229,19 @@ void egl_cursorSetSize(EGL_Cursor * cursor, const float w, const float h)
|
|||||||
atomic_store(&cursor->size, size);
|
atomic_store(&cursor->size, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void egl_cursorSetState(EGL_Cursor * cursor, const bool visible, const float x, const float y)
|
void egl_cursorSetScale(EGL_Cursor * cursor, const float scale)
|
||||||
|
{
|
||||||
|
atomic_store(&cursor->scale, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void egl_cursorSetState(EGL_Cursor * cursor, const bool visible,
|
||||||
|
const float x, const float y, const float hx, const float hy)
|
||||||
{
|
{
|
||||||
cursor->visible = visible;
|
cursor->visible = visible;
|
||||||
struct CursorPos pos = { .x = x, .y = y};
|
struct CursorPos pos = { .x = x , .y = y };
|
||||||
|
struct CursorPos hs = { .x = hx, .y = hy };
|
||||||
atomic_store(&cursor->pos, pos);
|
atomic_store(&cursor->pos, pos);
|
||||||
|
atomic_store(&cursor->hs , hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||||
@ -256,7 +264,8 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
|
|
||||||
case LG_CURSOR_COLOR:
|
case LG_CURSOR_COLOR:
|
||||||
{
|
{
|
||||||
egl_textureSetup(cursor->norm.texture, EGL_PF_BGRA, cursor->width, cursor->height, cursor->stride);
|
egl_textureSetup(cursor->norm.texture, EGL_PF_BGRA,
|
||||||
|
cursor->width, cursor->height, cursor->stride);
|
||||||
egl_textureUpdate(cursor->norm.texture, data);
|
egl_textureUpdate(cursor->norm.texture, data);
|
||||||
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
||||||
break;
|
break;
|
||||||
@ -264,10 +273,11 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
|
|
||||||
case LG_CURSOR_MONOCHROME:
|
case LG_CURSOR_MONOCHROME:
|
||||||
{
|
{
|
||||||
uint32_t and[cursor->width * cursor->height];
|
uint32_t and[cursor->height][cursor->width];
|
||||||
uint32_t xor[cursor->width * cursor->height];
|
uint32_t xor[cursor->height][cursor->width];
|
||||||
|
|
||||||
for(int y = 0; y < cursor->height; ++y)
|
for(int y = 0; y < cursor->height; ++y)
|
||||||
|
{
|
||||||
for(int x = 0; x < cursor->width; ++x)
|
for(int x = 0; x < cursor->width; ++x)
|
||||||
{
|
{
|
||||||
const uint8_t * srcAnd = data + (cursor->stride * y) + (x / 8);
|
const uint8_t * srcAnd = data + (cursor->stride * y) + (x / 8);
|
||||||
@ -276,12 +286,15 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
const uint32_t andMask = (*srcAnd & mask) ? 0xFFFFFFFF : 0xFF000000;
|
const uint32_t andMask = (*srcAnd & mask) ? 0xFFFFFFFF : 0xFF000000;
|
||||||
const uint32_t xorMask = (*srcXor & mask) ? 0x00FFFFFF : 0x00000000;
|
const uint32_t xorMask = (*srcXor & mask) ? 0x00FFFFFF : 0x00000000;
|
||||||
|
|
||||||
and[y * cursor->width + x] = andMask;
|
and[y][x] = andMask;
|
||||||
xor[y * cursor->width + x] = xorMask;
|
xor[y][x] = xorMask;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
egl_textureSetup (cursor->norm.texture, EGL_PF_BGRA, cursor->width, cursor->height, cursor->width * 4);
|
egl_textureSetup(cursor->norm.texture, EGL_PF_BGRA,
|
||||||
egl_textureSetup (cursor->mono.texture, EGL_PF_BGRA, cursor->width, cursor->height, cursor->width * 4);
|
cursor->width, cursor->height, sizeof(and[0]));
|
||||||
|
egl_textureSetup(cursor->mono.texture, EGL_PF_BGRA,
|
||||||
|
cursor->width, cursor->height, sizeof(xor[0]));
|
||||||
egl_textureUpdate(cursor->norm.texture, (uint8_t *)and);
|
egl_textureUpdate(cursor->norm.texture, (uint8_t *)and);
|
||||||
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor);
|
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor);
|
||||||
break;
|
break;
|
||||||
@ -292,8 +305,15 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
|
|
||||||
cursor->rotate = rotate;
|
cursor->rotate = rotate;
|
||||||
|
|
||||||
struct CursorPos pos = atomic_load(&cursor->pos);
|
struct CursorPos pos = atomic_load(&cursor->pos );
|
||||||
struct CursorSize size = atomic_load(&cursor->size);
|
float scale = atomic_load(&cursor->scale);
|
||||||
|
struct CursorPos hs = atomic_load(&cursor->hs );
|
||||||
|
struct CursorSize size = atomic_load(&cursor->size );
|
||||||
|
|
||||||
|
pos.x -= hs.x * scale;
|
||||||
|
pos.y -= hs.y * scale;
|
||||||
|
size.w *= scale;
|
||||||
|
size.h *= scale;
|
||||||
|
|
||||||
struct CursorState state = {
|
struct CursorState state = {
|
||||||
.visible = true,
|
.visible = true,
|
||||||
@ -342,13 +362,15 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
case LG_CURSOR_MONOCHROME:
|
case LG_CURSOR_MONOCHROME:
|
||||||
{
|
{
|
||||||
egl_shaderUse(cursor->norm.shader);
|
egl_shaderUse(cursor->norm.shader);
|
||||||
setCursorTexUniforms(cursor, &cursor->norm, true, pos.x, pos.y, size.w, size.h);
|
setCursorTexUniforms(cursor, &cursor->norm, true, pos.x, pos.y,
|
||||||
|
size.w, size.h, scale);
|
||||||
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
||||||
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
||||||
egl_modelRender(cursor->model);
|
egl_modelRender(cursor->model);
|
||||||
|
|
||||||
egl_shaderUse(cursor->mono.shader);
|
egl_shaderUse(cursor->mono.shader);
|
||||||
setCursorTexUniforms(cursor, &cursor->mono, true, pos.x, pos.y, size.w, size.h);
|
setCursorTexUniforms(cursor, &cursor->mono, true, pos.x, pos.y,
|
||||||
|
size.w, size.h, scale);
|
||||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||||
egl_modelSetTexture(cursor->model, cursor->mono.texture);
|
egl_modelSetTexture(cursor->model, cursor->mono.texture);
|
||||||
egl_modelRender(cursor->model);
|
egl_modelRender(cursor->model);
|
||||||
@ -358,7 +380,8 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
case LG_CURSOR_COLOR:
|
case LG_CURSOR_COLOR:
|
||||||
{
|
{
|
||||||
egl_shaderUse(cursor->norm.shader);
|
egl_shaderUse(cursor->norm.shader);
|
||||||
setCursorTexUniforms(cursor, &cursor->norm, false, pos.x, pos.y, size.w, size.h);
|
setCursorTexUniforms(cursor, &cursor->norm, false, pos.x, pos.y,
|
||||||
|
size.w, size.h, scale);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
egl_modelRender(cursor->model);
|
egl_modelRender(cursor->model);
|
||||||
break;
|
break;
|
||||||
@ -367,7 +390,8 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
|||||||
case LG_CURSOR_MASKED_COLOR:
|
case LG_CURSOR_MASKED_COLOR:
|
||||||
{
|
{
|
||||||
egl_shaderUse(cursor->mono.shader);
|
egl_shaderUse(cursor->mono.shader);
|
||||||
setCursorTexUniforms(cursor, &cursor->mono, false, pos.x, pos.y, size.w, size.h);
|
setCursorTexUniforms(cursor, &cursor->mono, false, pos.x, pos.y,
|
||||||
|
size.w, size.h, scale);
|
||||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||||
egl_modelRender(cursor->model);
|
egl_modelRender(cursor->model);
|
||||||
break;
|
break;
|
||||||
|
@ -45,8 +45,10 @@ bool egl_cursorSetShape(
|
|||||||
|
|
||||||
void egl_cursorSetSize(EGL_Cursor * cursor, const float x, const float y);
|
void egl_cursorSetSize(EGL_Cursor * cursor, const float x, const float y);
|
||||||
|
|
||||||
|
void egl_cursorSetScale(EGL_Cursor * cursor, const float scale);
|
||||||
|
|
||||||
void egl_cursorSetState(EGL_Cursor * cursor, const bool visible,
|
void egl_cursorSetState(EGL_Cursor * cursor, const bool visible,
|
||||||
const float x, const float y);
|
const float x, const float y, const float hx, const float hy);
|
||||||
|
|
||||||
struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||||
LG_RendererRotate rotate, int width, int height);
|
LG_RendererRotate rotate, int width, int height);
|
||||||
|
@ -103,9 +103,11 @@ struct Inst
|
|||||||
|
|
||||||
bool cursorVisible;
|
bool cursorVisible;
|
||||||
int cursorX , cursorY;
|
int cursorX , cursorY;
|
||||||
|
int cursorHX , cursorHY;
|
||||||
float mouseWidth , mouseHeight;
|
float mouseWidth , mouseHeight;
|
||||||
float mouseScaleX, mouseScaleY;
|
float mouseScaleX, mouseScaleY;
|
||||||
bool showDamage;
|
bool showDamage;
|
||||||
|
bool scalePointer;
|
||||||
|
|
||||||
struct CursorState cursorLast;
|
struct CursorState cursorLast;
|
||||||
|
|
||||||
@ -197,6 +199,13 @@ static struct Option egl_options[] =
|
|||||||
.type = OPTION_TYPE_BOOL,
|
.type = OPTION_TYPE_BOOL,
|
||||||
.value.x_bool = false
|
.value.x_bool = false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.module = "egl",
|
||||||
|
.name = "scalePointer",
|
||||||
|
.description = "Keep the pointer size 1:1 when downscaling",
|
||||||
|
.type = OPTION_TYPE_BOOL,
|
||||||
|
.value.x_bool = true
|
||||||
|
},
|
||||||
|
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
@ -381,8 +390,10 @@ static void egl_calc_mouse_state(struct Inst * this)
|
|||||||
egl_cursorSetState(
|
egl_cursorSetState(
|
||||||
this->cursor,
|
this->cursor,
|
||||||
this->cursorVisible,
|
this->cursorVisible,
|
||||||
(((float)this->cursorX * this->mouseScaleX) - 1.0f) * this->scaleX,
|
(((float)this->cursorX * this->mouseScaleX) - 1.0f) * this->scaleX,
|
||||||
(((float)this->cursorY * this->mouseScaleY) - 1.0f) * this->scaleY
|
(((float)this->cursorY * this->mouseScaleY) - 1.0f) * this->scaleY,
|
||||||
|
((float)this->cursorHX * this->mouseScaleX) * this->scaleX,
|
||||||
|
((float)this->cursorHY * this->mouseScaleY) * this->scaleY
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -391,8 +402,10 @@ static void egl_calc_mouse_state(struct Inst * this)
|
|||||||
egl_cursorSetState(
|
egl_cursorSetState(
|
||||||
this->cursor,
|
this->cursor,
|
||||||
this->cursorVisible,
|
this->cursorVisible,
|
||||||
(((float)this->cursorX * this->mouseScaleX) - 1.0f) * this->scaleY,
|
(((float)this->cursorX * this->mouseScaleX) - 1.0f) * this->scaleY,
|
||||||
(((float)this->cursorY * this->mouseScaleY) - 1.0f) * this->scaleX
|
(((float)this->cursorY * this->mouseScaleY) - 1.0f) * this->scaleX,
|
||||||
|
((float)this->cursorHX * this->mouseScaleX) * this->scaleY,
|
||||||
|
((float)this->cursorHY * this->mouseScaleY) * this->scaleX
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -465,6 +478,12 @@ 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)
|
||||||
|
{
|
||||||
|
float scale = max(1.0f,
|
||||||
|
this->formatValid ? (float)this->format.width / this->width : 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;
|
||||||
@ -497,12 +516,15 @@ static bool egl_onMouseShape(LG_Renderer * renderer, const LG_RendererCursor cur
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_onMouseEvent(LG_Renderer * renderer, const bool visible, const int x, const int y)
|
static bool egl_onMouseEvent(LG_Renderer * renderer, const bool visible,
|
||||||
|
int x, int y, const int hx, const int hy)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
this->cursorVisible = visible;
|
this->cursorVisible = visible;
|
||||||
this->cursorX = x;
|
this->cursorX = x + hx;
|
||||||
this->cursorY = y;
|
this->cursorY = y + hy;
|
||||||
|
this->cursorHX = hx;
|
||||||
|
this->cursorHY = hy;
|
||||||
egl_calc_mouse_state(this);
|
egl_calc_mouse_state(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -534,6 +556,12 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->scalePointer)
|
||||||
|
{
|
||||||
|
float scale = max(1.0f, (float)format.width / this->width);
|
||||||
|
egl_cursorSetScale(this->cursor, scale);
|
||||||
|
}
|
||||||
|
|
||||||
egl_update_scale_type(this);
|
egl_update_scale_type(this);
|
||||||
egl_damageSetup(this->damage, format.width, format.height);
|
egl_damageSetup(this->damage, format.width, format.height);
|
||||||
|
|
||||||
@ -818,6 +846,8 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
|||||||
if (this->noSwapDamage)
|
if (this->noSwapDamage)
|
||||||
DEBUG_WARN("egl:noSwapDamage specified, disabling swap buffers with damage.");
|
DEBUG_WARN("egl:noSwapDamage specified, disabling swap buffers with damage.");
|
||||||
|
|
||||||
|
this->scalePointer = option_get_bool("egl", "scalePointer");
|
||||||
|
|
||||||
if (!g_egl_dynProcs.glEGLImageTargetTexture2DOES)
|
if (!g_egl_dynProcs.glEGLImageTargetTexture2DOES)
|
||||||
DEBUG_INFO("glEGLImageTargetTexture2DOES unavilable, DMA support disabled");
|
DEBUG_INFO("glEGLImageTargetTexture2DOES unavilable, DMA support disabled");
|
||||||
else if (!g_egl_dynProcs.eglCreateImage || !g_egl_dynProcs.eglDestroyImage)
|
else if (!g_egl_dynProcs.eglCreateImage || !g_egl_dynProcs.eglDestroyImage)
|
||||||
|
@ -5,11 +5,25 @@ in vec2 uv;
|
|||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D sampler1;
|
||||||
|
uniform float scale;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 tmp = texture(sampler1, uv);
|
vec4 tmp;
|
||||||
|
if (scale > 1.0)
|
||||||
|
{
|
||||||
|
vec2 ts = vec2(textureSize(sampler1, 0));
|
||||||
|
vec2 px = (uv - (0.5 / ts)) * ts;
|
||||||
|
if (px.x < 0.0 || px.y < 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
tmp = texelFetch(sampler1, ivec2(px), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp = texture(sampler1, uv);
|
||||||
|
|
||||||
if (tmp.rgb == vec3(0.0, 0.0, 0.0))
|
if (tmp.rgb == vec3(0.0, 0.0, 0.0))
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
color = tmp;
|
color = tmp;
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,26 @@ precision mediump float;
|
|||||||
|
|
||||||
#include "color_blind.h"
|
#include "color_blind.h"
|
||||||
|
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D sampler1;
|
||||||
|
uniform float scale;
|
||||||
uniform int cbMode;
|
uniform int cbMode;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
color = texture(sampler1, uv);
|
if (scale > 1.0)
|
||||||
|
{
|
||||||
|
vec2 ts = vec2(textureSize(sampler1, 0));
|
||||||
|
vec2 px = (uv - (0.5 / ts)) * ts;
|
||||||
|
if (px.x < 0.0 || px.y < 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
color = texelFetch(sampler1, ivec2(px), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
color = texture(sampler1, uv);
|
||||||
|
|
||||||
if (cbMode > 0)
|
if (cbMode > 0)
|
||||||
color = cbTransform(color, cbMode);
|
color = cbTransform(color, cbMode);
|
||||||
|
@ -338,7 +338,8 @@ bool opengl_onMouseShape(LG_Renderer * renderer, const LG_RendererCursor cursor,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opengl_onMouseEvent(LG_Renderer * renderer, const bool visible, const int x, const int y)
|
bool opengl_onMouseEvent(LG_Renderer * renderer, const bool visible,
|
||||||
|
int x, int y, const int hx, const int hy)
|
||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
|
@ -341,7 +341,9 @@ int main_cursorThread(void * unused)
|
|||||||
RENDERER(onMouseEvent,
|
RENDERER(onMouseEvent,
|
||||||
g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput),
|
g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput),
|
||||||
g_cursor.guest.x,
|
g_cursor.guest.x,
|
||||||
g_cursor.guest.y
|
g_cursor.guest.y,
|
||||||
|
g_cursor.guest.hx,
|
||||||
|
g_cursor.guest.hy
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!g_state.stopVideo)
|
if (!g_state.stopVideo)
|
||||||
@ -456,7 +458,9 @@ int main_cursorThread(void * unused)
|
|||||||
RENDERER(onMouseEvent,
|
RENDERER(onMouseEvent,
|
||||||
g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput),
|
g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput),
|
||||||
g_cursor.guest.x,
|
g_cursor.guest.x,
|
||||||
g_cursor.guest.y
|
g_cursor.guest.y,
|
||||||
|
g_cursor.guest.hx,
|
||||||
|
g_cursor.guest.hy
|
||||||
);
|
);
|
||||||
|
|
||||||
if (g_params.mouseRedraw && g_cursor.guest.visible && !g_state.stopVideo)
|
if (g_params.mouseRedraw && g_cursor.guest.visible && !g_state.stopVideo)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user