summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTapani Pälli <tapani.palli@intel.com>2013-02-27 08:02:06 +0200
committerTapani Pälli <tapani.palli@intel.com>2013-03-01 10:59:47 +0200
commit6acef2e0ae6cfae1817578e5fc22c04105a3a653 (patch)
tree9614543e80c044dd1a9979f70409810e19e092cb
parentf3c326e3a15df2b1d8e0387ab634ec29dafd7707 (diff)
downloadexternal_drm_gralloc-6acef2e0ae6cfae1817578e5fc22c04105a3a653.zip
external_drm_gralloc-6acef2e0ae6cfae1817578e5fc22c04105a3a653.tar.gz
external_drm_gralloc-6acef2e0ae6cfae1817578e5fc22c04105a3a653.tar.bz2
gralloc: use proper mode for hdmi output
Patch uses the best mode available on hdmi output and creates a private buffer that is used for pageflipping. Primary display content is copied to private buffer on each page flip. This patch removes current hack where same mode is assumed from hdmi output, this caused graphical artifacts with some tv's. Also some more debug output is added. Change-Id: Ic862a8374f46992f0ff92545da8a010f9684b934 Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
-rw-r--r--gralloc_drm_kms.c92
-rw-r--r--gralloc_drm_priv.h3
2 files changed, 71 insertions, 24 deletions
diff --git a/gralloc_drm_kms.c b/gralloc_drm_kms.c
index 7c7a903..0680bf0 100644
--- a/gralloc_drm_kms.c
+++ b/gralloc_drm_kms.c
@@ -207,11 +207,25 @@ static int drm_kms_page_flip(struct gralloc_drm_t *drm,
return 0;
pthread_mutex_lock(&drm->hdmi_mutex);
- if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED) {
- ret = drmModePageFlip(drm->fd, drm->hdmi.crtc_id, bo->fb_id, 0, NULL);
+ if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo) {
+
+ int dst_x1 = 0, dst_y1 = 0;
+
+ if (drm->hdmi.bo->handle->width > bo->handle->width)
+ dst_x1 = (drm->hdmi.bo->handle->width - bo->handle->width) / 2;
+ if (drm->hdmi.bo->handle->height > bo->handle->height)
+ dst_y1 = (drm->hdmi.bo->handle->height - bo->handle->height) / 2;
+
+ drm->drv->blit(drm->drv, drm->hdmi.bo, bo,
+ dst_x1, dst_y1,
+ dst_x1 + bo->handle->width,
+ dst_y1 + bo->handle->height,
+ 0, 0, bo->handle->width, bo->handle->height);
+
+ ret = drmModePageFlip(drm->fd, drm->hdmi.crtc_id, drm->hdmi.bo->fb_id, 0, NULL);
if (ret && errno != EBUSY)
ALOGE("failed to perform page flip for hdmi (%s) (crtc %d fb %d))",
- strerror(errno), drm->hdmi.crtc_id, bo->fb_id);
+ strerror(errno), drm->hdmi.crtc_id, drm->hdmi.bo->fb_id);
}
pthread_mutex_unlock(&drm->hdmi_mutex);
@@ -327,8 +341,8 @@ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)
}
pthread_mutex_lock(&drm->hdmi_mutex);
- if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED)
- drm_kms_set_crtc(drm, &drm->hdmi, bo->fb_id);
+ if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
+ drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
pthread_mutex_unlock(&drm->hdmi_mutex);
return ret;
@@ -368,8 +382,8 @@ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)
ret = drm_kms_set_crtc(drm, &drm->primary, bo->fb_id);
pthread_mutex_lock(&drm->hdmi_mutex);
- if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED)
- drm_kms_set_crtc(drm, &drm->hdmi, bo->fb_id);
+ if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
+ drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
pthread_mutex_unlock(&drm->hdmi_mutex);
drm->current_front = bo;
@@ -557,14 +571,16 @@ static int drm_kms_init_with_connector(struct gralloc_drm_t *drm,
if (i == drm->resources->count_crtcs)
return -EINVAL;
+ output->bo = NULL;
output->crtc_id = drm->resources->crtcs[i];
output->connector_id = connector->connector_id;
/* print connector info */
if (connector->count_modes > 1) {
- ALOGI("there are %d modes on connector 0x%x",
+ ALOGI("there are %d modes on connector 0x%x, type %d",
connector->count_modes,
- connector->connector_id);
+ connector->connector_id,
+ connector->connector_type);
for (i = 0; i < connector->count_modes; i++)
ALOGI(" %s", connector->modes[i].name);
}
@@ -636,6 +652,31 @@ static drmModeConnectorPtr fetch_connector(struct gralloc_drm_t *drm,
/*
+ * Initializes hdmi output with a connector and allocates
+ * a private framebuffer for it. This is called on startup if
+ * hdmi cable is connected and also on hotplug events.
+ */
+static void init_hdmi_output(struct gralloc_drm_t *drm,
+ drmModeConnectorPtr connector)
+{
+ drm_kms_init_with_connector(drm, &drm->hdmi, connector);
+
+ ALOGD("%s, allocate private buffer for hdmi [%dx%d]",
+ __func__, drm->hdmi.mode.hdisplay, drm->hdmi.mode.vdisplay);
+
+ drm->hdmi.bo = gralloc_drm_bo_create(drm,
+ drm->hdmi.mode.hdisplay, drm->hdmi.mode.vdisplay,
+ drm->hdmi.fb_format,
+ GRALLOC_USAGE_SW_WRITE_OFTEN|GRALLOC_USAGE_HW_RENDER);
+
+ gralloc_drm_bo_add_fb(drm->hdmi.bo);
+
+ drm->hdmi_mode = HDMI_CLONED;
+ drm->hdmi.active = 1;
+}
+
+
+/*
* Thread that listens to uevents and checks if hdmi state changes
*/
static void *hdmi_observer(void *data)
@@ -672,23 +713,25 @@ static void *hdmi_observer(void *data)
if (value) {
hdmi = fetch_connector(drm, DRM_MODE_CONNECTOR_HDMIA);
if (hdmi) {
- drm_kms_init_with_connector(drm, &drm->hdmi, hdmi);
- drmModeFreeConnector(hdmi);
+
+ ALOGD("init hdmi on hotplug event");
+ init_hdmi_output(drm, hdmi);
/* will trigger modeset */
drm->first_post = 1;
- /* HACK, assume same mode for now */
- memcpy(&drm->hdmi.mode, &drm->primary.mode,
- sizeof(drmModeModeInfo));
+ drmModeFreeConnector(hdmi);
- drm->hdmi_mode = HDMI_CLONED;
- drm->hdmi.active = 1;
pthread_mutex_unlock(&drm->hdmi_mutex);
}
break;
} else {
drm->hdmi.active = 0;
+
+ ALOGD("destroy hdmi private buffer");
+ gralloc_drm_bo_decref(drm->hdmi.bo);
+ drm->hdmi.bo = NULL;
+
pthread_mutex_unlock(&drm->hdmi_mutex);
break;
}
@@ -787,24 +830,21 @@ int gralloc_drm_init_kms(struct gralloc_drm_t *drm)
}
}
+
/* check if hdmi is connected already */
hdmi = fetch_connector(drm, DRM_MODE_CONNECTOR_HDMIA);
if (hdmi) {
if (hdmi->connector_id == drm->primary.connector_id) {
/* special case: our primary connector is hdmi */
+ ALOGD("hdmi is the primary connector");
goto skip_hdmi_modes;
}
- drm_kms_init_with_connector(drm, &drm->hdmi, hdmi);
- drmModeFreeConnector(hdmi);
-
- /* HACK, assume same mode for now */
- memcpy(&drm->hdmi.mode, &drm->primary.mode,
- sizeof(drmModeModeInfo));
+ ALOGD("init hdmi on startup");
+ init_hdmi_output(drm, hdmi);
- drm->hdmi_mode = HDMI_CLONED;
- drm->hdmi.active = 1;
+ drmModeFreeConnector(hdmi);
}
/* launch hdmi observer thread */
@@ -859,6 +899,10 @@ void gralloc_drm_fini_kms(struct gralloc_drm_t *drm)
drm->plane_resources = NULL;
}
+ /* destroy private buffer of hdmi output */
+ if (drm->hdmi.bo)
+ gralloc_drm_bo_decref(drm->hdmi.bo);
+
drm_singleton = NULL;
}
diff --git a/gralloc_drm_priv.h b/gralloc_drm_priv.h
index 0ab4ea5..eed433f 100644
--- a/gralloc_drm_priv.h
+++ b/gralloc_drm_priv.h
@@ -56,6 +56,9 @@ struct gralloc_drm_output
int fb_format;
int bpp;
uint32_t active;
+
+ /* 'private fb' for this output */
+ struct gralloc_drm_bo_t *bo;
};
struct gralloc_drm_t {