[opengl] added support for alerts

This commit is contained in:
Geoffrey McRae 2018-05-29 11:08:25 +10:00
parent 89959b48a7
commit fbbee1cdac

View file

@ -33,12 +33,14 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "debug.h"
#include "utils.h"
#include "lg-decoders.h"
#include "ll.h"
#define BUFFER_COUNT 2
#define FPS_TEXTURE 0
#define MOUSE_TEXTURE 1
#define TEXTURE_COUNT 2
#define ALERT_TEXTURE 2
#define TEXTURE_COUNT 3
struct Options
{
@ -56,6 +58,13 @@ static struct Options defaultOptions =
.amdPinnedMem = true,
};
struct Alert
{
SDL_Surface *text;
float r, g, b, a;
uint64_t timeout;
};
struct Inst
{
LG_RendererParams params;
@ -96,6 +105,8 @@ struct Inst
GLsync fences[BUFFER_COUNT];
void * decoderFrames[BUFFER_COUNT];
GLuint textures[TEXTURE_COUNT];
struct ll * alerts;
int alertList;
bool fpsTexture;
uint64_t lastFrameTime;
@ -155,6 +166,7 @@ bool opengl_create(void ** opaque, const LG_RendererParams params)
LG_LOCK_INIT(this->syncLock );
LG_LOCK_INIT(this->mouseLock );
this->alerts = ll_new();
return true;
}
@ -183,6 +195,15 @@ void opengl_deinitialize(void * opaque)
LG_LOCK_FREE(this->syncLock );
LG_LOCK_FREE(this->mouseLock );
struct Alert * alert;
while(ll_shift(this->alerts, (void **)&alert))
{
if (alert->text)
SDL_FreeSurface(alert->text);
free(alert);
}
ll_free(this->alerts);
free(this);
}
@ -288,6 +309,79 @@ bool opengl_on_frame_event(void * opaque, const LG_RendererFormat format, const
return true;
}
void opengl_on_alert(void * opaque, const LG_RendererAlert alert, const char * message)
{
struct Inst * this = (struct Inst *)opaque;
struct Alert * a = malloc(sizeof(struct Alert));
memset(a, 0, sizeof(struct Alert));
const SDL_Color color = {0xff, 0xff, 0xff};
switch(alert)
{
case LG_ALERT_INFO:
a->r = 0.0f;
a->g = 0.0f;
a->b = 0.8f;
a->a = 0.8f;
break;
case LG_ALERT_SUCCESS:
a->r = 0.0f;
a->g = 0.8f;
a->b = 0.0f;
a->a = 0.8f;
break;
case LG_ALERT_WARNING:
a->r = 0.8f;
a->g = 0.5f;
a->b = 0.0f;
a->a = 0.8f;
break;
case LG_ALERT_ERROR:
a->r = 1.0f;
a->g = 0.0f;
a->b = 0.0f;
a->a = 0.8f;
break;
}
if (!(a->text = TTF_RenderText_Blended(this->params.alertFont, message, color)))
{
DEBUG_ERROR("Failed to render alert text: %s", TTF_GetError());
free(a);
return;
}
ll_push(this->alerts, a);
}
void surface_to_texture(SDL_Surface * surface, GLuint texture)
{
glBindTexture(GL_TEXTURE_2D , texture );
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->w);
glTexImage2D(
GL_TEXTURE_2D,
0,
surface->format->BytesPerPixel,
surface->w,
surface->h,
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
surface->pixels
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
}
bool opengl_render(void * opaque, SDL_Window * window)
{
struct Inst * this = (struct Inst *)opaque;
@ -340,36 +434,16 @@ bool opengl_render(void * opaque, SDL_Window * window)
const float avgFPS = 1000.0f / (((float)this->renderTime / this->frameCount ) / 1e6f);
const float renderFPS = 1000.0f / (((float)this->renderTime / this->renderCount) / 1e6f);
snprintf(str, sizeof(str), "UPS: %8.4f, FPS: %8.4f", avgFPS, renderFPS);
SDL_Color color = {0xff, 0xff, 0xff};
const SDL_Color color = {0xff, 0xff, 0xff};
SDL_Surface *textSurface = NULL;
if (!(textSurface = TTF_RenderText_Blended(this->params.font, str, color)))
{
DEBUG_ERROR("Failed to render text");
DEBUG_ERROR("Failed to render text: %s", TTF_GetError());
LG_UNLOCK(this->formatLock);
return false;
}
glBindTexture(GL_TEXTURE_2D , this->textures[FPS_TEXTURE]);
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
glPixelStorei(GL_UNPACK_ROW_LENGTH, textSurface->w );
glTexImage2D(
GL_TEXTURE_2D,
0,
textSurface->format->BytesPerPixel,
textSurface->w,
textSurface->h,
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
textSurface->pixels
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
surface_to_texture(textSurface, this->textures[FPS_TEXTURE]);
this->fpsRect.x = 5;
this->fpsRect.y = 5;
@ -422,6 +496,60 @@ bool opengl_render(void * opaque, SDL_Window * window)
if (this->fpsTexture)
glCallList(this->fpsList);
struct Alert * alert;
while(ll_peek_head(this->alerts, (void **)&alert))
{
if (alert->timeout == 0)
{
surface_to_texture(alert->text, this->textures[ALERT_TEXTURE]);
glNewList(this->alertList, GL_COMPILE);
const int p = 4;
const int w = alert->text->w + p * 2;
const int h = alert->text->h + p * 2;
glTranslatef(-(w / 2), -(h / 2), 0.0f);
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glColor4f(alert->r, alert->g, alert->b, alert->a);
glBegin(GL_TRIANGLE_STRIP);
glVertex2i(0, 0);
glVertex2i(w, 0);
glVertex2i(0, h);
glVertex2i(w, h);
glEnd();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->textures[ALERT_TEXTURE]);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(p, p, 0.0f);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f); glVertex2i(0 , 0 );
glTexCoord2f(1.0f, 0.0f); glVertex2i(alert->text->w, 0 );
glTexCoord2f(0.0f, 1.0f); glVertex2i(0 , alert->text->h);
glTexCoord2f(1.0f, 1.0f); glVertex2i(alert->text->w, alert->text->h);
glEnd();
glDisable(GL_BLEND);
glEndList();
alert->timeout = microtime() + 2*1000000;
SDL_FreeSurface(alert->text);
alert->text = NULL;
}
else if (alert->timeout < microtime())
{
free(alert);
ll_shift(this->alerts, NULL);
continue;
}
glPushMatrix();
glLoadIdentity();
glTranslatef(this->window.x / 2, this->window.y / 2, 0.0f);
glCallList(this->alertList);
glPopMatrix();
break;
}
if (this->opt.preventBuffer)
{
SDL_GL_SwapWindow(window);
@ -523,6 +651,7 @@ const LG_Renderer LGR_OpenGL =
.on_mouse_shape = opengl_on_mouse_shape,
.on_mouse_event = opengl_on_mouse_event,
.on_frame_event = opengl_on_frame_event,
.on_alert = opengl_on_alert,
.render = opengl_render
};
@ -644,6 +773,7 @@ static bool configure(struct Inst * this, SDL_Window *window)
this->texList = glGenLists(BUFFER_COUNT);
this->fpsList = glGenLists(1);
this->mouseList = glGenLists(1);
this->alertList = glGenLists(1);
// generate the pixel unpack buffers if the decoder isn't going to do it for us
if (!this->decoder->has_gl)