Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
  5.  * Copyright 2010 LunarG, Inc.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the
  10.  * "Software"), to deal in the Software without restriction, including
  11.  * without limitation the rights to use, copy, modify, merge, publish,
  12.  * distribute, sub license, and/or sell copies of the Software, and to
  13.  * permit persons to whom the Software is furnished to do so, subject to
  14.  * the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice (including the
  17.  * next paragraph) shall be included in all copies or substantial portions
  18.  * of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26.  * DEALINGS IN THE SOFTWARE.
  27.  *
  28.  **************************************************************************/
  29.  
  30.  
  31. #include <assert.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34.  
  35. #include "egldisplay.h"
  36. #include "eglmode.h"
  37. #include "eglcurrent.h"
  38. #include "eglscreen.h"
  39.  
  40.  
  41. #ifdef EGL_MESA_screen_surface
  42.  
  43.  
  44. #define MIN2(A, B)  (((A) < (B)) ? (A) : (B))
  45.  
  46.  
  47. /**
  48.  * Given an EGLModeMESA handle, return the corresponding _EGLMode object
  49.  * or null if non-existant.
  50.  */
  51. _EGLMode *
  52. _eglLookupMode(EGLModeMESA mode, _EGLDisplay *disp)
  53. {
  54.    EGLint scrnum;
  55.  
  56.    if (!disp || !disp->Screens)
  57.       return NULL;
  58.  
  59.    /* loop over all screens on the display */
  60.    for (scrnum = 0; scrnum < disp->Screens->Size; scrnum++) {
  61.       const _EGLScreen *scrn = disp->Screens->Elements[scrnum];
  62.       EGLint idx;
  63.  
  64.       /*
  65.        * the mode ids of a screen ranges from scrn->Handle to scrn->Handle +
  66.        * scrn->NumModes
  67.        */
  68.       if (mode >= scrn->Handle &&
  69.           mode < scrn->Handle + _EGL_SCREEN_MAX_MODES) {
  70.          idx = mode - scrn->Handle;
  71.  
  72.          assert(idx < scrn->NumModes && scrn->Modes[idx].Handle == mode);
  73.  
  74.          return &scrn->Modes[idx];
  75.       }
  76.    }
  77.  
  78.    return NULL;
  79. }
  80.  
  81.  
  82. /**
  83.  * Parse the attrib_list to fill in the fields of the given _eglMode
  84.  * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
  85.  */
  86. static EGLBoolean
  87. _eglParseModeAttribs(_EGLMode *mode, const EGLint *attrib_list)
  88. {
  89.    EGLint i;
  90.  
  91.    /* init all attribs to EGL_DONT_CARE */
  92.    mode->Handle = EGL_DONT_CARE;
  93.    mode->Width = EGL_DONT_CARE;
  94.    mode->Height = EGL_DONT_CARE;
  95.    mode->RefreshRate = EGL_DONT_CARE;
  96.    mode->Optimal = EGL_DONT_CARE;
  97.    mode->Interlaced = EGL_DONT_CARE;
  98.    mode->Name = NULL;
  99.  
  100.    for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
  101.       switch (attrib_list[i]) {
  102.       case EGL_MODE_ID_MESA:
  103.          mode->Handle = attrib_list[++i];
  104.          if (mode->Handle <= 0) {
  105.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(handle)");
  106.             return EGL_FALSE;
  107.          }
  108.          break;
  109.       case EGL_WIDTH:
  110.          mode->Width = attrib_list[++i];
  111.          if (mode->Width <= 0) {
  112.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(width)");
  113.             return EGL_FALSE;
  114.          }
  115.          break;
  116.       case EGL_HEIGHT:
  117.          mode->Height = attrib_list[++i];
  118.          if (mode->Height <= 0) {
  119.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(height)");
  120.             return EGL_FALSE;
  121.          }
  122.          break;
  123.       case EGL_REFRESH_RATE_MESA:
  124.          mode->RefreshRate = attrib_list[++i];
  125.          if (mode->RefreshRate <= 0) {
  126.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(refresh rate)");
  127.             return EGL_FALSE;
  128.          }
  129.          break;
  130.       case EGL_INTERLACED_MESA:
  131.          mode->Interlaced = attrib_list[++i];
  132.          if (mode->Interlaced != EGL_TRUE && mode->Interlaced != EGL_FALSE) {
  133.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(interlaced)");
  134.             return EGL_FALSE;
  135.          }
  136.          break;
  137.       case EGL_OPTIMAL_MESA:
  138.          mode->Optimal = attrib_list[++i];
  139.          if (mode->Optimal != EGL_TRUE && mode->Optimal != EGL_FALSE) {
  140.             _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(optimal)");
  141.             return EGL_FALSE;
  142.          }
  143.          break;
  144.       default:
  145.          _eglError(EGL_BAD_ATTRIBUTE, "eglChooseModeMESA");
  146.          return EGL_FALSE;
  147.       }
  148.    }
  149.    return EGL_TRUE;
  150. }
  151.  
  152.  
  153. /**
  154.  * Determine if the candidate mode's attributes are at least as good
  155.  * as the minimal mode's.
  156.  * \return EGL_TRUE if qualifies, EGL_FALSE otherwise
  157.  */
  158. static EGLBoolean
  159. _eglModeQualifies(const _EGLMode *c, const _EGLMode *min)
  160. {
  161.    if (min->Handle != EGL_DONT_CARE && c->Handle != min->Handle)
  162.       return EGL_FALSE;
  163.    if (min->Width != EGL_DONT_CARE && c->Width < min->Width)
  164.       return EGL_FALSE;
  165.    if (min->Height != EGL_DONT_CARE && c->Height < min->Height)
  166.       return EGL_FALSE;
  167.    if (min->RefreshRate != EGL_DONT_CARE && c->RefreshRate < min->RefreshRate)
  168.       return EGL_FALSE;
  169.    if (min->Optimal != EGL_DONT_CARE && c->Optimal != min->Optimal)
  170.       return EGL_FALSE;
  171.    if (min->Interlaced != EGL_DONT_CARE && c->Interlaced != min->Interlaced)
  172.       return EGL_FALSE;
  173.  
  174.    return EGL_TRUE;
  175. }
  176.  
  177.  
  178. /**
  179.  * Return value of given mode attribute, or -1 if bad attrib.
  180.  */
  181. static EGLint
  182. getModeAttrib(const _EGLMode *m, EGLint attrib)
  183. {
  184.    switch (attrib) {
  185.    case EGL_MODE_ID_MESA:
  186.       return m->Handle;
  187.    case EGL_WIDTH:
  188.       return m->Width;
  189.    case EGL_HEIGHT:
  190.       return m->Height;
  191.    case EGL_REFRESH_RATE_MESA:
  192.       return m->RefreshRate;
  193.    case EGL_OPTIMAL_MESA:
  194.       return m->Optimal;
  195.    case EGL_INTERLACED_MESA:
  196.       return m->Interlaced;
  197.    default:
  198.       return -1;
  199.    }
  200. }
  201.  
  202.  
  203. #define SMALLER 1
  204. #define LARGER  2
  205.  
  206. struct sort_info {
  207.    EGLint Attrib;
  208.    EGLint Order; /* SMALLER or LARGER */
  209. };
  210.  
  211. /* the order of these entries is the priority */
  212. static struct sort_info SortInfo[] = {
  213.    { EGL_OPTIMAL_MESA, LARGER },
  214.    { EGL_INTERLACED_MESA, SMALLER },
  215.    { EGL_WIDTH, LARGER },
  216.    { EGL_HEIGHT, LARGER },
  217.    { EGL_REFRESH_RATE_MESA, LARGER },
  218.    { EGL_MODE_ID_MESA, SMALLER },
  219.    { 0, 0 }
  220. };
  221.  
  222.  
  223. /**
  224.  * Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
  225.  * belongs after b, or 0 if they're equal.
  226.  * Used by qsort().
  227.  */
  228. static int
  229. _eglCompareModes(const void *a, const void *b)
  230. {
  231.    const _EGLMode *aMode = *((const _EGLMode **) a);
  232.    const _EGLMode *bMode = *((const _EGLMode **) b);
  233.    EGLint i;
  234.  
  235.    for (i = 0; SortInfo[i].Attrib; i++) {
  236.       const EGLint aVal = getModeAttrib(aMode, SortInfo[i].Attrib);
  237.       const EGLint bVal = getModeAttrib(bMode, SortInfo[i].Attrib);
  238.       if (aVal == bVal) {
  239.          /* a tie */
  240.          continue;
  241.       }
  242.       else if (SortInfo[i].Order == SMALLER) {
  243.          return (aVal < bVal) ? -1 : 1;
  244.       }
  245.       else if (SortInfo[i].Order == LARGER) {
  246.          return (aVal > bVal) ? -1 : 1;
  247.       }
  248.    }
  249.  
  250.    /* all attributes identical */
  251.    return 0;
  252. }
  253.  
  254.  
  255. /**
  256.  * Search for EGLModes which match the given attribute list.
  257.  * Called via eglChooseModeMESA API function.
  258.  */
  259. EGLBoolean
  260. _eglChooseModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
  261.                    const EGLint *attrib_list, EGLModeMESA *modes,
  262.                    EGLint modes_size, EGLint *num_modes)
  263. {
  264.    _EGLMode **modeList, min;
  265.    EGLint i, count;
  266.  
  267.    if (!_eglParseModeAttribs(&min, attrib_list)) {
  268.       /* error code will have been recorded */
  269.       return EGL_FALSE;
  270.    }
  271.  
  272.    /* allocate array of mode pointers */
  273.    modeList = malloc(modes_size * sizeof(_EGLMode *));
  274.    if (!modeList) {
  275.       _eglError(EGL_BAD_MODE_MESA, "eglChooseModeMESA(out of memory)");
  276.       return EGL_FALSE;
  277.    }
  278.  
  279.    /* make array of pointers to qualifying modes */
  280.    for (i = count = 0; i < scrn->NumModes && count < modes_size; i++) {
  281.       if (_eglModeQualifies(scrn->Modes + i, &min)) {
  282.          modeList[count++] = scrn->Modes + i;
  283.       }
  284.    }
  285.  
  286.    /* sort array of pointers */
  287.    qsort(modeList, count, sizeof(_EGLMode *), _eglCompareModes);
  288.  
  289.    /* copy mode handles to output array */
  290.    for (i = 0; i < count; i++) {
  291.       modes[i] = modeList[i]->Handle;
  292.    }
  293.  
  294.    free(modeList);
  295.  
  296.    *num_modes = count;
  297.  
  298.    return EGL_TRUE;
  299. }
  300.  
  301.  
  302.  
  303. /**
  304.  * Return all possible modes for the given screen.  No sorting of results.
  305.  * Called via eglGetModesMESA() API function.
  306.  */
  307. EGLBoolean
  308. _eglGetModesMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
  309.                  EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes)
  310. {
  311.    if (modes) {
  312.       EGLint i;
  313.       *num_modes = MIN2(scrn->NumModes, modes_size);
  314.       for (i = 0; i < *num_modes; i++) {
  315.          modes[i] = scrn->Modes[i].Handle;
  316.       }
  317.    }
  318.    else {
  319.       /* just return total number of supported modes */
  320.       *num_modes = scrn->NumModes;
  321.    }
  322.  
  323.    return EGL_TRUE;
  324. }
  325.  
  326.  
  327. /**
  328.  * Query an attribute of a mode.
  329.  */
  330. EGLBoolean
  331. _eglGetModeAttribMESA(_EGLDriver *drv, _EGLDisplay *dpy,
  332.                       _EGLMode *m, EGLint attribute, EGLint *value)
  333. {
  334.    EGLint v;
  335.  
  336.    v = getModeAttrib(m, attribute);
  337.    if (v < 0) {
  338.       _eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttribMESA");
  339.       return EGL_FALSE;
  340.    }
  341.    *value = v;
  342.    return EGL_TRUE;
  343. }
  344.  
  345.  
  346. /**
  347.  * Return human-readable string for given mode.
  348.  * This is the default function called by eglQueryModeStringMESA().
  349.  */
  350. const char *
  351. _eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m)
  352. {
  353.    return m->Name;
  354. }
  355.  
  356.  
  357. #endif /* EGL_MESA_screen_surface */
  358.