summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gralloc.c3
-rw-r--r--gralloc_drm.h5
-rw-r--r--gralloc_drm_kms.c151
-rw-r--r--gralloc_drm_priv.h25
4 files changed, 183 insertions, 1 deletions
diff --git a/gralloc.c b/gralloc.c
index 44dc248..873945d 100644
--- a/gralloc.c
+++ b/gralloc.c
@@ -352,6 +352,9 @@ struct drm_module_t HAL_MODULE_INFO_SYM = {
.unlock = drm_mod_unlock,
.perform = drm_mod_perform
},
+ .hwc_reserve_plane = gralloc_drm_reserve_plane,
+ .hwc_disable_planes = gralloc_drm_disable_planes,
+
.mutex = PTHREAD_MUTEX_INITIALIZER,
.drm = NULL
};
diff --git a/gralloc_drm.h b/gralloc_drm.h
index 891526f..8554cf7 100644
--- a/gralloc_drm.h
+++ b/gralloc_drm.h
@@ -136,6 +136,11 @@ int gralloc_drm_bo_add_fb(struct gralloc_drm_bo_t *bo);
void gralloc_drm_bo_rm_fb(struct gralloc_drm_bo_t *bo);
int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo);
+int gralloc_drm_reserve_plane(struct gralloc_drm_t *drm, buffer_handle_t handle,
+ uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h,
+ uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h);
+void gralloc_drm_disable_planes(struct gralloc_drm_t *mod);
+
#ifdef __cplusplus
}
#endif
diff --git a/gralloc_drm_kms.c b/gralloc_drm_kms.c
index 0680bf0..4eb3dfa 100644
--- a/gralloc_drm_kms.c
+++ b/gralloc_drm_kms.c
@@ -104,7 +104,7 @@ unsigned int planes_for_format(struct gralloc_drm_t *drm,
for (i=0; i<drm->plane_resources->count_planes; i++, plane++)
for (j=0; j<plane->drm_plane->count_formats; j++)
if (plane->drm_plane->formats[j] == drm_format)
- mask |= (2 << plane->drm_plane->plane_id);
+ mask |= (1U << plane->drm_plane->plane_id);
return mask;
}
@@ -183,6 +183,152 @@ static void page_flip_handler(int fd, unsigned int sequence,
}
/*
+ * Set a plane.
+ */
+static int gralloc_drm_bo_setplane(struct gralloc_drm_t *drm,
+ struct gralloc_drm_plane_t *plane)
+{
+ struct gralloc_drm_bo_t *bo = NULL;
+ int err;
+
+ if (plane->handle)
+ bo = gralloc_drm_bo_from_handle(plane->handle);
+
+ // create a framebuffer if does not exist
+ if (bo && bo->fb_id == 0) {
+ err = gralloc_drm_bo_add_fb(bo);
+ if (err) {
+ ALOGE("%s: could not create drm fb, (%s)",
+ __func__, strerror(-err));
+ return err;
+ }
+ }
+
+ err = drmModeSetPlane(drm->fd,
+ plane->drm_plane->plane_id,
+ drm->primary.crtc_id,
+ bo ? bo->fb_id : 0,
+ 0, // flags
+ plane->dst_x,
+ plane->dst_y,
+ plane->dst_w,
+ plane->dst_h,
+ plane->src_x << 16,
+ plane->src_y << 16,
+ plane->src_w << 16,
+ plane->src_h << 16);
+
+ if (err) {
+ /* clear plane_mask so that this buffer won't be tried again */
+ struct gralloc_drm_handle_t *drm_handle =
+ (struct gralloc_drm_handle_t *) plane->handle;
+ drm_handle->plane_mask = 0;
+
+ ALOGE("drmModeSetPlane : error (%s) (plane %d crtc %d fb %d)",
+ strerror(-err),
+ plane->drm_plane->plane_id,
+ drm->primary.crtc_id,
+ bo ? bo->fb_id : 0);
+ }
+
+ if (plane->prev)
+ gralloc_drm_bo_decref(plane->prev);
+
+ if (bo)
+ bo->refcount++;
+
+ plane->prev = bo;
+
+ return err;
+}
+
+/*
+ * Sets all the active planes to be displayed.
+ */
+static void gralloc_drm_set_planes(struct gralloc_drm_t *drm)
+{
+ struct gralloc_drm_plane_t *plane = drm->planes;
+ unsigned int i;
+ for (i = 0; i < drm->plane_resources->count_planes;
+ i++, plane++) {
+ /*
+ * Disable overlay if it is not active
+ * or if there is error during setplane
+ */
+ if (!plane->active)
+ plane->handle = 0;
+
+ if (gralloc_drm_bo_setplane(drm, plane))
+ plane->active = 0;
+ }
+}
+
+/*
+ * Interface for HWC, used to reserve a plane for a layer.
+ */
+int gralloc_drm_reserve_plane(struct gralloc_drm_t *drm,
+ buffer_handle_t handle,
+ uint32_t dst_x,
+ uint32_t dst_y,
+ uint32_t dst_w,
+ uint32_t dst_h,
+ uint32_t src_x,
+ uint32_t src_y,
+ uint32_t src_w,
+ uint32_t src_h)
+{
+ unsigned int i, j;
+ struct gralloc_drm_handle_t *drm_handle =
+ gralloc_drm_handle(handle);
+ int plane_count = drm->plane_resources->count_planes;
+ struct gralloc_drm_plane_t *plane = drm->planes;
+
+ /* no supported planes for this handle */
+ if (!drm_handle->plane_mask) {
+ ALOGE("%s: buffer %p cannot be shown on a plane\n",
+ __func__, drm_handle);
+ return -EINVAL;
+ }
+
+ for (j = 0; j < plane_count; j++, plane++) {
+ /* if plane is available and can support this buffer */
+ if (!plane->active &&
+ drm_handle->plane_mask &
+ (1U << plane->drm_plane->plane_id)) {
+
+ plane->dst_x = dst_x;
+ plane->dst_y = dst_y;
+ plane->dst_w = dst_w;
+ plane->dst_h = dst_h;
+ plane->src_x = src_x;
+ plane->src_y = src_y;
+ plane->src_w = src_w;
+ plane->src_h = src_h;
+ plane->handle = handle;
+ plane->active = 1;
+
+ return 0;
+ }
+ }
+
+ /* no free planes available */
+ return -EBUSY;
+}
+
+/*
+ * Interface for HWC, used to disable all the overlays.
+ */
+void gralloc_drm_disable_planes(struct gralloc_drm_t *drm)
+{
+ struct gralloc_drm_plane_t *plane = drm->planes;
+ unsigned int i;
+
+ for (i = 0; i < drm->plane_resources->count_planes; i++, plane++)
+ plane->active = 0;
+}
+
+
+/*
* Schedule a page flip.
*/
static int drm_kms_page_flip(struct gralloc_drm_t *drm,
@@ -229,6 +375,9 @@ static int drm_kms_page_flip(struct gralloc_drm_t *drm,
}
pthread_mutex_unlock(&drm->hdmi_mutex);
+ /* set planes to be displayed */
+ gralloc_drm_set_planes(drm);
+
ret = drmModePageFlip(drm->fd, drm->primary.crtc_id, bo->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, (void *) drm);
if (ret) {
diff --git a/gralloc_drm_priv.h b/gralloc_drm_priv.h
index dc7d505..eb4338c 100644
--- a/gralloc_drm_priv.h
+++ b/gralloc_drm_priv.h
@@ -49,6 +49,25 @@ enum hdmi_output_mode {
struct gralloc_drm_plane_t {
drmModePlane *drm_plane;
+
+ /* plane has been set to display a layer */
+ uint32_t active;
+
+ /* handle to display */
+ buffer_handle_t handle;
+
+ /* position, crop and scale */
+ uint32_t src_x;
+ uint32_t src_y;
+ uint32_t src_w;
+ uint32_t src_h;
+ uint32_t dst_x;
+ uint32_t dst_y;
+ uint32_t dst_w;
+ uint32_t dst_h;
+
+ /* previous buffer, for refcounting */
+ struct gralloc_drm_bo_t *prev;
};
struct gralloc_drm_output
@@ -106,6 +125,12 @@ struct gralloc_drm_t {
struct drm_module_t {
gralloc_module_t base;
+ /* HWC plane API */
+ int (*hwc_reserve_plane) (struct gralloc_drm_t *mod, buffer_handle_t handle,
+ uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h,
+ uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h);
+ void (*hwc_disable_planes) (struct gralloc_drm_t *mod);
+
pthread_mutex_t mutex;
struct gralloc_drm_t *drm;
};