mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
Fix v4l2 mjpeg on nvidia, yuyv on nvidia not done
This commit is contained in:
10
TODO
10
TODO
@@ -365,10 +365,14 @@ Update man page with info about v4l2 and new region capture format. Mention that
|
||||
|
||||
Make multiple -w portal work with -restore-portal-session.
|
||||
|
||||
Test if webcam capture works on intel and nvidia. Especially nvidia on x11 because it uses glx there for nvfbc while v4l2 needs egl.
|
||||
|
||||
Play with DRM_FORMAT_MOD_LINEAR or other linear formats to avoid cuda copy. If it's already in linear format then instead check the format of the target texture and use the same format.
|
||||
|
||||
Give early error when using invalid v4l2 path like with monitor. Use gsr_capture_v4l2_list_devices for query. Or maybe remove the early error for monitor to simplify the code.
|
||||
|
||||
Support camera capture with pipewire to support multiple applications recording camera at the same time. Might not be as efficient as V4L2.
|
||||
Support camera capture with pipewire to support multiple applications recording camera at the same time. Might not be as efficient as V4L2.
|
||||
|
||||
Taking a screenshot of camera with mjpeg doesn't work correctly because it updates buffer asynchronously. v4l2 capture should only return 0 if the copy of the data to the texture has finished.
|
||||
|
||||
Make capture from multiple sources work on nvidia x11 when capturing monitor + window. It doesn't work right now because monitor requires glx (nvfbc) while window requires egl.
|
||||
|
||||
Support v4l2 mplane on devices where it's supported (where it's more efficient). My camera doesn't support mplane.
|
||||
@@ -6,12 +6,13 @@
|
||||
#include "vec2.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS 6
|
||||
#define GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS 8
|
||||
#define GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS 2
|
||||
|
||||
typedef enum {
|
||||
GSR_SOURCE_COLOR_RGB,
|
||||
GSR_SOURCE_COLOR_BGR
|
||||
GSR_SOURCE_COLOR_BGR,
|
||||
GSR_SOURCE_COLOR_YUYV
|
||||
} gsr_source_color;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -133,14 +133,12 @@ typedef void(*__GLXextFuncPtr)(void);
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_READ_ONLY 0x88B8
|
||||
#define GL_WRITE_ONLY 0x88B9
|
||||
#define GL_READ_WRITE 0x88BA
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
|
||||
#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
@@ -259,7 +257,6 @@ struct gsr_egl {
|
||||
void (*glTexParameterfv)(unsigned int target, unsigned int pname, const float *params);
|
||||
void (*glTexImage2D)(unsigned int target, int level, int internalFormat, int width, int height, int border, unsigned int format, unsigned int type, const void *pixels);
|
||||
void (*glTexSubImage2D)(unsigned int target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, const void *pixels);
|
||||
void (*glTexStorage2D)(unsigned int target, int levels, unsigned int internalformat, int width, int height);
|
||||
void (*glGetTexImage)(unsigned int target, int level, unsigned int format, unsigned int type, void *pixels);
|
||||
void (*glGenFramebuffers)(int n, unsigned int *framebuffers);
|
||||
void (*glBindFramebuffer)(unsigned int target, unsigned int framebuffer);
|
||||
@@ -309,7 +306,7 @@ struct gsr_egl {
|
||||
void (*glScissor)(int x, int y, int width, int height);
|
||||
void (*glCreateBuffers)(int n, unsigned int *buffers);
|
||||
void (*glReadPixels)(int x, int y, int width, int height, unsigned int format, unsigned int type, void *pixels);
|
||||
void* (*glMapBuffer)(unsigned int target, unsigned int access);
|
||||
void* (*glMapBufferRange)(unsigned int target, intptr_t offset, ssize_t length, unsigned int access);
|
||||
unsigned char (*glUnmapBuffer)(unsigned int target);
|
||||
void (*glGetIntegerv)(unsigned int pname, int *params);
|
||||
};
|
||||
|
||||
@@ -250,7 +250,7 @@ static bool gsr_capture_v4l2_map_buffer(gsr_capture_v4l2 *self, const struct v4l
|
||||
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,
|
||||
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_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,
|
||||
@@ -490,7 +490,7 @@ static void gsr_capture_v4l2_decode_jpeg_to_texture(gsr_capture_v4l2 *self, cons
|
||||
self->params.egl->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, self->pbos[next_pbo_index]);
|
||||
self->params.egl->glBufferData(GL_PIXEL_UNPACK_BUFFER, self->capture_size.x * self->capture_size.y * 4, 0, GL_DYNAMIC_DRAW);
|
||||
|
||||
void *mapped_buffer = self->params.egl->glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
void *mapped_buffer = self->params.egl->glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, self->capture_size.x * self->capture_size.y * 4, GL_MAP_WRITE_BIT);
|
||||
if(mapped_buffer) {
|
||||
if(self->tjDecompress2(self->jpeg_decompressor, self->dmabuf_map[buf->index], buf->bytesused, mapped_buffer, jpeg_width, 0, jpeg_height, TJPF_RGBA, TJFLAG_FASTDCT) != 0)
|
||||
fprintf(stderr, "gsr error: gsr_capture_v4l2_capture: failed to decompress camera jpeg data, error: %s\n", self->tjGetErrorStr2(self->jpeg_decompressor));
|
||||
@@ -536,6 +536,8 @@ static int gsr_capture_v4l2_capture(gsr_capture *cap, gsr_capture_metadata *capt
|
||||
const vec2i output_size = scale_keep_aspect_ratio(self->capture_size, capture_metadata->recording_size);
|
||||
const vec2i target_pos = gsr_capture_get_target_position(output_size, capture_metadata);
|
||||
|
||||
self->params.egl->glFlush();
|
||||
|
||||
//if(self->got_first_frame) {
|
||||
gsr_color_conversion_draw(color_conversion, self->texture_id,
|
||||
target_pos, output_size,
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define GRAPHICS_SHADER_INDEX_Y 0
|
||||
#define GRAPHICS_SHADER_INDEX_UV 1
|
||||
#define GRAPHICS_SHADER_INDEX_Y_EXTERNAL 2
|
||||
#define GRAPHICS_SHADER_INDEX_UV_EXTERNAL 3
|
||||
#define GRAPHICS_SHADER_INDEX_RGB 4
|
||||
#define GRAPHICS_SHADER_INDEX_RGB_EXTERNAL 5
|
||||
#define GRAPHICS_SHADER_INDEX_Y 0
|
||||
#define GRAPHICS_SHADER_INDEX_UV 1
|
||||
#define GRAPHICS_SHADER_INDEX_Y_EXTERNAL 2
|
||||
#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
|
||||
|
||||
/* https://en.wikipedia.org/wiki/YCbCr, see study/color_space_transform_matrix.png */
|
||||
|
||||
@@ -248,6 +250,86 @@ static unsigned int load_graphics_shader_rgb(gsr_shader *shader, gsr_egl *egl, g
|
||||
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),
|
||||
"#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 =
|
||||
" vec2 resolution = vec2(textureSize(tex1, 0));\n"
|
||||
" vec2 uv = 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"
|
||||
" 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"
|
||||
" y = this_color.r;\n"
|
||||
" u = prev_color.g;\n"
|
||||
" v = this_color.g;\n"
|
||||
" }\n"
|
||||
" FragColor = vec4(\n"
|
||||
" y + 1.4065 * (v - 0.5),\n"
|
||||
" y - 0.3455 * (u - 0.5) - 0.7169 * (v - 0.5),\n"
|
||||
" y + 1.1790 * (u - 0.5),\n"
|
||||
" 1.0);\n";
|
||||
|
||||
char fragment_shader[4096];
|
||||
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 int load_framebuffers(gsr_color_conversion *self) {
|
||||
/* TODO: Only generate the necessary amount of framebuffers (self->params.num_destination_textures) */
|
||||
const unsigned int draw_buffer = GL_COLOR_ATTACHMENT0;
|
||||
@@ -314,7 +396,12 @@ static bool gsr_color_conversion_load_graphics_shaders(gsr_color_conversion *sel
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
if(load_graphics_shader_rgb(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_RGB], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_RGB], false) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y graphics shader\n");
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load RGB graphics shader\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_rgb(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_RGB], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_RGB], false) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to RGB graphics shader\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -328,19 +415,24 @@ static bool gsr_color_conversion_load_external_graphics_shaders(gsr_color_conver
|
||||
case GSR_DESTINATION_COLOR_NV12:
|
||||
case GSR_DESTINATION_COLOR_P010: {
|
||||
if(load_graphics_shader_y(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_Y_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_Y_EXTERNAL], self->params.destination_color, self->params.color_range, true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y graphics shader\n");
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_uv(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_UV_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_UV_EXTERNAL], self->params.destination_color, self->params.color_range, true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV graphics shader\n");
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
if(load_graphics_shader_rgb(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_RGB_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_RGB_EXTERNAL], true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y graphics shader\n");
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load RGB graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(load_graphics_shader_yuyv_to_rgb(&self->graphics_shaders[GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL], self->params.egl, &self->graphics_uniforms[GRAPHICS_SHADER_INDEX_YUYV_TO_RGB_EXTERNAL], true) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load YUYV to RGB graphics shader (external)\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -539,35 +631,53 @@ static void gsr_color_conversion_draw_graphics(gsr_color_conversion *self, unsig
|
||||
self->params.egl->glBindBuffer(GL_ARRAY_BUFFER, self->vertex_buffer_object_id);
|
||||
self->params.egl->glBufferSubData(GL_ARRAY_BUFFER, 0, 24 * sizeof(float), vertices);
|
||||
|
||||
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)
|
||||
// TODO:
|
||||
switch(source_color) {
|
||||
case GSR_SOURCE_COLOR_RGB:
|
||||
case GSR_SOURCE_COLOR_BGR: {
|
||||
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)
|
||||
|
||||
int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_Y_EXTERNAL : GRAPHICS_SHADER_INDEX_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);
|
||||
int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_Y_EXTERNAL : GRAPHICS_SHADER_INDEX_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);
|
||||
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_UV_EXTERNAL : GRAPHICS_SHADER_INDEX_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);
|
||||
shader_index = external_texture ? GRAPHICS_SHADER_INDEX_UV_EXTERNAL : GRAPHICS_SHADER_INDEX_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_RGB_EXTERNAL : GRAPHICS_SHADER_INDEX_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;
|
||||
}
|
||||
case GSR_DESTINATION_COLOR_RGB8: {
|
||||
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)
|
||||
|
||||
const int shader_index = external_texture ? GRAPHICS_SHADER_INDEX_RGB_EXTERNAL : GRAPHICS_SHADER_INDEX_RGB;
|
||||
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);
|
||||
|
||||
@@ -282,7 +282,6 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
|
||||
{ (void**)&self->glTexParameterfv, "glTexParameterfv" },
|
||||
{ (void**)&self->glTexImage2D, "glTexImage2D" },
|
||||
{ (void**)&self->glTexSubImage2D, "glTexSubImage2D" },
|
||||
{ (void**)&self->glTexStorage2D, "glTexStorage2D" },
|
||||
{ (void**)&self->glGetTexImage, "glGetTexImage" },
|
||||
{ (void**)&self->glGenFramebuffers, "glGenFramebuffers" },
|
||||
{ (void**)&self->glBindFramebuffer, "glBindFramebuffer" },
|
||||
@@ -330,7 +329,7 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
|
||||
{ (void**)&self->glDebugMessageCallback, "glDebugMessageCallback" },
|
||||
{ (void**)&self->glScissor, "glScissor" },
|
||||
{ (void**)&self->glReadPixels, "glReadPixels" },
|
||||
{ (void**)&self->glMapBuffer, "glMapBuffer" },
|
||||
{ (void**)&self->glMapBufferRange, "glMapBufferRange" },
|
||||
{ (void**)&self->glUnmapBuffer, "glUnmapBuffer" },
|
||||
{ (void**)&self->glGetIntegerv, "glGetIntegerv" },
|
||||
|
||||
|
||||
@@ -2301,7 +2301,7 @@ static gsr_capture* create_capture_impl(const args_parser &arg_parser, gsr_egl *
|
||||
gsr_capture_v4l2_params v4l2_params;
|
||||
memset(&v4l2_params, 0, sizeof(v4l2_params));
|
||||
v4l2_params.egl = egl;
|
||||
v4l2_params.output_resolution = {0, 0};
|
||||
v4l2_params.output_resolution = arg_parser.output_resolution;
|
||||
v4l2_params.device_path = capture_source.name.c_str();
|
||||
v4l2_params.pixfmt = capture_source.v4l2_pixfmt;
|
||||
v4l2_params.fps = arg_parser.fps;
|
||||
@@ -2505,9 +2505,9 @@ static void capture_image_to_file(args_parser &arg_parser, gsr_egl *egl, gsr_win
|
||||
fprintf(stderr, "gsr error: failed to get kms, error: %d (%s)\n", kms_response.result, kms_response.err_msg);
|
||||
}
|
||||
|
||||
bool all_sources_captured = true;
|
||||
should_stop_error = false;
|
||||
for(VideoSource &video_source : video_sources) {
|
||||
should_stop_error = false;
|
||||
gsr_capture_tick(video_source.capture);
|
||||
if(gsr_capture_should_stop(video_source.capture, &should_stop_error)) {
|
||||
running = 0;
|
||||
break;
|
||||
@@ -2524,6 +2524,7 @@ static void capture_image_to_file(args_parser &arg_parser, gsr_egl *egl, gsr_win
|
||||
gsr_color_conversion_clear(&color_conversion);
|
||||
}
|
||||
|
||||
bool all_sources_captured = true;
|
||||
for(VideoSource &video_source : video_sources) {
|
||||
// It can fail, for example when capturing portal and the target is a monitor that hasn't been updated.
|
||||
// This can also happen for example if the system suspends and the monitor to capture's framebuffer is gone, or if the target window disappeared.
|
||||
|
||||
@@ -631,9 +631,7 @@ unsigned int gl_create_texture(gsr_egl *egl, int width, int height, int internal
|
||||
unsigned int texture_id = 0;
|
||||
egl->glGenTextures(1, &texture_id);
|
||||
egl->glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
// TODO:
|
||||
egl->glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
|
||||
//egl->glTexStorage2D(GL_TEXTURE_2D, 1, internal_format, width, height);
|
||||
|
||||
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
|
||||
Reference in New Issue
Block a user