DRM: Add support for drmModeAddFB2

When working in 64-bit, handles passed to the kernel
DRM can not be user-space pointer anymore, but rather
should be a real kernel handles (fds). A change is needed
in the UI components and the kernel to fix this
functionality. in addition, since the multi-plane buffers
need multiple FDs, drmModeAddFB2 is needed to support that.
This is a new API that does not affect current functionality.

Change-Id: Iea5f57fccc43af5e8371cbd31cfd81a35959fe04
Tracked-On: https://jira01.devtools.intel.com/browse/IMINAN-7099
Signed-off-by: AtanasX D Zlatinski <atanasx.d.zlatinski@intel.com>
Reviewed-on: https://android.intel.com/160389
Reviewed-by: cactus <cactus@intel.com>
Reviewed-by: Agarwal, Tarun <tarun.agarwal@intel.com>
Tested-by: Agarwal, Tarun <tarun.agarwal@intel.com>
Reviewed-on: https://android.intel.com:443/291373
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index 8764fe3..c5d1639 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -208,6 +208,28 @@
 	*buf_id = f.fb_id;
 	return 0;
 }
+int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
+		  uint32_t pixel_format, uint32_t bo_handles[4],
+		  uint32_t pitches[4], uint32_t offsets[4],
+		  uint32_t *buf_id, uint32_t flags)
+{
+	struct drm_mode_fb_cmd2 f;
+	int ret;
+
+	f.width  = width;
+	f.height = height;
+	f.pixel_format = pixel_format;
+	f.flags = flags;
+	memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0]));
+	memcpy(f.pitches, pitches, 4 * sizeof(pitches[0]));
+	memcpy(f.offsets, offsets, 4 * sizeof(offsets[0]));
+
+	if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
+		return ret;
+
+	*buf_id = f.fb_id;
+	return 0;
+}
 
 int drmModeRmFB(int fd, uint32_t bufferId)
 {
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index 58e828d..014d537 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -297,6 +297,13 @@
 extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
 			uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
 			uint32_t *buf_id);
+
+/* ...with a specific pixel format */
+extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
+			 uint32_t pixel_format, uint32_t bo_handles[4],
+			 uint32_t pitches[4], uint32_t offsets[4],
+			 uint32_t *buf_id, uint32_t flags);
+
 /**
  * Destroies the given framebuffer.
  */
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 5bea948..ad29e1f 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -794,6 +794,7 @@
 
 #define DRM_IOCTL_MODE_GETFB		DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
 #define DRM_IOCTL_MODE_ADDFB		DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_RMFB		DRM_IOWR(0xAF, uint32_t)
 
 /*@}*/
diff --git a/shared-core/drm_mode.h b/shared-core/drm_mode.h
index 3bc74e8..43006b5 100644
--- a/shared-core/drm_mode.h
+++ b/shared-core/drm_mode.h
@@ -235,6 +235,33 @@
 	__u32 handle;
 };
 
+#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */
+
+struct drm_mode_fb_cmd2 {
+	__u32 fb_id;
+	__u32 width, height;
+	__u32 pixel_format; /* fourcc code from drm_fourcc.h */
+	__u32 flags;
+
+	/*
+	 * In case of planar formats, this ioctl allows up to 4
+	 * buffer objects with offsets and pitches per plane.
+	 * The pitch and offset order is dictated by the fourcc,
+	 * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
+	 *
+	 *   YUV 4:2:0 image with a plane of 8 bit Y samples
+	 *   followed by an interleaved U/V plane containing
+	 *   8 bit 2x2 subsampled colour difference samples.
+	 *
+	 * So it would consist of Y as offset[0] and UV as
+	 * offset[1].  Note that offset[0] will generally
+	 * be 0.
+	 */
+	__u32 handles[4];
+	__u32 pitches[4]; /* pitch for each plane */
+	__u32 offsets[4]; /* offset of each plane */
+};
+
 #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
 #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
 #define DRM_MODE_FB_DIRTY_FLAGS         0x03