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