[igt-dev] [PATCH i-g-t 3/8] lib/fb: Handle planar formats in igt_calc_fb_size and create_bo_for_fb

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Tue Jan 23 12:56:37 UTC 2018


By adding support for planar formats to igt_calc_fb_size and create_bo_for_fb,
we can calculate dimensions and create backing storage for planar framebuffers.

This is required for adding support to create planar framebuffers in the next patch.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 lib/igt_fb.c | 168 +++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 123 insertions(+), 45 deletions(-)

diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index da07d1a9e21f..6a331f06724b 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -54,14 +54,16 @@
  */
 
 /* drm fourcc/cairo format maps */
-#define DF(did, cid, _bpp, _depth)	\
-	{ DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, _bpp, _depth }
+#define DF(did, cid, ...)	\
+	{ DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, __VA_ARGS__ }
 static struct format_desc_struct {
 	uint32_t drm_id;
 	cairo_format_t cairo_id;
 	const char *name;
 	int bpp;
 	int depth;
+	int planes;
+	int plane_bpp[4];
 } format_desc[] = {
 	DF(RGB565,	RGB16_565,	16, 16),
 	//DF(RGB888,	INVALID,	24, 24),
@@ -74,6 +76,20 @@ static struct format_desc_struct {
 #define for_each_format(f)	\
 	for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
 
+static struct format_desc_struct *lookup_drm_format(uint32_t drm_format)
+{
+	struct format_desc_struct *format;
+
+	for_each_format(format) {
+		if (format->drm_id != drm_format)
+			continue;
+
+		return format;
+	}
+
+	return NULL;
+}
+
 /**
  * igt_get_fb_tile_size:
  * @fd: the DRM file descriptor
@@ -142,27 +158,68 @@ void igt_get_fb_tile_size(int fd, uint64_t tiling, int fb_bpp,
 	}
 }
 
-/**
- * igt_calc_fb_size:
- * @fd: the DRM file descriptor
- * @width: width of the framebuffer in pixels
- * @height: height of the framebuffer in pixels
- * @format: drm fourcc pixel format code
- * @tiling: tiling layout of the framebuffer (as framebuffer modifier)
- * @size_ret: returned size for the framebuffer
- * @stride_ret: returned stride for the framebuffer
- *
- * This function returns valid stride and size values for a framebuffer with the
- * specified parameters.
- */
-void igt_calc_fb_size(int fd, int width, int height, uint32_t format, uint64_t tiling,
-		      unsigned *size_ret, unsigned *stride_ret)
+static unsigned planar_stride(struct format_desc_struct *format, unsigned width, int plane)
+{
+	unsigned cpp = format->plane_bpp[plane] / 8;
+
+	if (format->drm_id == DRM_FORMAT_NV12 && plane == 1)
+		return (width + 1) / 2 * cpp;
+
+	return width * cpp;
+}
+
+static unsigned planar_height(struct format_desc_struct *format, unsigned height, int plane)
+{
+	if (format->drm_id == DRM_FORMAT_NV12 && plane == 1)
+		return (height + 1) / 2;
+
+	return height;
+}
+
+static void calc_fb_size_planar(int fd, int width, int height,
+				struct format_desc_struct *format,
+				uint64_t tiling, unsigned *size_ret,
+				unsigned *stride_ret, unsigned *offsets)
+{
+	int plane;
+	unsigned stride = 0, tile_width, tile_height;
+
+	*size_ret = 0;
+
+	for (plane = 0; plane < format->planes; plane++) {
+		unsigned plane_stride;
+
+		igt_get_fb_tile_size(fd, tiling, format->plane_bpp[plane], &tile_width, &tile_height);
+
+		plane_stride = ALIGN(planar_stride(format, width, plane), tile_width);
+		if (stride < plane_stride)
+			stride = plane_stride;
+	}
+
+	for (plane = 0; plane < format->planes; plane++) {
+		if (offsets)
+			offsets[plane] = *size_ret;
+
+		igt_get_fb_tile_size(fd, tiling, format->plane_bpp[plane], &tile_width, &tile_height);
+
+		*size_ret += stride * ALIGN(planar_height(format, height, plane), tile_height);
+	}
+
+	if (offsets)
+		for (; plane < 4; plane++)
+			offsets[plane] = 0;
+
+	*stride_ret = stride;
+}
+
+static void calc_fb_size_packed(int fd, int width, int height,
+				struct format_desc_struct *format, uint64_t tiling,
+				unsigned *size_ret, unsigned *stride_ret)
 {
 	unsigned int tile_width, tile_height, stride, size;
-	int bpp = igt_drm_format_to_bpp(format);
-	int byte_width = width * (bpp / 8);
+	int byte_width = width * (format->bpp / 8);
 
-	igt_get_fb_tile_size(fd, tiling, bpp, &tile_width, &tile_height);
+	igt_get_fb_tile_size(fd, tiling, format->bpp, &tile_width, &tile_height);
 
 	if (tiling != LOCAL_DRM_FORMAT_MOD_NONE &&
 	    intel_gen(intel_get_drm_devid(fd)) <= 3) {
@@ -176,7 +233,7 @@ void igt_calc_fb_size(int fd, int width, int height, uint32_t format, uint64_t t
 		 * tiled. But then that failure is expected.
 		 */
 
-		v = width * bpp / 8;
+		v = byte_width;
 		for (stride = 512; stride < v; stride *= 2)
 			;
 
@@ -192,6 +249,31 @@ void igt_calc_fb_size(int fd, int width, int height, uint32_t format, uint64_t t
 	*size_ret = size;
 }
 
+/**
+ * igt_calc_fb_size:
+ * @fd: the DRM file descriptor
+ * @width: width of the framebuffer in pixels
+ * @height: height of the framebuffer in pixels
+ * @format: drm fourcc pixel format code
+ * @tiling: tiling layout of the framebuffer (as framebuffer modifier)
+ * @size_ret: returned size for the framebuffer
+ * @stride_ret: returned stride for the framebuffer
+ *
+ * This function returns valid stride and size values for a framebuffer with the
+ * specified parameters.
+ */
+void igt_calc_fb_size(int fd, int width, int height, uint32_t drm_format, uint64_t tiling,
+		      unsigned *size_ret, unsigned *stride_ret)
+{
+	struct format_desc_struct *format = lookup_drm_format(drm_format);
+	igt_assert(format);
+
+	if (format->planes > 1)
+		calc_fb_size_planar(fd, width, height, format, tiling, size_ret, stride_ret, NULL);
+	else
+		calc_fb_size_packed(fd, width, height, format, tiling, size_ret, stride_ret);
+}
+
 /**
  * igt_fb_mod_to_tiling:
  * @modifier: DRM framebuffer modifier
@@ -245,17 +327,20 @@ uint64_t igt_fb_tiling_to_mod(uint64_t tiling)
 }
 
 /* helpers to create nice-looking framebuffers */
-static int create_bo_for_fb(int fd, int width, int height, uint32_t format,
+static int create_bo_for_fb(int fd, int width, int height,
+			    struct format_desc_struct *format,
 			    uint64_t tiling, unsigned size, unsigned stride,
 			    unsigned *size_ret, unsigned *stride_ret,
 			    bool *is_dumb)
 {
 	int bo;
 
-	if (tiling || size || stride) {
+	igt_assert(format);
+
+	if (tiling || size || stride || format->planes > 1) {
 		unsigned calculated_size, calculated_stride;
 
-		igt_calc_fb_size(fd, width, height, format, tiling,
+		igt_calc_fb_size(fd, width, height, format->drm_id, tiling,
 				 &calculated_size, &calculated_stride);
 		if (stride == 0)
 			stride = calculated_stride;
@@ -290,12 +375,10 @@ static int create_bo_for_fb(int fd, int width, int height, uint32_t format,
 			return -EINVAL;
 		}
 	} else {
-		int bpp = igt_drm_format_to_bpp(format);
-
 		if (is_dumb)
 			*is_dumb = true;
 
-		return kmstest_dumb_create(fd, width, height, bpp, stride_ret,
+		return kmstest_dumb_create(fd, width, height, format->bpp, stride_ret,
 					   size_ret);
 	}
 }
@@ -323,8 +406,8 @@ int igt_create_bo_with_dimensions(int fd, int width, int height,
 				  unsigned stride, unsigned *size_ret,
 				  unsigned *stride_ret, bool *is_dumb)
 {
-	return create_bo_for_fb(fd, width, height, format, modifier, 0, stride,
-			     size_ret, stride_ret, is_dumb);
+	return create_bo_for_fb(fd, width, height, lookup_drm_format(format),
+				modifier, 0, stride, size_ret, stride_ret, is_dumb);
 }
 
 /**
@@ -671,9 +754,10 @@ igt_create_fb_with_bo_size(int fd, int width, int height,
 
 	igt_debug("%s(width=%d, height=%d, format=0x%x, tiling=0x%"PRIx64", size=%d)\n",
 		  __func__, width, height, format, tiling, bo_size);
-	fb->gem_handle = create_bo_for_fb(fd, width, height, format, tiling,
-					  bo_size, bo_stride, &fb->size,
-					  &fb->stride, &fb->is_dumb);
+	fb->gem_handle = create_bo_for_fb(fd, width, height,
+					  lookup_drm_format(format),
+					  tiling, bo_size, bo_stride,
+					  &fb->size, &fb->stride, &fb->is_dumb);
 	igt_assert(fb->gem_handle > 0);
 
 	igt_debug("%s(handle=%d, pitch=%d)\n",
@@ -1069,7 +1153,7 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
 	 * destination, tiling it at the same time.
 	 */
 	blit->linear.handle = create_bo_for_fb(fd, fb->width, fb->height,
-					       fb->drm_format,
+					       lookup_drm_format(fb->drm_format),
 					       LOCAL_DRM_FORMAT_MOD_NONE, 0,
 					       0, &blit->linear.size,
 					       &blit->linear.stride,
@@ -1293,14 +1377,12 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth)
  */
 uint32_t igt_drm_format_to_bpp(uint32_t drm_format)
 {
-	struct format_desc_struct *f;
+	struct format_desc_struct *f = lookup_drm_format(drm_format);
 
-	for_each_format(f)
-		if (f->drm_id == drm_format)
-			return f->bpp;
-
-	igt_assert_f(0, "can't find a bpp format for %08x (%s)\n",
+	igt_assert_f(f, "can't find a bpp format for %08x (%s)\n",
 		     drm_format, igt_format_str(drm_format));
+
+	return f->bpp;
 }
 
 /**
@@ -1313,13 +1395,9 @@ uint32_t igt_drm_format_to_bpp(uint32_t drm_format)
  */
 const char *igt_format_str(uint32_t drm_format)
 {
-	struct format_desc_struct *f;
-
-	for_each_format(f)
-		if (f->drm_id == drm_format)
-			return f->name;
+	struct format_desc_struct *f = lookup_drm_format(drm_format);
 
-	return "invalid";
+	return f ? f->name : "invalid";
 }
 
 /**
-- 
2.15.1



More information about the igt-dev mailing list