Skip to contentSkip to conversation

fbdev: make the best-fit section of fb_find_mode return the closest matching mode

PATCH In review Michal Januszewski 2 participants 3 messages Jan 27, 2008 – Feb 10, 2008 Framebuffer layer

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fbdev: make the best-fit section of fb_find_mode return the closest matching mode

From: Michal Januszewski <[email protected]>

Currently, if a perfect match in terms of resolution is not found, fb_find_mode() only looks for a best-fit mode among modes with a higher resolution than the one requested. Thus, if the user requests a resolution higher than the largest supported one, they are dropped to the default mode (usually a low resolution one).

Change this behaviour so that the true closest match in terms of the city-block metric is returned.

---

drivers/video/modedb.c +6 -6
index 08d0725..bc29ef3 100644
@@ -655,15 +655,15 @@ done:
 	best = -1;
 	DPRINTK("Trying best-fit modes\n");
 	for (i = 0; i < dbsize; i++) {
-	    if (xres <= db[i].xres && yres <= db[i].yres) {
 		DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
 		if (!fb_try_mode(var, info, &db[i], bpp)) {
-		    if (diff > (db[i].xres - xres) + (db[i].yres - yres)) {
-			diff = (db[i].xres - xres) + (db[i].yres - yres);
-			best = i;
-		    }
+			if (diff > abs(db[i].xres - xres) +
+				   abs(db[i].yres - yres)) {
+				diff = abs(db[i].xres - xres) +
+				       abs(db[i].yres - yres);
+				best = i;
+			}
 		}
-	    }
 	}
 	if (best != -1) {
 	    fb_try_mode(var, info, &db[best], bpp);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

#1 lore raw
Quoted 9 lines · On Sun, 27 Jan 2008 12:31:16 +0100 Michal Januszewski <[email protected]> wrote:

From: Michal Januszewski <[email protected]>

Currently, if a perfect match in terms of resolution is not found, fb_find_mode() only looks for a best-fit mode among modes with a higher resolution than the one requested. Thus, if the user requests a resolution higher than the largest supported one, they are dropped to the default mode (usually a low resolution one).

Quoted 3 lines

Change this behaviour so that the true closest match in terms of the city-block metric is returned.

This may be not ideal solution in case there exist both lower and higher matches. If given resolution is closer (even by few pixels) to lower one, your method will choose the lower one.
It may be incorrect for e.g. picture viewer (the higher resolution shows the whole picture with margins, the smaller one shows rescaled or cut picture).

IMHO, the choice of higher resolution (if possible) should be preferred. It is also closer to the old solution.

Kind regards,
Krzysztof

----------------------------------------------------------------------
Nadchodzi galaktyczna wojna!
Sprawdz >> http://link.interia.pl/f1ce0

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

#2 lore raw

PATCH 1/1 fbdev: make the best-fit section of fb_find_mode return the closest matching mode

From: Michal Januszewski <[email protected]>

Currently, if a perfect match in terms of resolution is not found, fb_find_mode() only looks for a best-fit mode among modes with a higher resolution than the one requested. Thus, if the user requests a resolution higher than the largest supported one, they are dropped to the default mode (usually a low resolution one).

Change this behaviour so that all valid video modes are considered when looking for a best-fit mode, while still preferring modes with a higher resolution.

---

drivers/video/modedb.c +16 -8
index 08d0725..0b6a45f 100644
@@ -522,7 +522,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
 	int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
 	unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
 	int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
-	u32 best, diff;
+	u32 best, diff, tdiff;
 
 	for (i = namelen-1; i >= 0; i--) {
 	    switch (name[i]) {
@@ -651,19 +651,27 @@ done:
 		return (refresh_specified) ? 2 : 1;
 	}
 
-	diff = xres + yres;
+	diff = 2 * (xres + yres);
 	best = -1;
 	DPRINTK("Trying best-fit modes\n");
 	for (i = 0; i < dbsize; i++) {
-	    if (xres <= db[i].xres && yres <= db[i].yres) {
 		DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
 		if (!fb_try_mode(var, info, &db[i], bpp)) {
-		    if (diff > (db[i].xres - xres) + (db[i].yres - yres)) {
-			diff = (db[i].xres - xres) + (db[i].yres - yres);
-			best = i;
-		    }
+			tdiff = abs(db[i].xres - xres) +
+				abs(db[i].yres - yres);
+
+			/*
+			 * Penalize modes with resolutions smaller
+			 * than requested.
+			 */
+			if (xres > db[i].xres || yres > db[i].yres)
+				tdiff += xres + yres;
+
+			if (diff > tdiff) {
+				diff = tdiff;
+				best = i;
+			}
 		}
-	    }
 	}
 	if (best != -1) {
 	    fb_try_mode(var, info, &db[best], bpp);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/