summaryrefslogtreecommitdiffstats
path: root/hwc
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-09-14 18:24:18 -0500
committerErik Gilling <konkers@android.com>2011-09-21 14:07:46 -0700
commit834b8ba01376239a2f286a3766c14bdeeb166498 (patch)
tree561c4b0fe3b183fcca9fd467a6b1f36147296f94 /hwc
parentde312ecd147a97473f050456e457aa50881c1724 (diff)
downloadhardware_ti_omap4xxx-834b8ba01376239a2f286a3766c14bdeeb166498.tar.gz
hardware_ti_omap4xxx-834b8ba01376239a2f286a3766c14bdeeb166498.tar.bz2
hardware_ti_omap4xxx-834b8ba01376239a2f286a3766c14bdeeb166498.zip
hwc: unify HDMI docking and cloning
If we have a surface with external display usage marked, switch to docking (clone only that surface to HDMI). Once the surface goes away, switch back to cloning. Also change docking mode support: Select dockable surface based on the usage bit instead of the color format. For multiple such surfaces, pick the one with the largest display area. Change meaning of hwc_dev->ext transform bits for docking mode. These are applied purely to the surface buffer, instead of as an additional transform on the surface displayed on LCD. In other words, the surface displayed on HDMI is independent of the UI orientation. Change-Id: Ic6895ba0ff275ca374eb72d0fa7d93a634111d1a
Diffstat (limited to 'hwc')
-rw-r--r--hwc/hwc.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/hwc/hwc.c b/hwc/hwc.c
index f01b3dc..c326a57 100644
--- a/hwc/hwc.c
+++ b/hwc/hwc.c
@@ -102,6 +102,8 @@ struct omap4_hwc_device {
int flags_rgb_order;
int flags_nv12_only;
int ext;
+ int ext_requested;
+ int ext_last;
};
typedef struct omap4_hwc_device omap4_hwc_device_t;
@@ -199,6 +201,13 @@ static int sync_id = 0;
#define is_BGR(format) ((format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888)
#define is_NV12(format) ((format) == HAL_PIXEL_FORMAT_TI_NV12 || (format) == HAL_PIXEL_FORMAT_TI_NV12_PADDED)
+static int dockable(hwc_layer_t *layer)
+{
+ IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
+
+ return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP);
+}
+
static unsigned int mem1d(IMG_native_handle_t *handle)
{
if (handle == NULL)
@@ -567,6 +576,7 @@ struct counts {
unsigned int RGB;
unsigned int BGR;
unsigned int NV12;
+ unsigned int dockable;
unsigned int displays;
unsigned int max_hw_overlays;
unsigned int max_scaling_overlays;
@@ -577,7 +587,6 @@ static inline int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts
{
int tv = hwc_dev->ext & EXT_TV;
int nonscaling_ovls = NUM_NONSCALING_OVERLAYS;
- int tform = hwc_dev->ext & EXT_TRANSFORM;
num->max_hw_overlays = MAX_HW_OVERLAYS;
/*
@@ -585,12 +594,14 @@ static inline int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts
* have to be disabled, and the disabling has to take effect on the current display.
* We keep track of the available number of overlays here.
*/
- if (hwc_dev->ext & EXT_DOCK) {
+ if ((hwc_dev->ext & EXT_DOCK) || (hwc_dev->ext && num->dockable)) {
/* some overlays may already be used by the external display, so we account for this */
/* reserve just a video pipeline for HDMI if docking */
- hwc_dev->ext_ovls = num->NV12 ? 1 : 0;
+ hwc_dev->ext_ovls = num->dockable ? 1 : 0;
num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls);
+ hwc_dev->ext &= ~EXT_TRANSFORM;
+ hwc_dev->ext |= EXT_DOCK;
} else if (hwc_dev->ext) {
/*
* otherwise, manage just from half the pipelines. NOTE: there is
@@ -603,6 +614,7 @@ static inline int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts
num->max_hw_overlays -= hwc_dev->last_ext_ovls;
hwc_dev->ext_ovls = 0;
}
+ int tform = hwc_dev->ext & EXT_TRANSFORM;
/*
* :TRICKY: We may not have enough overlays on the external display. We "reserve" them
@@ -652,6 +664,11 @@ static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev,
!(tform && !is_NV12(handle->iFormat));
}
+static inline int display_area(struct dss2_ovl_info *o)
+{
+ return o->cfg.win.w * o->cfg.win.h;
+}
+
static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list)
{
omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
@@ -660,6 +677,7 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t*
unsigned int i;
pthread_mutex_lock(&hwc_dev->lock);
+ hwc_dev->ext = hwc_dev->ext_requested;
memset(dsscomp, 0x0, sizeof(*dsscomp));
dsscomp->sync_id = sync_id++;
@@ -684,6 +702,9 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t*
else if (is_NV12(handle->iFormat))
num.NV12++;
+ if (dockable(layer))
+ num.dockable++;
+
num.mem += mem1d(handle);
}
}
@@ -713,7 +734,7 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t*
int z = 0;
int fb_z = -1;
int scaled_gfx = 0;
- int ix_nv12 = -1;
+ int ix_docking = -1;
/* set up if DSS layers */
unsigned int mem_used = 0;
@@ -754,9 +775,11 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t*
scaled_gfx = 0;
}
- /* remember first NV12 layer */
- if (is_NV12(handle->iFormat) && ix_nv12 < 0)
- ix_nv12 = dsscomp->num_ovls;
+ /* remember largest dockable layer */
+ if (dockable(layer) &&
+ (ix_docking < 0 ||
+ display_area(dsscomp->ovls + dsscomp->num_ovls) > display_area(dsscomp->ovls + ix_docking)))
+ ix_docking = dsscomp->num_ovls;
dsscomp->num_ovls++;
z++;
@@ -812,35 +835,45 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t*
if (hwc_dev->ext && hwc_dev->ext_ovls) {
int ix_back, ix_front, ix;
if (hwc_dev->ext & EXT_DOCK) {
- /* mirror only NV12 layer */
- ix_back = ix_front = ix_nv12;
+ /* mirror only 1 external layer */
+ ix_back = ix_front = ix_docking;
} else {
/* mirror all layers */
ix_back = 0;
ix_front = dsscomp->num_ovls - 1;
+
+ /* reset mode if we are coming from docking */
+ if (hwc_dev->ext != hwc_dev->ext_last)
+ set_ext_matrix(hwc_dev, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height);
}
- for (ix = ix_back; ix >= 0 && ix <= ix_front; ix++) {
- memcpy(dsscomp->ovls + dsscomp->num_ovls, dsscomp->ovls + ix, sizeof(dsscomp->ovls[ix]));
- dsscomp->ovls[dsscomp->num_ovls].cfg.zorder += hwc_dev->post2_layers;
+ for (ix = ix_back; hwc_dev->ext && ix >= 0 && ix <= ix_front; ix++) {
+ struct dss2_ovl_info *o = dsscomp->ovls + dsscomp->num_ovls;
+ memcpy(o, dsscomp->ovls + ix, sizeof(dsscomp->ovls[ix]));
+ o->cfg.zorder += hwc_dev->post2_layers;
/* reserve overlays at end for other display */
- dsscomp->ovls[dsscomp->num_ovls].cfg.ix = MAX_HW_OVERLAYS - 1 - (ix - ix_back);
- dsscomp->ovls[dsscomp->num_ovls].cfg.mgr_ix = 1;
- dsscomp->ovls[dsscomp->num_ovls].ba = ix;
+ o->cfg.ix = MAX_HW_OVERLAYS - 1 - (ix - ix_back);
+ o->cfg.mgr_ix = 1;
+ o->ba = ix;
if (hwc_dev->ext & EXT_DOCK) {
/* full screen video */
- dsscomp->ovls[dsscomp->num_ovls].cfg.win.x = 0;
- dsscomp->ovls[dsscomp->num_ovls].cfg.win.y = 0;
- set_ext_matrix(hwc_dev, dsscomp->ovls[dsscomp->num_ovls].cfg.win.w,
- dsscomp->ovls[dsscomp->num_ovls].cfg.win.h);
+ o->cfg.win.x = 0;
+ o->cfg.win.y = 0;
+ o->cfg.win.w = o->cfg.crop.w;
+ o->cfg.win.h = o->cfg.crop.h;
+ o->cfg.rotation = 0;
+ o->cfg.mirror = 0;
+
+ set_ext_matrix(hwc_dev, o->cfg.win.w, o->cfg.win.h);
}
- omap4_hwc_adjust_ext_layer(hwc_dev, dsscomp->ovls + dsscomp->num_ovls);
+ omap4_hwc_adjust_ext_layer(hwc_dev, o);
dsscomp->num_ovls++;
z++;
}
}
+ hwc_dev->ext_last = hwc_dev->ext;
if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS)
LOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls);
@@ -1170,6 +1203,9 @@ static void handle_hotplug(omap4_hwc_device_t *hwc_dev, int state)
(hwc_dev->ext & EXT_HFLIP) ? "+hflip" : "");
pthread_mutex_unlock(&hwc_dev->lock);
+ hwc_dev->ext_requested = hwc_dev->ext;
+ hwc_dev->ext_last = hwc_dev->ext;
+
if (hwc_dev->procs && hwc_dev->procs->invalidate) {
hwc_dev->procs->invalidate(hwc_dev->procs);
usleep(30000);