[client] egl: fix race condition in help overlay

egl_help_set_text and egl_help_render were both accessing bmp->help from
different threads. This creates a race condition in which if the help text
is quickly toggled on and off, it stays on.

This has been fixed with an atomic exchange.
This commit is contained in:
Quantum 2021-01-31 17:23:22 -05:00 committed by Geoffrey McRae
parent 1d99c821eb
commit b45f7a6733

View File

@ -24,6 +24,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "shader.h"
#include "model.h"
#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
@ -41,7 +42,8 @@ struct EGL_Help
EGL_Shader * shader;
EGL_Shader * shaderBG;
EGL_Model * model;
LG_FontBitmap * bmp;
_Atomic(LG_FontBitmap *) bmp;
bool shouldRender;
int iwidth, iheight;
@ -101,7 +103,6 @@ bool egl_help_init(EGL_Help ** help, const LG_Font * font, LG_FontObj fontObj)
return false;
}
(*help)->uSize = egl_shader_get_uniform_location((*help)->shader , "size" );
(*help)->uScreen = egl_shader_get_uniform_location((*help)->shader , "screen");
(*help)->uSizeBG = egl_shader_get_uniform_location((*help)->shaderBG, "size" );
@ -116,6 +117,8 @@ bool egl_help_init(EGL_Help ** help, const LG_Font * font, LG_FontObj fontObj)
egl_model_set_default((*help)->model);
egl_model_set_texture((*help)->model, (*help)->texture);
atomic_init(&(*help)->bmp, NULL);
return true;
}
@ -135,37 +138,40 @@ void egl_help_free(EGL_Help ** help)
void egl_help_set_text(EGL_Help * help, const char * help_text)
{
if (!help_text)
{
help->shouldRender = false;
return;
}
help->bmp = help->font->render(help->fontObj, 0xffffff00, help_text);
if (!help->bmp)
LG_FontBitmap * bmp = NULL;
if (help_text)
{
bmp = help->font->render(help->fontObj, 0xffffff00, help_text);
if (!bmp)
DEBUG_ERROR("Failed to render help text");
return;
} else
help->shouldRender = false;
bmp = atomic_exchange(&help->bmp, bmp);
if (bmp)
{
help->font->release(help->fontObj, bmp);
}
}
void egl_help_render(EGL_Help * help, const float scaleX, const float scaleY)
{
if (help->bmp)
LG_FontBitmap * bmp = atomic_exchange(&help->bmp, NULL);
if (bmp)
{
if (help->iwidth != help->bmp->width || help->iheight != help->bmp->height)
if (help->iwidth != bmp->width || help->iheight != bmp->height)
{
help->iwidth = help->bmp->width;
help->iheight = help->bmp->height;
help->width = (float)help->bmp->width;
help->height = (float)help->bmp->height;
help->iwidth = bmp->width;
help->iheight = bmp->height;
help->width = (float)bmp->width;
help->height = (float)bmp->height;
egl_texture_setup(
help->texture,
EGL_PF_BGRA,
help->bmp->width ,
help->bmp->height,
help->bmp->width * help->bmp->bpp,
bmp->width ,
bmp->height,
bmp->width * bmp->bpp,
false,
false
);
@ -174,12 +180,11 @@ void egl_help_render(EGL_Help * help, const float scaleX, const float scaleY)
egl_texture_update
(
help->texture,
help->bmp->pixels
bmp->pixels
);
help->shouldRender = true;
help->font->release(help->fontObj, help->bmp);
help->bmp = NULL;
help->font->release(help->fontObj, bmp);
}
if (!help->shouldRender)