diff options
Diffstat (limited to 'src/gallium/auxiliary/util/u_tests.c')
-rw-r--r-- | src/gallium/auxiliary/util/u_tests.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c new file mode 100644 index 00000000000..9483f0699d6 --- /dev/null +++ b/src/gallium/auxiliary/util/u_tests.c @@ -0,0 +1,270 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_tests.h" + +#include "util/u_draw_quad.h" +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_simple_shaders.h" +#include "util/u_surface.h" +#include "util/u_tile.h" +#include "cso_cache/cso_context.h" +#include <stdio.h> + +#define TOLERANCE 0.01 + +static struct pipe_resource * +util_create_texture2d(struct pipe_screen *screen, unsigned width, + unsigned height, enum pipe_format format) +{ + struct pipe_resource templ = {{0}}; + + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.format = format; + templ.usage = PIPE_USAGE_DEFAULT; + templ.bind = PIPE_BIND_SAMPLER_VIEW | + (util_format_is_depth_or_stencil(format) ? + PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET); + + return screen->resource_create(screen, &templ); +} + +static void +util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx, + struct pipe_resource *tex) +{ + struct pipe_surface templ = {{0}}, *surf; + struct pipe_framebuffer_state fb = {0}; + + templ.format = tex->format; + surf = ctx->create_surface(ctx, tex, &templ); + + fb.width = tex->width0; + fb.height = tex->height0; + fb.cbufs[0] = surf; + fb.nr_cbufs = 1; + + cso_set_framebuffer(cso, &fb); + pipe_surface_reference(&surf, NULL); +} + +static void +util_set_blend_normal(struct cso_context *cso) +{ + struct pipe_blend_state blend = {0}; + + blend.rt[0].colormask = PIPE_MASK_RGBA; + cso_set_blend(cso, &blend); +} + +static void +util_set_dsa_disable(struct cso_context *cso) +{ + struct pipe_depth_stencil_alpha_state dsa = {{0}}; + + cso_set_depth_stencil_alpha(cso, &dsa); +} + +static void +util_set_rasterizer_normal(struct cso_context *cso) +{ + struct pipe_rasterizer_state rs = {0}; + + rs.half_pixel_center = 1; + rs.bottom_edge_rule = 1; + rs.depth_clip = 1; + + cso_set_rasterizer(cso, &rs); +} + +static void +util_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex) +{ + struct pipe_viewport_state viewport; + + viewport.scale[0] = 0.5f * tex->width0; + viewport.scale[1] = 0.5f * tex->height0; + viewport.scale[2] = 1.0f; + viewport.scale[3] = 1.0f; + viewport.translate[0] = 0.5f * tex->width0; + viewport.translate[1] = 0.5f * tex->height0; + viewport.translate[2] = 0.0f; + viewport.translate[3] = 0.0f; + + cso_set_viewport(cso, &viewport); +} + +static void +util_set_interleaved_vertex_elements(struct cso_context *cso, + unsigned num_elements) +{ + int i; + struct pipe_vertex_element *velem = + calloc(1, num_elements * sizeof(struct pipe_vertex_element)); + + for (i = 0; i < num_elements; i++) { + velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + velem[i].src_offset = i * 16; + } + + cso_set_vertex_elements(cso, num_elements, velem); + free(velem); +} + +static bool +util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex, + unsigned offx, unsigned offy, unsigned w, unsigned h, + const float *expected) +{ + struct pipe_transfer *transfer; + void *map; + float *pixels = malloc(w * h * 4 * sizeof(float)); + int x,y,c; + bool pass = true; + + map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ, + offx, offy, w, h, &transfer); + pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels); + pipe_transfer_unmap(ctx, transfer); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + float *probe = &pixels[(y*w + x)*4]; + + for (c = 0; c < 4; c++) + if (fabs(probe[c] - expected[c]) >= TOLERANCE) { + printf("Probe color at (%i,%i), ", offx+x, offy+y); + printf("Expected: %.3f, %.3f, %.3f, %.3f, ", + expected[0], expected[1], expected[2], expected[3]); + printf("Got: %.3f, %.3f, %.3f, %.3f\n", + probe[0], probe[1], probe[2], probe[2]); + pass = false; + goto done; + } + } + } +done: + + free(pixels); + return pass; +} + +/** + * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION. + * + * The viewport state is set as usual, but it should have no effect. + * Clipping should also be disabled. + * + * POSITION.xyz should already be multiplied by 1/w and POSITION.w should + * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't + * multiplied by 1/w (otherwise nothing would be rendered). + * + * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w + * during perspective interpolation is not tested. + */ +static void +tgsi_vs_window_space_position(struct pipe_context *ctx) +{ + struct cso_context *cso; + struct pipe_resource *cb; + void *fs, *vs; + bool pass = true; + + static uint vs_attribs[] = { + TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC + }; + static uint vs_indices[] = {0, 0}; + static float vertices[] = { + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 256, 0, 0, 1, 0, 0, 1, + 256, 256, 0, 0, 1, 0, 0, 1, + 256, 0, 0, 0, 1, 0, 0, 1, + }; + static float red[] = {1, 0, 0, 1}; + static float clear_color[] = {0.1, 0.1, 0.1, 0.1}; + + if (!ctx->screen->get_param(ctx->screen, + PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) { + printf("Test(%s) = skip\n", __func__); + return; + } + + cso = cso_create_context(ctx); + cb = util_create_texture2d(ctx->screen, 256, 256, + PIPE_FORMAT_R8G8B8A8_UNORM); + + /* Set states. */ + util_set_framebuffer_cb0(cso, ctx, cb); + util_set_blend_normal(cso); + util_set_dsa_disable(cso); + util_set_rasterizer_normal(cso); + util_set_max_viewport(cso, cb); + util_set_interleaved_vertex_elements(cso, 2); + + /* Fragment shader. */ + fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC, + TGSI_INTERPOLATE_LINEAR, TRUE); + cso_set_fragment_shader_handle(cso, fs); + + /* Vertex shader. */ + vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices, + TRUE); + cso_set_vertex_shader_handle(cso, vs); + + /* Clear and draw. */ + ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0); + util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2); + + /* Probe pixels. */ + pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, + cb->width0, cb->height0, red); + + /* Cleanup. */ + cso_release_all(cso); + cso_destroy_context(cso); + ctx->delete_vs_state(ctx, vs); + ctx->delete_fs_state(ctx, fs); + pipe_resource_reference(&cb, NULL); + + printf("Test(%s) = %s\n", __func__, pass ? "pass" : "fail"); +} + +/** + * Run all tests. This should be run with a clean context after + * context_create. + */ +void +util_run_tests(struct pipe_context *ctx) +{ + tgsi_vs_window_space_position(ctx); +} |