• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
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 glcMisc.cpp
21  * \brief Miscellaneous helper functions.
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "glcMisc.hpp"
25 #include "gluDefs.hpp"
26 #include "glw.h"
27 
28 using namespace glw;
29 
30 namespace glcts
31 {
32 
33 /* utility functions from the book OpenGL ES 2.0 Programming Guide */
34 /* -15 stored using a single precision bias of 127 */
35 const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
36 /* max exponent value in single precision that will be converted */
37 /* to Inf or Nan when stored as a half-float */
38 const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
39 /* 255 is the max exponent biased value */
40 const unsigned int FLOAT_MAX_BIASED_EXP      = (0xFF << 23);
41 const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
42 
floatToHalfFloat(float f)43 GLhalf floatToHalfFloat(float f)
44 {
45     union
46     {
47         float v;
48         unsigned int x;
49     };
50     v                 = f;
51     unsigned int sign = (GLhalf)(x >> 31);
52     unsigned int mantissa;
53     unsigned int exp;
54     GLhalf hf;
55 
56     /* get mantissa */
57     mantissa = x & ((1 << 23) - 1);
58     /* get exponent bits */
59     exp = x & FLOAT_MAX_BIASED_EXP;
60     if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
61     {
62         /* check if the original single precision float number is a NaN */
63         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
64         {
65             /* we have a single precision NaN */
66             mantissa = (1 << 23) - 1;
67         }
68         else
69         {
70             /* 16-bit half-float representation stores number as Inf */
71             mantissa = 0;
72         }
73         hf = (((GLhalf)sign) << 15) | (GLhalf)(HALF_FLOAT_MAX_BIASED_EXP) | (GLhalf)(mantissa >> 13);
74     }
75     /* check if exponent is <= -15 */
76     else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
77     {
78         /* store a denorm half-float value or zero */
79         exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
80         mantissa |= (1 << 23);
81 
82         if (exp < 18)
83             mantissa >>= (14 + exp);
84         else
85             mantissa = 0;
86 
87         hf = (((GLhalf)sign) << 15) | (GLhalf)(mantissa);
88     }
89     else
90     {
91         hf = (((GLhalf)sign) << 15) | (GLhalf)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
92              (GLhalf)(mantissa >> 13);
93     }
94 
95     return hf;
96 }
97 
98 /* -15 stored using a single precision bias of 127 */
99 const unsigned int FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
100 /* max exponent value in single precision that will be converted */
101 /* to Inf or Nan when stored as a half-float */
102 const unsigned int FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
103 const unsigned int FLOAT11_MAX_BIASED_EXP                  = (0x1F << 6);
104 
floatToUnisgnedF11(float f)105 GLuint floatToUnisgnedF11(float f)
106 {
107     union
108     {
109         float v;
110         unsigned int x;
111     };
112     v                 = f;
113     unsigned int sign = (GLhalf)(x >> 31);
114     unsigned int mantissa;
115     unsigned int exp;
116     GLuint f11;
117 
118     /* get mantissa */
119     mantissa = x & ((1 << 23) - 1);
120     /* get exponent bits */
121     exp = x & FLOAT_MAX_BIASED_EXP;
122 
123     /* minus f32 value */
124     if (sign > 0)
125     {
126         /* f32 NaN -> f11 NaN */
127         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
128         {
129             f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(0x0000003F);
130         }
131         /* Others round to 0.0 */
132         else
133         {
134             f11 = 0x00000000;
135         }
136 
137         return f11;
138     }
139 
140     /* only check positive value below */
141     if (exp >= FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
142     {
143         /* check if the original single precision float number is a NaN */
144         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
145         {
146             /* we have a single precision NaN */
147             mantissa = (1 << 23) - 1;
148         }
149         else
150         {
151             /* 11-bit float representation stores number as Inf */
152             mantissa = 0;
153         }
154         f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(mantissa >> 17);
155     }
156     /* check if exponent is <= -15 */
157     else if (exp <= FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
158     {
159         /* store a denorm 11-bit float value or zero */
160         exp = (FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
161         mantissa |= (1 << 23);
162         if (18 + exp >= sizeof(mantissa) * 8)
163         {
164             mantissa = 0;
165         }
166         else
167         {
168             mantissa >>= (18 + exp);
169         }
170         f11 = mantissa;
171     }
172     else
173     {
174         f11 = ((exp - FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 17) | (mantissa >> 17);
175     }
176 
177     return f11;
178 }
179 
180 /* -15 stored using a single precision bias of 127 */
181 const unsigned int FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
182 /* max exponent value in single precision that will be converted */
183 /* to Inf or Nan when stored as a half-float */
184 const unsigned int FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
185 const unsigned int FLOAT10_MAX_BIASED_EXP                  = (0x1F << 5);
186 
floatToUnisgnedF10(float f)187 GLuint floatToUnisgnedF10(float f)
188 {
189     union
190     {
191         float v;
192         unsigned int x;
193     };
194     v                 = f;
195     unsigned int sign = (GLhalf)(x >> 31);
196     unsigned int mantissa;
197     unsigned int exp;
198     GLuint f10;
199 
200     /* get mantissa */
201     mantissa = x & ((1 << 23) - 1);
202     /* get exponent bits */
203     exp = x & FLOAT_MAX_BIASED_EXP;
204 
205     /* minus f32 value */
206     if (sign > 0)
207     {
208         /* f32 NaN -> f10 NaN */
209         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
210         {
211             f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(0x0000001F);
212         }
213         /* Others round to 0.0 */
214         else
215         {
216             f10 = 0x00000000;
217         }
218 
219         return f10;
220     }
221 
222     /* only check positive value below */
223     if (exp >= FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
224     {
225         /* check if the original single precision float number is a NaN */
226         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
227         {
228             /* we have a single precision NaN */
229             mantissa = (1 << 23) - 1;
230         }
231         else
232         {
233             /* 10-bit float representation stores number as Inf */
234             mantissa = 0;
235         }
236         f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(mantissa >> 18);
237     }
238     /* check if exponent is <= -15 */
239     else if (exp <= FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
240     {
241         /* store a denorm 11-bit float value or zero */
242         exp = (FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
243         mantissa |= (1 << 23);
244         if (19 + exp >= sizeof(mantissa) * 8)
245         {
246             mantissa = 0;
247         }
248         else
249         {
250             mantissa >>= (19 + exp);
251         }
252         f10 = mantissa;
253     }
254     else
255     {
256         f10 = ((exp - FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 18) | (mantissa >> 18);
257     }
258 
259     return f10;
260 }
261 
halfFloatToFloat(GLhalf hf)262 float halfFloatToFloat(GLhalf hf)
263 {
264     unsigned int sign     = (unsigned int)(hf >> 15);
265     unsigned int mantissa = (unsigned int)(hf & ((1 << 10) - 1));
266     unsigned int exp      = (unsigned int)(hf & HALF_FLOAT_MAX_BIASED_EXP);
267     union
268     {
269         float f;
270         unsigned int ui;
271     };
272 
273     if (exp == HALF_FLOAT_MAX_BIASED_EXP)
274     {
275         /* we have a half-float NaN or Inf */
276         /* half-float NaNs will be converted to a single precision NaN */
277         /* half-float Infs will be converted to a single precision Inf */
278         exp = FLOAT_MAX_BIASED_EXP;
279         if (mantissa)
280             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
281     }
282     else if (exp == 0x0)
283     {
284         /* convert half-float zero/denorm to single precision value */
285         if (mantissa)
286         {
287             mantissa <<= 1;
288             exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
289             /* check for leading 1 in denorm mantissa */
290             while ((mantissa & (1 << 10)) == 0)
291             {
292                 /* for every leading 0, decrement single precision exponent by 1 */
293                 /* and shift half-float mantissa value to the left */
294                 mantissa <<= 1;
295                 exp -= (1 << 23);
296             }
297             /* clamp the mantissa to 10-bits */
298             mantissa &= ((1 << 10) - 1);
299             /* shift left to generate single-precision mantissa of 23-bits */
300             mantissa <<= 13;
301         }
302     }
303     else
304     {
305         /* shift left to generate single-precision mantissa of 23-bits */
306         mantissa <<= 13;
307         /* generate single precision biased exponent value */
308         exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
309     }
310     ui = (sign << 31) | exp | mantissa;
311     return f;
312 }
313 
unsignedF11ToFloat(GLuint f11)314 float unsignedF11ToFloat(GLuint f11)
315 {
316     unsigned int mantissa = (unsigned int)(f11 & ((1 << 6) - 1));
317     unsigned int exp      = (unsigned int)(f11 & FLOAT11_MAX_BIASED_EXP);
318     union
319     {
320         float f;
321         unsigned int ui;
322     };
323 
324     if (exp == FLOAT11_MAX_BIASED_EXP)
325     {
326         /* we have a f11 NaN or Inf */
327         /* f11 NaNs will be converted to a single precision NaN */
328         /* f11 Infs will be converted to a single precision Inf */
329         exp = FLOAT_MAX_BIASED_EXP;
330         if (mantissa)
331             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
332     }
333     else if (exp == 0x0)
334     {
335         /* convert f11 zero/denorm to single precision value */
336         if (mantissa)
337         {
338             mantissa <<= 1;
339             exp = FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
340             /* check for leading 1 in denorm mantissa */
341             while ((mantissa & (1 << 10)) == 0)
342             {
343                 /* for every leading 0, decrement single precision exponent by 1 */
344                 /* and shift half-float mantissa value to the left */
345                 mantissa <<= 1;
346                 exp -= (1 << 23);
347             }
348             /* clamp the mantissa to 6-bits */
349             mantissa &= ((1 << 6) - 1);
350             /* shift left to generate single-precision mantissa of 23-bits */
351             mantissa <<= 17;
352         }
353     }
354     else
355     {
356         /* shift left to generate single-precision mantissa of 23-bits */
357         mantissa <<= 17;
358         /* generate single precision biased exponent value */
359         exp = (exp << 17) + FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
360     }
361     ui = exp | mantissa;
362     return f;
363 }
364 
unsignedF10ToFloat(GLuint f10)365 float unsignedF10ToFloat(GLuint f10)
366 {
367     unsigned int mantissa = (unsigned int)(f10 & ((1 << 5) - 1));
368     unsigned int exp      = (unsigned int)(f10 & FLOAT10_MAX_BIASED_EXP);
369     union
370     {
371         float f;
372         unsigned int ui;
373     };
374 
375     if (exp == FLOAT10_MAX_BIASED_EXP)
376     {
377         /* we have a f11 NaN or Inf */
378         /* f11 NaNs will be converted to a single precision NaN */
379         /* f11 Infs will be converted to a single precision Inf */
380         exp = FLOAT_MAX_BIASED_EXP;
381         if (mantissa)
382             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
383     }
384     else if (exp == 0x0)
385     {
386         /* convert f11 zero/denorm to single precision value */
387         if (mantissa)
388         {
389             mantissa <<= 1;
390             exp = FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
391             /* check for leading 1 in denorm mantissa */
392             while ((mantissa & (1 << 10)) == 0)
393             {
394                 /* for every leading 0, decrement single precision exponent by 1 */
395                 /* and shift half-float mantissa value to the left */
396                 mantissa <<= 1;
397                 exp -= (1 << 23);
398             }
399             /* clamp the mantissa to 5-bits */
400             mantissa &= ((1 << 5) - 1);
401             /* shift left to generate single-precision mantissa of 23-bits */
402             mantissa <<= 18;
403         }
404     }
405     else
406     {
407         /* shift left to generate single-precision mantissa of 23-bits */
408         mantissa <<= 18;
409         /* generate single precision biased exponent value */
410         exp = (exp << 18) + FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
411     }
412     ui = exp | mantissa;
413     return f;
414 }
415 
getBits(const glw::Functions & gl,bool isContextES,GLenum target,GLenum bits,GLint * value)416 bool getBits(const glw::Functions &gl, bool isContextES, GLenum target, GLenum bits, GLint *value)
417 {
418     if (!isContextES)
419     {
420         GLint colorAttachment    = 0;
421         GLenum depthAttachment   = GL_DEPTH;
422         GLenum stencilAttachment = GL_STENCIL;
423         GLint fbo                = 0;
424         if (target == GL_READ_FRAMEBUFFER)
425         {
426             gl.getIntegerv(GL_READ_FRAMEBUFFER_BINDING, &fbo);
427             GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
428         }
429         else
430         {
431             gl.getIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
432             GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
433         }
434 
435         if (fbo)
436         {
437             depthAttachment   = GL_DEPTH_ATTACHMENT;
438             stencilAttachment = GL_STENCIL_ATTACHMENT;
439         }
440         if (target == GL_READ_FRAMEBUFFER)
441         {
442             gl.getIntegerv(GL_READ_BUFFER, &colorAttachment);
443             GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
444         }
445         else
446         {
447             gl.getIntegerv(GL_DRAW_BUFFER, &colorAttachment);
448             GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
449         }
450 
451         if (colorAttachment == GL_BACK)
452             colorAttachment = GL_BACK_LEFT;
453         else if (colorAttachment == GL_FRONT)
454             colorAttachment = GL_FRONT_LEFT;
455 
456         switch (bits)
457         {
458         case GL_RED_BITS:
459             gl.getFramebufferAttachmentParameteriv(target, colorAttachment, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, value);
460             GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
461             break;
462         case GL_GREEN_BITS:
463             gl.getFramebufferAttachmentParameteriv(target, colorAttachment, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
464                                                    value);
465             GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
466             break;
467         case GL_BLUE_BITS:
468             gl.getFramebufferAttachmentParameteriv(target, colorAttachment, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, value);
469             GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
470             break;
471         case GL_ALPHA_BITS:
472             gl.getFramebufferAttachmentParameteriv(target, colorAttachment, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
473                                                    value);
474             GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
475             break;
476         case GL_DEPTH_BITS:
477         case GL_STENCIL_BITS:
478             /*
479              * OPENGL SPECS 4.5: Paragraph  9.2. BINDING AND MANAGING FRAMEBUFFER OBJECTS p.335
480              * If the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE, then either no framebuffer is bound to target;
481              * or a default framebuffer is queried, attachment is GL_DEPTH or GL_STENCIL,
482              * and the number of depth or stencil bits, respectively, is zero....
483              * and all other queries will generate an INVALID_OPERATION error.
484              * */
485             if (fbo == 0)
486             { //default framebuffer
487                 gl.getFramebufferAttachmentParameteriv(target, (bits == GL_DEPTH_BITS ? GL_DEPTH : GL_STENCIL),
488                                                        GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, value);
489                 GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
490                 if (*value == GL_NONE)
491                 {
492                     *value = 0;
493                     break;
494                 }
495             }
496             switch (bits)
497             {
498             case GL_DEPTH_BITS:
499                 gl.getFramebufferAttachmentParameteriv(target, depthAttachment, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
500                                                        value);
501                 GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
502                 break;
503             case GL_STENCIL_BITS:
504                 gl.getFramebufferAttachmentParameteriv(target, stencilAttachment,
505                                                        GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, value);
506                 GLU_EXPECT_NO_ERROR(gl.getError(), "getFramebufferAttachmentParameteriv");
507                 break;
508             }
509             break;
510         default:
511             gl.getIntegerv(bits, value);
512             GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
513             break;
514         }
515     }
516     else
517     {
518         gl.getIntegerv(bits, value);
519         GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
520     }
521     return true;
522 }
523 
getReadbufferBits(const glw::Functions & gl,bool isContextES,GLenum bits,GLint * value)524 bool getReadbufferBits(const glw::Functions &gl, bool isContextES, GLenum bits, GLint *value)
525 {
526     return getBits(gl, isContextES, GL_READ_FRAMEBUFFER, bits, value);
527 }
528 
getDrawbufferBits(const glw::Functions & gl,bool isContextES,GLenum bits,GLint * value)529 bool getDrawbufferBits(const glw::Functions &gl, bool isContextES, GLenum bits, GLint *value)
530 {
531     return getBits(gl, isContextES, GL_DRAW_FRAMEBUFFER, bits, value);
532 }
533 
534 } // namespace glcts
535