LCOV - code coverage report
Current view: top level - src/opengl - formats.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 116 146 79.5 %
Date: 2025-03-29 09:04:10 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 106 174 60.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of libplacebo.
       3                 :            :  *
       4                 :            :  * libplacebo is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU Lesser General Public
       6                 :            :  * License as published by the Free Software Foundation; either
       7                 :            :  * version 2.1 of the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * libplacebo is distributed in the hope that it will be useful,
      10                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :  * GNU Lesser General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Lesser General Public
      15                 :            :  * License along with libplacebo.  If not, see <http://www.gnu.org/licenses/>.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "gpu.h"
      19                 :            : #include "common.h"
      20                 :            : #include "formats.h"
      21                 :            : #include "utils.h"
      22                 :            : 
      23                 :            : #ifdef PL_HAVE_UNIX
      24                 :            : static bool supported_fourcc(struct pl_gl *p, EGLint fourcc)
      25                 :            : {
      26         [ +  + ]:        540 :     for (int i = 0; i < p->egl_formats.num; ++i)
      27         [ +  + ]:        536 :         if (fourcc == p->egl_formats.elem[i])
      28                 :            :             return true;
      29                 :            :     return false;
      30                 :            : }
      31                 :            : #endif
      32                 :            : 
      33                 :            : #define FMT(_name, bits, ftype, _caps)               \
      34                 :            :     (struct pl_fmt_t) {                              \
      35                 :            :         .name = _name,                               \
      36                 :            :         .type = PL_FMT_##ftype,                      \
      37                 :            :         .caps = (enum pl_fmt_caps) (_caps),          \
      38                 :            :         .sample_order = {0, 1, 2, 3},                \
      39                 :            :         .component_depth = {bits, bits, bits, bits}, \
      40                 :            :     }
      41                 :            : 
      42                 :            : // Convenience to make the names simpler
      43                 :            : enum {
      44                 :            :     // Type aliases
      45                 :            :     U8    = GL_UNSIGNED_BYTE,
      46                 :            :     U16   = GL_UNSIGNED_SHORT,
      47                 :            :     U32   = GL_UNSIGNED_INT,
      48                 :            :     I8    = GL_BYTE,
      49                 :            :     I16   = GL_SHORT,
      50                 :            :     I32   = GL_INT,
      51                 :            :     FLT   = GL_FLOAT,
      52                 :            :     HALF  = GL_HALF_FLOAT,
      53                 :            : 
      54                 :            :     // Component aliases
      55                 :            :     R     = GL_RED,
      56                 :            :     RG    = GL_RG,
      57                 :            :     RGB   = GL_RGB,
      58                 :            :     RGBA  = GL_RGBA,
      59                 :            :     BGRA  = GL_BGRA,
      60                 :            :     RI    = GL_RED_INTEGER,
      61                 :            :     RGI   = GL_RG_INTEGER,
      62                 :            :     RGBI  = GL_RGB_INTEGER,
      63                 :            :     RGBAI = GL_RGBA_INTEGER,
      64                 :            : 
      65                 :            :     // Capability aliases
      66                 :            :     S     = PL_FMT_CAP_SAMPLEABLE,
      67                 :            :     L     = PL_FMT_CAP_LINEAR,
      68                 :            :     F     = PL_FMT_CAP_RENDERABLE | PL_FMT_CAP_BLITTABLE, // FBO support
      69                 :            :     V     = PL_FMT_CAP_VERTEX,
      70                 :            : };
      71                 :            : 
      72                 :            : // Basic 8-bit formats
      73                 :            : const struct gl_format formats_norm8[] = {
      74                 :            :     {GL_R8,             R,     U8,  FMT("r8",       8, UNORM, S|L|F|V)},
      75                 :            :     {GL_RG8,            RG,    U8,  FMT("rg8",      8, UNORM, S|L|F|V)},
      76                 :            :     {GL_RGB8,           RGB,   U8,  FMT("rgb8",     8, UNORM, S|L|F|V)},
      77                 :            :     {GL_RGBA8,          RGBA,  U8,  FMT("rgba8",    8, UNORM, S|L|F|V)},
      78                 :            : };
      79                 :            : 
      80                 :            : // Signed variants
      81                 :            : /* TODO: these are broken in mesa
      82                 :            : const struct gl_format formats_snorm8[] = {
      83                 :            :     {GL_R8_SNORM,       R,     I8,  FMT("r8s",      8, SNORM, S|L|F|V)},
      84                 :            :     {GL_RG8_SNORM,      RG,    I8,  FMT("rg8s",     8, SNORM, S|L|F|V)},
      85                 :            :     {GL_RGB8_SNORM,     RGB,   I8,  FMT("rgb8s",    8, SNORM, S|L|F|V)},
      86                 :            :     {GL_RGBA8_SNORM,    RGBA,  I8,  FMT("rgba8s",   8, SNORM, S|L|F|V)},
      87                 :            : };
      88                 :            : */
      89                 :            : 
      90                 :            : // BGRA 8-bit
      91                 :            : const struct gl_format formats_bgra8[] = {
      92                 :            :     {GL_RGBA8,          BGRA,  U8,  {
      93                 :            :         .name               = "bgra8",
      94                 :            :         .type               = PL_FMT_UNORM,
      95                 :            :         .caps               = S|L|F|V,
      96                 :            :         .sample_order       = {2, 1, 0, 3},
      97                 :            :         .component_depth    = {8, 8, 8, 8},
      98                 :            :     }},
      99                 :            : };
     100                 :            : 
     101                 :            : // Basic 16-bit formats, excluding rgb16 (special cased below)
     102                 :            : const struct gl_format formats_norm16[] = {
     103                 :            :     {GL_R16,            R,     U16, FMT("r16",     16, UNORM, S|L|F|V)},
     104                 :            :     {GL_RG16,           RG,    U16, FMT("rg16",    16, UNORM, S|L|F|V)},
     105                 :            :     {GL_RGBA16,         RGBA,  U16, FMT("rgba16",  16, UNORM, S|L|F|V)},
     106                 :            : };
     107                 :            : 
     108                 :            : // Renderable version of rgb16
     109                 :            : const struct gl_format formats_rgb16_fbo[] = {
     110                 :            :     {GL_RGB16,          RGB,   U16, FMT("rgb16",   16, UNORM, S|L|F|V)},
     111                 :            : };
     112                 :            : 
     113                 :            : // Non-renderable version of rgb16
     114                 :            : const struct gl_format formats_rgb16_fallback[] = {
     115                 :            :     {GL_RGB16,          RGB,   U16, FMT("rgb16",   16, UNORM, S|L|V)},
     116                 :            : };
     117                 :            : 
     118                 :            : // Signed 16-bit variants
     119                 :            : /* TODO: these are broken in mesa and nvidia
     120                 :            : const struct gl_format formats_snorm16[] = {
     121                 :            :     {GL_R16_SNORM,      R,     I16, FMT("r16s",    16, SNORM, S|L|F|V)},
     122                 :            :     {GL_RG16_SNORM,     RG,    I16, FMT("rg16s",   16, SNORM, S|L|F|V)},
     123                 :            :     {GL_RGB16_SNORM,    RGB,   I16, FMT("rgb16s",  16, SNORM, S|L|F|V)},
     124                 :            :     {GL_RGBA16_SNORM,   RGBA,  I16, FMT("rgba16s", 16, SNORM, S|L|F|V)},
     125                 :            : };
     126                 :            : */
     127                 :            : 
     128                 :            : // 32-bit floating point texture formats
     129                 :            : const struct gl_format formats_float32[] = {
     130                 :            :     {GL_R32F,           R,     FLT, FMT("r32f",    32, FLOAT, S|L|F|V)},
     131                 :            :     {GL_RG32F,          RG,    FLT, FMT("rg32f",   32, FLOAT, S|L|F|V)},
     132                 :            :     {GL_RGB32F,         RGB,   FLT, FMT("rgb32f",  32, FLOAT, S|L|F|V)},
     133                 :            :     {GL_RGBA32F,        RGBA,  FLT, FMT("rgba32f", 32, FLOAT, S|L|F|V)},
     134                 :            : };
     135                 :            : 
     136                 :            : // 16-bit floating point texture formats
     137                 :            : const struct gl_format formats_float16[] = {
     138                 :            :     {GL_R16F,           R,     FLT,  FMT("r16f",    16, FLOAT, S|L|F)},
     139                 :            :     {GL_RG16F,          RG,    FLT,  FMT("rg16f",   16, FLOAT, S|L|F)},
     140                 :            :     {GL_RGB16F,         RGB,   FLT,  FMT("rgb16f",  16, FLOAT, S|L|F)},
     141                 :            :     {GL_RGBA16F,        RGBA,  FLT,  FMT("rgba16f", 16, FLOAT, S|L|F)},
     142                 :            : };
     143                 :            : 
     144                 :            : // 16-bit half float texture formats
     145                 :            : const struct gl_format formats_half16[] = {
     146                 :            :     {GL_R16F,           R,     HALF, FMT("r16hf",   16, FLOAT, S|L|F)},
     147                 :            :     {GL_RG16F,          RG,    HALF, FMT("rg16hf",  16, FLOAT, S|L|F)},
     148                 :            :     {GL_RGB16F,         RGB,   HALF, FMT("rgb16hf", 16, FLOAT, S|L|F)},
     149                 :            :     {GL_RGBA16F,        RGBA,  HALF, FMT("rgba16hf",16, FLOAT, S|L|F)},
     150                 :            : };
     151                 :            : 
     152                 :            : // Renderable 16-bit float formats (excluding rgb16f)
     153                 :            : const struct gl_format formats_float16_fbo[] = {
     154                 :            :     {GL_R16F,           R,     HALF, FMT("r16hf",   16, FLOAT, S|L|F)},
     155                 :            :     {GL_RG16F,          RG,    HALF, FMT("rg16hf",  16, FLOAT, S|L|F)},
     156                 :            :     {GL_RGB16F,         RGB,   HALF, FMT("rgb16hf", 16, FLOAT, S|L)},
     157                 :            :     {GL_RGBA16F,        RGBA,  HALF, FMT("rgba16hf",16, FLOAT, S|L|F)},
     158                 :            :     {GL_R16F,           R,     FLT,  FMT("r16f",    16, FLOAT, S|L|F)},
     159                 :            :     {GL_RG16F,          RG,    FLT,  FMT("rg16f",   16, FLOAT, S|L|F)},
     160                 :            :     {GL_RGB16F,         RGB,   FLT,  FMT("rgb16f",  16, FLOAT, S|L)},
     161                 :            :     {GL_RGBA16F,        RGBA,  FLT,  FMT("rgba16f", 16, FLOAT, S|L|F)},
     162                 :            : };
     163                 :            : 
     164                 :            : // Non-renderable 16-bit float formats
     165                 :            : const struct gl_format formats_float16_fallback[] = {
     166                 :            :     {GL_R16F,           R,     HALF, FMT("r16hf",   16, FLOAT, S|L)},
     167                 :            :     {GL_RG16F,          RG,    HALF, FMT("rg16hf",  16, FLOAT, S|L)},
     168                 :            :     {GL_RGB16F,         RGB,   HALF, FMT("rgb16hf", 16, FLOAT, S|L)},
     169                 :            :     {GL_RGBA16F,        RGBA,  HALF, FMT("rgba16hf",16, FLOAT, S|L)},
     170                 :            :     {GL_R16F,           R,     FLT,  FMT("r16f",    16, FLOAT, S|L)},
     171                 :            :     {GL_RG16F,          RG,    FLT,  FMT("rg16f",   16, FLOAT, S|L)},
     172                 :            :     {GL_RGB16F,         RGB,   FLT,  FMT("rgb16f",  16, FLOAT, S|L)},
     173                 :            :     {GL_RGBA16F,        RGBA,  FLT,  FMT("rgba16f", 16, FLOAT, S|L)},
     174                 :            : };
     175                 :            : 
     176                 :            : // (Unsigned) integer formats
     177                 :            : const struct gl_format formats_uint[] = {
     178                 :            :     {GL_R8UI,           RI,    U8,  FMT("r8u",      8, UINT, S|F|V)},
     179                 :            :     {GL_RG8UI,          RGI,   U8,  FMT("rg8u",     8, UINT, S|F|V)},
     180                 :            :     {GL_RGB8UI,         RGBI,  U8,  FMT("rgb8u",    8, UINT, S|V)},
     181                 :            :     {GL_RGBA8UI,        RGBAI, U8,  FMT("rgba8u",   8, UINT, S|F|V)},
     182                 :            :     {GL_R16UI,          RI,    U16, FMT("r16u",    16, UINT, S|F|V)},
     183                 :            :     {GL_RG16UI,         RGI,   U16, FMT("rg16u",   16, UINT, S|F|V)},
     184                 :            :     {GL_RGB16UI,        RGBI,  U16, FMT("rgb16u",  16, UINT, S|V)},
     185                 :            :     {GL_RGBA16UI,       RGBAI, U16, FMT("rgba16u", 16, UINT, S|F|V)},
     186                 :            : };
     187                 :            : 
     188                 :            : /* TODO
     189                 :            :     {GL_R32UI,          RI,    U32, FMT("r32u",    32, UINT)},
     190                 :            :     {GL_RG32UI,         RGI,   U32, FMT("rg32u",   32, UINT)},
     191                 :            :     {GL_RGB32UI,        RGBI,  U32, FMT("rgb32u",  32, UINT)},
     192                 :            :     {GL_RGBA32UI,       RGBAI, U32, FMT("rgba32u", 32, UINT)},
     193                 :            : 
     194                 :            :     {GL_R8I,            RI,    I8,  FMT("r8i",      8, SINT)},
     195                 :            :     {GL_RG8I,           RGI,   I8,  FMT("rg8i",     8, SINT)},
     196                 :            :     {GL_RGB8I,          RGBI,  I8,  FMT("rgb8i",    8, SINT)},
     197                 :            :     {GL_RGBA8I,         RGBAI, I8,  FMT("rgba8i",   8, SINT)},
     198                 :            :     {GL_R16I,           RI,    I16, FMT("r16i",    16, SINT)},
     199                 :            :     {GL_RG16I,          RGI,   I16, FMT("rg16i",   16, SINT)},
     200                 :            :     {GL_RGB16I,         RGBI,  I16, FMT("rgb16i",  16, SINT)},
     201                 :            :     {GL_RGBA16I,        RGBAI, I16, FMT("rgba16i", 16, SINT)},
     202                 :            :     {GL_R32I,           RI,    I32, FMT("r32i",    32, SINT)},
     203                 :            :     {GL_RG32I,          RGI,   I32, FMT("rg32i",   32, SINT)},
     204                 :            :     {GL_RGB32I,         RGBI,  I32, FMT("rgb32i",  32, SINT)},
     205                 :            :     {GL_RGBA32I,        RGBAI, I32, FMT("rgba32i", 32, SINT)},
     206                 :            : */
     207                 :            : 
     208                 :            : // GL2 legacy formats
     209                 :            : const struct gl_format formats_legacy_gl2[] = {
     210                 :            :     {GL_RGB8,           RGB,   U8,  FMT("rgb8",     8, UNORM, S|L|V)},
     211                 :            :     {GL_RGBA8,          RGBA,  U8,  FMT("rgba8",    8, UNORM, S|L|V)},
     212                 :            :     {GL_RGB16,          RGB,   U16, FMT("rgb16",   16, UNORM, S|L|V)},
     213                 :            :     {GL_RGBA16,         RGBA,  U16, FMT("rgba16",  16, UNORM, S|L|V)},
     214                 :            : };
     215                 :            : 
     216                 :            : // GLES2 legacy formats
     217                 :            : const struct gl_format formats_legacy_gles2[] = {
     218                 :            :     {GL_RGB,            RGB,   U8,  FMT("rgb",      8, UNORM, S|L)},
     219                 :            :     {GL_RGBA,           RGBA,  U8,  FMT("rgba",     8, UNORM, S|L)},
     220                 :            : };
     221                 :            : 
     222                 :            : // GLES BGRA
     223                 :            : const struct gl_format formats_bgra_gles[] = {
     224                 :            :     {GL_BGRA,           BGRA,  U8,  {
     225                 :            :         .name               = "bgra8",
     226                 :            :         .type               = PL_FMT_UNORM,
     227                 :            :         .caps               = S|L|F|V,
     228                 :            :         .sample_order       = {2, 1, 0, 3},
     229                 :            :         .component_depth    = {8, 8, 8, 8},
     230                 :            :     }},
     231                 :            : };
     232                 :            : 
     233                 :            : // Fallback for vertex-only formats, as a last resort
     234                 :            : const struct gl_format formats_basic_vertex[] = {
     235                 :            :     {GL_R32F,           R,     FLT, FMT("r32f",    32, FLOAT, V)},
     236                 :            :     {GL_RG32F,          RG,    FLT, FMT("rg32f",   32, FLOAT, V)},
     237                 :            :     {GL_RGB32F,         RGB,   FLT, FMT("rgb32f",  32, FLOAT, V)},
     238                 :            :     {GL_RGBA32F,        RGBA,  FLT, FMT("rgba32f", 32, FLOAT, V)},
     239                 :            : };
     240                 :            : 
     241                 :        116 : static void add_format(pl_gpu pgpu, const struct gl_format *gl_fmt)
     242                 :            : {
     243                 :            :     struct pl_gpu_t *gpu = (struct pl_gpu_t *) pgpu;
     244                 :        116 :     struct pl_gl *p = PL_PRIV(gpu);
     245                 :            : 
     246                 :        116 :     struct pl_fmt_t *fmt = pl_alloc_obj(gpu, fmt, gl_fmt);
     247                 :        116 :     const struct gl_format **fmtp = PL_PRIV(fmt);
     248                 :        116 :     *fmt = gl_fmt->tmpl;
     249                 :        116 :     *fmtp = gl_fmt;
     250                 :            : 
     251                 :            :     // Calculate the host size and number of components
     252   [ +  +  +  +  :        116 :     switch (gl_fmt->fmt) {
                      - ]
     253                 :         28 :     case GL_RED:
     254                 :            :     case GL_RED_INTEGER:
     255                 :         28 :         fmt->num_components = 1;
     256                 :         28 :         break;
     257                 :         28 :     case GL_RG:
     258                 :            :     case GL_RG_INTEGER:
     259                 :         28 :         fmt->num_components = 2;
     260                 :         28 :         break;
     261                 :         28 :     case GL_RGB:
     262                 :            :     case GL_RGB_INTEGER:
     263                 :         28 :         fmt->num_components = 3;
     264                 :         28 :         break;
     265                 :         32 :     case GL_RGBA:
     266                 :            :     case GL_RGBA_INTEGER:
     267                 :            :     case GL_BGRA:
     268                 :         32 :         fmt->num_components = 4;
     269                 :         32 :         break;
     270                 :            :     default:
     271                 :          0 :         pl_unreachable();
     272                 :            :     }
     273                 :            : 
     274                 :            :     int size;
     275   [ +  +  -  + ]:        116 :     switch (gl_fmt->type) {
     276                 :            :     case GL_BYTE:
     277                 :            :     case GL_UNSIGNED_BYTE:
     278                 :            :         size = 1;
     279                 :            :         break;
     280                 :         48 :     case GL_SHORT:
     281                 :            :     case GL_UNSIGNED_SHORT:
     282                 :            :     case GL_HALF_FLOAT:
     283                 :            :         size = 2;
     284                 :         48 :         break;
     285                 :         32 :     case GL_INT:
     286                 :            :     case GL_UNSIGNED_INT:
     287                 :            :     case GL_FLOAT:
     288                 :            :         size = 4;
     289                 :         32 :         break;
     290                 :            :     default:
     291                 :          0 :         pl_unreachable();
     292                 :            :     }
     293                 :            : 
     294                 :            :     // Host visible representation
     295                 :        116 :     fmt->texel_size = fmt->num_components * size;
     296                 :        116 :     fmt->texel_align = 1;
     297         [ +  + ]:        412 :     for (int i = 0; i < fmt->num_components; i++)
     298                 :        296 :         fmt->host_bits[i] = size * 8;
     299                 :            : 
     300                 :            :     // Compute internal size by summing up the depth
     301                 :            :     int ibits = 0;
     302         [ +  + ]:        412 :     for (int i = 0; i < fmt->num_components; i++)
     303                 :        296 :         ibits += fmt->component_depth[i];
     304                 :        116 :     fmt->internal_size = (ibits + 7) / 8;
     305                 :            : 
     306                 :            :     // We're not the ones actually emulating these texture format - the
     307                 :            :     // driver is - but we might as well set the hint.
     308                 :        116 :     fmt->emulated = fmt->texel_size != fmt->internal_size;
     309                 :            : 
     310                 :            :     // 3-component formats are almost surely also emulated
     311         [ +  + ]:        116 :     if (fmt->num_components == 3)
     312                 :         28 :         fmt->emulated = true;
     313                 :            : 
     314                 :            :     // Older OpenGL most likely emulates 32-bit float formats as well
     315   [ +  +  +  + ]:        116 :     if (p->gl_ver < 30 && fmt->component_depth[0] >= 32)
     316                 :          4 :         fmt->emulated = true;
     317                 :            : 
     318                 :            :     // For sanity, clear the superfluous fields
     319         [ +  + ]:        284 :     for (int i = fmt->num_components; i < 4; i++) {
     320                 :        168 :         fmt->component_depth[i] = 0;
     321                 :        168 :         fmt->sample_order[i] = 0;
     322                 :        168 :         fmt->host_bits[i] = 0;
     323                 :            :     }
     324                 :            : 
     325                 :        116 :     fmt->glsl_type = pl_var_glsl_type_name(pl_var_from_fmt(fmt, ""));
     326                 :        116 :     fmt->glsl_format = pl_fmt_glsl_format(fmt, fmt->num_components);
     327                 :        116 :     fmt->fourcc = pl_fmt_fourcc(fmt);
     328         [ -  + ]:        116 :     pl_assert(fmt->glsl_type);
     329                 :            : 
     330                 :            : #ifdef PL_HAVE_UNIX
     331   [ +  -  +  +  :        152 :     if (p->has_modifiers && fmt->fourcc && supported_fourcc(p, fmt->fourcc)) {
                   +  + ]
     332                 :         32 :         int num_mods = 0;
     333                 :         32 :         bool ok = eglQueryDmaBufModifiersEXT(p->egl_dpy, fmt->fourcc,
     334                 :            :                                              0, NULL, NULL, &num_mods);
     335   [ +  -  +  - ]:         32 :         if (ok && num_mods) {
     336                 :            :             // On my system eglQueryDmaBufModifiersEXT seems to never return
     337                 :            :             // MOD_INVALID even though eglExportDMABUFImageQueryMESA happily
     338                 :            :             // returns such modifiers. Since we handle INVALID by not
     339                 :            :             // requiring modifiers at all, always add this value to the
     340                 :            :             // list of supported modifiers. May result in duplicates, but
     341                 :            :             // whatever.
     342                 :         32 :             uint64_t *mods = pl_calloc(fmt, num_mods + 1, sizeof(uint64_t));
     343                 :         32 :             mods[0] = DRM_FORMAT_MOD_INVALID;
     344                 :         32 :             ok = eglQueryDmaBufModifiersEXT(p->egl_dpy, fmt->fourcc, num_mods,
     345                 :         32 :                                             &mods[1], NULL, &num_mods);
     346                 :            : 
     347         [ +  - ]:         32 :             if (ok) {
     348                 :         32 :                 fmt->modifiers = mods;
     349                 :         32 :                 fmt->num_modifiers = num_mods + 1;
     350                 :            :             } else {
     351                 :          0 :                 pl_free(mods);
     352                 :            :             }
     353                 :            :         }
     354                 :            : 
     355                 :         32 :         eglGetError(); // ignore probing errors
     356                 :            :     }
     357                 :            : 
     358         [ +  + ]:        116 :     if (!fmt->num_modifiers) {
     359                 :            :         // Hacky fallback for older drivers that don't support properly
     360                 :            :         // querying modifiers
     361                 :            :         static const uint64_t static_mods[] = {
     362                 :            :             DRM_FORMAT_MOD_INVALID,
     363                 :            :             DRM_FORMAT_MOD_LINEAR,
     364                 :            :         };
     365                 :            : 
     366                 :         84 :         fmt->num_modifiers = PL_ARRAY_SIZE(static_mods);
     367                 :         84 :         fmt->modifiers = static_mods;
     368                 :            :     }
     369                 :            : #endif
     370                 :            : 
     371                 :            :     // Gathering requires checking the format type (and extension presence)
     372         [ +  + ]:        116 :     if (fmt->caps & PL_FMT_CAP_SAMPLEABLE)
     373                 :        112 :         fmt->gatherable = p->gather_comps >= fmt->num_components;
     374                 :            : 
     375                 :            :     bool host_readable = false;
     376         [ +  + ]:        116 :     if (p->gl_ver && p->has_readback)
     377                 :            :         host_readable = true;
     378                 :            :     // Reading from textures on GLES requires FBO support for this fmt
     379         [ +  + ]:        116 :     if (fmt->caps & PL_FMT_CAP_RENDERABLE) {
     380                 :            :         // this combination always works in glReadPixels
     381   [ +  +  +  + ]:        101 :         if ((gl_fmt->fmt == GL_RGBA && gl_fmt->type == GL_UNSIGNED_BYTE) ||
     382         [ -  + ]:         97 :             p->has_readback)
     383                 :            :             host_readable = true;
     384                 :            :     }
     385         [ +  + ]:         15 :     if (host_readable)
     386                 :        107 :         fmt->caps |= PL_FMT_CAP_HOST_READABLE;
     387                 :            : 
     388   [ +  +  +  +  :        116 :     if (gpu->glsl.compute && fmt->glsl_format && p->has_storage)
                   +  - ]
     389                 :         22 :         fmt->caps |= PL_FMT_CAP_STORABLE | PL_FMT_CAP_READWRITE;
     390                 :            : 
     391                 :            :     // GLES 2 can't do blitting
     392         [ -  + ]:        116 :     if (p->gles_ver && p->gles_ver < 30)
     393                 :          0 :         fmt->caps &= ~PL_FMT_CAP_BLITTABLE;
     394                 :            : 
     395                 :            :     // Only float-type formats are considered blendable in OpenGL
     396      [ +  -  + ]:        116 :     switch (fmt->type) {
     397                 :            :     case PL_FMT_UNKNOWN:
     398                 :            :     case PL_FMT_UINT:
     399                 :            :     case PL_FMT_SINT:
     400                 :            :         break;
     401                 :         84 :     case PL_FMT_FLOAT:
     402                 :            :     case PL_FMT_UNORM:
     403                 :            :     case PL_FMT_SNORM:
     404         [ +  + ]:         84 :         if (fmt->caps & PL_FMT_CAP_RENDERABLE)
     405                 :         77 :             fmt->caps |= PL_FMT_CAP_BLENDABLE;
     406                 :            :         break;
     407                 :            :     case PL_FMT_TYPE_COUNT:
     408                 :          0 :         pl_unreachable();
     409                 :            :     }
     410                 :            : 
     411                 :            :     // TODO: Texel buffers
     412                 :            : 
     413   [ +  +  +  +  :        116 :     PL_ARRAY_APPEND_RAW(gpu, gpu->formats, gpu->num_formats, fmt);
                   -  + ]
     414                 :        116 : }
     415                 :            : 
     416                 :            : #define DO_FORMATS(formats)                                 \
     417                 :            :     do {                                                    \
     418                 :            :         for (int i = 0; i < PL_ARRAY_SIZE(formats); i++)    \
     419                 :            :             add_format(gpu, &formats[i]);                   \
     420                 :            :     } while (0)
     421                 :            : 
     422                 :          4 : bool gl_setup_formats(struct pl_gpu_t *gpu)
     423                 :            : {
     424                 :          4 :     struct pl_gl *p = PL_PRIV(gpu);
     425                 :            : 
     426                 :            : #ifdef PL_HAVE_UNIX
     427         [ +  - ]:          4 :     if (p->has_modifiers) {
     428                 :          4 :         EGLint num_formats = 0;
     429                 :          4 :         bool ok = eglQueryDmaBufFormatsEXT(p->egl_dpy, 0, NULL,
     430                 :            :                                            &num_formats);
     431   [ +  -  +  - ]:          4 :         if (ok && num_formats) {
     432                 :          4 :             p->egl_formats.elem = pl_calloc(gpu, num_formats, sizeof(EGLint));
     433                 :          4 :             p->egl_formats.num = num_formats;
     434                 :          4 :             ok = eglQueryDmaBufFormatsEXT(p->egl_dpy, num_formats,
     435                 :            :                                           p->egl_formats.elem, &num_formats);
     436         [ -  + ]:          4 :             pl_assert(ok);
     437                 :            : 
     438                 :          4 :             PL_DEBUG(gpu, "EGL formats supported:");
     439         [ +  + ]:        192 :             for (int i = 0; i < num_formats; ++i) {
     440         [ +  - ]:        188 :                 PL_DEBUG(gpu, "    0x%08x(%.4s)", p->egl_formats.elem[i],
     441                 :            :                          PRINT_FOURCC(p->egl_formats.elem[i]));
     442                 :            :             }
     443                 :            :         }
     444                 :            :     }
     445                 :            : #endif
     446                 :            : 
     447         [ +  + ]:          4 :     if (p->gl_ver >= 30) {
     448                 :            :         // Desktop GL3+ has everything
     449         [ +  + ]:         15 :         DO_FORMATS(formats_norm8);
     450         [ +  + ]:          6 :         DO_FORMATS(formats_bgra8);
     451         [ +  + ]:         12 :         DO_FORMATS(formats_norm16);
     452         [ +  + ]:          6 :         DO_FORMATS(formats_rgb16_fbo);
     453         [ +  + ]:         15 :         DO_FORMATS(formats_float32);
     454         [ +  + ]:         15 :         DO_FORMATS(formats_float16);
     455         [ +  + ]:         15 :         DO_FORMATS(formats_half16);
     456         [ +  + ]:         27 :         DO_FORMATS(formats_uint);
     457                 :          3 :         goto done;
     458                 :            :     }
     459                 :            : 
     460         [ -  + ]:          1 :     if (p->gl_ver >= 21) {
     461                 :            :         // If we have a reasonable set of extensions, we can enable most
     462                 :            :         // things. Otherwise, pick simple fallback formats
     463         [ #  # ]:          0 :         if (pl_opengl_has_ext(p->gl, "GL_ARB_texture_float") &&
     464         [ #  # ]:          0 :             pl_opengl_has_ext(p->gl, "GL_ARB_texture_rg") &&
     465         [ #  # ]:          0 :             pl_opengl_has_ext(p->gl, "GL_ARB_framebuffer_object"))
     466                 :            :         {
     467         [ #  # ]:          0 :             DO_FORMATS(formats_norm8);
     468         [ #  # ]:          0 :             DO_FORMATS(formats_bgra8);
     469         [ #  # ]:          0 :             DO_FORMATS(formats_norm16);
     470         [ #  # ]:          0 :             DO_FORMATS(formats_rgb16_fbo);
     471         [ #  # ]:          0 :             DO_FORMATS(formats_float32);
     472         [ #  # ]:          0 :             DO_FORMATS(formats_float16);
     473         [ #  # ]:          0 :             if (pl_opengl_has_ext(p->gl, "GL_ARB_half_float_pixel"))
     474                 :            :             {
     475         [ #  # ]:          0 :                 DO_FORMATS(formats_half16);
     476                 :            :             }
     477                 :            :         } else {
     478                 :            :             // Fallback for GL2
     479         [ #  # ]:          0 :             DO_FORMATS(formats_legacy_gl2);
     480         [ #  # ]:          0 :             DO_FORMATS(formats_basic_vertex);
     481                 :            :         }
     482                 :          0 :         goto done;
     483                 :            :     }
     484                 :            : 
     485         [ +  - ]:          1 :     if (p->gles_ver >= 30) {
     486                 :            :         // GLES 3.0 has some basic formats, with framebuffers for float16
     487                 :            :         // depending on GL_EXT_color_buffer_(half_)float support
     488         [ +  + ]:          5 :         DO_FORMATS(formats_norm8);
     489         [ +  - ]:          1 :         if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_norm16")) {
     490         [ +  + ]:          4 :             DO_FORMATS(formats_norm16);
     491         [ +  + ]:          2 :             DO_FORMATS(formats_rgb16_fallback);
     492                 :            :         }
     493         [ +  - ]:          1 :         if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_format_BGRA8888"))
     494         [ +  + ]:          2 :             DO_FORMATS(formats_bgra_gles);
     495         [ +  + ]:          9 :         DO_FORMATS(formats_uint);
     496         [ +  + ]:          5 :         DO_FORMATS(formats_basic_vertex);
     497   [ -  +  -  - ]:          1 :         if (p->gles_ver >= 32 || pl_opengl_has_ext(p->gl, "GL_EXT_color_buffer_float")) {
     498         [ +  + ]:          9 :             DO_FORMATS(formats_float16_fbo);
     499                 :            :         } else {
     500         [ #  # ]:          0 :             DO_FORMATS(formats_float16_fallback);
     501                 :            :         }
     502                 :          1 :         goto done;
     503                 :            :     }
     504                 :            : 
     505         [ #  # ]:          0 :     if (p->gles_ver >= 20) {
     506                 :            :         // GLES 2.0 only has some legacy fallback formats, with support for
     507                 :            :         // float16 depending on GL_EXT_texture_norm16 being present
     508         [ #  # ]:          0 :         DO_FORMATS(formats_legacy_gles2);
     509         [ #  # ]:          0 :         DO_FORMATS(formats_basic_vertex);
     510         [ #  # ]:          0 :         if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_rg")) {
     511         [ #  # ]:          0 :             DO_FORMATS(formats_norm8);
     512                 :            :         }
     513         [ #  # ]:          0 :         if (pl_opengl_has_ext(p->gl, "GL_EXT_texture_format_BGRA8888")) {
     514         [ #  # ]:          0 :             DO_FORMATS(formats_bgra_gles);
     515                 :            :         }
     516                 :          0 :         goto done;
     517                 :            :     }
     518                 :            : 
     519                 :            :     // Last resort fallback. Probably not very useful
     520         [ #  # ]:          0 :     DO_FORMATS(formats_basic_vertex);
     521                 :          0 :     goto done;
     522                 :            : 
     523                 :          4 : done:
     524                 :          4 :     return gl_check_err(gpu, "gl_setup_formats");
     525                 :            : }

Generated by: LCOV version 1.16