diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 502 |
1 files changed, 107 insertions, 395 deletions
diff --git a/src/utils.c b/src/utils.c index 82c51b5..c1d399a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -14,13 +14,13 @@ #include <xf86drmMode.h> #include <xf86drm.h> -#include <libdrm/drm_fourcc.h> #include <X11/Xatom.h> #include <X11/extensions/Xrandr.h> -#include <va/va_drmcommon.h> #include <libavcodec/avcodec.h> #include <libavutil/hwcontext_vaapi.h> +#define DRM_NUM_BUF_ATTRS 4 + double clock_get_monotonic_seconds(void) { struct timespec ts; ts.tv_sec = 0; @@ -110,7 +110,7 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni // but gpu screen recorder captures the drm framebuffer instead of x11 api. This drm framebuffer which doesn't increase in size when using xrandr scaling. // Maybe a better option would be to get the drm crtc size instead. const XRRModeInfo *mode_info = get_mode_info(screen_res, crt_info->mode); - if(mode_info && out_info->nameLen < (int)sizeof(display_name)) { + if(mode_info) { snprintf(display_name, sizeof(display_name), "%.*s", (int)out_info->nameLen, out_info->name); const gsr_monitor_rotation rotation = x11_rotation_to_gsr_rotation(crt_info->rotation); const vec2i monitor_size = get_monitor_size_rotated(mode_info->width, mode_info->height, rotation); @@ -152,21 +152,22 @@ int get_connector_type_by_name(const char *name) { return -1; } -drm_connector_type_count* drm_connector_types_get_index(drm_connector_type_count *type_counts, int *num_type_counts, int connector_type) { - for(int i = 0; i < *num_type_counts; ++i) { - if(type_counts[i].type == connector_type) - return &type_counts[i]; +int get_connector_type_id_by_name(const char *name) { + int len = strlen(name); + int num_start = 0; + for(int i = len - 1; i >= 0; --i) { + const bool is_num = name[i] >= '0' && name[i] <= '9'; + if(!is_num) { + num_start = i + 1; + break; + } } - if(*num_type_counts == CONNECTOR_TYPE_COUNTS) - return NULL; + const int num_len = len - num_start; + if(num_len <= 0) + return -1; - const int index = *num_type_counts; - type_counts[index].type = connector_type; - type_counts[index].count = 0; - type_counts[index].count_active = 0; - ++*num_type_counts; - return &type_counts[index]; + return atoi(name + num_start); } uint32_t monitor_identifier_from_type_and_count(int monitor_type_index, int monitor_type_count) { @@ -197,9 +198,6 @@ static void for_each_active_monitor_output_drm(const char *card_path, active_mon drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); - drm_connector_type_count type_counts[CONNECTOR_TYPE_COUNTS]; - int num_type_counts = 0; - char display_name[256]; drmModeResPtr resources = drmModeGetResources(fd); if(resources) { @@ -208,35 +206,29 @@ static void for_each_active_monitor_output_drm(const char *card_path, active_mon if(!connector) continue; - drm_connector_type_count *connector_type = drm_connector_types_get_index(type_counts, &num_type_counts, connector->connector_type); - const char *connection_name = drmModeGetConnectorTypeName(connector->connector_type); - const int connection_name_len = strlen(connection_name); - if(connector_type) - ++connector_type->count; - if(connector->connection != DRM_MODE_CONNECTED) { drmModeFreeConnector(connector); continue; } - if(connector_type) - ++connector_type->count_active; - uint64_t crtc_id = 0; connector_get_property_by_name(fd, connector, "CRTC_ID", &crtc_id); drmModeCrtcPtr crtc = drmModeGetCrtc(fd, crtc_id); - if(connector_type && crtc_id > 0 && crtc && connection_name_len + 5 < (int)sizeof(display_name)) { - const int display_name_len = snprintf(display_name, sizeof(display_name), "%s-%d", connection_name, connector_type->count); + const char *connection_name = drmModeGetConnectorTypeName(connector->connector_type); + + if(connection_name && crtc_id > 0 && crtc) { const int connector_type_index_name = get_connector_type_by_name(display_name); - gsr_monitor monitor = { + const int display_name_len = snprintf(display_name, sizeof(display_name), "%s-%u", connection_name, connector->connector_type_id); + + const gsr_monitor monitor = { .name = display_name, .name_len = display_name_len, .pos = { .x = crtc->x, .y = crtc->y }, .size = { .x = (int)crtc->width, .y = (int)crtc->height }, .connector_id = connector->connector_id, .rotation = GSR_MONITOR_ROT_0, - .monitor_identifier = connector_type_index_name != -1 ? monitor_identifier_from_type_and_count(connector_type_index_name, connector_type->count_active) : 0 + .monitor_identifier = connector_type_index_name != -1 ? monitor_identifier_from_type_and_count(connector_type_index_name, connector->connector_type_id) : 0 }; callback(&monitor, userdata); } @@ -289,6 +281,7 @@ bool get_monitor_by_name(const gsr_egl *egl, gsr_connection_type connection_type typedef struct { const gsr_monitor *monitor; gsr_monitor_rotation rotation; + vec2i position; bool match_found; } get_monitor_by_connector_id_userdata; @@ -300,6 +293,7 @@ static void get_monitor_by_name_and_size_callback(const gsr_monitor *monitor, vo get_monitor_by_connector_id_userdata *data = (get_monitor_by_connector_id_userdata*)userdata; if(monitor->name && data->monitor->name && strcmp(monitor->name, data->monitor->name) == 0 && vec2i_eql(monitor->size, data->monitor->size)) { data->rotation = monitor->rotation; + data->position = monitor->pos; data->match_found = true; } } @@ -310,39 +304,51 @@ static void get_monitor_by_connector_id_callback(const gsr_monitor *monitor, voi (!monitor->connector_id && monitor->monitor_identifier == data->monitor->monitor_identifier)) { data->rotation = monitor->rotation; + data->position = monitor->pos; data->match_found = true; } } -gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_window *window, const gsr_monitor *monitor) { +bool drm_monitor_get_display_server_data(const gsr_window *window, const gsr_monitor *monitor, gsr_monitor_rotation *monitor_rotation, vec2i *monitor_position) { + *monitor_rotation = GSR_MONITOR_ROT_0; + *monitor_position = (vec2i){0, 0}; + if(gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_WAYLAND) { { get_monitor_by_connector_id_userdata userdata; userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; + userdata.position = (vec2i){0, 0}; userdata.match_found = false; gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_name_and_size_callback, &userdata); - if(userdata.match_found) - return userdata.rotation; + if(userdata.match_found) { + *monitor_rotation = userdata.rotation; + *monitor_position = userdata.position; + return true; + } } { get_monitor_by_connector_id_userdata userdata; userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; + userdata.position = (vec2i){0, 0}; userdata.match_found = false; gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_connector_id_callback, &userdata); - return userdata.rotation; + *monitor_rotation = userdata.rotation; + *monitor_position = userdata.position; + return userdata.match_found; } } else { get_monitor_by_connector_id_userdata userdata; userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; + userdata.position = (vec2i){0, 0}; userdata.match_found = false; gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_connector_id_callback, &userdata); - return userdata.rotation; + *monitor_rotation = userdata.rotation; + *monitor_position = userdata.position; + return userdata.match_found; } - - return GSR_MONITOR_ROT_0; } bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { @@ -350,13 +356,9 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { bool supported = true; const unsigned char *gl_vendor = egl->glGetString(GL_VENDOR); const unsigned char *gl_renderer = egl->glGetString(GL_RENDERER); - const unsigned char *gl_version = egl->glGetString(GL_VERSION); info->gpu_version = 0; info->is_steam_deck = false; - info->driver_major = 0; - info->driver_minor = 0; - info->driver_patch = 0; if(!gl_vendor) { fprintf(stderr, "gsr error: failed to get gpu vendor\n"); @@ -382,6 +384,8 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { info->vendor = GSR_GPU_VENDOR_INTEL; else if(strstr((const char*)gl_vendor, "NVIDIA")) info->vendor = GSR_GPU_VENDOR_NVIDIA; + else if(strstr((const char*)gl_vendor, "Broadcom")) + info->vendor = GSR_GPU_VENDOR_BROADCOM; else { fprintf(stderr, "gsr error: unknown gpu vendor: %s\n", gl_vendor); supported = false; @@ -394,33 +398,10 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { info->is_steam_deck = strstr((const char*)gl_renderer, "vangogh") != NULL; } - if(gl_version) { - const char *mesa_p = strstr((const char*)gl_version, "Mesa "); - if(mesa_p) { - mesa_p += 5; - int major = 0; - int minor = 0; - int patch = 0; - if(sscanf(mesa_p, "%d.%d.%d", &major, &minor, &patch) == 3) { - info->driver_major = major; - info->driver_minor = minor; - info->driver_patch = patch; - } - } - } - end: return supported; } -bool version_greater_than(int major, int minor, int patch, int other_major, int other_minor, int other_patch) { - return (major > other_major) || (major == other_major && minor > other_minor) || (major == other_major && minor == other_minor && patch > other_patch); -} - -bool gl_driver_version_greater_than(const gsr_gpu_info *gpu_info, int major, int minor, int patch) { - return version_greater_than(gpu_info->driver_major, gpu_info->driver_minor, gpu_info->driver_patch, major, minor, patch); -} - bool try_card_has_valid_plane(const char *card_path) { drmVersion *ver = NULL; drmModePlaneResPtr planes = NULL; @@ -529,6 +510,41 @@ int create_directory_recursive(char *path) { } void setup_dma_buf_attrs(intptr_t *img_attr, uint32_t format, uint32_t width, uint32_t height, const int *fds, const uint32_t *offsets, const uint32_t *pitches, const uint64_t *modifiers, int num_planes, bool use_modifier) { + const uint32_t plane_fd_attrs[DRM_NUM_BUF_ATTRS] = { + EGL_DMA_BUF_PLANE0_FD_EXT, + EGL_DMA_BUF_PLANE1_FD_EXT, + EGL_DMA_BUF_PLANE2_FD_EXT, + EGL_DMA_BUF_PLANE3_FD_EXT + }; + + const uint32_t plane_offset_attrs[DRM_NUM_BUF_ATTRS] = { + EGL_DMA_BUF_PLANE0_OFFSET_EXT, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, + EGL_DMA_BUF_PLANE2_OFFSET_EXT, + EGL_DMA_BUF_PLANE3_OFFSET_EXT + }; + + const uint32_t plane_pitch_attrs[DRM_NUM_BUF_ATTRS] = { + EGL_DMA_BUF_PLANE0_PITCH_EXT, + EGL_DMA_BUF_PLANE1_PITCH_EXT, + EGL_DMA_BUF_PLANE2_PITCH_EXT, + EGL_DMA_BUF_PLANE3_PITCH_EXT + }; + + const uint32_t plane_modifier_lo_attrs[DRM_NUM_BUF_ATTRS] = { + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT + }; + + const uint32_t plane_modifier_hi_attrs[DRM_NUM_BUF_ATTRS] = { + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT + }; + size_t img_attr_index = 0; img_attr[img_attr_index++] = EGL_LINUX_DRM_FOURCC_EXT; @@ -540,79 +556,23 @@ void setup_dma_buf_attrs(intptr_t *img_attr, uint32_t format, uint32_t width, ui img_attr[img_attr_index++] = EGL_HEIGHT; img_attr[img_attr_index++] = height; - if(num_planes >= 1) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE0_FD_EXT; - img_attr[img_attr_index++] = fds[0]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - img_attr[img_attr_index++] = offsets[0]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - img_attr[img_attr_index++] = pitches[0]; - - if(use_modifier) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - img_attr[img_attr_index++] = modifiers[0] & 0xFFFFFFFFULL; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - img_attr[img_attr_index++] = modifiers[0] >> 32ULL; - } - } - - if(num_planes >= 2) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE1_FD_EXT; - img_attr[img_attr_index++] = fds[1]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; - img_attr[img_attr_index++] = offsets[1]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; - img_attr[img_attr_index++] = pitches[1]; - - if(use_modifier) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; - img_attr[img_attr_index++] = modifiers[1] & 0xFFFFFFFFULL; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; - img_attr[img_attr_index++] = modifiers[1] >> 32ULL; - } - } - - if(num_planes >= 3) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE2_FD_EXT; - img_attr[img_attr_index++] = fds[2]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT; - img_attr[img_attr_index++] = offsets[2]; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; - img_attr[img_attr_index++] = pitches[2]; - - if(use_modifier) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; - img_attr[img_attr_index++] = modifiers[2] & 0xFFFFFFFFULL; - - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; - img_attr[img_attr_index++] = modifiers[2] >> 32ULL; - } - } - - if(num_planes >= 4) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE3_FD_EXT; - img_attr[img_attr_index++] = fds[3]; + assert(num_planes <= DRM_NUM_BUF_ATTRS); + for(int i = 0; i < num_planes; ++i) { + img_attr[img_attr_index++] = plane_fd_attrs[i]; + img_attr[img_attr_index++] = fds[i]; - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT; - img_attr[img_attr_index++] = offsets[3]; + img_attr[img_attr_index++] = plane_offset_attrs[i]; + img_attr[img_attr_index++] = offsets[i]; - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE3_PITCH_EXT; - img_attr[img_attr_index++] = pitches[3]; + img_attr[img_attr_index++] = plane_pitch_attrs[i]; + img_attr[img_attr_index++] = pitches[i]; if(use_modifier) { - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT; - img_attr[img_attr_index++] = modifiers[3] & 0xFFFFFFFFULL; + img_attr[img_attr_index++] = plane_modifier_lo_attrs[i]; + img_attr[img_attr_index++] = modifiers[i] & 0xFFFFFFFFULL; - img_attr[img_attr_index++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT; - img_attr[img_attr_index++] = modifiers[3] >> 32ULL; + img_attr[img_attr_index++] = plane_modifier_hi_attrs[i]; + img_attr[img_attr_index++] = modifiers[i] >> 32ULL; } } @@ -620,268 +580,6 @@ void setup_dma_buf_attrs(intptr_t *img_attr, uint32_t format, uint32_t width, ui assert(img_attr_index <= 44); } -static VADisplay video_codec_context_get_vaapi_display(AVCodecContext *video_codec_context) { - AVBufferRef *hw_frames_ctx = video_codec_context->hw_frames_ctx; - if(!hw_frames_ctx) - return NULL; - - AVHWFramesContext *hw_frame_context = (AVHWFramesContext*)hw_frames_ctx->data; - AVHWDeviceContext *device_context = (AVHWDeviceContext*)hw_frame_context->device_ctx; - if(device_context->type != AV_HWDEVICE_TYPE_VAAPI) - return NULL; - - AVVAAPIDeviceContext *vactx = device_context->hwctx; - return vactx->display; -} - -bool video_codec_context_is_vaapi(AVCodecContext *video_codec_context) { - if(!video_codec_context) - return false; - - AVBufferRef *hw_frames_ctx = video_codec_context->hw_frames_ctx; - if(!hw_frames_ctx) - return false; - - AVHWFramesContext *hw_frame_context = (AVHWFramesContext*)hw_frames_ctx->data; - AVHWDeviceContext *device_context = (AVHWDeviceContext*)hw_frame_context->device_ctx; - return device_context->type == AV_HWDEVICE_TYPE_VAAPI; -} - -static uint32_t drm_fourcc_to_va_fourcc(uint32_t drm_fourcc) { - switch(drm_fourcc) { - case DRM_FORMAT_XRGB8888: return VA_FOURCC_BGRX; - case DRM_FORMAT_XBGR8888: return VA_FOURCC_RGBX; - case DRM_FORMAT_RGBX8888: return VA_FOURCC_XBGR; - case DRM_FORMAT_BGRX8888: return VA_FOURCC_XRGB; - case DRM_FORMAT_ARGB8888: return VA_FOURCC_BGRA; - case DRM_FORMAT_ABGR8888: return VA_FOURCC_RGBA; - case DRM_FORMAT_RGBA8888: return VA_FOURCC_ABGR; - case DRM_FORMAT_BGRA8888: return VA_FOURCC_ARGB; - default: return drm_fourcc; - } -} - -bool vaapi_copy_drm_planes_to_video_surface(AVCodecContext *video_codec_context, AVFrame *video_frame, vec2i source_pos, vec2i source_size, vec2i dest_pos, vec2i dest_size, uint32_t format, vec2i size, const int *fds, const uint32_t *offsets, const uint32_t *pitches, const uint64_t *modifiers, int num_planes) { - VAConfigID config_id = 0; - VAContextID context_id = 0; - VASurfaceID input_surface_id = 0; - VABufferID buffer_id = 0; - bool success = true; - - VADisplay va_dpy = video_codec_context_get_vaapi_display(video_codec_context); - if(!va_dpy) { - success = false; - goto done; - } - - VAStatus va_status = vaCreateConfig(va_dpy, VAProfileNone, VAEntrypointVideoProc, NULL, 0, &config_id); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaCreateConfig failed, error: %s\n", vaErrorStr(va_status)); - success = false; - goto done; - } - - VASurfaceID output_surface_id = (uintptr_t)video_frame->data[3]; - va_status = vaCreateContext(va_dpy, config_id, size.x, size.y, VA_PROGRESSIVE, &output_surface_id, 1, &context_id); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaCreateContext failed, error: %s\n", vaErrorStr(va_status)); - success = false; - goto done; - } - - VADRMPRIMESurfaceDescriptor buf = {0}; - buf.fourcc = drm_fourcc_to_va_fourcc(format);//VA_FOURCC_BGRX; // TODO: VA_FOURCC_BGRA, VA_FOURCC_X2R10G10B10 - buf.width = size.x; - buf.height = size.y; - buf.num_objects = num_planes; - buf.num_layers = 1; - buf.layers[0].drm_format = format; - buf.layers[0].num_planes = buf.num_objects; - for(int i = 0; i < num_planes; ++i) { - buf.objects[i].fd = fds[i]; - buf.objects[i].size = size.y * pitches[i]; // TODO: - buf.objects[i].drm_format_modifier = modifiers[i]; - - buf.layers[0].object_index[i] = i; - buf.layers[0].offset[i] = offsets[i]; - buf.layers[0].pitch[i] = pitches[i]; - } - - VASurfaceAttrib attribs[2] = {0}; - attribs[0].type = VASurfaceAttribMemoryType; - attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; - attribs[0].value.type = VAGenericValueTypeInteger; - attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2; - attribs[1].type = VASurfaceAttribExternalBufferDescriptor; - attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; - attribs[1].value.type = VAGenericValueTypePointer; - attribs[1].value.value.p = &buf; - - // TODO: RT_FORMAT with 10 bit/hdr, VA_RT_FORMAT_RGB32_10 - // TODO: Max size same as source_size - va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_RGB32, size.x, size.y, &input_surface_id, 1, attribs, 2); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaCreateSurfaces failed, error: %s\n", vaErrorStr(va_status)); - success = false; - goto done; - } - - const VARectangle source_region = { - .x = source_pos.x, - .y = source_pos.y, - .width = source_size.x, - .height = source_size.y - }; - - const VARectangle output_region = { - .x = dest_pos.x, - .y = dest_pos.y, - .width = dest_size.x, - .height = dest_size.y - }; - - const bool scaled = dest_size.x != source_size.x || dest_size.y != source_size.y; - - // Copying a surface to another surface will automatically perform the color conversion. Thanks vaapi! - VAProcPipelineParameterBuffer params = {0}; - params.surface = input_surface_id; - params.surface_region = NULL; - params.surface_region = &source_region; - params.output_region = &output_region; - params.output_background_color = 0; - params.filter_flags = scaled ? (VA_FILTER_SCALING_HQ | VA_FILTER_INTERPOLATION_BILINEAR) : 0; - params.pipeline_flags = VA_PROC_PIPELINE_FAST; - - params.input_color_properties.colour_primaries = 1; - params.input_color_properties.transfer_characteristics = 1; - params.input_color_properties.matrix_coefficients = 1; - params.surface_color_standard = VAProcColorStandardBT709; // TODO: - params.input_color_properties.color_range = video_frame->color_range == AVCOL_RANGE_JPEG ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED; - - params.output_color_properties.colour_primaries = 1; - params.output_color_properties.transfer_characteristics = 1; - params.output_color_properties.matrix_coefficients = 1; - params.output_color_standard = VAProcColorStandardBT709; // TODO: - params.output_color_properties.color_range = video_frame->color_range == AVCOL_RANGE_JPEG ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED; - - params.processing_mode = VAProcPerformanceMode; - - // VAProcPipelineCaps pipeline_caps = {0}; - // va_status = vaQueryVideoProcPipelineCaps(self->va_dpy, - // self->context_id, - // NULL, 0, - // &pipeline_caps); - // if(va_status == VA_STATUS_SUCCESS) { - // fprintf(stderr, "pipeline_caps: %u, %u\n", (unsigned int)pipeline_caps.rotation_flags, pipeline_caps.blend_flags); - // } - - // TODO: params.output_hdr_metadata - - // TODO: - // if (first surface to render) - // pipeline_param->output_background_color = 0xff000000; // black - - va_status = vaCreateBuffer(va_dpy, context_id, VAProcPipelineParameterBufferType, sizeof(params), 1, ¶ms, &buffer_id); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaCreateBuffer failed, error: %d\n", va_status); - success = false; - goto done; - } - - va_status = vaBeginPicture(va_dpy, context_id, output_surface_id); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaBeginPicture failed, error: %d\n", va_status); - success = false; - goto done; - } - - va_status = vaRenderPicture(va_dpy, context_id, &buffer_id, 1); - if(va_status != VA_STATUS_SUCCESS) { - vaEndPicture(va_dpy, context_id); - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaRenderPicture failed, error: %d\n", va_status); - success = false; - goto done; - } - - va_status = vaEndPicture(va_dpy, context_id); - if(va_status != VA_STATUS_SUCCESS) { - fprintf(stderr, "gsr error: vaapi_copy_drm_planes_to_video_surface: vaEndPicture failed, error: %d\n", va_status); - success = false; - goto done; - } - - // vaSyncBuffer(va_dpy, buffer_id, 1000 * 1000 * 1000); - // vaSyncSurface(va_dpy, input_surface_id); - // vaSyncSurface(va_dpy, output_surface_id); - - done: - if(buffer_id) - vaDestroyBuffer(va_dpy, buffer_id); - - if(input_surface_id) - vaDestroySurfaces(va_dpy, &input_surface_id, 1); - - if(context_id) - vaDestroyContext(va_dpy, context_id); - - if(config_id) - vaDestroyConfig(va_dpy, config_id); - - return success; -} - -bool vaapi_copy_egl_image_to_video_surface(gsr_egl *egl, EGLImage image, vec2i source_pos, vec2i source_size, vec2i dest_pos, vec2i dest_size, AVCodecContext *video_codec_context, AVFrame *video_frame) { - if(!image) - return false; - - int texture_fourcc = 0; - int texture_num_planes = 0; - uint64_t texture_modifiers = 0; - if(!egl->eglExportDMABUFImageQueryMESA(egl->egl_display, image, &texture_fourcc, &texture_num_planes, &texture_modifiers)) { - fprintf(stderr, "gsr error: gsr_capture_xcomposite_vaapi_tick: eglExportDMABUFImageQueryMESA failed\n"); - return false; - } - - if(texture_num_planes <= 0 || texture_num_planes > 8) { - fprintf(stderr, "gsr error: gsr_capture_xcomposite_vaapi_tick: expected planes size to be 0<planes<=8 for drm buf, got %d planes\n", texture_num_planes); - return false; - } - - int texture_fds[8]; - int32_t texture_strides[8]; - int32_t texture_offsets[8]; - - while(egl->eglGetError() != EGL_SUCCESS){} - if(!egl->eglExportDMABUFImageMESA(egl->egl_display, image, texture_fds, texture_strides, texture_offsets)) { - fprintf(stderr, "gsr error: gsr_capture_xcomposite_vaapi_tick: eglExportDMABUFImageMESA failed, error: %d\n", egl->eglGetError()); - return false; - } - - int fds[8]; - uint32_t offsets[8]; - uint32_t pitches[8]; - uint64_t modifiers[8]; - for(int i = 0; i < texture_num_planes; ++i) { - fds[i] = texture_fds[i]; - offsets[i] = texture_offsets[i]; - pitches[i] = texture_strides[i]; - modifiers[i] = texture_modifiers; - - if(fds[i] == -1) - texture_num_planes = i; - } - const bool success = texture_num_planes > 0 && vaapi_copy_drm_planes_to_video_surface(video_codec_context, video_frame, source_pos, source_size, dest_pos, dest_size, texture_fourcc, source_size, fds, offsets, pitches, modifiers, texture_num_planes); - - for(int i = 0; i < texture_num_planes; ++i) { - if(texture_fds[i] > 0) { - close(texture_fds[i]); - texture_fds[i] = -1; - } - } - - return success; -} - vec2i scale_keep_aspect_ratio(vec2i from, vec2i to) { if(from.x == 0 || from.y == 0) return (vec2i){0, 0}; @@ -898,3 +596,17 @@ vec2i scale_keep_aspect_ratio(vec2i from, vec2i to) { return from; } + +unsigned int gl_create_texture(gsr_egl *egl, int width, int height, int internal_format, unsigned int format, int filter) { + unsigned int texture_id = 0; + egl->glGenTextures(1, &texture_id); + egl->glBindTexture(GL_TEXTURE_2D, texture_id); + //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); + + egl->glBindTexture(GL_TEXTURE_2D, 0); + return texture_id; +} |