mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +00:00
t/gui: Add OpenGL sink code
This commit is contained in:
parent
968952aa9e
commit
c474112782
|
@ -16,6 +16,7 @@ include_directories(
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
gui_common.h
|
gui_common.h
|
||||||
gui_main.c
|
gui_main.c
|
||||||
|
gui_ogl.c
|
||||||
gui_prober.c
|
gui_prober.c
|
||||||
gui_sdl2.c
|
gui_sdl2.c
|
||||||
../../../external/glad/gl.h
|
../../../external/glad/gl.h
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xrt/xrt_defines.h"
|
#include "xrt/xrt_frame.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -55,6 +55,23 @@ struct program
|
||||||
struct time_state *timekeeping;
|
struct time_state *timekeeping;
|
||||||
struct xrt_device *xdevs[NUM_XDEVS];
|
struct xrt_device *xdevs[NUM_XDEVS];
|
||||||
struct xrt_prober *xp;
|
struct xrt_prober *xp;
|
||||||
|
|
||||||
|
struct gui_ogl_texture *texs[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A OpenGL texture.
|
||||||
|
*
|
||||||
|
* @ingroup gui
|
||||||
|
*/
|
||||||
|
struct gui_ogl_texture
|
||||||
|
{
|
||||||
|
uint64_t seq;
|
||||||
|
uint64_t dropped;
|
||||||
|
const char *name;
|
||||||
|
uint32_t w, h;
|
||||||
|
uint32_t id;
|
||||||
|
bool half;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -118,6 +135,27 @@ gui_prober_update(struct program *p);
|
||||||
void
|
void
|
||||||
gui_prober_teardown(struct program *p);
|
gui_prober_teardown(struct program *p);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Create a sink that will turn frames into OpenGL textures, since the frame
|
||||||
|
* can come from another thread @ref gui_ogl_sink_update needs to be called.
|
||||||
|
*
|
||||||
|
* Destruction is handled by the frame context.
|
||||||
|
*
|
||||||
|
* @ingroup gui
|
||||||
|
*/
|
||||||
|
struct gui_ogl_texture *
|
||||||
|
gui_ogl_sink_create(const char *name,
|
||||||
|
struct xrt_frame_context *xfctx,
|
||||||
|
struct xrt_frame_sink **out_sink);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Update the texture to the latest received frame.
|
||||||
|
*
|
||||||
|
* @ingroup gui
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gui_ogl_sink_update(struct gui_ogl_texture *);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
176
src/xrt/targets/gui/gui_ogl.c
Normal file
176
src/xrt/targets/gui/gui_ogl.c
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
// Copyright 2019, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief OpenGL functions to drive the gui.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup gui
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xrt/xrt_frame.h"
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
|
||||||
|
#include "gui_common.h"
|
||||||
|
#include "glad/gl.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct gui_ogl_sink
|
||||||
|
{
|
||||||
|
struct gui_ogl_texture tex;
|
||||||
|
|
||||||
|
struct xrt_frame_sink sink;
|
||||||
|
struct xrt_frame_node node;
|
||||||
|
|
||||||
|
struct xrt_frame *frame;
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
bool running;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
push_frame(struct xrt_frame_sink *xs, struct xrt_frame *xf)
|
||||||
|
{
|
||||||
|
struct gui_ogl_sink *s = container_of(xs, struct gui_ogl_sink, sink);
|
||||||
|
|
||||||
|
// The fields are protected.
|
||||||
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
|
||||||
|
// If we are in the process of shutting down, don't take the reference.
|
||||||
|
if (s->running) {
|
||||||
|
xrt_frame_reference(&s->frame, xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
break_apart(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gui_ogl_sink *s = container_of(node, struct gui_ogl_sink, node);
|
||||||
|
|
||||||
|
// Stop receiving any more reference.
|
||||||
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
s->running = false;
|
||||||
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gui_ogl_sink *s = container_of(node, struct gui_ogl_sink, node);
|
||||||
|
|
||||||
|
glDeleteTextures(1, &s->tex.id);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&s->mutex);
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_r8g8b8(struct gui_ogl_sink *s, GLint w, GLint h, uint8_t *data)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, s->tex.id);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB,
|
||||||
|
GL_UNSIGNED_BYTE, data);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_l8(struct gui_ogl_sink *s, GLint w, GLint h, uint8_t *data)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, s->tex.id);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED,
|
||||||
|
GL_UNSIGNED_BYTE, data);
|
||||||
|
GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
|
||||||
|
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gui_ogl_sink_update(struct gui_ogl_texture *tex)
|
||||||
|
{
|
||||||
|
struct gui_ogl_sink *s = container_of(tex, struct gui_ogl_sink, tex);
|
||||||
|
(void)s;
|
||||||
|
|
||||||
|
// Take the frame no need to adjust reference.
|
||||||
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
struct xrt_frame *frame = s->frame;
|
||||||
|
s->frame = NULL;
|
||||||
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
|
if (frame == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint w, h;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
w = frame->width;
|
||||||
|
h = frame->height;
|
||||||
|
|
||||||
|
if (tex->w != (uint32_t)w || tex->h != (uint32_t)h) {
|
||||||
|
tex->w = w;
|
||||||
|
tex->h = h;
|
||||||
|
|
||||||
|
// Automatically set the half scaling.
|
||||||
|
if (tex->w >= 1024 || tex->h >= 1024) {
|
||||||
|
tex->half = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->seq = frame->source_sequence;
|
||||||
|
data = frame->data;
|
||||||
|
|
||||||
|
switch (frame->format) {
|
||||||
|
case XRT_FORMAT_R8G8B8: update_r8g8b8(s, w, h, data); break;
|
||||||
|
case XRT_FORMAT_L8: update_l8(s, w, h, data); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrt_frame_reference(&frame, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gui_ogl_texture *
|
||||||
|
gui_ogl_sink_create(const char *name,
|
||||||
|
struct xrt_frame_context *xfctx,
|
||||||
|
struct xrt_frame_sink **out_sink)
|
||||||
|
{
|
||||||
|
struct gui_ogl_sink *s = U_TYPED_CALLOC(struct gui_ogl_sink);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
s->sink.push_frame = push_frame;
|
||||||
|
s->node.break_apart = break_apart;
|
||||||
|
s->node.destroy = destroy;
|
||||||
|
s->tex.name = name;
|
||||||
|
s->tex.w = 256;
|
||||||
|
s->tex.h = 256;
|
||||||
|
s->running = true;
|
||||||
|
|
||||||
|
ret = pthread_mutex_init(&s->mutex, NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
free(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary texture
|
||||||
|
glGenTextures(1, &s->tex.id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, s->tex.id);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
GLint w = 1;
|
||||||
|
GLint h = 1;
|
||||||
|
struct xrt_colour_rgb_u8 pink = {255, 0, 255};
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB,
|
||||||
|
GL_UNSIGNED_BYTE, &pink.r);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
*out_sink = &s->sink;
|
||||||
|
|
||||||
|
return &s->tex;
|
||||||
|
}
|
Loading…
Reference in a new issue