From 19da4706f3763cf2c8eb333fbbc6e31e69d63850 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 27 Mar 2017 11:54:38 -0400 Subject: [PATCH] ecore-drm2: Add hardware plane functions 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 --- src/Makefile_Ecore_Drm2.am | 1 + src/lib/ecore_drm2/Ecore_Drm2.h | 20 +++++ src/lib/ecore_drm2/ecore_drm2_plane.c | 105 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/lib/ecore_drm2/ecore_drm2_plane.c diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am index 1c328e33de..8e9620d714 100644 --- a/src/Makefile_Ecore_Drm2.am +++ b/src/Makefile_Ecore_Drm2.am @@ -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 \ diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index e75a57847e..62eebc1e52 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -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 index 0000000000..3df0cbb63a --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2_plane.c @@ -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 +}