aboutsummaryrefslogtreecommitdiff
path: root/src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c502
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, &params, &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;
+}