1 /*
2  * Copyright (C) 2014 Intel Corporation
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * IN THE SOFTWARE.
22  */
23 
24 /** @file level.c
25  *
26  * Test the binding of individual mipmap levels to an image unit by
27  * dumping the whole accessible contents of an image to the
28  * framebuffer and then checking that the observed values match the
29  * bound mipmap level.  The same mipmap level is then overwritten by
30  * the shader program after its contents have been read.
31  */
32 
33 #include "common.h"
34 
35 /** Window width. */
36 #define W 16
37 
38 /** Window height. */
39 #define H 96
40 
41 /** Total number of pixels in the window and image. */
42 #define N (W * H)
43 
44 /** Maximum number of mipmap levels. */
45 #define M 11
46 
47 PIGLIT_GL_TEST_CONFIG_BEGIN
48 
49 config.supports_gl_core_version = 32;
50 
51 config.window_width = W;
52 config.window_height = H;
53 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
54 config.khr_no_error_support = PIGLIT_NO_ERRORS;
55 
56 PIGLIT_GL_TEST_CONFIG_END
57 
58 static bool
init_image(const struct image_info img,unsigned l)59 init_image(const struct image_info img, unsigned l)
60 {
61         const unsigned num_levels = image_num_levels(img);
62         uint32_t pixels[4 * N * M];
63         unsigned i;
64 
65         for (i = 0; i < 4 * N * num_levels; ++i)
66                 pixels[i] = encode(img.format, i);
67 
68         return upload_image_levels(img, num_levels, l, 0, pixels);
69 }
70 
71 static bool
check_fb(const struct grid_info grid,const struct image_info img,unsigned l)72 check_fb(const struct grid_info grid, const struct image_info img, unsigned l)
73 {
74         const unsigned offset = 4 * image_level_offset(img, l);
75         const unsigned n = 4 * product(grid.size);
76         uint32_t pixels_fb[4 * N], expect_fb[4 * N];
77         unsigned i;
78 
79         if (!download_result(grid, pixels_fb))
80                 return false;
81 
82         for (i = 0; i < n; ++i) {
83                 /*
84                  * The framebuffer contents should reflect level l of
85                  * the image which is read by the shader program.
86                  */
87                 expect_fb[i] = encode(grid.format, offset + i);
88         }
89 
90         if (!check_pixels_v(image_info_for_grid(grid), pixels_fb, expect_fb)) {
91                 printf("  Source: framebuffer\n");
92                 return false;
93         }
94 
95         return true;
96 }
97 
98 static bool
check_img(const struct image_info img,unsigned l)99 check_img(const struct image_info img, unsigned l)
100 {
101         const unsigned num_levels = image_num_levels(img);
102         uint32_t pixels_img[4 * N * M], expect_img[4 * N];
103         unsigned i, j;
104 
105         if (!download_image_levels(img, num_levels, 0, pixels_img))
106                 return false;
107 
108         for (j = 0; j < num_levels; ++j) {
109                 const struct image_info level_img = image_info_for_level(img, j);
110                 const unsigned offset = 4 * image_level_offset(img, j);
111                 const unsigned n = 4 * product(level_img.size);
112 
113                 for (i = 0; i < n; ++i) {
114                         if (j == l) {
115                                 /*
116                                  * Level l should have been modified
117                                  * by the shader.
118                                  */
119                                 expect_img[i] = encode(img.format, 33);
120                         } else {
121                                 /*
122                                  * Other levels should have remained
123                                  * unchanged.
124                                  */
125                                 expect_img[i] = encode(img.format, offset + i);
126                         }
127                 }
128 
129                 if (!check_pixels_v(level_img, &pixels_img[offset],
130                                     expect_img)) {
131                         printf("  Source: image level %d\n", j);
132                         return false;
133                 }
134         }
135 
136         return true;
137 }
138 
139 /**
140  * Bind an individual level of a texture mipmap to an image unit, read
141  * its contents and write back a different value to the same location.
142  */
143 static bool
run_test(const struct image_target_info * target)144 run_test(const struct image_target_info *target)
145 {
146         const unsigned level = 3;
147         const struct image_info img = image_info(
148                 target->target, GL_RGBA32F, W, H);
149         const struct image_info level_img = image_info_for_level(img, level);
150         const struct grid_info grid = {
151                 GL_FRAGMENT_SHADER_BIT, img.format,
152                 image_optimal_extent(level_img.size)
153         };
154         GLuint prog = generate_program(
155                 grid, GL_FRAGMENT_SHADER,
156                 concat(image_hunk(level_img, ""),
157                        hunk("IMAGE_UNIFORM_T img;\n"
158                             "\n"
159                             "GRID_T op(ivec2 idx, GRID_T x) {\n"
160                             "        GRID_T v = imageLoad(img, IMAGE_ADDR(idx));\n"
161                             "        imageStore(img, IMAGE_ADDR(idx), DATA_T(33));\n"
162                             "        return v;\n"
163                             "}\n"), NULL));
164         bool ret = prog && init_fb(grid) &&
165                 init_image(img, level) &&
166                 set_uniform_int(prog, "img", 0) &&
167                 draw_grid(grid, prog) &&
168                 check_fb(grid, img, level) &&
169                 check_img(img, level);
170 
171         glDeleteProgram(prog);
172         return ret;
173 }
174 
175 void
piglit_init(int argc,char ** argv)176 piglit_init(int argc, char **argv)
177 {
178         enum piglit_result status = PIGLIT_PASS;
179         const struct image_target_info *target;
180 
181         piglit_require_extension("GL_ARB_shader_image_load_store");
182 
183         for (target = image_targets(); target->name; ++target) {
184                 if (image_target_mipmapping_dimensions(target))
185                         subtest(&status, true, run_test(target),
186                                 "%s level binding test", target->name);
187         }
188 
189         piglit_report_result(status);
190 }
191 
192 enum piglit_result
piglit_display(void)193 piglit_display(void)
194 {
195         return PIGLIT_FAIL;
196 }
197