• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    EXT_texture_shared_exponent
4
5Name Strings
6
7    GL_EXT_texture_shared_exponent
8
9Contact
10
11    Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)
12
13Contributors
14
15    Pat Brown, NVIDIA
16    Jon Leech
17    Bruce Merry, ARM
18
19Status
20
21    Shipping
22
23Version
24
25    Date: July 18, 2008
26    Revision: 1.0
27
28Number
29
30    333
31
32Dependencies
33
34    OpenGL 1.1 required
35
36    ARB_color_buffer_float affects this extension.
37
38    EXT_framebuffer_object affects this extension.
39
40    This extension is written against the OpenGL 2.0 (September 7,
41    2004) specification.
42
43Overview
44
45    Existing texture formats provide either fixed-point formats with
46    limited range and precision but with compact encodings (allowing 32
47    or fewer bits per multi-component texel), or floating-point formats
48    with tremendous range and precision but without compact encodings
49    (typically 16 or 32 bits per component).
50
51    This extension adds a new packed format and new internal texture
52    format for encoding 3-component vectors (typically RGB colors) with
53    a single 5-bit exponent (biased up by 15) and three 9-bit mantissas
54    for each respective component.  There is no sign bit so all three
55    components must be non-negative.  The fractional mantissas are
56    stored without an implied 1 to the left of the decimal point.
57    Neither infinity nor not-a-number (NaN) are representable in this
58    shared exponent format.
59
60    This 32 bits/texel shared exponent format is particularly well-suited
61    to high dynamic range (HDR) applications where light intensity is
62    typically stored as non-negative red, green, and blue components
63    with considerable range.
64
65New Procedures and Functions
66
67    None
68
69New Tokens
70
71    Accepted by the <internalformat> parameter of TexImage1D,
72    TexImage2D, TexImage3D, CopyTexImage1D, CopyTexImage2D, and
73    RenderbufferStorageEXT:
74
75        RGB9_E5_EXT                                    0x8C3D
76
77    Accepted by the <type> parameter of DrawPixels, ReadPixels,
78    TexImage1D, TexImage2D, GetTexImage, TexImage3D, TexSubImage1D,
79    TexSubImage2D, TexSubImage3D, GetHistogram, GetMinmax,
80    ConvolutionFilter1D, ConvolutionFilter2D, ConvolutionFilter3D,
81    GetConvolutionFilter, SeparableFilter2D, GetSeparableFilter,
82    ColorTable, ColorSubTable, and GetColorTable:
83
84        UNSIGNED_INT_5_9_9_9_REV_EXT                  0x8C3E
85
86    Accepted by the <pname> parameter of GetTexLevelParameterfv and
87    GetTexLevelParameteriv:
88
89        TEXTURE_SHARED_SIZE_EXT                        0x8C3F
90
91Additions to Chapter 2 of the 2.0 Specification (OpenGL Operation)
92
93    None
94
95Additions to Chapter 3 of the 2.0 Specification (Rasterization)
96
97 -- Section 3.6.4, Rasterization of Pixel Rectangles
98
99    Add a new row to Table 3.5 (page 128):
100
101        type Parameter                 Corresponding  Special
102        Token Name                     GL Data Type   Interpretation
103        -----------------------------  -------------  --------------
104        UNSIGNED_INT_5_9_9_9_REV_EXT   uint           yes
105
106    Add a new row to table 3.8: Packed pixel formats (page 132):
107
108        type Parameter                 GL Data  Number of   Matching
109        Token Name                     Type     Components  Pixel Formats
110        -----------------------------  -------  ----------  -------------
111        UNSIGNED_INT_5_9_9_9_REV_EXT   uint     4           RGB
112
113    Add a new entry to table 3.11: UNSIGNED_INT formats (page 134):
114
115        UNSIGNED_INT_5_9_9_9_REV_EXT:
116
117        31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
118        +-------------+--------------------------+---------------------------+--------------------------+
119        |  4th        |          3rd             |        2nd                |           1st            |
120        +-------------+--------------------------+---------------------------+--------------------------+
121
122    Add to the end of the 2nd paragraph starting "Pixels are draw using":
123
124    "If type is UNSIGNED_INT_5_9_9_9_REV_EXT and format is not RGB then
125    the error INVALID_ENUM occurs."
126
127    Add UNSIGNED_INT_5_9_9_9_REV_EXT to the list of packed formats in
128    the 10th paragraph after the "Packing" subsection (page 130).
129
130    Add before the 3rd paragraph (page 135, starting "Calling DrawPixels
131    with a type of BITMAP...") from the end of the "Packing" subsection:
132
133    "Calling DrawPixels with a type of UNSIGNED_INT_5_9_9_9_REV_EXT and
134    format of RGB is a special case in which the data are a series of GL
135    uint values.  Each uint value specifies 4 packed components as shown
136    in table 3.11.  The 1st, 2nd, 3rd, and 4th components are called
137    p_red, p_green, p_blue, and p_exp respectively and are treated as
138    unsigned integers.  These are then used to compute floating-point
139    RGB components (ignoring the "Conversion to floating-point" section
140    below in this case) as follows:
141
142       red   = p_red   * 2^(p_exp - B - N)
143       green = p_green * 2^(p_exp - B - N)
144       blue  = p_blue  * 2^(p_exp - B - N)
145
146    where B is 15 (the exponent bias) and N is 9 (the number of mantissa
147    bits)."
148
149 -- Section 3.8.1, Texture Image Specification:
150
151    "Alternatively if the internalformat is RGB9_E5_EXT, the red, green,
152    and blue bits are converted to a shared exponent format according
153    to the following procedure:
154
155    Components red, green, and blue are first clamped (in the process,
156    mapping NaN to zero) so:
157
158        red_c   = max(0, min(sharedexp_max, red))
159        green_c = max(0, min(sharedexp_max, green))
160        blue_c  = max(0, min(sharedexp_max, blue))
161
162    where sharedexp_max is (2^N-1)/2^N * 2^(Emax-B), N is the number
163    of mantissa bits per component, Emax is the maximum allowed biased
164    exponent value (careful: not necessarily 2^E-1 when E is the number of
165    exponent bits), bits, and B is the exponent bias.  For the RGB9_E5_EXT
166    format, N=9, Emax=31, and B=15.
167
168    The largest clamped component, max_c, is determined:
169
170        max_c = max(red_c, green_c, blue_c)
171
172    A preliminary shared exponent is computed:
173
174        exp_shared_p = max(-B-1, floor(log2(max_c))) + 1 + B
175
176    A refined shared exponent is then computed as:
177
178        max_s   = floor(max_c   / 2^(exp_shared_p - B - N) + 0.5)
179
180                     { exp_shared_p,    0 <= max_s <  2^N
181        exp_shared = {
182                     { exp_shared_p+1,       max_s == 2^N
183
184    These integers values in the range 0 to 2^N-1 are then computed:
185
186        red_s   = floor(red_c   / 2^(exp_shared - B - N) + 0.5)
187        green_s = floor(green_c / 2^(exp_shared - B - N) + 0.5)
188        blue_s  = floor(blue_c  / 2^(exp_shared - B - N) + 0.5)
189
190    Then red_s, green_s, and blue_s are stored along with exp_shared in
191    the red, green, blue, and shared bits respectively of the texture
192    image.
193
194    An implementation accepting pixel data of type
195    UNSIGNED_INT_5_9_9_9_REV_EXT with a format of RGB is allowed to store
196    the components "as is" if the implementation can determine the current
197    pixel transfer state act as an identity transform on the components."
198
199    Add a new row and the "shared bits" column (blank for all existing
200    rows) to Table 3.16 (page 154).
201
202        Sized                  Base             R     G     B     A     L     I     D     shared
203        Internal Format        Internal Format  bits  bits  bits  bits  bits  bits  bits  bits
204        ---------------------  ---------------  ----  ----  ----  ----  ----  ----  ----  ------
205        RGB9_E5_EXT            RGB              9     9     9                             5
206
207 -- Section 3.8.x, Shared Exponent Texture Color Conversion
208
209    Insert this section AFTER section 3.8.14 Texture Comparison Modes
210    and BEFORE section 3.8.15 Texture Application (and after the "sRGB
211    Texture Color Conversion" if EXT_texture_sRGB is supported).
212
213    "If the currently bound texture's internal format is RGB9_E5_EXT, the
214    red, green, blue, and shared bits are converted to color components
215    (prior to filtering) using the following shared exponent decoding.
216
217    The components red_s, green_s, blue_s, and exp_shared values (see
218    section 3.8.1) are treated as unsigned integers and are converted
219    to red, green, blue as follows:
220
221       red   = red_s   * 2^(exp_shared - B)
222       green = green_s * 2^(exp_shared - B)
223       blue  = blue_s  * 2^(exp_shared - B)"
224
225Additions to Chapter 4 of the 2.0 Specification (Per-Fragment Operations
226and the Frame Buffer)
227
228 -- Section 4.3.2, Reading Pixels
229
230    Add a row to table 4.7 (page 224);
231
232                                                 Component
233    type Parameter                 GL Data Type  Conversion Formula
234    -----------------------------  ------------  ------------------
235    UNSIGNED_INT_5_9_9_9_REV_EXT   uint          special
236
237    Replace second paragraph of "Final Conversion" (page 222) to read:
238
239    For an RGBA color, if <type> is not FLOAT or
240    UNSIGNED_INT_5_9_9_9_REV_EXT, or if the CLAMP_READ_COLOR_ARB is
241    TRUE, or CLAMP_READ_COLOR_ARB is FIXED_ONLY_ARB and the selected
242    color (or texture) buffer is a fixed-point buffer, each component
243    is first clamped to [0,1].  Then the appropriate conversion formula
244    from table 4.7 is applied the component.
245
246    In the special case when calling ReadPixels with a type of
247    UNSIGNED_INT_5_9_9_9_REV_EXT and format of RGB, the conversion
248    is done as follows:  The returned data are packed into a series of
249    GL uint values. The red, green, and blue components are converted
250    to red_s, green_s, blue_s, and exp_shared integers as described in
251    section 3.8.1 when the internalformat is RGB9_E5_EXT.  The red_s,
252    green_s, blue_s, and exp_shared are then packed as the 1st, 2nd,
253    3rd, and 4th components of the UNSIGNED_INT_5_9_9_9_REV_EXT format
254    as shown in table 3.11."
255
256Additions to Chapter 5 of the 2.0 Specification (Special Functions)
257
258    None
259
260Additions to Chapter 6 of the 2.0 Specification (State and State Requests)
261
262 -- Section 6.1.3, Enumerated Queries
263
264    Add TEXTURE_SHARED_SIZE_EXT to the list of queries in the first
265    sentence of the fifth paragraph (page 247) so it reads:
266
267    "For texture images with uncompressed internal formats, queries of
268    value of TEXTURE_RED_SIZE, TEXTURE_GREEN_SIZE, TEXTURE_BLUE_SIZE,
269    TEXTURE_ALPHA_SIZE, TEXTURE_LUMINANCE_SIZE, TEXTURE_DEPTH_SIZE,
270    TEXTURE_SHARED_SIZE_EXTT, and TEXTURE_INTENSITY_SIZE return the
271    actual resolutions of the stored image array components, not the
272    resolutions specified when the image array was defined."
273
274Additions to the OpenGL Shading Language specification
275
276    None
277
278Additions to the GLX Specification
279
280    None
281
282GLX Protocol
283
284    None.
285
286Dependencies on ARB_color_buffer_float
287
288    If ARB_color_buffer_float is not supported, replace this amended
289    sentence from 4.3.2 above
290
291    "For an RGBA color, if <type> is not FLOAT or
292    UNSIGNED_INT_5_9_9_9_REV_EXT, or if the CLAMP_READ_COLOR_ARB is TRUE, or
293    CLAMP_READ_COLOR_ARB is FIXED_ONLY_ARB and the selected color buffer
294    (or texture image for GetTexImage) is a fixed-point buffer (or texture
295    image for GetTexImage), each component is first clamped to [0,1]."
296
297    with
298
299    "For an RGBA color, if <type> is not FLOAT or
300    UNSIGNED_INT_5_9_9_9_REV_EXT and the selected color buffer (or
301    texture image for GetTexImage) is a fixed-point buffer (or texture
302    image for GetTexImage), each component is first clamped to [0,1]."
303
304Dependencies on EXT_framebuffer_object
305
306    If EXT_framebuffer_object is not supported, then
307    RenderbufferStorageEXT is not supported and the RGB9_E5_EXT
308    internalformat is therefore not supported by RenderbufferStorageEXT.
309
310Errors
311
312    Relaxation of INVALID_ENUM errors
313    ---------------------------------
314
315    TexImage1D, TexImage2D, TexImage3D, CopyTexImage1D, CopyTexImage2D,
316    and RenderbufferStorageEXT accept the new RGB9_E5_EXT token for
317    internalformat.
318
319    DrawPixels, ReadPixels, TexImage1D, TexImage2D, GetTexImage,
320    TexImage3D, TexSubImage1D, TexSubImage2D, TexSubImage3D,
321    GetHistogram, GetMinmax, ConvolutionFilter1D, ConvolutionFilter2D,
322    ConvolutionFilter3D, GetConvolutionFilter, SeparableFilter2D,
323    GetSeparableFilter, ColorTable, ColorSubTable, and GetColorTable
324    accept the new UNSIGNED_INT_5_9_9_9_REV_EXT token for type.
325
326    GetTexLevelParameterfv and GetTexLevelParameteriv accept the new
327    TEXTURE_SHARED_SIZE_EXT token for <pname>.
328
329    New errors
330    ----------
331
332    INVALID_OPERATION is generated by DrawPixels, ReadPixels, TexImage1D,
333    TexImage2D, GetTexImage, TexImage3D, TexSubImage1D, TexSubImage2D,
334    TexSubImage3D, GetHistogram, GetMinmax, ConvolutionFilter1D,
335    ConvolutionFilter2D, ConvolutionFilter3D, GetConvolutionFilter,
336    SeparableFilter2D, GetSeparableFilter, ColorTable, ColorSubTable,
337    and GetColorTable if <type> is UNSIGNED_INT_5_9_9_9_REV_EXT
338    and <format> is not RGB.
339
340New State
341
342    In table 6.17, Textures (page 278), increment the 42 in "n x Z42*"
343    by 1 for the RGB9_E5_EXT format.
344
345    [NOTE: The OpenGL 2.0 specification actually should read "n x Z48*"
346    because of the 6 generic compressed internal formats in table 3.18.]
347
348    Add the following entry to table 6.17:
349
350Get Value                Type    Get Command            Value   Description                           Sec.  Attribute
351-----------------------  ------  --------------------  -------  ------------------------------------  ----  ---------
352TEXTURE_SHARED_SIZE_EXT  n x Z+  GetTexLevelParameter  0        xD texture image i's shared exponent  3.8   -
353                                                                field size
354
355New Implementation Dependent State
356
357    None
358
359Appendix
360
361    This source code provides ANSI C routines.  It assumes the C "float"
362    data type is stored with the IEEE 754 32-bit floating-point format.
363    Make sure you define __LITTLE_ENDIAN or __BIG_ENDIAN appropriate
364    for your target system.
365
366    XXX: code below not tested on big-endian platform...
367
368------------------- start of source code ------------------------
369
370#include <assert.h>
371#include <math.h>
372#include <stdio.h>
373#include <stdlib.h>
374
375#define __LITTLE_ENDIAN  1
376#define __BIG_ENDIAN     2
377
378#ifdef _WIN32
379#define __BYTE_ORDER __LITTLE_ENDIAN
380#endif
381
382#define RGB9E5_EXPONENT_BITS          5
383#define RGB9E5_MANTISSA_BITS          9
384#define RGB9E5_EXP_BIAS               15
385#define RGB9E5_MAX_VALID_BIASED_EXP   31
386
387#define MAX_RGB9E5_EXP               (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS)
388#define RGB9E5_MANTISSA_VALUES       (1<<RGB9E5_MANTISSA_BITS)
389#define MAX_RGB9E5_MANTISSA          (RGB9E5_MANTISSA_VALUES-1)
390#define MAX_RGB9E5                   (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP))
391#define EPSILON_RGB9E5               ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS))
392
393typedef struct {
394#ifdef __BYTE_ORDER
395#if __BYTE_ORDER == __BIG_ENDIAN
396  unsigned int negative:1;
397  unsigned int biasedexponent:8;
398  unsigned int mantissa:23;
399#elif __BYTE_ORDER == __LITTLE_ENDIAN
400  unsigned int mantissa:23;
401  unsigned int biasedexponent:8;
402  unsigned int negative:1;
403#endif
404#endif
405} BitsOfIEEE754;
406
407typedef union {
408  unsigned int raw;
409  float value;
410  BitsOfIEEE754 field;
411} float754;
412
413typedef struct {
414#ifdef __BYTE_ORDER
415#if __BYTE_ORDER == __BIG_ENDIAN
416  unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
417  unsigned int b:RGB9E5_MANTISSA_BITS;
418  unsigned int g:RGB9E5_MANTISSA_BITS;
419  unsigned int r:RGB9E5_MANTISSA_BITS;
420#elif __BYTE_ORDER == __LITTLE_ENDIAN
421  unsigned int r:RGB9E5_MANTISSA_BITS;
422  unsigned int g:RGB9E5_MANTISSA_BITS;
423  unsigned int b:RGB9E5_MANTISSA_BITS;
424  unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
425#endif
426#endif
427} BitsOfRGB9E5;
428
429typedef union {
430  unsigned int raw;
431  BitsOfRGB9E5 field;
432} rgb9e5;
433
434float ClampRange_for_rgb9e5(float x)
435{
436  if (x > 0.0) {
437    if (x >= MAX_RGB9E5) {
438      return MAX_RGB9E5;
439    } else {
440      return x;
441    }
442  } else {
443    /* NaN gets here too since comparisons with NaN always fail! */
444    return 0.0;
445  }
446}
447
448float MaxOf3(float x, float y, float z)
449{
450  if (x > y) {
451    if (x > z) {
452      return x;
453    } else {
454      return z;
455    }
456  } else {
457    if (y > z) {
458      return y;
459    } else {
460      return z;
461    }
462  }
463}
464
465/* Ok, FloorLog2 is not correct for the denorm and zero values, but we
466   are going to do a max of this value with the minimum rgb9e5 exponent
467   that will hide these problem cases. */
468int FloorLog2(float x)
469{
470  float754 f;
471
472  f.value = x;
473  return (f.field.biasedexponent - 127);
474}
475
476int Max(int x, int y)
477{
478  if (x > y) {
479    return x;
480  } else {
481    return y;
482  }
483}
484
485rgb9e5 float3_to_rgb9e5(const float rgb[3])
486{
487  rgb9e5 retval;
488  float maxrgb;
489  int rm, gm, bm;
490  float rc, gc, bc;
491  int exp_shared;
492  double denom;
493
494  rc = ClampRange_for_rgb9e5(rgb[0]);
495  gc = ClampRange_for_rgb9e5(rgb[1]);
496  bc = ClampRange_for_rgb9e5(rgb[2]);
497
498  maxrgb = MaxOf3(rc, gc, bc);
499  exp_shared = Max(-RGB9E5_EXP_BIAS-1, FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS;
500  assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
501  assert(exp_shared >= 0);
502  /* This pow function could be replaced by a table. */
503  denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS);
504
505  maxm = (int) floor(maxrgb / denom + 0.5);
506  if (maxm == MAX_RGB9E5_MANTISSA+1) {
507    denom *= 2;
508    exp_shared += 1;
509    assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
510  } else {
511    assert(maxm <= MAX_RGB9E5_MANTISSA);
512  }
513
514  rm = (int) floor(rc / denom + 0.5);
515  gm = (int) floor(gc / denom + 0.5);
516  bm = (int) floor(bc / denom + 0.5);
517
518  assert(rm <= MAX_RGB9E5_MANTISSA);
519  assert(gm <= MAX_RGB9E5_MANTISSA);
520  assert(bm <= MAX_RGB9E5_MANTISSA);
521  assert(rm >= 0);
522  assert(gm >= 0);
523  assert(bm >= 0);
524
525  retval.field.r = rm;
526  retval.field.g = gm;
527  retval.field.b = bm;
528  retval.field.biasedexponent = exp_shared;
529
530  return retval;
531}
532
533void rgb9e5_to_float3(rgb9e5 v, float retval[3])
534{
535  int exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS;
536  float scale = (float) pow(2, exponent);
537
538  retval[0] = v.field.r * scale;
539  retval[1] = v.field.g * scale;
540  retval[2] = v.field.b * scale;
541}
542
543------------------- end of source code ------------------------
544
545Issues
546
547    1)  What should this extension be called?
548
549        RESOLVED: EXT_texture_shared_exponent
550
551        The "EXT_texture" part indicates the extension is in the texture
552        domain and "shared_exponent" indicates the extension is adding
553        a new shared exponent formats.
554
555        EXT_texture_rgb9e5 was considered but there's no precedent for
556        extension names to be so explicit (or cryptic?) about format
557        specifics in the extension name.
558
559    2)  There are many possible encodings for a shared exponent format.
560        Which encoding does this extension specify?
561
562        RESOLVED:  A single 5-bit exponent stored as an unsigned
563        value biased by 15 and three 9-bit mantissas for each of 3
564        components.  There are no sign bits so all three components
565        must be non-negative.  The fractional mantissas assume an implied
566        0 left of the decimal point because having an implied leading
567        1 is inconsistent with sharing the exponent.  Neither Infinity
568        nor Not-a-Number (NaN) are representable in this shared exponent
569        format.
570
571        We chose this format because it closely matches the range and
572        precision of the s10e5 half-precision floating-point described
573        in the ARB_half_float_pixel and ARB_texture_float specifications.
574
575    3)  Why not an 8-bit shared exponent?
576
577        RESOLVED:  Greg Ward's RGBE shared exponent encoding uses an
578        8-bit exponent (same as a single-precision IEEE value) but we
579        believe the rgb9e5 is more generally useful than rgb8e8.
580
581        An 8-bit exponent provides far more range than is typically
582        required for graphics applications.  However, an extra bit
583        of precision for each component helps in situations where a
584        high magnitude component dominates a low magnitude component.
585        Having an 8-bit shared exponent and 8-bit mantissas are amenable
586        to CPUs that facilitate 8-bit sized reads and writes over non-byte
587        aligned fields, but GPUs do not suffer from this issue.
588
589        Indeed GPUs with s10e5 texture filtering can use that same
590        filtering hardware for rgb9e5 textures.
591
592        However, future extensions could add other shared exponent formats
593        so we name the tokens to indicate the
594
595    4)  Should there be an external format and type for rgb9e5?
596
597        RESOLVED:  Yes, hence the external format GL_RGB9_E5_EXT and
598        type GL_UNSIGNED_INT_5_9_9_9_REV_EXT.  This makes it fast to load
599        GL_RGB9_E5_EXT textures without any translation by the driver.
600
601    5)  Why is the exponent bias 15?
602
603        RESOLVED:  The best technical choice of 15.  Hopefully, this
604        discussion sheds insight into the numerics of the shared exponent
605        format in general.
606
607        With conventional floating-point formats, the number corresponding
608        to a finite, non-denorm, non-zero floating-point value is
609
610            value = -1^sgn * 2^(exp-bias) * 1.frac
611
612        where sgn is the sign bit (so 1 for sgn negative because -1^-1
613        == -1 and 0 means positive because -1^0 == +1), exp is an
614        (unsigned) BIASED exponent and bias is the format's constant bias
615        to subtract to get the unbiased (possibly negative) exponent;
616        and frac is the fractional portion of the mantissa with the
617        "1." indicating an implied leading 1.
618
619        An exp value of zero indicates so-called denormalized values
620        (denorms).  With conventional floating-point formats, the number
621        corresponding to a denorm floating-point value is
622
623            value = -1^sgn * 2^(exp-bias+1) * 0.frac
624
625        where the only difference between the denorm and non-denorm case
626        is the bias is one greater in the denorm case and the implied
627        leading digit is a zero instead of a one.
628
629        Ideally, the rgb9e5 shared exponent format would represent
630        roughly the same range of finite values as the s10e5 format
631        specified by the ARB_texture_float extension.  The s10e5 format
632        has an exponent bias of 15.
633
634        While conventional floating-point formats cleverly use an implied
635        leading 1 for non-denorm, finite values, a shared exponent format
636        cannot use an implied leading 1 because each component may have
637        a different magnitude for its most-significant binary digit.
638        The implied leading 1 assumes we have the flexibility to adjust
639        the mantissa and exponent together to ensure an implied leading 1.
640        That flexibility is not present when the exponent is shared.
641
642        So the rgb9e5 format cannot assume an implied leading one.
643        Instead, an implied leading zero is assumed (much like the
644        conventional denorm case).
645
646        The rgb9e5 format eliminate support representing negative,
647        Infinite, not-a-number (NaN), and denorm values.
648
649        We've already discussed how the BIASED zero exponent is used to
650        encode denorm values (and zero) with conventional floating-point
651        formats.  The largest BIASED exponent (31 for s10e5, 127 for
652        s23e8) for conventional floating-point fomats indicates Infinity
653        and NaN values.  This means these two extrema exponent values are
654        "off limits" for run-of-the-mill values.
655
656        The numbers corresponding to a shared exponent format value are:
657
658            value_r = 2^(exp-bias) * 0.frac_r
659            value_g = 2^(exp-bias) * 0.frac_g
660            value_b = 2^(exp-bias) * 0.frac_b
661
662        where there is no sgn since all values are non-negative, exp is
663        the (unsigned) BIASED exponent and bias is the format's constant
664        bias to subtract to get the unbiased (possibly negative) exponent;
665        and frac_r, frac_g, and frac_b are the fractional portion of
666        the mantissas of the r, g, and b components respectively with
667        "0." indicating an implied leading 0.
668
669        There should be no "off limits" exponents for the shared exponent
670        format since there is no requirement for representing Infinity
671        or NaN values and denorm is not a special case.  Because of
672        the implied leading zero, any component with all zeros for its
673        mantissa is zero, no matter the shared exponent's value.
674
675        So the run-of-the-mill BIASED range of exponents for s10e5 is
676        1 to 30.  But the rgb9e5 shared exponent format consistently
677        uses the same rule for all exponents from 0 to 31.
678
679        What exponent bias best allows us to represent the range of
680        s10e5 with the rgb9e5 format?  15.
681
682        Consider the maximum representable finite s10e5 magnitude.
683        The exponent would be 30 (31 would encode an Infinite or NaN
684        value) and the binary mantissa would be 1 followed by ten
685        fractional 1's.  Effectively:
686
687            s10e5_max  =  1.1111111111 * 2^(30-15)
688                       =  1.1111111111 * 2^15
689
690        For an rgb9e5 value with a bias of 15, the largest representable
691        value is:
692
693            rgb9e5_max =  0.111111111  * 2^(31-15)
694                       =  0.111111111  * 2^16
695                       =  1.11111111   * 2^15
696
697        If you ignore two LSBs, these values are nearly identical.
698        The rgb9e5_max value is exactly representable as an s10e5 value.
699
700        For an rgb9e5 value with a bias of 15, the smallest non-zero
701        representable value is:
702
703            rgb9e5_min =  0.000000001  * 2^(0-15)
704            rgb9e5_min =  0.000000001  * 2^-15
705            rgb9e5_min =  0.0000000001 * 2^-14
706
707        So the s10e5_min and rgb9e5_min values exactly match (of course,
708        this assumes the shared exponent bias is 15 which might not be
709        the case if other components demand higher exponents).
710
711    8)  Should there be an rgb9e5 framebuffer format?
712
713        RESOLVED:  No.  Rendering to rgb9e5 is better left to another
714        extension and would require the hardware to convert from a
715        (floating-point) RGBA value into an rgb9e5 encoding.
716
717        Interactions with EXT_framebuffer_object are specified,
718        but the expectation is this is not a renderable
719        format and glCheckFramebufferStatusEXT would return
720        GL_FRAMEBUFFER_UNSUPPORTED_EXT.
721
722        An implementation certainly could make this texture internal
723        format renderable when used with a framebuffer object.  Note that
724        the shared exponent means masked components may be lossy in
725        their masking.  For example, a very small but non-zero value in
726        a masked component could get flushed to zero if a large enough
727        value is written into an unmasked component.
728
729    9)  Should automatic mipmap generation be supported for rgb9e5
730        textures?
731
732        RESOLVED:  Yes.
733
734    10) Should non-texture and non-framebuffer commands for loading
735        pixel data accept the GL_UNSIGNED_INT_5_9_9_9_REV_EXT type?
736
737        RESOLVED:  Yes.
738
739        Once the pixel path has to support the new type/format combination
740        of GL_UNSIGNED_INT_5_9_9_9_REV_EXT / GL_RGB for specifying and
741        querying texture images, it might as well be supported for all
742        commands that pack and unpack RGB pixel data.
743
744        The specification is written such that the glDrawPixels
745        type/format parameters are accepted by glReadPixels,
746        glTexGetImage, glTexImage2D, and other commands that are specified
747        in terms of glDrawPixels.
748
749    11) Should non-texture internal formats (such as for color tables,
750        convolution kernels, histogram bins, and min/max tables) accept
751        GL_RGB9_E5_EXT format?
752
753        RESOLVED:  No.
754
755        That's pointless.  No hardware is ever likely to support
756        GL_RGB9_E5_EXT internalformats for anything other than textures
757        and maybe color buffers in the future.  This format is not
758        interesting for color tables, convolution kernels, etc.
759
760    12) Should a format be supported with sign bits for each component?
761
762        RESOLVED:  No.
763
764        An srgb8e5 format with a sign bit per component could be useful
765        but is better left to another extension.
766
767    13) The rgb9e5 allows two 32-bit values encoded as rgb9e5 to
768        correspond to the exact same 3 components when expanded to
769        floating-point.  Is this a problem?
770
771        RESOLVED:  No, there's no problem here.
772
773        An encoder is likely to always pack components so at least
774        one mantissa will have an explicit leading one, but there's no
775        requirement for that.
776
777        Applications might be able to take advantage of this by quickly
778        dividing all three components by a power-of-two by simply
779        subtracting log2 of the power-of-two from the shared exponent (as
780        long as the exponent is greater than zero prior to the subtract).
781
782        Arguably, the shared exponent format could maintain a slight
783        amount of extra precision (one bit per mantissa) if the format
784        said if the most significant bits of all three mantissas are
785        either all one or all zero and the biased shared exponent was not
786        zero, then an implied leading 1 should be assumed and the shared
787        exponent should be treated as one smaller than it really is.
788        While this would preserve an extra least-significant bit of
789        mantissa precision for components of approximately the same
790        magnitude, it would complicate the encoding and decoding of
791        shared exponent values.
792
793    14) Can you provide some C code for encoding three floating-point
794        values into the rgb9e5 format?
795
796        RESOLVED:  Sure.  See the Appendix.
797
798    15) Should we support a non-REV version of the
799        GL_UNSIGNED_INT_5_9_9_9_REV_EXT token?
800
801        RESOLVED:  No.  The shared exponent is always the 5 most
802        significant bits of the 32 bit word.  The first (red) mantissa
803        is in the least significant 9 bits, followed by 9 bits for the
804        second (green) mantissa, followed by 9 bits for the third (blue)
805        mantissa.  We don't want to promote different arrangements of
806        the bitfields for rgb9e5 values.
807
808    16) Can you use the GL_UNSIGNED_INT_5_9_9_9_REV_EXT format with
809        just any format?
810
811        RESOLVED:  You can only use the GL_UNSIGNED_INT_5_9_9_9_REV_EXT
812        format with GL_RGB.  Otherwise, the GL generates
813        a GL_INVALID_OPERATION error.  Conceptually,
814        GL_UNSIGNED_INT_5_9_9_9_REV_EXT is a 3-component format
815        that just happens to have 5 shared bits too.  Just as the
816        GL_UNSIGNED_BYTE_3_3_2 format just works with GL_RGB (or else
817        the GL generates a GL_INVALID_OPERATION error), so should
818        GL_UNSIGNED_INT_5_9_9_9_REV_EXT.
819
820    17) What should GL_TEXTURE_SHARED_SIZE_EXT return when queried with
821        GetTexLevelParameter?
822
823        RESOLVED:  Return 5 for the RGB9_E5_EXT internal format and 0
824        for all other existing formats.
825
826        This is a count of the number of bits in the shared exponent.
827
828    18) What should GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, and
829        GL_TEXTURE_BLUE_SIZE return when queried with GetTexLevelParameter
830        for a GL_RGB9_E5_EXT texture?
831
832        RESOLVED:  Return 9 for each.
833
834Revision History
835
836    Rev.    Date    Author    Changes
837    ----  --------  --------  --------------------------------------------
838    0.5   02/18/07  mjk       Initial public version
839    1.0   07/18/08  mjk       correct significant errors in spec language
840                              and C code
841