opengl: Add low level support for tiled formats
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Tue, 12 Apr 2022 16:24:03 +0000 (12:24 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 2 May 2022 19:10:43 +0000 (19:10 +0000)
This adds support for tiled format in stride and plane size
code.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2190>

subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.c
subprojects/gst-plugins-base/gst-libs/gst/gl/gstglmemory.c
subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c

index 18588c1..1714051 100644 (file)
@@ -553,6 +553,21 @@ _drm_rgba_fourcc_from_info (const GstVideoInfo * info, int plane,
   }
 }
 
+static gint
+get_egl_stride (const GstVideoInfo * info, gint plane)
+{
+  const GstVideoFormatInfo *finfo = info->finfo;
+  gint stride = info->stride[plane];
+  guint ws;
+
+  if (!GST_VIDEO_FORMAT_INFO_IS_TILED (finfo))
+    return stride;
+
+  gst_video_format_info_get_tile_sizes (finfo, plane, &ws, NULL);
+
+  return GST_VIDEO_TILE_X_TILES (stride) << ws;
+}
+
 /**
  * gst_egl_image_from_dmabuf:
  * @context: a #GstGLContext (must be an EGL context)
@@ -601,7 +616,7 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
   attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
   attribs[atti++] = offset;
   attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
-  attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane);
+  attribs[atti++] = get_egl_stride (in_info, plane);
   attribs[atti] = EGL_NONE;
   g_assert (atti == G_N_ELEMENTS (attribs) - 1);
 
@@ -905,7 +920,7 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
     attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
     attribs[atti++] = offset[0];
     attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
-    attribs[atti++] = in_info->stride[0];
+    attribs[atti++] = get_egl_stride (in_info, 0);
     if (with_modifiers) {
       attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
       attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
@@ -921,7 +936,7 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
     attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
     attribs[atti++] = offset[1];
     attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
-    attribs[atti++] = in_info->stride[1];
+    attribs[atti++] = get_egl_stride (in_info, 1);
     if (with_modifiers) {
       attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
       attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
@@ -937,7 +952,7 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
     attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
     attribs[atti++] = offset[2];
     attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
-    attribs[atti++] = in_info->stride[2];
+    attribs[atti++] = get_egl_stride (in_info, 2);
     if (with_modifiers) {
       attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
       attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
index 9cb0787..118f07e 100644 (file)
@@ -59,7 +59,7 @@
 
 #define GL_MEM_WIDTH(gl_mem) _get_plane_width (&gl_mem->info, gl_mem->plane)
 #define GL_MEM_HEIGHT(gl_mem) _get_plane_height (&gl_mem->info, gl_mem->plane)
-#define GL_MEM_STRIDE(gl_mem) GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->info, gl_mem->plane)
+#define GL_MEM_STRIDE(gl_mem) _get_mem_stride (gl_mem)
 
 static GstAllocator *_gl_memory_allocator;
 
@@ -122,19 +122,43 @@ _get_plane_width (const GstVideoInfo * info, guint plane)
 static inline guint
 _get_plane_height (const GstVideoInfo * info, guint plane)
 {
+  if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo)) {
+    guint hs;
+    gsize stride;
+
+    gst_video_format_info_get_tile_sizes (info->finfo, plane, NULL, &hs);
+    stride = GST_VIDEO_INFO_PLANE_STRIDE (info, plane);
+
+    return GST_VIDEO_TILE_Y_TILES (stride) << hs;
+  }
+
   if (GST_VIDEO_INFO_IS_YUV (info)) {
     gint comp[GST_VIDEO_MAX_COMPONENTS];
     gst_video_format_info_component (info->finfo, plane, comp);
     return GST_VIDEO_INFO_COMP_HEIGHT (info, comp[0]);
-  } else {
-    /* RGB, GRAY */
-    return GST_VIDEO_INFO_HEIGHT (info);
   }
+
+  /* RGB, GRAY */
+  return GST_VIDEO_INFO_HEIGHT (info);
+}
+
+static guint
+_get_mem_stride (GstGLMemory * gl_mem)
+{
+  const GstVideoFormatInfo *finfo = gl_mem->info.finfo;
+  guint stride = GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->info, gl_mem->plane);
+
+  if (!GST_VIDEO_FORMAT_INFO_IS_TILED (finfo))
+    return stride;
+
+  return
+      GST_VIDEO_TILE_X_TILES (stride) << GST_VIDEO_FORMAT_INFO_TILE_WS (finfo);
 }
 
 static inline void
 _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
 {
+  GstVideoInfo *info = &gl_mem->info;
   guint n_gl_bytes;
   GstGLFormat tex_format;
   guint tex_type;
@@ -142,7 +166,6 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
   gl_mem->tex_scaling[0] = 1.0f;
   gl_mem->tex_scaling[1] = 1.0f;
   gl_mem->unpack_length = 1;
-  gl_mem->tex_width = GL_MEM_WIDTH (gl_mem);
 
   gst_gl_format_type_from_sized_gl_format (gl_mem->tex_format, &tex_format,
       &tex_type);
@@ -152,6 +175,13 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
     return;
   }
 
+  /* For tiles, we need GL not to clip on the display width, as the would make
+   * some tile not fully accessible by GLSL. */
+  if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo))
+    gl_mem->tex_width = GL_MEM_STRIDE (gl_mem) / n_gl_bytes;
+  else
+    gl_mem->tex_width = GL_MEM_WIDTH (gl_mem);
+
   if (USING_OPENGL (context) || USING_GLES3 (context)
       || USING_OPENGL3 (context)) {
     gl_mem->unpack_length = GL_MEM_STRIDE (gl_mem) / n_gl_bytes;
index cb9e858..570d0e1 100644 (file)
@@ -613,6 +613,7 @@ gsize
 gst_gl_get_plane_data_size (const GstVideoInfo * info,
     const GstVideoAlignment * align, guint plane)
 {
+  const GstVideoFormatInfo *finfo = info->finfo;
   gint comp[GST_VIDEO_MAX_COMPONENTS];
   gint padded_height;
   gsize plane_size;
@@ -627,7 +628,21 @@ gst_gl_get_plane_data_size (const GstVideoInfo * info,
   padded_height =
       GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, comp[0], padded_height);
 
-  plane_size = GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height;
+  if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
+    gsize stride;
+    gint x_tiles, y_tiles;
+    gint tile_size;
+
+    tile_size = gst_video_format_info_get_tile_sizes (finfo, plane, NULL, NULL);
+
+    stride = GST_VIDEO_INFO_PLANE_STRIDE (info, plane);
+    x_tiles = GST_VIDEO_TILE_X_TILES (stride);
+    y_tiles = GST_VIDEO_TILE_Y_TILES (stride);
+
+    plane_size = x_tiles * y_tiles * tile_size;
+  } else {
+    plane_size = GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height;
+  }
 
   return plane_size;
 }