diff --git a/include/color_conversion.h b/include/color_conversion.h index cb074a1..e6eece6 100644 --- a/include/color_conversion.h +++ b/include/color_conversion.h @@ -46,6 +46,7 @@ typedef struct { gsr_destination_color destination_color; unsigned int destination_textures[2]; + vec2i destination_textures_size[2]; int num_destination_textures; gsr_color_range color_range; diff --git a/include/egl.h b/include/egl.h index c95d491..fb67768 100644 --- a/include/egl.h +++ b/include/egl.h @@ -118,8 +118,6 @@ typedef void(*__GLXextFuncPtr)(void); #define GL_TEXTURE_WRAP_T 0x2803 #define GL_TEXTURE_MAG_FILTER 0x2800 #define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WIDTH 0x1000 -#define GL_TEXTURE_HEIGHT 0x1001 #define GL_NEAREST 0x2600 #define GL_CLAMP_TO_EDGE 0x812F #define GL_LINEAR 0x2601 diff --git a/include/encoder/video/video.h b/include/encoder/video/video.h index 7a706b5..a77a1aa 100644 --- a/include/encoder/video/video.h +++ b/include/encoder/video/video.h @@ -15,7 +15,7 @@ struct gsr_video_encoder { void (*destroy)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); void (*copy_textures_to_frame)(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion); /* Can be NULL */ /* |textures| should be able to fit 2 elements */ - void (*get_textures)(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color); + void (*get_textures)(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color); void *priv; bool started; @@ -25,6 +25,6 @@ struct gsr_video_encoder { bool gsr_video_encoder_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame); void gsr_video_encoder_destroy(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); void gsr_video_encoder_copy_textures_to_frame(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion); -void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color); +void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color); #endif /* GSR_ENCODER_VIDEO_H */ diff --git a/include/window_texture.h b/include/window_texture.h index 6ee5df4..bdada33 100644 --- a/include/window_texture.h +++ b/include/window_texture.h @@ -11,6 +11,8 @@ typedef struct { unsigned int texture_id; int redirected; gsr_egl *egl; + unsigned int window_width; + unsigned int window_height; } WindowTexture; /* Returns 0 on success */ diff --git a/src/capture/xcomposite.c b/src/capture/xcomposite.c index db41f63..dfb987e 100644 --- a/src/capture/xcomposite.c +++ b/src/capture/xcomposite.c @@ -100,13 +100,8 @@ static int gsr_capture_xcomposite_start(gsr_capture *cap, gsr_capture_metadata * return -1; } - self->texture_size.x = 0; - self->texture_size.y = 0; - - self->params.egl->glBindTexture(GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&self->window_texture)); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &self->texture_size.x); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &self->texture_size.y); - self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); + self->texture_size.x = self->window_texture.window_width; + self->texture_size.y = self->window_texture.window_height; if(self->params.output_resolution.x == 0 && self->params.output_resolution.y == 0) { capture_metadata->width = self->texture_size.x; @@ -148,13 +143,8 @@ static void gsr_capture_xcomposite_tick(gsr_capture *cap) { window_texture_deinit(&self->window_texture); window_texture_init(&self->window_texture, self->display, self->window, self->params.egl); // TODO: Do not do the below window_texture_on_resize after this - self->texture_size.x = 0; - self->texture_size.y = 0; - - self->params.egl->glBindTexture(GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&self->window_texture)); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &self->texture_size.x); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &self->texture_size.y); - self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); + self->texture_size.x = self->window_texture.window_width; + self->texture_size.y = self->window_texture.window_height; self->window_resized = false; self->clear_background = true; @@ -172,13 +162,8 @@ static void gsr_capture_xcomposite_tick(gsr_capture *cap) { return; } - self->texture_size.x = 0; - self->texture_size.y = 0; - - self->params.egl->glBindTexture(GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&self->window_texture)); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &self->texture_size.x); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &self->texture_size.y); - self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); + self->texture_size.x = self->window_texture.window_width; + self->texture_size.y = self->window_texture.window_height; self->clear_background = true; } diff --git a/src/color_conversion.c b/src/color_conversion.c index 2e97c9a..dfc9c80 100644 --- a/src/color_conversion.c +++ b/src/color_conversion.c @@ -824,13 +824,7 @@ static void gsr_color_conversion_dispatch_compute_shader(gsr_color_conversion *s } static void gsr_color_conversion_draw_graphics(gsr_color_conversion *self, unsigned int texture_id, bool external_texture, float rotation_matrix[2][2], vec2i source_position, vec2i source_size, vec2i destination_pos, vec2i texture_size, vec2f scale, gsr_source_color source_color) { - /* TODO: Do not call this every frame? */ - vec2i dest_texture_size = {0, 0}; - self->params.egl->glBindTexture(GL_TEXTURE_2D, self->params.destination_textures[0]); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &dest_texture_size.x); - self->params.egl->glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &dest_texture_size.y); - self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); - + const vec2i dest_texture_size = self->params.destination_textures_size[0]; const int texture_target = external_texture ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; self->params.egl->glBindTexture(texture_target, texture_id); diff --git a/src/encoder/video/nvenc.c b/src/encoder/video/nvenc.c index 5f578c2..0318a17 100644 --- a/src/encoder/video/nvenc.c +++ b/src/encoder/video/nvenc.c @@ -12,6 +12,7 @@ typedef struct { gsr_video_encoder_nvenc_params params; unsigned int target_textures[2]; + vec2i target_texture_size[2]; AVBufferRef *device_ctx; @@ -95,7 +96,8 @@ static bool gsr_video_encoder_nvenc_setup_textures(gsr_video_encoder_nvenc *self const int div[2] = {1, 2}; // divide UV texture size by 2 because chroma is half size for(int i = 0; i < 2; ++i) { - self->target_textures[i] = gl_create_texture(self->params.egl, video_codec_context->width / div[i], video_codec_context->height / div[i], self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); + self->target_texture_size[i] = (vec2i){ video_codec_context->width / div[i], video_codec_context->height / div[i] }; + self->target_textures[i] = gl_create_texture(self->params.egl, self->target_texture_size[i].x, self->target_texture_size[i].y, self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); if(self->target_textures[i] == 0) { fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_setup_textures: failed to create opengl texture\n"); return false; @@ -198,10 +200,12 @@ static void gsr_video_encoder_nvenc_copy_textures_to_frame(gsr_video_encoder *en self->cuda.cuStreamSynchronize(self->cuda_stream); } -static void gsr_video_encoder_nvenc_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color) { +static void gsr_video_encoder_nvenc_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color) { gsr_video_encoder_nvenc *self = encoder->priv; textures[0] = self->target_textures[0]; textures[1] = self->target_textures[1]; + texture_sizes[0] = self->target_texture_size[0]; + texture_sizes[1] = self->target_texture_size[1]; *num_textures = 2; *destination_color = self->params.color_depth == GSR_COLOR_DEPTH_10_BITS ? GSR_DESTINATION_COLOR_P010 : GSR_DESTINATION_COLOR_NV12; } diff --git a/src/encoder/video/software.c b/src/encoder/video/software.c index d8d9828..b473bb9 100644 --- a/src/encoder/video/software.c +++ b/src/encoder/video/software.c @@ -13,6 +13,7 @@ typedef struct { gsr_video_encoder_software_params params; unsigned int target_textures[2]; + vec2i texture_sizes[2]; } gsr_video_encoder_software; static bool gsr_video_encoder_software_setup_textures(gsr_video_encoder_software *self, AVCodecContext *video_codec_context, AVFrame *frame) { @@ -34,7 +35,8 @@ static bool gsr_video_encoder_software_setup_textures(gsr_video_encoder_software const int div[2] = {1, 2}; // divide UV texture size by 2 because chroma is half size for(int i = 0; i < 2; ++i) { - self->target_textures[i] = gl_create_texture(self->params.egl, video_codec_context->width / div[i], video_codec_context->height / div[i], self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); + self->texture_sizes[i] = (vec2i){ video_codec_context->width / div[i], video_codec_context->height / div[i] }; + self->target_textures[i] = gl_create_texture(self->params.egl, self->texture_sizes[i].x, self->texture_sizes[i].y, self->params.color_depth == GSR_COLOR_DEPTH_8_BITS ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i], GL_NEAREST); if(self->target_textures[i] == 0) { fprintf(stderr, "gsr error: gsr_capture_kms_setup_cuda_textures: failed to create opengl texture\n"); return false; @@ -86,10 +88,12 @@ static void gsr_video_encoder_software_copy_textures_to_frame(gsr_video_encoder //self->params.egl->glFinish(); } -static void gsr_video_encoder_software_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color) { +static void gsr_video_encoder_software_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color) { gsr_video_encoder_software *self = encoder->priv; textures[0] = self->target_textures[0]; textures[1] = self->target_textures[1]; + texture_sizes[0] = self->texture_sizes[0]; + texture_sizes[1] = self->texture_sizes[1]; *num_textures = 2; *destination_color = self->params.color_depth == GSR_COLOR_DEPTH_10_BITS ? GSR_DESTINATION_COLOR_P010 : GSR_DESTINATION_COLOR_NV12; } diff --git a/src/encoder/video/vaapi.c b/src/encoder/video/vaapi.c index 0daf4d8..9cf4def 100644 --- a/src/encoder/video/vaapi.c +++ b/src/encoder/video/vaapi.c @@ -16,6 +16,7 @@ typedef struct { gsr_video_encoder_vaapi_params params; unsigned int target_textures[2]; + vec2i texture_sizes[2]; AVBufferRef *device_ctx; VADisplay va_dpy; @@ -112,6 +113,7 @@ static bool gsr_video_encoder_vaapi_setup_textures(gsr_video_encoder_vaapi *self intptr_t img_attr[44]; setup_dma_buf_attrs(img_attr, formats[i], self->prime.width / div[i], self->prime.height / div[i], fds, offsets, pitches, modifiers, self->prime.layers[layer].num_planes, true); + self->texture_sizes[i] = (vec2i){ self->prime.width / div[i], self->prime.height / div[i] }; while(self->params.egl->eglGetError() != EGL_SUCCESS){} EGLImage image = self->params.egl->eglCreateImage(self->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr); @@ -214,10 +216,12 @@ void gsr_video_encoder_vaapi_stop(gsr_video_encoder_vaapi *self, AVCodecContext } } -static void gsr_video_encoder_vaapi_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color) { +static void gsr_video_encoder_vaapi_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color) { gsr_video_encoder_vaapi *self = encoder->priv; textures[0] = self->target_textures[0]; textures[1] = self->target_textures[1]; + texture_sizes[0] = self->texture_sizes[0]; + texture_sizes[1] = self->texture_sizes[1]; *num_textures = 2; *destination_color = self->params.color_depth == GSR_COLOR_DEPTH_10_BITS ? GSR_DESTINATION_COLOR_P010 : GSR_DESTINATION_COLOR_NV12; } diff --git a/src/encoder/video/video.c b/src/encoder/video/video.c index ce3b61b..80f2cf0 100644 --- a/src/encoder/video/video.c +++ b/src/encoder/video/video.c @@ -22,7 +22,7 @@ void gsr_video_encoder_copy_textures_to_frame(gsr_video_encoder *encoder, AVFram encoder->copy_textures_to_frame(encoder, frame, color_conversion); } -void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color) { +void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color) { assert(encoder->started); - encoder->get_textures(encoder, textures, num_textures, destination_color); + encoder->get_textures(encoder, textures, texture_sizes, num_textures, destination_color); } diff --git a/src/encoder/video/vulkan.c b/src/encoder/video/vulkan.c index 802934d..16b21a1 100644 --- a/src/encoder/video/vulkan.c +++ b/src/encoder/video/vulkan.c @@ -16,6 +16,7 @@ typedef struct { gsr_video_encoder_vulkan_params params; unsigned int target_textures[2]; + vec2i texture_sizes[2]; AVBufferRef *device_ctx; } gsr_video_encoder_vulkan; @@ -224,6 +225,9 @@ static bool gsr_video_encoder_vulkan_setup_textures(gsr_video_encoder_vulkan *se fprintf(stderr, "3 gl error: %d\n", self->params.egl->glGetError()); self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); + + self->texture_sizes[0] = (vec2i){ frame->width, frame->height }; + self->texture_sizes[1] = (vec2i){ frame->width/2, frame->height/2 }; } #endif return true; @@ -270,10 +274,12 @@ void gsr_video_encoder_vulkan_stop(gsr_video_encoder_vulkan *self, AVCodecContex av_buffer_unref(&self->device_ctx); } -static void gsr_video_encoder_vulkan_get_textures(gsr_video_encoder *encoder, unsigned int *textures, int *num_textures, gsr_destination_color *destination_color) { +static void gsr_video_encoder_vulkan_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color) { gsr_video_encoder_vulkan *self = encoder->priv; textures[0] = self->target_textures[0]; textures[1] = self->target_textures[1]; + texture_sizes[0] = self->texture_sizes[0]; + texture_sizes[1] = self->texture_sizes[1]; *num_textures = 2; *destination_color = self->params.color_depth == GSR_COLOR_DEPTH_10_BITS ? GSR_DESTINATION_COLOR_P010 : GSR_DESTINATION_COLOR_NV12; } diff --git a/src/main.cpp b/src/main.cpp index 84559f6..f93a363 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2315,6 +2315,7 @@ static void capture_image_to_file(args_parser &arg_parser, gsr_egl *egl, gsr_ima color_conversion_params.load_external_image_shader = gsr_capture_uses_external_image(capture); color_conversion_params.destination_textures[0] = image_writer.texture; + color_conversion_params.destination_textures_size[0] = { capture_metadata.width, capture_metadata.height }; color_conversion_params.num_destination_textures = 1; color_conversion_params.destination_color = GSR_DESTINATION_COLOR_RGB8; @@ -3354,7 +3355,7 @@ int main(int argc, char **argv) { color_conversion_params.color_range = arg_parser.color_range; color_conversion_params.egl = &egl; color_conversion_params.load_external_image_shader = gsr_capture_uses_external_image(capture); - gsr_video_encoder_get_textures(video_encoder, color_conversion_params.destination_textures, &color_conversion_params.num_destination_textures, &color_conversion_params.destination_color); + gsr_video_encoder_get_textures(video_encoder, color_conversion_params.destination_textures, color_conversion_params.destination_textures_size, &color_conversion_params.num_destination_textures, &color_conversion_params.destination_color); gsr_color_conversion color_conversion; if(gsr_color_conversion_init(&color_conversion, &color_conversion_params) != 0) { diff --git a/src/plugins.c b/src/plugins.c index a064714..061534c 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -33,6 +33,7 @@ bool gsr_plugins_init(gsr_plugins *self, gsr_plugin_init_params init_params, gsr .egl = egl, .destination_color = GSR_DESTINATION_COLOR_RGB8, /* TODO: Support 10-bits, use init_params.color_depth */ .destination_textures[0] = self->texture, + .destination_textures_size[0] = (vec2i){ init_params.width, init_params.height }, .num_destination_textures = 1, .color_range = GSR_COLOR_RANGE_FULL, .load_external_image_shader = false, diff --git a/src/window_texture.c b/src/window_texture.c index ba7212a..6b093c5 100644 --- a/src/window_texture.c +++ b/src/window_texture.c @@ -20,6 +20,8 @@ int window_texture_init(WindowTexture *window_texture, Display *display, Window window_texture->texture_id = 0; window_texture->redirected = 0; window_texture->egl = egl; + window_texture->window_width = 0; + window_texture->window_height = 0; if(!x11_supports_composite_named_window_pixmap(display)) return 1; @@ -67,6 +69,11 @@ int window_texture_on_resize(WindowTexture *self) { EGL_NONE, }; + Window root_window; + int window_x, window_y; + unsigned int window_border, window_depth; + XGetGeometry(self->display, self->window, &root_window, &window_x, &window_y, &self->window_width, &self->window_height, &window_border, &window_depth); + pixmap = XCompositeNameWindowPixmap(self->display, self->window); if(!pixmap) { result = 2;