ecore-drm2: Add hardware plane functions
authorChris Michael <cp.michael@samsung.com>
Mon, 27 Mar 2017 15:54:38 +0000 (11:54 -0400)
committerChris Michael <cp.michael@samsung.com>
Tue, 18 Apr 2017 11:55:10 +0000 (07:55 -0400)
This patch adds a new file where we can store any additional functions
we may need to work with hardware planes. Currently the file contains
a public function that can be used to assign a given Ecore_Drm2_Fb to
a hardware plane

@feature

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/Makefile_Ecore_Drm2.am
src/lib/ecore_drm2/Ecore_Drm2.h
src/lib/ecore_drm2/ecore_drm2_plane.c [new file with mode: 0644]

index 1c328e3..8e9620d 100644 (file)
@@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \
   lib/ecore_drm2/Ecore_Drm2.h
 
 lib_ecore_drm2_libecore_drm2_la_SOURCES = \
+lib/ecore_drm2/ecore_drm2_plane.c \
 lib/ecore_drm2/ecore_drm2_fb.c \
 lib/ecore_drm2/ecore_drm2_outputs.c \
 lib/ecore_drm2/ecore_drm2_device.c \
index e75a578..62eebc1 100644 (file)
@@ -99,6 +99,7 @@ typedef void (*Ecore_Drm2_Release_Handler)(void *data, Ecore_Drm2_Fb *b);
  * @li @ref Ecore_Drm2_Device_Group
  * @li @ref Ecore_Drm2_Output_Group
  * @li @ref Ecore_Drm2_Fb_Group
+ * @li @ref Ecore_Drm2_Plane_Group
  */
 
 /**
@@ -988,6 +989,25 @@ EAPI void *ecore_drm2_fb_bo_get(Ecore_Drm2_Fb *fb);
  */
 EAPI Ecore_Drm2_Fb *ecore_drm2_fb_dmabuf_import(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int strides[4], int dmabuf_fd[4], int dmabuf_fd_count);
 
+/**
+ * @defgroup Ecore_Drm2_Plane_Group Functions that deal with hardware planes
+ *
+ * Functions that deal with hardware plane manipulation
+ */
+
+/**
+ * Find a hardware plane where a given Ecore_Drm2_Fb can go based on format and size
+ *
+ * @param output
+ * @param fb
+ *
+ * @return A newly allocated plane object, or NULL otherwise
+ *
+ * @ingroup Ecore_Drm2_Plane_Group
+ * @since 1.20
+ */
+EAPI Ecore_Drm2_Plane *ecore_drm2_plane_assign(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb);
+
 # endif
 
 #endif
diff --git a/src/lib/ecore_drm2/ecore_drm2_plane.c b/src/lib/ecore_drm2/ecore_drm2_plane.c
new file mode 100644 (file)
index 0000000..3df0cbb
--- /dev/null
@@ -0,0 +1,105 @@
+#include "ecore_drm2_private.h"
+
+static Eina_Bool
+_plane_format_supported(Ecore_Drm2_Plane_State *pstate, uint32_t format)
+{
+   Eina_Bool ret = EINA_FALSE;
+   unsigned int i = 0;
+
+   for (; i < pstate->num_formats; i++)
+     {
+        if (pstate->formats[i] == format)
+          {
+             ret = EINA_TRUE;
+             break;
+          }
+     }
+
+   return ret;
+}
+
+static void
+_plane_cursor_size_get(int fd, int *width, int *height)
+{
+   uint64_t caps;
+   int ret;
+
+   if (width)
+     {
+        *width = 64;
+        ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &caps);
+        if (ret == 0) *width = caps;
+     }
+   if (height)
+     {
+        *height = 64;
+        ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &caps);
+        if (ret == 0) *height = caps;
+     }
+}
+
+EAPI Ecore_Drm2_Plane *
+ecore_drm2_plane_assign(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb)
+{
+#ifdef HAVE_ATOMIC_DRM
+   Eina_List *l;
+   Ecore_Drm2_Plane *plane;
+   Ecore_Drm2_Plane_State *pstate;
+
+   if (!_ecore_drm2_use_atomic) return NULL;
+
+   /* use algo based on format, size, etc to find a plane this FB can go in */
+   EINA_LIST_FOREACH(output->plane_states, l, pstate)
+     {
+        /* test if this plane supports the given format */
+        if (!_plane_format_supported(pstate, fb->format))
+          continue;
+
+        if (pstate->type.value == DRM_PLANE_TYPE_CURSOR)
+          {
+             int cw, ch;
+
+             _plane_cursor_size_get(output->fd, &cw, &ch);
+
+             /* check that this fb can fit in cursor plane */
+             if ((fb->w > cw) || (fb->h > ch))
+               continue;
+
+             /* if we reach here, this FB can go on the cursor plane */
+             goto out;
+          }
+        else if (pstate->type.value == DRM_PLANE_TYPE_OVERLAY)
+          {
+             /* there are no size checks for an overlay plane */
+             goto out;
+          }
+        else if (pstate->type.value == DRM_PLANE_TYPE_PRIMARY)
+          {
+             if ((fb->w > output->current_mode->width) ||
+                 (fb->h > output->current_mode->height))
+               continue;
+
+             /* if we reach here, this FB can go on the primary plane */
+             goto out;
+          }
+     }
+
+   return NULL;
+
+out:
+   /* create plane */
+   plane = calloc(1, sizeof(Ecore_Drm2_Plane));
+   if (!plane) return NULL;
+
+   plane->type = pstate->type.value;
+   plane->qfb = fb;
+   plane->state = pstate;
+
+   DBG("FB %d assigned to Plane %d", fb->id, pstate->obj_id);
+   output->planes = eina_list_append(output->planes, plane);
+
+   return plane;
+#else
+   return NULL;
+#endif
+}