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