diff options
author | Ma Jian <majian@jidemail.com> | 2016-06-17 11:51:07 +0800 |
---|---|---|
committer | Chih-Wei Huang <cwhuang@linux.org.tw> | 2016-06-27 19:55:33 +0800 |
commit | 7c9a5244690da7f5ab282475a31c0dfb17aa9880 (patch) | |
tree | bf5666079c6323f646b8eb67b2b8197be74c4fd8 | |
parent | 9b6333c0470a43e4a94ab3d94e0b4cf4558fd9ef (diff) | |
download | external_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.c | 59 |
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); |