summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMa Jian <majian@jidemail.com>2016-06-17 11:51:07 +0800
committerChih-Wei Huang <cwhuang@linux.org.tw>2016-06-27 19:55:33 +0800
commit7c9a5244690da7f5ab282475a31c0dfb17aa9880 (patch)
treebf5666079c6323f646b8eb67b2b8197be74c4fd8
parent9b6333c0470a43e4a94ab3d94e0b4cf4558fd9ef (diff)
downloadexternal_drm_gralloc-7c9a5244690da7f5ab282475a31c0dfb17aa9880.zip
external_drm_gralloc-7c9a5244690da7f5ab282475a31c0dfb17aa9880.tar.gz
external_drm_gralloc-7c9a5244690da7f5ab282475a31c0dfb17aa9880.tar.bz2
Best fit the external display
NO_REF_TASK tested: 1) set persist.remixos.disp_best_fit to true 2) plugin the HDMI, the resolution should be the one fit the primary screen (i.e. the resolution should be larger than or equal to primery resolution, and it is the closest one) 3) set persist.remixos.disp_best_fit to false 4) plugin HDMI again, the external display will use the default resolution. Change-Id: I80b0fe6e7cc676ce1915f07f267204734bfc645f
-rw-r--r--gralloc_drm_kms.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/gralloc_drm_kms.c b/gralloc_drm_kms.c
index 6bd4add..6cefd6f 100644
--- a/gralloc_drm_kms.c
+++ b/gralloc_drm_kms.c
@@ -838,13 +838,41 @@ static drmModeModeInfoPtr generate_mode(int h_pixels, int v_lines, float freq)
return (m);
}
-static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
+static int mode_distance_best_fit(
+ int xres_base,
+ int yres_base,
+ int xres,
+ int yres,
+ double prefered_aspect)
+{
+ const double eps = 0.3;
+
+ if (xres_base > xres || yres_base > yres) {
+ // if the res cannot cover base res, return max int
+ return INT_MAX;
+ } else if (fabs((double) xres / yres - prefered_aspect) > eps) {
+ // if the aspect is too different with prefered_aspect, return max int
+ return INT_MAX;
+ } else {
+ return (xres - xres_base) * (xres - xres_base) +
+ (yres - yres_base) * (yres - yres_base) +
+ ((xres / yres) - prefered_aspect) * ((xres / yres) - prefered_aspect);
+ }
+}
+
+static int mode_distance_closest(int xres_base, int yres_base, int xres, int yres) {
+ return (xres - xres_base) * (xres - xres_base) +
+ (yres - yres_base) * (yres - yres_base);
+}
+
+static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp, drmModeModeInfoPtr primary_mode)
{
char value[PROPERTY_VALUE_MAX];
drmModeModeInfoPtr mode;
int dist, i;
int xres = 0, yres = 0, rate = 0;
int forcemode = 0;
+ int bestfit = 0;
if (property_get("debug.drm.mode", value, NULL)) {
char *p = value, *end;
@@ -875,6 +903,12 @@ static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
ALOGI("will use %dx%d@%dHz", xres, yres, rate);
forcemode = 1;
}
+ } else if (primary_mode != NULL) {
+ xres = primary_mode->hdisplay;
+ yres = primary_mode->vdisplay;
+ *bpp = 0;
+ bestfit = 1;
+ ALOGI("will find the best fit for %dx%d", xres, yres);
} else {
*bpp = 0;
}
@@ -890,8 +924,16 @@ static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
int tmp;
if (xres && yres) {
- tmp = (m->hdisplay - xres) * (m->hdisplay - xres) +
- (m->vdisplay - yres) * (m->vdisplay - yres);
+ if (bestfit) {
+ tmp = mode_distance_best_fit(
+ xres,
+ yres,
+ m->hdisplay,
+ m->vdisplay,
+ (double) connector->modes[0].hdisplay / connector->modes[0].vdisplay);
+ } else {
+ tmp = mode_distance_closest(xres, yres, m->hdisplay, m->vdisplay);
+ }
}
else {
/* use the first preferred mode */
@@ -921,6 +963,8 @@ static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
return mode;
}
+static int used_crtcs = 0;
+
/*
* Initialize KMS with a connector.
*/
@@ -929,7 +973,6 @@ static int drm_kms_init_with_connector(struct gralloc_drm_t *drm,
{
drmModeEncoderPtr encoder;
drmModeModeInfoPtr mode;
- static int used_crtcs = 0;
int bpp, i;
if (!connector->count_modes)
@@ -972,7 +1015,11 @@ static int drm_kms_init_with_connector(struct gralloc_drm_t *drm,
connector->modes[0].name);
}
- mode = find_mode(connector, &bpp);
+ if (property_get_bool("persist.remixos.disp_best_fit", 1) && output != &drm->primary) {
+ mode = find_mode(connector, &bpp, &drm->primary.mode);
+ } else {
+ mode = find_mode(connector, &bpp, NULL);
+ }
ALOGI("the best mode is %s", mode->name);
@@ -1109,6 +1156,7 @@ static void *hdmi_observer(void *data)
}
} else {
drm->hdmi.active = 0;
+ used_crtcs &= ~(1 << drm->hdmi.pipe);
ALOGD("destroy hdmi private buffer");
gralloc_drm_bo_decref(drm->hdmi.bo);
@@ -1132,6 +1180,7 @@ static void *hdmi_observer(void *data)
drm->first_post = 1;
} else if (!hdmi && drm->hdmi.active) {
drm->hdmi.active = 0;
+ used_crtcs &= ~(1 << drm->hdmi.pipe);
ALOGD("destroy hdmi private buffer");
gralloc_drm_bo_decref(drm->hdmi.bo);