gallium/u_tests: test a NULL texture sampler view
[mesa.git] / src / gallium / auxiliary / util / u_tests.c
index 764c4c319444747d9bb33ea02a1944556ba36701..10111539c78a627102cc887765d42f5540ccaf49 100644 (file)
@@ -138,15 +138,70 @@ util_set_interleaved_vertex_elements(struct cso_context *cso,
    free(velem);
 }
 
+static void *
+util_set_passthrough_vertex_shader(struct cso_context *cso,
+                                   struct pipe_context *ctx,
+                                   bool window_space)
+{
+   static const uint vs_attribs[] = {
+      TGSI_SEMANTIC_POSITION,
+      TGSI_SEMANTIC_GENERIC
+   };
+   static const uint vs_indices[] = {0, 0};
+   void *vs;
+
+   vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices,
+                                            window_space);
+   cso_set_vertex_shader_handle(cso, vs);
+   return vs;
+}
+
+static void
+util_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *ctx,
+                                 struct pipe_resource *cb)
+{
+   static const float clear_color[] = {0.1, 0.1, 0.1, 0.1};
+
+   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);
+
+   ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0);
+}
+
+static void
+util_draw_fullscreen_quad(struct cso_context *cso)
+{
+   static float vertices[] = {
+     -1, -1, 0, 1,   0, 0, 0, 0,
+     -1,  1, 0, 1,   0, 1, 0, 0,
+      1,  1, 0, 1,   1, 1, 0, 0,
+      1, -1, 0, 1,   1, 0, 0, 0
+   };
+   util_set_interleaved_vertex_elements(cso, 2);
+   util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
+}
+
+/**
+ * Probe and test if the rectangle contains the expected color.
+ *
+ * If "num_expected_colors" > 1, at least one expected color must match
+ * the probed color. "expected" should be an array of 4*num_expected_colors
+ * floats.
+ */
 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)
+util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
+                           unsigned offx, unsigned offy, unsigned w,
+                           unsigned h,
+                           const float *expected,
+                           unsigned num_expected_colors)
 {
    struct pipe_transfer *transfer;
    void *map;
    float *pixels = malloc(w * h * 4 * sizeof(float));
-   int x,y,c;
+   int x,y,e,c;
    bool pass = true;
 
    map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
@@ -154,21 +209,31 @@ util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
    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;
+   for (e = 0; e < num_expected_colors; e++) {
+      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[e*4+c]) >= TOLERANCE) {
+                  if (e < num_expected_colors-1)
+                     goto next_color; /* test the next expected color */
+
+                  printf("Probe color at (%i,%i),  ", offx+x, offy+y);
+                  printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
+                         expected[e*4], expected[e*4+1],
+                         expected[e*4+2], expected[e*4+3]);
+                  printf("Got: %.3f, %.3f, %.3f, %.3f\n",
+                         probe[0], probe[1], probe[2], probe[2]);
+                  pass = false;
+                  goto done;
+               }
             }
+         }
       }
+      break; /* this color was successful */
+
+   next_color:;
    }
 done:
 
@@ -176,6 +241,30 @@ done:
    return pass;
 }
 
+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)
+{
+   return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1);
+}
+
+enum {
+   SKIP = -1,
+   FAIL = 0, /* also "false" */
+   PASS = 1 /* also "true" */
+};
+
+static void
+util_report_result_helper(const char *name, int status)
+{
+   printf("Test(%s) = %s\n", name,
+          status == SKIP ? "skip" :
+          status == PASS ? "pass" : "fail");
+}
+
+#define util_report_result(status) util_report_result_helper(__func__, status)
+
 /**
  * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
  *
@@ -196,38 +285,18 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
    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};
+   static const float red[] = {1, 0, 0, 1};
 
    if (!ctx->screen->get_param(ctx->screen,
                                PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) {
-      printf("Test(%s) = skip\n", __func__);
+      util_report_result(SKIP);
       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);
+   util_set_common_states_and_clear(cso, ctx, cb);
 
    /* Fragment shader. */
    fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
@@ -235,13 +304,19 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
    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);
+   vs = util_set_passthrough_vertex_shader(cso, ctx, true);
+
+   /* Draw. */
+   {
+      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,
+      };
+      util_set_interleaved_vertex_elements(cso, 2);
+      util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
+   }
 
    /* Probe pixels. */
    pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
@@ -253,7 +328,47 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
    ctx->delete_fs_state(ctx, fs);
    pipe_resource_reference(&cb, NULL);
 
-   printf("Test(%s) = %s\n", __func__, pass ? "pass" : "fail");
+   util_report_result(pass);
+}
+
+static void
+null_sampler_view(struct pipe_context *ctx)
+{
+   struct cso_context *cso;
+   struct pipe_resource *cb;
+   void *fs, *vs;
+   bool pass = true;
+   /* 2 expected colors: */
+   static const float expected[] = {0, 0, 0, 1,
+                                    0, 0, 0, 0};
+
+   cso = cso_create_context(ctx);
+   cb = util_create_texture2d(ctx->screen, 256, 256,
+                              PIPE_FORMAT_R8G8B8A8_UNORM);
+   util_set_common_states_and_clear(cso, ctx, cb);
+
+   ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
+
+   /* Fragment shader. */
+   fs = util_make_fragment_tex_shader(ctx, TGSI_TEXTURE_2D,
+                                      TGSI_INTERPOLATE_LINEAR);
+   cso_set_fragment_shader_handle(cso, fs);
+
+   /* Vertex shader. */
+   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+   util_draw_fullscreen_quad(cso);
+
+   /* Probe pixels. */
+   pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
+                                  cb->width0, cb->height0, expected, 2);
+
+   /* Cleanup. */
+   cso_destroy_context(cso);
+   ctx->delete_vs_state(ctx, vs);
+   ctx->delete_fs_state(ctx, fs);
+   pipe_resource_reference(&cb, NULL);
+
+   util_report_result(pass);
 }
 
 /**
@@ -266,6 +381,7 @@ util_run_tests(struct pipe_screen *screen)
    struct pipe_context *ctx = screen->context_create(screen, NULL);
 
    tgsi_vs_window_space_position(ctx);
+   null_sampler_view(ctx);
 
    ctx->destroy(ctx);