2 * Copyright (C) 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * Common image format, target and shader stage metadata.
32 image_optimal_extent(struct image_extent ext
)
34 const unsigned n
= product(ext
);
35 const unsigned w
= 1 << MIN2(ffs(n
) - 1, (int)log2(n
) / 2);
36 const struct image_extent opt
= {
43 const struct image_format_info image_formats_load_store
[] = {
44 { "rgba32f", GL_RGBA32F
, GL_RGBA
, GL_FLOAT
, { 32, 32, 32, 32 } },
45 { "rgba16f", GL_RGBA16F
, GL_RGBA
, GL_HALF_FLOAT
, { 16, 16, 16, 16 } },
46 { "rg32f", GL_RG32F
, GL_RG
, GL_FLOAT
, { 32, 32, 0, 0 } },
47 { "rg16f", GL_RG16F
, GL_RG
, GL_HALF_FLOAT
, { 16, 16, 0, 0 } },
48 { "r11f_g11f_b10f", GL_R11F_G11F_B10F
, GL_RGB
, GL_UNSIGNED_INT_10F_11F_11F_REV
, { 11, 11, 10, 0 } },
49 { "r32f", GL_R32F
, GL_RED
, GL_FLOAT
, { 32, 0, 0, 0 } },
50 { "r16f", GL_R16F
, GL_RED
, GL_HALF_FLOAT
, { 16, 0, 0, 0 } },
51 { "rgba32ui", GL_RGBA32UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_INT
, { 32, 32, 32, 32 } },
52 { "rgba16ui", GL_RGBA16UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_SHORT
, { 16, 16, 16, 16 } },
53 { "rgb10_a2ui", GL_RGB10_A2UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_INT_2_10_10_10_REV
, { 10, 10, 10, 2 } },
54 { "rgba8ui", GL_RGBA8UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_BYTE
, { 8, 8, 8, 8 } },
55 { "rg32ui", GL_RG32UI
, GL_RG_INTEGER
, GL_UNSIGNED_INT
, { 32, 32, 0, 0 } },
56 { "rg16ui", GL_RG16UI
, GL_RG_INTEGER
, GL_UNSIGNED_SHORT
, { 16, 16, 0, 0 } },
57 { "rg8ui", GL_RG8UI
, GL_RG_INTEGER
, GL_UNSIGNED_BYTE
, { 8, 8, 0, 0 } },
58 { "r32ui", GL_R32UI
, GL_RED_INTEGER
, GL_UNSIGNED_INT
, { 32, 0, 0, 0 } },
59 { "r16ui", GL_R16UI
, GL_RED_INTEGER
, GL_UNSIGNED_SHORT
, { 16, 0, 0, 0 } },
60 { "r8ui", GL_R8UI
, GL_RED_INTEGER
, GL_UNSIGNED_BYTE
, { 8, 0, 0, 0 } },
61 { "rgba32i", GL_RGBA32I
, GL_RGBA_INTEGER
, GL_INT
, { 32, 32, 32, 32 } },
62 { "rgba16i", GL_RGBA16I
, GL_RGBA_INTEGER
, GL_SHORT
, { 16, 16, 16, 16 } },
63 { "rgba8i", GL_RGBA8I
, GL_RGBA_INTEGER
, GL_BYTE
, { 8, 8, 8, 8 } },
64 { "rg32i", GL_RG32I
, GL_RG_INTEGER
, GL_INT
, { 32, 32, 0, 0 } },
65 { "rg16i", GL_RG16I
, GL_RG_INTEGER
, GL_SHORT
, { 16, 16, 0, 0 } },
66 { "rg8i", GL_RG8I
, GL_RG_INTEGER
, GL_BYTE
, { 8, 8, 0, 0 } },
67 { "r32i", GL_R32I
, GL_RED_INTEGER
, GL_INT
, { 32, 0, 0, 0 } },
68 { "r16i", GL_R16I
, GL_RED_INTEGER
, GL_SHORT
, { 16, 0, 0, 0 } },
69 { "r8i", GL_R8I
, GL_RED_INTEGER
, GL_BYTE
, { 8, 0, 0, 0 } },
70 { "rgba16", GL_RGBA16
, GL_RGBA
, GL_UNSIGNED_SHORT
, { 16, 16, 16, 16 } },
71 { "rgb10_a2", GL_RGB10_A2
, GL_RGBA
, GL_UNSIGNED_INT_2_10_10_10_REV
, { 10, 10, 10, 2 } },
72 { "rgba8", GL_RGBA8
, GL_RGBA
, GL_UNSIGNED_BYTE
, { 8, 8, 8, 8 } },
73 { "rg16", GL_RG16
, GL_RG
, GL_UNSIGNED_SHORT
, { 16, 16, 0, 0 } },
74 { "rg8", GL_RG8
, GL_RG
, GL_UNSIGNED_BYTE
, { 8, 8, 0, 0 } },
75 { "r16", GL_R16
, GL_RED
, GL_UNSIGNED_SHORT
, { 16, 0, 0, 0 } },
76 { "r8", GL_R8
, GL_RED
, GL_UNSIGNED_BYTE
, { 8, 0, 0, 0 } },
77 { "rgba16_snorm", GL_RGBA16_SNORM
, GL_RGBA
, GL_SHORT
, { 16, 16, 16, 16 } },
78 { "rgba8_snorm", GL_RGBA8_SNORM
, GL_RGBA
, GL_BYTE
, { 8, 8, 8, 8 } },
79 { "rg16_snorm", GL_RG16_SNORM
, GL_RG
, GL_SHORT
, { 16, 16, 0, 0 } },
80 { "rg8_snorm", GL_RG8_SNORM
, GL_RG
, GL_BYTE
, { 8, 8, 0, 0 } },
81 { "r16_snorm", GL_R16_SNORM
, GL_RED
, GL_SHORT
, { 16, 0, 0, 0 } },
82 { "r8_snorm", GL_R8_SNORM
, GL_RED
, GL_BYTE
, { 8, 0, 0, 0 } },
86 const struct image_format_info image_formats_atomic
[] = {
87 { "r32ui", GL_R32UI
, GL_RED_INTEGER
, GL_UNSIGNED_INT
, { 32, 0, 0, 0 } },
88 { "r32i", GL_R32I
, GL_RED_INTEGER
, GL_INT
, { 32, 0, 0, 0 } },
92 const struct image_format_info
*
93 get_image_format(GLenum f
)
95 const struct image_format_info
*format
;
97 for (format
= image_formats_load_store
; format
->format
; ++format
) {
98 if (format
->format
== f
)
106 * Information specific to an image base data type as seen by the
109 struct image_type_info
{
110 /** Logical base format as seen by the shader. */
113 /** Logical component type as seen by the shader. */
116 /** Logical internal format as seen by the shader. */
117 GLenum base_internal_format
;
119 /** Matching GLSL component data type. */
120 const char *scalar_type_name
;
122 /** Matching GLSL vector data type. */
123 const char *vector_type_name
;
125 /** GLSL image type prefix ("i", "u" or ""). */
126 const char *image_type_name
;
129 static const struct image_type_info
*
130 get_image_type(const struct image_format_info
*format
)
132 switch (format
->pixel_format
) {
137 static const struct image_type_info type
= {
138 GL_RGBA
, GL_FLOAT
, GL_RGBA32F
,
139 "float", "vec4", "image"
143 case GL_RGBA_INTEGER
:
146 switch (format
->pixel_type
) {
150 static const struct image_type_info type
= {
151 GL_RGBA_INTEGER
, GL_INT
, GL_RGBA32I
,
152 "int", "ivec4", "iimage"
156 case GL_UNSIGNED_INT
:
157 case GL_UNSIGNED_SHORT
:
158 case GL_UNSIGNED_INT_2_10_10_10_REV
:
159 case GL_UNSIGNED_BYTE
: {
160 static const struct image_type_info type
= {
161 GL_RGBA_INTEGER
, GL_UNSIGNED_INT
, GL_RGBA32UI
,
162 "uint", "uvec4", "uimage"
175 image_base_format(const struct image_format_info
*format
)
177 return get_image_type(format
)->base_format
;
181 image_base_type(const struct image_format_info
*format
)
183 return get_image_type(format
)->base_type
;
187 image_base_internal_format(const struct image_format_info
*format
)
189 return get_image_type(format
)->base_internal_format
;
193 image_scalar_type_name(const struct image_format_info
*format
)
195 return get_image_type(format
)->scalar_type_name
;
199 image_vector_type_name(const struct image_format_info
*format
)
201 return get_image_type(format
)->vector_type_name
;
205 image_type_name(const struct image_format_info
*format
)
207 return get_image_type(format
)->image_type_name
;
211 image_pixel_size(const struct image_format_info
*format
)
213 return format
->bits
[0] + format
->bits
[1] +
214 format
->bits
[2] + format
->bits
[3];
218 image_compat_format(const struct image_format_info
*format
)
220 const unsigned bits
= image_pixel_size(format
);
244 image_num_components(const struct image_format_info
*format
)
246 return (!!format
->bits
[0] + !!format
->bits
[1] +
247 !!format
->bits
[2] + !!format
->bits
[3]);
251 image_format_scale(const struct image_format_info
*format
)
253 struct image_datum v
= { 0.0 };
256 for (i
= 0; i
< 4 && format
->bits
[i
]; ++i
) {
257 switch (image_base_type(format
)) {
263 set_idx(v
, i
, 1u << (format
->bits
[i
] - 2));
266 case GL_UNSIGNED_INT
:
267 set_idx(v
, i
, 1u << (format
->bits
[i
] - 1));
279 image_channel_fraction_bits(const struct image_format_info
*format
, unsigned i
)
281 if (image_base_type(format
) == GL_FLOAT
&& format
->bits
[i
]) {
282 switch (format
->pixel_type
) {
289 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
290 return format
->bits
[i
] - 5;
294 return format
->bits
[i
] - 1;
296 case GL_UNSIGNED_SHORT
:
297 case GL_UNSIGNED_INT_2_10_10_10_REV
:
298 case GL_UNSIGNED_BYTE
:
299 return format
->bits
[i
];
310 image_format_epsilon(const struct image_format_info
*format
)
312 struct image_datum v
= { 0.0 };
315 for (i
= 0; i
< 4; ++i
) {
316 unsigned p
= image_channel_fraction_bits(format
, i
);
317 set_idx(v
, i
, (p
? MAX2(1.0 / ((1 << p
) - 1), 1e-5) : 0));
324 encode(const struct image_format_info
*format
, double x
)
326 switch (image_base_type(format
)) {
327 case GL_UNSIGNED_INT
:
342 decode(const struct image_format_info
*format
, uint32_t x
)
344 switch (image_base_type(format
)) {
345 case GL_UNSIGNED_INT
:
359 const struct image_target_info
*
362 const struct image_target_info known
[] = {
363 { "1D", GL_TEXTURE_1D
, "int" },
364 { "2D", GL_TEXTURE_2D
, "ivec2" },
365 { "3D", GL_TEXTURE_3D
, "ivec3" },
366 { "2DRect", GL_TEXTURE_RECTANGLE
, "ivec2" },
367 { "Cube", GL_TEXTURE_CUBE_MAP
, "ivec3" },
368 { "Buffer", GL_TEXTURE_BUFFER
, "int" },
369 { "1DArray", GL_TEXTURE_1D_ARRAY
, "ivec2" },
370 { "2DArray", GL_TEXTURE_2D_ARRAY
, "ivec3" },
371 { "CubeArray", GL_TEXTURE_CUBE_MAP_ARRAY
, "ivec3" },
372 { "2DMS", GL_TEXTURE_2D_MULTISAMPLE
, "ivec2" },
373 { "2DMSArray", GL_TEXTURE_2D_MULTISAMPLE_ARRAY
, "ivec3" },
376 static struct image_target_info supported
[ARRAY_SIZE(known
)];
378 if (!supported
[0].name
) {
379 int max_samples
= 0, i
, n
= 0;
381 glGetIntegerv(GL_MAX_IMAGE_SAMPLES
, &max_samples
);
383 for (i
= 0; i
< ARRAY_SIZE(known
); ++i
) {
384 if ((known
[i
].target
!= GL_TEXTURE_2D_MULTISAMPLE
&&
385 known
[i
].target
!= GL_TEXTURE_2D_MULTISAMPLE_ARRAY
) ||
387 supported
[n
++] = known
[i
];
395 const struct image_target_info
*
396 get_image_target(GLenum t
)
398 const struct image_target_info
*target
;
400 for (target
= image_targets(); target
->target
; ++target
) {
401 if (target
->target
== t
)
409 image_target_limits(const struct image_target_info
*target
)
411 struct image_extent ext
= { 1, 1, 1, 1 };
413 switch (target
->target
) {
415 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.x
);
419 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.x
);
420 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.y
);
424 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, (int *)&ext
.x
);
425 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, (int *)&ext
.y
);
426 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, (int *)&ext
.z
);
429 case GL_TEXTURE_RECTANGLE
:
430 glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE
, (int *)&ext
.x
);
431 glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE
, (int *)&ext
.y
);
434 case GL_TEXTURE_CUBE_MAP
:
435 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, (int *)&ext
.x
);
436 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, (int *)&ext
.y
);
440 case GL_TEXTURE_BUFFER
:
441 glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE
, (int *)&ext
.x
);
444 case GL_TEXTURE_1D_ARRAY
:
445 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.x
);
446 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, (int *)&ext
.y
);
449 case GL_TEXTURE_2D_ARRAY
:
450 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.x
);
451 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.y
);
452 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, (int *)&ext
.z
);
455 case GL_TEXTURE_CUBE_MAP_ARRAY
:
456 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, (int *)&ext
.x
);
457 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, (int *)&ext
.y
);
458 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, (int *)&ext
.z
);
461 case GL_TEXTURE_2D_MULTISAMPLE
:
462 glGetIntegerv(GL_MAX_IMAGE_SAMPLES
, (int *)&ext
.x
);
463 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.y
);
464 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.z
);
467 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
468 glGetIntegerv(GL_MAX_IMAGE_SAMPLES
, (int *)&ext
.x
);
469 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.y
);
470 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (int *)&ext
.z
);
471 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, (int *)&ext
.w
);
482 image_target_samples(const struct image_target_info
*target
)
484 if (target
->target
== GL_TEXTURE_2D_MULTISAMPLE
||
485 target
->target
== GL_TEXTURE_2D_MULTISAMPLE_ARRAY
) {
486 return image_target_limits(target
).x
;
493 image_extent_for_target(const struct image_target_info
*target
,
494 unsigned w
, unsigned h
)
496 switch (target
->target
) {
497 case GL_TEXTURE_1D
: {
498 struct image_extent ext
= { w
* h
, 1, 1, 1 };
501 case GL_TEXTURE_2D
: {
502 struct image_extent ext
= { w
, h
, 1, 1 };
505 case GL_TEXTURE_3D
: {
506 struct image_extent ext
= { w
, w
, h
/ w
, 1 };
509 case GL_TEXTURE_RECTANGLE
: {
510 struct image_extent ext
= { w
, h
, 1, 1 };
513 case GL_TEXTURE_CUBE_MAP
: {
514 struct image_extent ext
= { w
, w
, h
/ w
, 1 };
518 case GL_TEXTURE_BUFFER
: {
519 struct image_extent ext
= { w
* h
, 1, 1, 1 };
522 case GL_TEXTURE_1D_ARRAY
: {
523 struct image_extent ext
= { w
, h
, 1, 1 };
526 case GL_TEXTURE_2D_ARRAY
: {
527 struct image_extent ext
= { w
, w
, h
/ w
, 1 };
530 case GL_TEXTURE_CUBE_MAP_ARRAY
: {
531 struct image_extent ext
= { w
, w
, h
/ w
, 1 };
532 assert(ext
.z
% 6 == 0);
535 case GL_TEXTURE_2D_MULTISAMPLE
: {
536 struct image_extent ext
= { 2, w
/ 2, h
, 1 };
539 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
: {
540 struct image_extent ext
= { 2, w
/ 2, w
, h
/ w
};
549 image_layer_target(const struct image_target_info
*target
)
551 switch (target
->target
) {
553 case GL_TEXTURE_1D_ARRAY
:
554 return GL_TEXTURE_1D
;
558 case GL_TEXTURE_CUBE_MAP
:
559 case GL_TEXTURE_2D_ARRAY
:
560 case GL_TEXTURE_CUBE_MAP_ARRAY
:
561 return GL_TEXTURE_2D
;
563 case GL_TEXTURE_RECTANGLE
:
564 return GL_TEXTURE_RECTANGLE
;
566 case GL_TEXTURE_BUFFER
:
567 return GL_TEXTURE_BUFFER
;
569 case GL_TEXTURE_2D_MULTISAMPLE
:
570 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
571 return GL_TEXTURE_2D_MULTISAMPLE
;
579 image_target_mipmapping_dimensions(const struct image_target_info
*target
)
581 switch (target
->target
) {
582 case GL_TEXTURE_RECTANGLE
:
583 case GL_TEXTURE_BUFFER
:
584 case GL_TEXTURE_2D_MULTISAMPLE
:
585 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
589 case GL_TEXTURE_1D_ARRAY
:
593 case GL_TEXTURE_CUBE_MAP
:
594 case GL_TEXTURE_2D_ARRAY
:
595 case GL_TEXTURE_CUBE_MAP_ARRAY
:
606 const struct image_stage_info
*
607 known_image_stages(void)
609 static const struct image_stage_info known
[] = {
610 { "Vertex", GL_VERTEX_SHADER
, GL_VERTEX_SHADER_BIT
},
611 { "Tessellation control", GL_TESS_CONTROL_SHADER
,
612 GL_TESS_CONTROL_SHADER_BIT
},
613 { "Tessellation evaluation", GL_TESS_EVALUATION_SHADER
,
614 GL_TESS_EVALUATION_SHADER_BIT
},
615 { "Geometry", GL_GEOMETRY_SHADER
, GL_GEOMETRY_SHADER_BIT
},
616 { "Fragment", GL_FRAGMENT_SHADER
, GL_FRAGMENT_SHADER_BIT
},
617 { "Compute", GL_COMPUTE_SHADER
, GL_COMPUTE_SHADER_BIT
},
623 const struct image_stage_info
*
626 static struct image_stage_info supported
[7];
628 if (!supported
[0].name
) {
629 const struct image_stage_info
*stage
;
632 for (stage
= known_image_stages(); stage
->stage
; ++stage
) {
633 if (image_stage_max_images(stage
)) {
634 assert(n
< ARRAY_SIZE(supported
) - 1);
635 supported
[n
++] = *stage
;
643 const struct image_stage_info
*
644 get_image_stage(GLenum s
)
646 const struct image_stage_info
*stage
;
648 for (stage
= image_stages(); stage
->stage
; ++stage
) {
649 if (stage
->stage
== s
)
657 * Get the number of images internally required by the framework for a
658 * pipeline with the given set of stages.
661 num_reserved_images(GLbitfield stages
)
663 /* One image uniform is reserved in the compute stage for the
664 * grid framework to read back the result of the program.
666 return (stages
& GL_COMPUTE_SHADER_BIT
? 1 : 0);
670 image_stage_max_images(const struct image_stage_info
*stage
)
674 switch (stage
->stage
) {
675 case GL_FRAGMENT_SHADER
:
676 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS
, &n
);
679 case GL_VERTEX_SHADER
:
680 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS
, &n
);
683 case GL_GEOMETRY_SHADER
:
684 if (piglit_get_gl_version() >= 32)
685 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS
, &n
);
688 case GL_TESS_CONTROL_SHADER
:
689 if (piglit_is_extension_supported("GL_ARB_tessellation_shader"))
690 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS
, &n
);
693 case GL_TESS_EVALUATION_SHADER
:
694 if (piglit_is_extension_supported("GL_ARB_tessellation_shader"))
695 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS
,
699 case GL_COMPUTE_SHADER
:
700 if (piglit_is_extension_supported("GL_ARB_compute_shader"))
701 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS
, &n
);
705 return MAX2(0, n
- num_reserved_images(stage
->bit
));
709 max_combined_images(void)
713 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS
, &n
);
714 return MAX2(0, n
- num_reserved_images(~0));
718 max_image_units(void)
722 glGetIntegerv(GL_MAX_IMAGE_UNITS
, &n
);
723 return MAX2(0, n
- num_reserved_images(~0));
727 image_num_layers(const struct image_info img
)
729 switch (image_layer_target(img
.target
)) {
736 case GL_TEXTURE_2D_MULTISAMPLE
:
745 image_num_levels(const struct image_info img
)
747 const unsigned d
= image_target_mipmapping_dimensions(img
.target
);
748 unsigned i
, size
= 1;
750 for (i
= 0; i
< d
; ++i
)
751 size
= MAX2(size
, get_idx(img
.size
, i
));
753 return (unsigned)log2(size
) + 1;
757 image_level_size(const struct image_info img
, unsigned l
)
759 const unsigned d
= image_target_mipmapping_dimensions(img
.target
);
760 struct image_extent size
;
763 for (i
= 0; i
< d
; ++i
)
764 set_idx(size
, i
, MAX2(get_idx(img
.size
, i
) >> l
, 1));
766 for (i
= d
; i
< 4; ++i
)
767 set_idx(size
, i
, get_idx(img
.size
, i
));