mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
Support v4l2 yuyv on nvidia
This commit is contained in:
@@ -628,18 +628,6 @@ static int gsr_capture_kms_capture(gsr_capture *cap, gsr_capture_metadata *captu
|
||||
}
|
||||
}
|
||||
|
||||
// static GLsync sync = NULL;
|
||||
|
||||
// if(sync) {
|
||||
// const unsigned int r = self->params.egl->glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 1000);
|
||||
// if(r != GL_CONDITION_SATISFIED && r != GL_ALREADY_SIGNALED) {
|
||||
// fprintf(stderr, "failed sync: %u\n", r);
|
||||
// }
|
||||
// self->params.egl->glDeleteSync(sync);
|
||||
// }
|
||||
|
||||
// sync = self->params.egl->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
//self->params.egl->glFlush();
|
||||
//self->params.egl->glFinish();
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ typedef struct {
|
||||
int fd;
|
||||
int dmabuf_fd[NUM_BUFFERS];
|
||||
EGLImage dma_image[NUM_BUFFERS];
|
||||
unsigned int texture_id;
|
||||
unsigned int texture_id[NUM_BUFFERS];
|
||||
unsigned int prev_texture_index;
|
||||
bool got_first_frame;
|
||||
|
||||
void *dmabuf_map[NUM_BUFFERS];
|
||||
@@ -72,6 +73,8 @@ typedef struct {
|
||||
tjhandle jpeg_decompressor;
|
||||
|
||||
double capture_start_time;
|
||||
|
||||
bool yuyv_conversion_fallback;
|
||||
} gsr_capture_v4l2;
|
||||
|
||||
static int xioctl(int fd, unsigned long request, void *arg) {
|
||||
@@ -90,9 +93,9 @@ static void gsr_capture_v4l2_stop(gsr_capture_v4l2 *self) {
|
||||
self->pbos[i] = 0;
|
||||
}
|
||||
|
||||
if(self->texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->texture_id);
|
||||
self->texture_id = 0;
|
||||
self->params.egl->glDeleteTextures(NUM_BUFFERS, self->texture_id);
|
||||
for(int i = 0; i < NUM_BUFFERS; ++i) {
|
||||
self->texture_id[i] = 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < NUM_BUFFERS; ++i) {
|
||||
@@ -246,32 +249,48 @@ static bool gsr_capture_v4l2_map_buffer(gsr_capture_v4l2 *self, const struct v4l
|
||||
return false;
|
||||
}
|
||||
case GSR_CAPTURE_V4L2_PIXFMT_YUYV: {
|
||||
self->params.egl->glGenTextures(NUM_BUFFERS, self->texture_id);
|
||||
|
||||
for(int i = 0; i < NUM_BUFFERS; ++i) {
|
||||
self->dma_image[i] = self->params.egl->eglCreateImage(self->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, (intptr_t[]) {
|
||||
EGL_WIDTH, fmt->fmt.pix.width,
|
||||
EGL_HEIGHT, fmt->fmt.pix.height,
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_YUYV, // TODO: Use DRM_FORMAT_RG88 on nvidia and custom shader. Test on intel as well, or use fallback method on every system.
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_YUYV,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, self->dmabuf_fd[i],
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, fmt->fmt.pix.bytesperline,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(!self->dma_image[i]) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: eglCreateImage failed, error: %d\n", self->params.egl->eglGetError());
|
||||
self->yuyv_conversion_fallback = true;
|
||||
self->dma_image[i] = self->params.egl->eglCreateImage(self->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, (intptr_t[]) {
|
||||
EGL_WIDTH, fmt->fmt.pix.width,
|
||||
EGL_HEIGHT, fmt->fmt.pix.height,
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_RG88,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, self->dmabuf_fd[i],
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, fmt->fmt.pix.bytesperline,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(!self->dma_image[i]) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: eglCreateImage failed, error: %d\n", self->params.egl->eglGetError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_id[i]);
|
||||
self->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, self->dma_image[i]);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
if(self->texture_id[i] == 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: failed to create texture\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self->params.egl->glGenTextures(1, &self->texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_id);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
if(self->texture_id == 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: failed to create texture\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
self->buffer_type = V4L2_BUFFER_TYPE_DMABUF;
|
||||
break;
|
||||
}
|
||||
@@ -283,13 +302,13 @@ static bool gsr_capture_v4l2_map_buffer(gsr_capture_v4l2 *self, const struct v4l
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: mmap failed, error: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// GL_RGBA is intentionally used here instead of GL_RGB, because the performance is much better when using glTexSubImage2D (22% cpu usage compared to 38% cpu usage)
|
||||
self->texture_id = gl_create_texture(self->params.egl, fmt->fmt.pix.width, fmt->fmt.pix.height, GL_RGBA8, GL_RGBA, GL_LINEAR);
|
||||
if(self->texture_id == 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: failed to create texture\n");
|
||||
return false;
|
||||
// GL_RGBA is intentionally used here instead of GL_RGB, because the performance is much better when using glTexSubImage2D (22% cpu usage compared to 38% cpu usage)
|
||||
self->texture_id[i] = gl_create_texture(self->params.egl, fmt->fmt.pix.width, fmt->fmt.pix.height, GL_RGBA8, GL_RGBA, GL_LINEAR);
|
||||
if(self->texture_id[i] == 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_map_buffer: failed to create texture\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!gsr_capture_v4l2_create_pbos(self, fmt->fmt.pix.width, fmt->fmt.pix.height))
|
||||
@@ -377,15 +396,6 @@ static int gsr_capture_v4l2_setup(gsr_capture_v4l2 *self) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Buggy driver paranoia */
|
||||
const uint32_t min_stride = fmt.fmt.pix.width * 2; // * 2 because the stride is width (Y) + width/2 (U) + width/2 (V)
|
||||
if(fmt.fmt.pix.bytesperline < min_stride)
|
||||
fmt.fmt.pix.bytesperline = min_stride;
|
||||
|
||||
const uint32_t min_size = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
|
||||
if(fmt.fmt.pix.sizeimage < min_size)
|
||||
fmt.fmt.pix.sizeimage = min_size;
|
||||
|
||||
self->capture_size.x = fmt.fmt.pix.width;
|
||||
self->capture_size.y = fmt.fmt.pix.height;
|
||||
|
||||
@@ -479,7 +489,7 @@ static void gsr_capture_v4l2_decode_jpeg_to_texture(gsr_capture_v4l2 *self, cons
|
||||
return;
|
||||
}
|
||||
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_id[buf->index]);
|
||||
|
||||
self->pbo_index = (self->pbo_index + 1) % NUM_PBOS;
|
||||
const unsigned int next_pbo_index = (self->pbo_index + 1) % NUM_PBOS;
|
||||
@@ -511,6 +521,8 @@ static int gsr_capture_v4l2_capture(gsr_capture *cap, gsr_capture_metadata *capt
|
||||
};
|
||||
|
||||
xioctl(self->fd, VIDIOC_DQBUF, &buf);
|
||||
unsigned int texture_index = buf.index;
|
||||
|
||||
if(buf.bytesused > 0 && !(buf.flags & V4L2_BUF_FLAG_ERROR)) {
|
||||
if(!self->got_first_frame)
|
||||
fprintf(stderr, "gsr info: gsr_capture_v4l2_capture: camera %s is now ready\n", self->params.device_path);
|
||||
@@ -518,9 +530,9 @@ static int gsr_capture_v4l2_capture(gsr_capture *cap, gsr_capture_metadata *capt
|
||||
|
||||
switch(self->buffer_type) {
|
||||
case V4L2_BUFFER_TYPE_DMABUF: {
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_id);
|
||||
self->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, self->dma_image[buf.index]);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
//self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_id);
|
||||
//self->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, self->dma_image[buf.index]);
|
||||
//self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
break;
|
||||
}
|
||||
case V4L2_BUFFER_TYPE_MMAP: {
|
||||
@@ -530,6 +542,10 @@ static int gsr_capture_v4l2_capture(gsr_capture *cap, gsr_capture_metadata *capt
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self->prev_texture_index = buf.index;
|
||||
} else {
|
||||
texture_index = self->prev_texture_index;
|
||||
}
|
||||
xioctl(self->fd, VIDIOC_QBUF, &buf);
|
||||
|
||||
@@ -537,13 +553,20 @@ static int gsr_capture_v4l2_capture(gsr_capture *cap, gsr_capture_metadata *capt
|
||||
const vec2i target_pos = gsr_capture_get_target_position(output_size, capture_metadata);
|
||||
|
||||
self->params.egl->glFlush();
|
||||
if(self->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA)
|
||||
self->params.egl->glFinish();
|
||||
|
||||
//if(self->got_first_frame) {
|
||||
gsr_color_conversion_draw(color_conversion, self->texture_id,
|
||||
if(self->buffer_type == V4L2_BUFFER_TYPE_DMABUF) {
|
||||
gsr_color_conversion_draw(color_conversion, self->texture_id[texture_index],
|
||||
target_pos, output_size,
|
||||
(vec2i){0, 0}, self->capture_size, self->capture_size,
|
||||
GSR_ROT_0, capture_metadata->flip, GSR_SOURCE_COLOR_RGB, self->buffer_type == V4L2_BUFFER_TYPE_DMABUF);
|
||||
//}
|
||||
GSR_ROT_0, capture_metadata->flip, self->yuyv_conversion_fallback ? GSR_SOURCE_COLOR_YUYV : GSR_SOURCE_COLOR_RGB, true);
|
||||
} else {
|
||||
gsr_color_conversion_draw(color_conversion, self->texture_id[texture_index],
|
||||
target_pos, output_size,
|
||||
(vec2i){0, 0}, self->capture_size, self->capture_size,
|
||||
GSR_ROT_0, capture_metadata->flip, GSR_SOURCE_COLOR_RGB, false);
|
||||
}
|
||||
|
||||
return self->got_first_frame ? 0 : -1;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
#define GRAPHICS_SHADER_INDEX_UV_EXTERNAL 3
|
||||
#define GRAPHICS_SHADER_INDEX_RGB 4
|
||||
#define GRAPHICS_SHADER_INDEX_RGB_EXTERNAL 5
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_RGB 6
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL 7
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_Y 6
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_UV 7
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_Y_EXTERNAL 8
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_UV_EXTERNAL 9
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_RGB 10
|
||||
#define GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL 11
|
||||
|
||||
/* https://en.wikipedia.org/wiki/YCbCr, see study/color_space_transform_matrix.png */
|
||||
|
||||
@@ -250,6 +254,135 @@ static unsigned int load_graphics_shader_rgb(gsr_shader *shader, gsr_egl *egl, g
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_graphics_shader_yuyv_to_y(gsr_shader *shader, gsr_egl *egl, gsr_color_graphics_uniforms *uniforms, bool external_texture) {
|
||||
char vertex_shader[2048];
|
||||
snprintf(vertex_shader, sizeof(vertex_shader),
|
||||
"#version 300 es \n"
|
||||
"in vec2 pos; \n"
|
||||
"in vec2 texcoords; \n"
|
||||
"out vec2 texcoords_out; \n"
|
||||
"uniform vec2 offset; \n"
|
||||
"uniform float rotation; \n"
|
||||
"uniform mat2 rotation_matrix; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" texcoords_out = vec2(texcoords.x - 0.5, texcoords.y - 0.5) * rotation_matrix + vec2(0.5, 0.5); \n"
|
||||
" gl_Position = vec4(offset.x, offset.y, 0.0, 0.0) + vec4(pos.x, pos.y, 0.0, 1.0); \n"
|
||||
"} \n");
|
||||
|
||||
const char *main_code =
|
||||
" vec4 pixel = texture(tex1, texcoords_out); \n"
|
||||
" FragColor.x = pixel.r; \n"
|
||||
" FragColor.w = 1.0; \n";
|
||||
|
||||
char fragment_shader[2048];
|
||||
if(external_texture) {
|
||||
snprintf(fragment_shader, sizeof(fragment_shader),
|
||||
"#version 300 es \n"
|
||||
"#extension GL_OES_EGL_image_external : enable \n"
|
||||
"#extension GL_OES_EGL_image_external_essl3 : require \n"
|
||||
"precision highp float; \n"
|
||||
"in vec2 texcoords_out; \n"
|
||||
"uniform samplerExternalOES tex1; \n"
|
||||
"out vec4 FragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
"%s"
|
||||
"} \n", main_code);
|
||||
} else {
|
||||
snprintf(fragment_shader, sizeof(fragment_shader),
|
||||
"#version 300 es \n"
|
||||
"precision highp float; \n"
|
||||
"in vec2 texcoords_out; \n"
|
||||
"uniform sampler2D tex1; \n"
|
||||
"out vec4 FragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
"%s"
|
||||
"} \n", main_code);
|
||||
}
|
||||
|
||||
if(gsr_shader_init(shader, egl, vertex_shader, fragment_shader) != 0)
|
||||
return -1;
|
||||
|
||||
gsr_shader_bind_attribute_location(shader, "pos", 0);
|
||||
gsr_shader_bind_attribute_location(shader, "texcoords", 1);
|
||||
uniforms->offset = egl->glGetUniformLocation(shader->program_id, "offset");
|
||||
uniforms->rotation_matrix = egl->glGetUniformLocation(shader->program_id, "rotation_matrix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int load_graphics_shader_yuyv_to_uv(gsr_shader *shader, gsr_egl *egl, gsr_color_graphics_uniforms *uniforms, bool external_texture) {
|
||||
char vertex_shader[2048];
|
||||
snprintf(vertex_shader, sizeof(vertex_shader),
|
||||
"#version 300 es \n"
|
||||
"in vec2 pos; \n"
|
||||
"in vec2 texcoords; \n"
|
||||
"out vec2 texcoords_out; \n"
|
||||
"uniform vec2 offset; \n"
|
||||
"uniform float rotation; \n"
|
||||
"uniform mat2 rotation_matrix; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" texcoords_out = vec2(texcoords.x - 0.5, texcoords.y - 0.5) * rotation_matrix + vec2(0.5, 0.5); \n"
|
||||
" gl_Position = (vec4(offset.x, offset.y, 0.0, 0.0) + vec4(pos.x, pos.y, 0.0, 1.0)) * vec4(0.5, 0.5, 1.0, 1.0) - vec4(0.5, 0.5, 0.0, 0.0); \n"
|
||||
"} \n");
|
||||
|
||||
const char *main_code =
|
||||
" vec2 resolution = vec2(textureSize(tex1, 0));\n"
|
||||
" ivec2 uv = ivec2(texcoords_out * resolution);\n"
|
||||
" float u = 0.0;\n"
|
||||
" float v = 0.0;\n"
|
||||
" vec4 this_color = texelFetch(tex1, uv, 0);\n"
|
||||
" if((uv.x & 1) == 0) {\n"
|
||||
" vec2 next_color = texelFetch(tex1, uv + ivec2(1, 0), 0).rg;\n"
|
||||
" u = this_color.g;\n"
|
||||
" v = next_color.g;\n"
|
||||
" } else {\n"
|
||||
" vec2 prev_color = texelFetch(tex1, uv - ivec2(1, 0), 0).rg;\n"
|
||||
" u = prev_color.g;\n"
|
||||
" v = this_color.g;\n"
|
||||
" }\n"
|
||||
" FragColor.rg = vec2(u, v);\n"
|
||||
" FragColor.w = 1.0;\n";
|
||||
|
||||
char fragment_shader[2048];
|
||||
if(external_texture) {
|
||||
snprintf(fragment_shader, sizeof(fragment_shader),
|
||||
"#version 300 es \n"
|
||||
"#extension GL_OES_EGL_image_external : enable \n"
|
||||
"#extension GL_OES_EGL_image_external_essl3 : require \n"
|
||||
"precision highp float; \n"
|
||||
"in vec2 texcoords_out; \n"
|
||||
"uniform samplerExternalOES tex1; \n"
|
||||
"out vec4 FragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
"%s"
|
||||
"} \n", main_code);
|
||||
} else {
|
||||
snprintf(fragment_shader, sizeof(fragment_shader),
|
||||
"#version 300 es \n"
|
||||
"precision highp float; \n"
|
||||
"in vec2 texcoords_out; \n"
|
||||
"uniform sampler2D tex1; \n"
|
||||
"out vec4 FragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
"%s"
|
||||
"} \n", main_code);
|
||||
}
|
||||
|
||||
if(gsr_shader_init(shader, egl, vertex_shader, fragment_shader) != 0)
|
||||
return -1;
|
||||
|
||||
gsr_shader_bind_attribute_location(shader, "pos", 0);
|
||||
gsr_shader_bind_attribute_location(shader, "texcoords", 1);
|
||||
uniforms->offset = egl->glGetUniformLocation(shader->program_id, "offset");
|
||||
uniforms->rotation_matrix = egl->glGetUniformLocation(shader->program_id, "rotation_matrix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int load_graphics_shader_yuyv_to_rgb(gsr_shader *shader, gsr_egl *egl, gsr_color_graphics_uniforms *uniforms, bool external_texture) {
|
||||
char vertex_shader[2048];
|
||||
snprintf(vertex_shader, sizeof(vertex_shader),
|
||||
@@ -268,21 +401,18 @@ static unsigned int load_graphics_shader_yuyv_to_rgb(gsr_shader *shader, gsr_egl
|
||||
|
||||
const char *main_code =
|
||||
" vec2 resolution = vec2(textureSize(tex1, 0));\n"
|
||||
" vec2 uv = texcoords_out * resolution;\n"
|
||||
" ivec2 uv = ivec2(texcoords_out * resolution);\n"
|
||||
" float y = 0.0;\n"
|
||||
" float u = 0.0;\n"
|
||||
" float v = 0.0;\n"
|
||||
" if(mod(uv.x, 2.0) < 1.0) {\n"
|
||||
" vec3 this_color = texture(tex1, texcoords_out).rgb;\n"
|
||||
" vec3 next_color = texture(tex1, texcoords_out + vec2(1.0, 0.0)/resolution).rgb;\n"
|
||||
"\n"
|
||||
" vec4 this_color = texelFetch(tex1, uv, 0);\n"
|
||||
" if((uv.x & 1) == 0) {\n"
|
||||
" vec2 next_color = texelFetch(tex1, uv + ivec2(1, 0), 0).rg;\n"
|
||||
" y = this_color.r;\n"
|
||||
" u = this_color.g;\n"
|
||||
" v = next_color.g;\n"
|
||||
" } else {\n"
|
||||
" vec3 this_color = texture(tex1, texcoords_out).rgb;\n"
|
||||
" vec3 prev_color = texture(tex1, texcoords_out - vec2(1.0, 0.0)/resolution).rgb;\n"
|
||||
"\n"
|
||||
" vec2 prev_color = texelFetch(tex1, uv - ivec2(1, 0), 0).rg;\n"
|
||||
" y = this_color.r;\n"
|
||||
" u = prev_color.g;\n"
|
||||
" v = this_color.g;\n"
|
||||
@@ -392,6 +522,16 @@ static bool gsr_color_conversion_load_graphics_shaders(gsr_color_conversion *sel
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV graphics shader\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_y(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_Y], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_Y], false) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to Y graphics shader\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_uv(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_UV], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_UV], false) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to UV graphics shader\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
@@ -423,6 +563,16 @@ static bool gsr_color_conversion_load_external_graphics_shaders(gsr_color_conver
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_y(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_Y_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_Y_EXTERNAL], true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to Y graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_uv(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_UV_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_UV_EXTERNAL], true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to UV graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
@@ -550,17 +700,17 @@ static void gsr_color_conversion_apply_rotation(gsr_rotation rotation, float rot
|
||||
}
|
||||
}
|
||||
|
||||
static void gsr_color_conversion_swizzle_texture_source(gsr_color_conversion *self, gsr_source_color source_color) {
|
||||
static void gsr_color_conversion_swizzle_texture_source(gsr_color_conversion *self, unsigned int texture_target, gsr_source_color source_color) {
|
||||
if(source_color == GSR_SOURCE_COLOR_BGR) {
|
||||
const int swizzle_mask[] = { GL_BLUE, GL_GREEN, GL_RED, 1 };
|
||||
self->params.egl->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
|
||||
self->params.egl->glTexParameteriv(texture_target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void gsr_color_conversion_swizzle_reset(gsr_color_conversion *self, gsr_source_color source_color) {
|
||||
static void gsr_color_conversion_swizzle_reset(gsr_color_conversion *self, unsigned int texture_target, gsr_source_color source_color) {
|
||||
if(source_color == GSR_SOURCE_COLOR_BGR) {
|
||||
const int swizzle_mask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
self->params.egl->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
|
||||
self->params.egl->glTexParameteriv(texture_target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +719,7 @@ static void gsr_color_conversion_draw_graphics(gsr_color_conversion *self, unsig
|
||||
return;
|
||||
|
||||
const vec2i dest_texture_size = self->params.destination_textures_size[0];
|
||||
const int texture_target = external_texture ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
|
||||
const unsigned int texture_target = external_texture ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
|
||||
|
||||
if(rotation == GSR_ROT_90 || rotation == GSR_ROT_270) {
|
||||
const float tmp = texture_size.x;
|
||||
@@ -578,7 +728,7 @@ static void gsr_color_conversion_draw_graphics(gsr_color_conversion *self, unsig
|
||||
}
|
||||
|
||||
self->params.egl->glBindTexture(texture_target, texture_id);
|
||||
gsr_color_conversion_swizzle_texture_source(self, source_color);
|
||||
gsr_color_conversion_swizzle_texture_source(self, texture_target, source_color);
|
||||
|
||||
const vec2f pos_norm = {
|
||||
((float)destination_pos.x / (dest_texture_size.x == 0 ? 1.0f : (float)dest_texture_size.x)) * 2.0f,
|
||||
@@ -674,21 +824,49 @@ static void gsr_color_conversion_draw_graphics(gsr_color_conversion *self, unsig
|
||||
break;
|
||||
}
|
||||
case GSR_SOURCE_COLOR_YUYV: {
|
||||
self->params.egl->glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffers[0]);
|
||||
//cap_xcomp->params.egl->glClear(GL_COLOR_BUFFER_BIT); // TODO: Do this in a separate clear_ function. We want to do that when using multiple drm to create the final image (multiple monitors for example)
|
||||
switch(self->params.destination_color) {
|
||||
case GSR_DESTINATION_COLOR_NV12:
|
||||
case GSR_DESTINATION_COLOR_P010: {
|
||||
self->params.egl->glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffers[0]);
|
||||
//cap_xcomp->params.egl->glClear(GL_COLOR_BUFFER_BIT); // TODO: Do this in a separate clear_ function. We want to do that when using multiple drm to create the final image (multiple monitors for example)
|
||||
|
||||
const int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL : GRAPHICS_SHADER_INDEX_YUYV_TO_RGB;
|
||||
gsr_shader_use(&self->graphics_shaders[shader_index]);
|
||||
self->params.egl->glUniformMatrix2fv(self->graphics_uniforms[shader_index].rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix);
|
||||
self->params.egl->glUniform2f(self->graphics_uniforms[shader_index].offset, pos_norm.x, pos_norm.y);
|
||||
self->params.egl->glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_YUYV_TO_Y_EXTERNAL : GRAPHICS_SHADER_INDEX_YUYV_TO_Y;
|
||||
gsr_shader_use(&self->graphics_shaders[shader_index]);
|
||||
self->params.egl->glUniformMatrix2fv(self->graphics_uniforms[shader_index].rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix);
|
||||
self->params.egl->glUniform2f(self->graphics_uniforms[shader_index].offset, pos_norm.x, pos_norm.y);
|
||||
self->params.egl->glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
if(self->params.num_destination_textures > 1) {
|
||||
self->params.egl->glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffers[1]);
|
||||
//cap_xcomp->params.egl->glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
shader_index = external_texture ? GRAPHICS_SHADER_INDEX_YUYV_TO_UV_EXTERNAL : GRAPHICS_SHADER_INDEX_YUYV_TO_UV;
|
||||
gsr_shader_use(&self->graphics_shaders[shader_index]);
|
||||
self->params.egl->glUniformMatrix2fv(self->graphics_uniforms[shader_index].rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix);
|
||||
self->params.egl->glUniform2f(self->graphics_uniforms[shader_index].offset, pos_norm.x, pos_norm.y);
|
||||
self->params.egl->glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
self->params.egl->glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffers[0]);
|
||||
//cap_xcomp->params.egl->glClear(GL_COLOR_BUFFER_BIT); // TODO: Do this in a separate clear_ function. We want to do that when using multiple drm to create the final image (multiple monitors for example)
|
||||
|
||||
const int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL : GRAPHICS_SHADER_INDEX_YUYV_TO_RGB;
|
||||
gsr_shader_use(&self->graphics_shaders[shader_index]);
|
||||
self->params.egl->glUniformMatrix2fv(self->graphics_uniforms[shader_index].rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix);
|
||||
self->params.egl->glUniform2f(self->graphics_uniforms[shader_index].offset, pos_norm.x, pos_norm.y);
|
||||
self->params.egl->glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self->params.egl->glBindVertexArray(0);
|
||||
self->params.egl->glUseProgram(0);
|
||||
gsr_color_conversion_swizzle_reset(self, source_color);
|
||||
gsr_color_conversion_swizzle_reset(self, texture_target, source_color);
|
||||
self->params.egl->glBindTexture(texture_target, 0);
|
||||
self->params.egl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
@@ -710,7 +888,6 @@ void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_
|
||||
|
||||
const int texture_target = external_texture ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
|
||||
self->params.egl->glBindTexture(texture_target, texture_id);
|
||||
gsr_color_conversion_swizzle_texture_source(self, source_color);
|
||||
|
||||
source_position.x += source_pos.x;
|
||||
source_position.y += source_pos.y;
|
||||
@@ -721,7 +898,6 @@ void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_
|
||||
self->params.egl->glMemoryBarrier(GL_ALL_BARRIER_BITS); // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
|
||||
self->params.egl->glUseProgram(0);
|
||||
|
||||
gsr_color_conversion_swizzle_reset(self, source_color);
|
||||
self->params.egl->glBindTexture(texture_target, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -333,10 +333,6 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
|
||||
{ (void**)&self->glUnmapBuffer, "glUnmapBuffer" },
|
||||
{ (void**)&self->glGetIntegerv, "glGetIntegerv" },
|
||||
|
||||
{ (void**)&self->glFenceSync, "glFenceSync" },
|
||||
{ (void**)&self->glDeleteSync, "glDeleteSync" },
|
||||
{ (void**)&self->glClientWaitSync, "glClientWaitSync" },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user