1Surface Formats 2=============== 3 4A surface format describes the encoding of color information into the actual 5data stored in memory. Surface formats in isl are specified via the 6:cpp:enum:`isl_format` enum. A complete list of surface formats is included at 7the end of this chapter. 8 9In general, a surface format definition consists of two parts: encoding and 10layout. 11 12Data Encoding 13------------- 14 15There are several different ways that one can encode a number (or vector) into 16a binary form, and each makes different trade-offs. By default, most color 17values lie in the range [0, 1], so one of the most common encodings for color 18data is unsigned normalized where the range of an unsigned integer of a 19particular size is mapped linearly onto the interval [0, 1]. While normalized 20is certainly the most common representation for color data, not all data is 21color data, and not all values are nicely bounded. The possible data encodings 22are specified by :cpp:enum:`isl_base_type`: 23 24.. doxygenenum:: isl_base_type 25 26Data Layout 27----------- 28 29The different data layouts fall into two categories: array and packed. When an 30array layout is used, the components are stored sequentially in an array of the 31given encoding. For instance, if the data is encoded in an 8-bit RGBA array 32format the data is stored in an array of type :c:type:`uint8_t` where the blue 33component of the :c:expr:`i`'th color value is accessed as: 34 35.. code-block:: C 36 37 uint8_t r = ((uint8_t *)data)[i * 4 + 0]; 38 uint8_t g = ((uint8_t *)data)[i * 4 + 1]; 39 uint8_t b = ((uint8_t *)data)[i * 4 + 2]; 40 uint8_t a = ((uint8_t *)data)[i * 4 + 3]; 41 42Array formats are popular because of their simplicity. However, they are 43limited to formats where all components have the same size and fit in 44a standard C data type. 45 46Packed formats, on the other hand, are encoded with the entire color value 47packed into a single 8, 16, or 32-bit value. The components are specified by 48which bits they occupy within that value. For instance, with the popular 49:c:expr:`RGB565` format, each :c:type:`vec3` takes up 16 bits and the 50:c:expr:`i`'th color value is accessed as: 51 52.. code-block:: C 53 54 uint8_t r = (*(uint16_t *)data >> 0) & 0x1f; 55 uint8_t g = (*(uint16_t *)data >> 5) & 0x3f; 56 uint8_t b = (*(uint16_t *)data >> 11) & 0x1f; 57 58Packed formats are useful because they allow you to specify formats with uneven 59component sizes such as :c:expr:`RGBA1010102` or where the components are 60smaller than 8 bits such as :c:expr:`RGB565` discussed above. It does, 61however, come with the restriction that the entire vector must fit within 8, 6216, or 32 bits. 63 64One has to be careful when reasoning about packed formats because it is easy to 65get the color order wrong. With array formats, the channel ordering is usually 66implied directly from the format name with :c:expr:`RGBA8888` storing the 67formats as in the first example and :c:expr:`BGRA8888` storing them in the BGRA 68ordering. Packed formats, however, are not as simple because some 69specifications choose to use a MSB to LSB ordering and others LSB to MSB. One 70must be careful to pay attention to the enum in question in order to avoid 71getting them backwards. 72 73From an API perspective, both types of formats are available. In Vulkan, the 74formats that are of the form :c:enumerator:`VK_FORMAT_xxx_PACKEDn` are packed 75formats where the entire color fits in :c:expr:`n` bits and formats without the 76:c:expr:`_PACKEDn` suffix are array formats. In GL, if you specify one of the 77base types such as :c:enumerator:`GL_FLOAT` you get an array format but if you 78specify a packed type such as :c:enumerator:`GL_UNSIGNED_INT_8_8_8_8_REV` you 79get a packed format. 80 81The following table provides a summary of the bit orderings of different packed 82format specifications. The bit ordering is relative to the reading of the enum 83name from left to right. 84 85===================== ============== 86Component Left → Right 87===================== ============== 88GL MSB → LSB 89Vulkan MSB → LSB 90mesa_format LSB → MSB 91Intel surface format LSB → MSB 92===================== ============== 93 94Understanding sRGB 95------------------ 96 97The sRGB colorspace is one of the least tractable concepts in the entire world 98of surfaces and formats. Most texture formats are stored in a linear 99colorspace where the floating-point value corresponds linearly to intensity 100values. The sRGB color space, on the other hand, is non-linear and provides 101greater precision in the lower-intensity (darker) end of the spectrum. The 102relationship between linear and sRGB is governed by the following continuous 103bijection: 104 105.. math:: 106 107 c_l = 108 \begin{cases} 109 \frac{c_s}{12.92} &\text{if } c_s \le 0.04045 \\\\ 110 \left(\frac{c_s + 0.055}{1.055}\right)^{2.4} &\text{if } c_s > 0.04045 111 \end{cases} 112 113where :math:`c_l` is the linear color and :math:`c_s` is the color in sRGB. 114It is important to note that, when an alpha channel is present, the alpha 115channel is always stored in the linear colorspace. 116 117The key to understanding sRGB is to think about it starting from the physical 118display. All displays work natively in sRGB. On older displays, there isn't 119so much a conversion operation as a fact of how the hardware works. All 120display hardware has a natural gamma curve required to get from linear to the 121signal level required to generate the correct color. On older CRT displays, 122the gamma curve of your average CRT is approximately the sRGB curve. More 123modern display hardware has support for additional gamma curves to try and get 124accurate colors but, for the sake of compatibility, everything still operates 125in sRGB. When an image is sent to the X server, X passes the pixels on to the 126display verbatim without doing any conversions. (Fun fact: When dealing with 127translucent windows, X blends in the wrong colorspace.) This means that the 128image into which you are rendering will always be interpreted as if it were in 129the sRGB colorspace. 130 131When sampling from a texture, the value returned to the shader is in the linear 132colorspace. The conversion from sRGB happens as part of sampling. In OpenGL, 133thanks mostly to history, there are various knobs for determining when you 134should or should not encode or decode sRGB. In 2007, GL_EXT_texture_sRGB added 135support for sRGB texture formats and was included in OpenGL 2.1. In 2010, 136GL_EXT_texture_sRGB_decode added a flag to allow you to disable texture 137decoding so that the shader received the data still in the sRGB colorspace. 138Then, in 2012, GL_ARB_texture_view came along and made 139GL_EXT_texture_sRGB_decode` simultaneously obsolete and very confusing. Now, 140thanks to the combination of extensions, you can upload a texture as linear, 141create an sRGB view of it and ask that sRGB not be decoded. What format is it 142in again? 143 144The situation with render targets is a bit different. Historically, you got 145your render target from the window system (which is always sRGB) and the spec 146said nothing whatsoever about encoding. All render targets were sRGB because 147that's how monitors worked and application writers were expected to understand 148that their final rendering needed to be in sRGB. However, with the advent of 149EXT_framebuffer_object this was no longer true. Also, sRGB was causing 150problems with blending because GL was blind to the fact that the output was 151sRGB and blending was occurring in the wrong colorspace. In 2006, a set of 152EXT_framebuffer_sRGB extensions added support (on both the GL and window-system 153sides) for detecting whether a particular framebuffer was in sRGB and 154instructing GL to do the conversion into the sRGB colorspace as the final step 155prior to writing out to the render target. Enabling sRGB also implied that 156blending would occur in the linear colorspace prior to sRGB conversion and 157would therefore be more accurate. When sRGB was added to the OpenGL ES spec in 1583.1, they added the query for sRGB but did not add the flag to allow you to 159turn it on and off. 160 161In Vulkan, this is all much more straightforward. Your format is sRGB or it 162isn't. If you have an sRGB image and you don't want sRGB decoding to happen 163when you sample from it, you simply create a c:struct:`VkImageView` that has 164the appropriate linear format and the data will be treated as linear and not 165converted. Similarly for render targets, blending always happens in the same 166colorspace as the shader output and you determine whether or not you want sRGB 167conversion by the format of the c:struct:`VkImageView` used as the render 168target. 169 170Surface Format Introspection API 171-------------------------------- 172 173ISL provides an API for introspecting the :cpp:enum:`isl_format` enum and 174getting various bits of information about a format. ISL provides helpers for 175introspecting both the data layout of an cpp:enum:`isl_format` and the 176capabilities of that format for a particular piece of Intel hardware. 177 178Format Layout Introspection 179^^^^^^^^^^^^^^^^^^^^^^^^^^^ 180 181To get the layout of a given :cpp:enum:`isl_format`, call 182:cpp:func:`isl_format_get_layout`: 183 184.. doxygenfunction:: isl_format_get_layout 185 186.. doxygenstruct:: isl_format_layout 187 :members: 188 189.. doxygenstruct:: isl_channel_layout 190 :members: 191 192There are also quite a few helpers for many of the common cases that allow you 193to avoid using :cpp:struct:`isl_format_layout` manually. There are a lot of 194them so we won't include a full list here. Look at isl.h for more details. 195 196Hardware Format Support Introspection 197^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 198 199This is provided by means of a table located in isl_format.c. Looking at the 200table directly is often useful for understanding HW support for various 201formats. However, for the purposes of code cleanliness, the table is not 202exposed directly and, instead, hardware support information is exposed via 203a set of helper functions: 204 205.. doxygenfunction:: isl_format_supports_rendering 206.. doxygenfunction:: isl_format_supports_alpha_blending 207.. doxygenfunction:: isl_format_supports_sampling 208.. doxygenfunction:: isl_format_supports_filtering 209.. doxygenfunction:: isl_format_supports_vertex_fetch 210.. doxygenfunction:: isl_format_supports_typed_writes 211.. doxygenfunction:: isl_format_supports_typed_reads 212.. doxygenfunction:: isl_format_supports_ccs_d 213.. doxygenfunction:: isl_format_supports_ccs_e 214.. doxygenfunction:: isl_format_supports_multisampling 215.. doxygenfunction:: isl_formats_are_ccs_e_compatible 216 217Surface Format Enums 218-------------------- 219 220Everything in ISL is done in terms of the :cpp:enum:`isl_format` enum. However, 221for the sake of interacting with other parts of Mesa, we provide a helper for 222converting a :cpp:enum:`pipe_format` to an :cpp:enum:`isl_format`: 223 224.. doxygenfunction:: isl_format_for_pipe_format 225 226The :cpp:enum:`isl_format` enum is as follows: 227 228.. doxygenenum:: isl_format 229