The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/videomode/pickmode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: pickmode.c,v 1.3 2011/04/09 18:22:31 jdc Exp $ */
    2 /* $FreeBSD$ */
    3 
    4 /*-
    5  * Copyright (c) 2006 The NetBSD Foundation
    6  * All rights reserved.
    7  *
    8  * this code was contributed to The NetBSD Foundation by Michael Lorenz
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS
   20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE NETBSD FOUNDATION BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   25  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */ 
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/libkern.h>
   37 #include <dev/videomode/videomode.h>
   38 #include "opt_videomode.h"
   39 
   40 #ifdef PICKMODE_DEBUG
   41 #define DPRINTF printf
   42 #else
   43 #define DPRINTF while (0) printf
   44 #endif
   45 
   46 const struct videomode *
   47 pick_mode_by_dotclock(int width, int height, int dotclock)
   48 {
   49         const struct videomode *this, *best = NULL;
   50         int i;
   51 
   52         DPRINTF("%s: looking for %d x %d at up to %d kHz\n", __func__, width,
   53             height, dotclock);
   54         for (i = 0; i < videomode_count; i++) {
   55                 this = &videomode_list[i];
   56                 if ((this->hdisplay != width) || (this->vdisplay != height) ||
   57                     (this->dot_clock > dotclock))
   58                         continue;
   59                 if (best != NULL) {
   60                         if (this->dot_clock > best->dot_clock)
   61                                 best = this;
   62                 } else
   63                         best = this;
   64         }
   65         if (best != NULL)
   66                 DPRINTF("found %s\n", best->name);
   67 
   68         return best;
   69 }
   70 
   71 const struct videomode *
   72 pick_mode_by_ref(int width, int height, int refresh)
   73 {
   74         const struct videomode *this, *best = NULL;
   75         int mref, closest = 1000, i, diff;
   76 
   77         DPRINTF("%s: looking for %d x %d at up to %d Hz\n", __func__, width,
   78             height, refresh);
   79         for (i = 0; i < videomode_count; i++) {
   80                 this = &videomode_list[i];
   81                 mref = this->dot_clock * 1000 / (this->htotal * this->vtotal);
   82                 diff = abs(mref - refresh);
   83                 if ((this->hdisplay != width) || (this->vdisplay != height))
   84                         continue;
   85                 DPRINTF("%s in %d hz, diff %d\n", this->name, mref, diff);
   86                 if (best != NULL) {
   87                         if (diff < closest) {
   88                                 best = this;
   89                                 closest = diff;
   90                         }
   91                 } else {
   92                         best = this;
   93                         closest = diff;
   94                 }
   95         }
   96         if (best != NULL)
   97                 DPRINTF("found %s %d\n", best->name, best->dot_clock);
   98 
   99         return best;
  100 }
  101 
  102 static inline void
  103 swap_modes(struct videomode *left, struct videomode *right)
  104 {
  105         struct videomode temp;
  106 
  107         temp = *left;
  108         *left = *right;
  109         *right = temp;
  110 }
  111 
  112 /*
  113  * Sort modes by refresh rate, aspect ratio (*), then resolution.
  114  * Preferred mode or largest mode is first in the list and other modes
  115  * are sorted on closest match to that mode.
  116  * (*) Note that the aspect ratio calculation treats "close" aspect ratios
  117  * (within 12.5%) as the same for this purpose.
  118  */
  119 #define DIVIDE(x, y)    (((x) + ((y) / 2)) / (y))
  120 void
  121 sort_modes(struct videomode *modes, struct videomode **preferred, int nmodes)
  122 {
  123         int aspect, refresh, hbest, vbest, abest, atemp, rbest, rtemp;
  124         int i, j;
  125         struct videomode *mtemp = NULL;
  126 
  127         if (nmodes < 2)
  128                 return;
  129 
  130         if (*preferred != NULL) {
  131                 /* Put the preferred mode first in the list */
  132                 aspect = (*preferred)->hdisplay * 100 / (*preferred)->vdisplay;
  133                 refresh = DIVIDE(DIVIDE((*preferred)->dot_clock * 1000,
  134                     (*preferred)->htotal), (*preferred)->vtotal);
  135                 if (*preferred != modes) {
  136                         swap_modes(*preferred, modes);
  137                         *preferred = modes;
  138                 }
  139         } else {
  140                 /*
  141                  * Find the largest horizontal and vertical mode and put that
  142                  * first in the list.  Preferred refresh rate is taken from
  143                  * the first mode of this size.
  144                  */
  145                 hbest = 0;
  146                 vbest = 0;
  147                 for (i = 0; i < nmodes; i++) {
  148                         if (modes[i].hdisplay > hbest) {
  149                                 hbest = modes[i].hdisplay;
  150                                 vbest = modes[i].vdisplay;
  151                                 mtemp = &modes[i];
  152                         } else if (modes[i].hdisplay == hbest &&
  153                             modes[i].vdisplay > vbest) {
  154                                 vbest = modes[i].vdisplay;
  155                                 mtemp = &modes[i];
  156                         }
  157                 }
  158                 aspect = mtemp->hdisplay * 100 / mtemp->vdisplay;
  159                 refresh = DIVIDE(DIVIDE(mtemp->dot_clock * 1000,
  160                     mtemp->htotal), mtemp->vtotal);
  161                 if (mtemp != modes)
  162                         swap_modes(mtemp, modes);
  163         }
  164 
  165         /* Sort other modes by refresh rate, aspect ratio, then resolution */
  166         for (j = 1; j < nmodes - 1; j++) {
  167                 rbest = 1000;
  168                 abest = 1000;
  169                 hbest = 0;
  170                 vbest = 0;
  171                 for (i = j; i < nmodes; i++) {
  172                         rtemp = abs(refresh -
  173                             DIVIDE(DIVIDE(modes[i].dot_clock * 1000,
  174                             modes[i].htotal), modes[i].vtotal));
  175                         atemp = (modes[i].hdisplay * 100 / modes[i].vdisplay);
  176                         if (rtemp < rbest) {
  177                                 rbest = rtemp;
  178                                 mtemp = &modes[i];
  179                         }
  180                         if (rtemp == rbest) {
  181                                 /* Treat "close" aspect ratios as identical */
  182                                 if (abs(abest - atemp) > (abest / 8) &&
  183                                     abs(aspect - atemp) < abs(aspect - abest)) {
  184                                         abest = atemp;
  185                                         mtemp = &modes[i];
  186                                 }
  187                                 if (atemp == abest ||
  188                                     abs(abest - atemp) <= (abest / 8)) {
  189                                         if (modes[i].hdisplay > hbest) {
  190                                                 hbest = modes[i].hdisplay;
  191                                                 mtemp = &modes[i];
  192                                         }
  193                                         if (modes[i].hdisplay == hbest &&
  194                                             modes[i].vdisplay > vbest) {
  195                                                 vbest = modes[i].vdisplay;
  196                                                 mtemp = &modes[i];
  197                                         }
  198                                 }
  199                         }
  200                 }
  201                 if (mtemp != &modes[j])
  202                         swap_modes(mtemp, &modes[j]);
  203         }
  204 }

Cache object: 00d2d08c057cef33e591c881d5fa6b0c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.