Merge "Remove invalid call to detach rbo from default fbo" into nyc-dev
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglChooseConfigReference.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Choose config reference implementation.
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglChooseConfigReference.hpp"
25
26 #include "egluUtil.hpp"
27 #include "egluConfigInfo.hpp"
28 #include "egluStrUtil.hpp"
29 #include "eglwLibrary.hpp"
30 #include "eglwEnums.hpp"
31
32 #include <algorithm>
33 #include <vector>
34 #include <map>
35
36 namespace deqp
37 {
38 namespace egl
39 {
40
41 using namespace eglw;
42 using eglu::ConfigInfo;
43
44 enum Criteria
45 {
46         CRITERIA_AT_LEAST = 0,
47         CRITERIA_EXACT,
48         CRITERIA_MASK,
49         CRITERIA_SPECIAL,
50
51         CRITERIA_LAST
52 };
53
54 enum SortOrder
55 {
56         SORTORDER_NONE  = 0,
57         SORTORDER_SMALLER,
58         SORTORDER_SPECIAL,
59
60         SORTORDER_LAST
61 };
62
63 struct AttribRule
64 {
65         EGLenum         name;
66         EGLint          value;
67         Criteria        criteria;
68         SortOrder       sortOrder;
69
70         AttribRule (void)
71                 : name                  (EGL_NONE)
72                 , value                 (EGL_NONE)
73                 , criteria              (CRITERIA_LAST)
74                 , sortOrder             (SORTORDER_LAST)
75         {
76         }
77
78         AttribRule (EGLenum name_, EGLint value_, Criteria criteria_, SortOrder sortOrder_)
79                 : name                  (name_)
80                 , value                 (value_)
81                 , criteria              (criteria_)
82                 , sortOrder             (sortOrder_)
83         {
84         }
85 };
86
87 class SurfaceConfig
88 {
89 private:
90         static int getCaveatRank (EGLenum caveat)
91         {
92                 switch (caveat)
93                 {
94                         case EGL_NONE:                                  return 0;
95                         case EGL_SLOW_CONFIG:                   return 1;
96                         case EGL_NON_CONFORMANT_CONFIG: return 2;
97                         default:
98                                 TCU_THROW(TestError, (std::string("Unknown config caveat: ") + eglu::getConfigCaveatStr(caveat).toString()).c_str());
99                 }
100         }
101
102         static int getColorBufferTypeRank (EGLenum type)
103         {
104                 switch (type)
105                 {
106                         case EGL_RGB_BUFFER:                    return 0;
107                         case EGL_LUMINANCE_BUFFER:              return 1;
108                         case EGL_YUV_BUFFER_EXT:                return 2;
109                         default:
110                                 TCU_THROW(TestError, (std::string("Unknown color buffer type: ") + eglu::getColorBufferTypeStr(type).toString()).c_str());
111                 }
112         }
113
114         typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);
115
116         static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
117         {
118                 return getCaveatRank((EGLenum)a.m_info.configCaveat) < getCaveatRank((EGLenum)b.m_info.configCaveat);
119         }
120
121         static bool compareColorBufferType (const SurfaceConfig& a, const SurfaceConfig& b)
122         {
123                 return getColorBufferTypeRank((EGLenum)a.m_info.colorBufferType) < getColorBufferTypeRank((EGLenum)b.m_info.colorBufferType);
124         }
125
126         static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
127         {
128                 DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
129                 switch (a.m_info.colorBufferType)
130                 {
131                         case EGL_RGB_BUFFER:
132                         {
133                                 const tcu::IVec4        mask    (specifiedRGBColors.cast<deInt32>());
134
135                                 return (a.m_info.redSize * mask[0] + a.m_info.greenSize * mask[1] + a.m_info.blueSize * mask[2] + a.m_info.alphaSize * mask[3])
136                                                 > (b.m_info.redSize * mask[0] + b.m_info.greenSize * mask[1] + b.m_info.blueSize * mask[2] + b.m_info.alphaSize * mask[3]);
137                         }
138
139                         case EGL_LUMINANCE_BUFFER:
140                         {
141                                 const tcu::IVec2        mask    (specifiedLuminanceColors.cast<deInt32>());
142
143                                 return (a.m_info.luminanceSize * mask[0] + a.m_info.alphaSize * mask[1]) > (b.m_info.luminanceSize * mask[0] + b.m_info.alphaSize * mask[1]);
144                         }
145
146                         case EGL_YUV_BUFFER_EXT:
147                                 // \todo [mika 2015-05-05] Sort YUV configs correctly. Currently all YUV configs are non-conformant and ordering can be relaxed.
148                                 return true;
149
150                         default:
151                                 DE_ASSERT(DE_FALSE);
152                                 return true;
153                 }
154         }
155
156         template <EGLenum Attribute>
157         static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b)
158         {
159                 return a.getAttribute(Attribute) < b.getAttribute(Attribute);
160         }
161 public:
162         SurfaceConfig (EGLConfig config, ConfigInfo &info)
163                 : m_config(config)
164                 , m_info(info)
165         {
166         }
167
168         EGLConfig getEglConfig (void) const
169         {
170                 return m_config;
171         }
172
173         EGLint getAttribute (const EGLenum attribute) const
174         {
175                 return m_info.getAttribute(attribute);
176         }
177
178         friend bool operator== (const SurfaceConfig& a, const SurfaceConfig& b)
179         {
180                 for (std::map<EGLenum, AttribRule>::const_iterator iter = SurfaceConfig::defaultRules.begin(); iter != SurfaceConfig::defaultRules.end(); iter++)
181                 {
182                         const EGLenum attribute = iter->first;
183
184                         if (a.getAttribute(attribute) != b.getAttribute(attribute)) return false;
185                 }
186                 return true;
187         }
188
189         bool compareTo (const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors) const
190         {
191                 static const SurfaceConfig::CompareFunc compareFuncs[] =
192                 {
193                         SurfaceConfig::compareCaveat,
194                         SurfaceConfig::compareColorBufferType,
195                         DE_NULL, // SurfaceConfig::compareColorBufferBits,
196                         SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
197                         SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
198                         SurfaceConfig::compareAttributeSmaller<EGL_SAMPLES>,
199                         SurfaceConfig::compareAttributeSmaller<EGL_DEPTH_SIZE>,
200                         SurfaceConfig::compareAttributeSmaller<EGL_STENCIL_SIZE>,
201                         SurfaceConfig::compareAttributeSmaller<EGL_ALPHA_MASK_SIZE>,
202                         SurfaceConfig::compareAttributeSmaller<EGL_CONFIG_ID>
203                 };
204
205                 if (*this == b)
206                         return false; // std::sort() can compare object to itself.
207
208                 for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(compareFuncs); ndx++)
209                 {
210                         if (!compareFuncs[ndx])
211                         {
212                                 if (compareColorBufferBits(*this, b, specifiedRGBColors, specifiedLuminanceColors))
213                                         return true;
214                                 else if (compareColorBufferBits(b, *this, specifiedRGBColors, specifiedLuminanceColors))
215                                         return false;
216
217                                 continue;
218                         }
219
220                         if (compareFuncs[ndx](*this, b))
221                                 return true;
222                         else if (compareFuncs[ndx](b, *this))
223                                 return false;
224                 }
225
226                 TCU_FAIL("Unable to compare configs - duplicate ID?");
227         }
228
229         static const std::map<EGLenum, AttribRule> defaultRules;
230
231         static std::map<EGLenum, AttribRule> initAttribRules (void)
232         {
233                 // \todo [2011-03-24 pyry] From EGL 1.4 spec - check that this is valid for other versions as well
234                 std::map<EGLenum, AttribRule> rules;
235
236                 //                                                                      Attribute                                                                       Default                         Selection Criteria      Sort Order                      Sort Priority
237                 rules[EGL_BUFFER_SIZE]                          = AttribRule(EGL_BUFFER_SIZE,                           0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      4
238                 rules[EGL_RED_SIZE]                                     = AttribRule(EGL_RED_SIZE,                                      0,                                      CRITERIA_AT_LEAST,      SORTORDER_SPECIAL);     //      3
239                 rules[EGL_GREEN_SIZE]                           = AttribRule(EGL_GREEN_SIZE,                            0,                                      CRITERIA_AT_LEAST,      SORTORDER_SPECIAL);     //      3
240                 rules[EGL_BLUE_SIZE]                            = AttribRule(EGL_BLUE_SIZE,                                     0,                                      CRITERIA_AT_LEAST,      SORTORDER_SPECIAL);     //      3
241                 rules[EGL_LUMINANCE_SIZE]                       = AttribRule(EGL_LUMINANCE_SIZE,                        0,                                      CRITERIA_AT_LEAST,      SORTORDER_SPECIAL);     //      3
242                 rules[EGL_ALPHA_SIZE]                           = AttribRule(EGL_ALPHA_SIZE,                            0,                                      CRITERIA_AT_LEAST,      SORTORDER_SPECIAL);     //      3
243                 rules[EGL_ALPHA_MASK_SIZE]                      = AttribRule(EGL_ALPHA_MASK_SIZE,                       0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      9
244                 rules[EGL_BIND_TO_TEXTURE_RGB]          = AttribRule(EGL_BIND_TO_TEXTURE_RGB,           EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
245                 rules[EGL_BIND_TO_TEXTURE_RGBA]         = AttribRule(EGL_BIND_TO_TEXTURE_RGBA,          EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
246                 rules[EGL_COLOR_BUFFER_TYPE]            = AttribRule(EGL_COLOR_BUFFER_TYPE,                     EGL_RGB_BUFFER,         CRITERIA_EXACT,         SORTORDER_NONE);        //      2
247                 rules[EGL_CONFIG_CAVEAT]                        = AttribRule(EGL_CONFIG_CAVEAT,                         EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_SPECIAL);     //      1
248                 rules[EGL_CONFIG_ID]                            = AttribRule(EGL_CONFIG_ID,                                     EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_SMALLER);     //      11
249                 rules[EGL_CONFORMANT]                           = AttribRule(EGL_CONFORMANT,                            0,                                      CRITERIA_MASK,          SORTORDER_NONE);
250                 rules[EGL_DEPTH_SIZE]                           = AttribRule(EGL_DEPTH_SIZE,                            0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      7
251                 rules[EGL_LEVEL]                                        = AttribRule(EGL_LEVEL,                                         0,                                      CRITERIA_EXACT,         SORTORDER_NONE);
252                 rules[EGL_MAX_SWAP_INTERVAL]            = AttribRule(EGL_MAX_SWAP_INTERVAL,                     EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
253                 rules[EGL_MIN_SWAP_INTERVAL]            = AttribRule(EGL_MIN_SWAP_INTERVAL,                     EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
254                 rules[EGL_NATIVE_RENDERABLE]            = AttribRule(EGL_NATIVE_RENDERABLE,                     EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
255                 rules[EGL_NATIVE_VISUAL_TYPE]           = AttribRule(EGL_NATIVE_VISUAL_TYPE,            EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_SPECIAL);     //      10
256                 rules[EGL_RENDERABLE_TYPE]                      = AttribRule(EGL_RENDERABLE_TYPE,                       EGL_OPENGL_ES_BIT,      CRITERIA_MASK,          SORTORDER_NONE);
257                 rules[EGL_SAMPLE_BUFFERS]                       = AttribRule(EGL_SAMPLE_BUFFERS,                        0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      5
258                 rules[EGL_SAMPLES]                                      = AttribRule(EGL_SAMPLES,                                       0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      6
259                 rules[EGL_STENCIL_SIZE]                         = AttribRule(EGL_STENCIL_SIZE,                          0,                                      CRITERIA_AT_LEAST,      SORTORDER_SMALLER);     //      8
260                 rules[EGL_SURFACE_TYPE]                         = AttribRule(EGL_SURFACE_TYPE,                          EGL_WINDOW_BIT,         CRITERIA_MASK,          SORTORDER_NONE);
261                 rules[EGL_TRANSPARENT_TYPE]                     = AttribRule(EGL_TRANSPARENT_TYPE,                      EGL_NONE,                       CRITERIA_EXACT,         SORTORDER_NONE);
262                 rules[EGL_TRANSPARENT_RED_VALUE]        = AttribRule(EGL_TRANSPARENT_RED_VALUE,         EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
263                 rules[EGL_TRANSPARENT_GREEN_VALUE]      = AttribRule(EGL_TRANSPARENT_GREEN_VALUE,       EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
264                 rules[EGL_TRANSPARENT_BLUE_VALUE]       = AttribRule(EGL_TRANSPARENT_BLUE_VALUE,        EGL_DONT_CARE,          CRITERIA_EXACT,         SORTORDER_NONE);
265
266                 return rules;
267         }
268 private:
269         EGLConfig m_config;
270         ConfigInfo m_info;
271 };
272
273 const std::map<EGLenum, AttribRule> SurfaceConfig::defaultRules = SurfaceConfig::initAttribRules();
274
275 class CompareConfigs
276 {
277 public:
278         CompareConfigs (const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
279                 : m_specifiedRGBColors                  (specifiedRGBColors)
280                 , m_specifiedLuminanceColors    (specifiedLuminanceColors)
281         {
282         }
283
284         bool operator() (const SurfaceConfig& a, const SurfaceConfig& b)
285         {
286                 return a.compareTo(b, m_specifiedRGBColors, m_specifiedLuminanceColors);
287         }
288
289 private:
290         const tcu::BVec4        m_specifiedRGBColors;
291         const tcu::BVec2        m_specifiedLuminanceColors;
292 };
293
294 class ConfigFilter
295 {
296 private:
297         std::map<EGLenum, AttribRule> m_rules;
298 public:
299         ConfigFilter ()
300                 : m_rules(SurfaceConfig::defaultRules)
301         {
302         }
303
304         void setValue (EGLenum name, EGLint value)
305         {
306                 DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
307                 m_rules[name].value = value;
308         }
309
310         void setValues (std::vector<std::pair<EGLenum, EGLint> > values)
311         {
312                 for (size_t ndx = 0; ndx < values.size(); ndx++)
313                 {
314                         const EGLenum   name    = values[ndx].first;
315                         const EGLint    value   = values[ndx].second;
316
317                         setValue(name, value);
318                 }
319         }
320
321         AttribRule getAttribute (EGLenum name)
322         {
323                 DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
324                 return m_rules[name];
325         }
326
327         bool isMatch (const SurfaceConfig& config)
328         {
329                 for (std::map<EGLenum, AttribRule>::const_iterator iter = m_rules.begin(); iter != m_rules.end(); iter++)
330                 {
331                         const AttribRule rule = iter->second;
332
333                         if (rule.value == EGL_DONT_CARE)
334                                 continue;
335                         else if (rule.name == EGL_MATCH_NATIVE_PIXMAP)
336                                 TCU_CHECK(rule.value == EGL_NONE); // Not supported
337                         else if (rule.name == EGL_TRANSPARENT_RED_VALUE || rule.name == EGL_TRANSPARENT_GREEN_VALUE || rule.name == EGL_TRANSPARENT_BLUE_VALUE)
338                                 continue;
339                         else
340                         {
341                                 const EGLint cfgValue = config.getAttribute(rule.name);
342
343                                 switch (rule.criteria)
344                                 {
345                                         case CRITERIA_EXACT:
346                                                 if (rule.value != cfgValue)
347                                                         return false;
348                                                 break;
349
350                                         case CRITERIA_AT_LEAST:
351                                                 if (rule.value > cfgValue)
352                                                         return false;
353                                                 break;
354
355                                         case CRITERIA_MASK:
356                                                 if ((rule.value & cfgValue) != rule.value)
357                                                         return false;
358                                                 break;
359
360                                         default:
361                                                 TCU_FAIL("Unknown criteria");
362                                 }
363                         }
364                 }
365
366                 return true;
367         }
368
369         tcu::BVec4 getSpecifiedRGBColors (void)
370         {
371                 const EGLenum bitAttribs[] =
372                 {
373                         EGL_RED_SIZE,
374                         EGL_GREEN_SIZE,
375                         EGL_BLUE_SIZE,
376                         EGL_ALPHA_SIZE
377                 };
378
379                 tcu::BVec4 result;
380
381                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
382                 {
383                         const EGLenum   attrib  = bitAttribs[ndx];
384                         const EGLint    value   = getAttribute(attrib).value;
385
386                         if (value != 0 && value != EGL_DONT_CARE)
387                                 result[ndx] = true;
388                         else
389                                 result[ndx] = false;
390                 }
391
392                 return result;
393         }
394
395         tcu::BVec2 getSpecifiedLuminanceColors (void)
396         {
397                 const EGLenum bitAttribs[] =
398                 {
399                         EGL_LUMINANCE_SIZE,
400                         EGL_ALPHA_SIZE
401                 };
402
403                 tcu::BVec2 result;
404
405                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
406                 {
407                         const EGLenum   attrib  = bitAttribs[ndx];
408                         const EGLint    value   = getAttribute(attrib).value;
409
410                         if (value != 0 && value != EGL_DONT_CARE)
411                                 result[ndx] = true;
412                         else
413                                 result[ndx] = false;
414                 }
415
416                 return result;
417         }
418
419         std::vector<SurfaceConfig> filter (const std::vector<SurfaceConfig>& configs)
420         {
421                 std::vector<SurfaceConfig> out;
422
423                 for (std::vector<SurfaceConfig>::const_iterator iter = configs.begin(); iter != configs.end(); iter++)
424                 {
425                         if (isMatch(*iter)) out.push_back(*iter);
426                 }
427
428                 return out;
429         }
430 };
431
432 void chooseConfigReference (const Library& egl, EGLDisplay display, std::vector<EGLConfig>& dst, const std::vector<std::pair<EGLenum, EGLint> >& attributes)
433 {
434         // Get all configs
435         std::vector<EGLConfig> eglConfigs = eglu::getConfigs(egl, display);
436
437         // Config infos
438         std::vector<ConfigInfo> configInfos;
439         configInfos.resize(eglConfigs.size());
440         for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
441                 eglu::queryConfigInfo(egl, display, eglConfigs[ndx], &configInfos[ndx]);
442
443         // Pair configs with info
444         std::vector<SurfaceConfig> configs;
445         for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
446                 configs.push_back(SurfaceConfig(eglConfigs[ndx], configInfos[ndx]));
447
448         // Filter configs
449         ConfigFilter configFilter;
450         configFilter.setValues(attributes);
451
452         std::vector<SurfaceConfig> filteredConfigs = configFilter.filter(configs);
453
454         // Sort configs
455         std::sort(filteredConfigs.begin(), filteredConfigs.end(), CompareConfigs(configFilter.getSpecifiedRGBColors(), configFilter.getSpecifiedLuminanceColors()));
456
457         // Write to dst list
458         dst.resize(filteredConfigs.size());
459         for (size_t ndx = 0; ndx < filteredConfigs.size(); ndx++)
460                 dst[ndx] = filteredConfigs[ndx].getEglConfig();
461 }
462
463 } // egl
464 } // deqp