gallium: let state trackers tell u_vbuf whether user VBOs are possible
[mesa.git] / src / gallium / auxiliary / util / u_tests.c
index 5257b548c511ac6eb420559568c1e53c2c1d7bcf..687e5118d7c300d347757fa07070d73242dc0d29 100644 (file)
@@ -33,7 +33,9 @@
 #include "util/u_memory.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_surface.h"
+#include "util/u_string.h"
 #include "util/u_tile.h"
+#include "tgsi/tgsi_strings.h"
 #include "tgsi/tgsi_text.h"
 #include "cso_cache/cso_context.h"
 #include <stdio.h>
@@ -127,7 +129,7 @@ static void
 util_set_interleaved_vertex_elements(struct cso_context *cso,
                                      unsigned num_elements)
 {
-   int i;
+   unsigned i;
    struct pipe_vertex_element *velem =
       calloc(1, num_elements * sizeof(struct pipe_vertex_element));
 
@@ -203,7 +205,7 @@ util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
    struct pipe_transfer *transfer;
    void *map;
    float *pixels = malloc(w * h * 4 * sizeof(float));
-   int x,y,e,c;
+   unsigned x,y,e,c;
    bool pass = true;
 
    map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
@@ -258,14 +260,21 @@ enum {
 };
 
 static void
-util_report_result_helper(const char *name, int status)
+util_report_result_helper(int status, const char *name, ...)
 {
-   printf("Test(%s) = %s\n", name,
+   char buf[256];
+   va_list ap;
+
+   va_start(ap, name);
+   util_vsnprintf(buf, sizeof(buf), name, ap);
+   va_end(ap);
+
+   printf("Test(%s) = %s\n", buf,
           status == SKIP ? "skip" :
           status == PASS ? "pass" : "fail");
 }
 
-#define util_report_result(status) util_report_result_helper(__func__, status)
+#define util_report_result(status) util_report_result_helper(status, __func__)
 
 /**
  * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
@@ -295,7 +304,7 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
       return;
    }
 
-   cso = cso_create_context(ctx);
+   cso = cso_create_context(ctx, 0);
    cb = util_create_texture2d(ctx->screen, 256, 256,
                               PIPE_FORMAT_R8G8B8A8_UNORM);
    util_set_common_states_and_clear(cso, ctx, cb);
@@ -334,17 +343,28 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
 }
 
 static void
-null_sampler_view(struct pipe_context *ctx)
+null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
 {
    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};
+   static const float expected_tex[] = {0, 0, 0, 1,
+                                        0, 0, 0, 0};
+   static const float expected_buf[] = {0, 0, 0, 0};
+   const float *expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ?
+                              expected_buf : expected_tex;
+   unsigned num_expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 1 : 2;
+
+   if (tgsi_tex_target == TGSI_TEXTURE_BUFFER &&
+       !ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
+      util_report_result_helper(SKIP, "%s: %s", __func__,
+                                tgsi_texture_names[tgsi_tex_target]);
+      return;
+   }
 
-   cso = cso_create_context(ctx);
+   cso = cso_create_context(ctx, 0);
    cb = util_create_texture2d(ctx->screen, 256, 256,
                               PIPE_FORMAT_R8G8B8A8_UNORM);
    util_set_common_states_and_clear(cso, ctx, cb);
@@ -352,8 +372,10 @@ null_sampler_view(struct pipe_context *ctx)
    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);
+   fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
+                                      TGSI_INTERPOLATE_LINEAR,
+                                      TGSI_RETURN_TYPE_FLOAT,
+                                      TGSI_RETURN_TYPE_FLOAT);
    cso_set_fragment_shader_handle(cso, fs);
 
    /* Vertex shader. */
@@ -362,7 +384,8 @@ null_sampler_view(struct pipe_context *ctx)
 
    /* Probe pixels. */
    pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
-                                  cb->width0, cb->height0, expected, 2);
+                                  cb->width0, cb->height0, expected,
+                                  num_expected);
 
    /* Cleanup. */
    cso_destroy_context(cso);
@@ -370,7 +393,8 @@ null_sampler_view(struct pipe_context *ctx)
    ctx->delete_fs_state(ctx, fs);
    pipe_resource_reference(&cb, NULL);
 
-   util_report_result(pass);
+   util_report_result_helper(pass, "%s: %s", __func__,
+                             tgsi_texture_names[tgsi_tex_target]);
 }
 
 static void
@@ -382,7 +406,7 @@ null_constant_buffer(struct pipe_context *ctx)
    bool pass = true;
    static const float zero[] = {0, 0, 0, 0};
 
-   cso = cso_create_context(ctx);
+   cso = cso_create_context(ctx, 0);
    cb = util_create_texture2d(ctx->screen, 256, 256,
                               PIPE_FORMAT_R8G8B8A8_UNORM);
    util_set_common_states_and_clear(cso, ctx, cb);
@@ -399,13 +423,14 @@ null_constant_buffer(struct pipe_context *ctx)
             "MOV OUT[0], CONST[0]\n"
             "END\n";
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
 
-      if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
+      if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
          puts("Can't compile a fragment shader.");
          util_report_result(FAIL);
          return;
       }
+      pipe_shader_state_from_tgsi(&state, tokens);
       fs = ctx->create_fs_state(ctx, &state);
       cso_set_fragment_shader_handle(cso, fs);
    }
@@ -427,6 +452,43 @@ null_constant_buffer(struct pipe_context *ctx)
    util_report_result(pass);
 }
 
+static void
+null_fragment_shader(struct pipe_context *ctx)
+{
+   struct cso_context *cso;
+   struct pipe_resource *cb;
+   void *vs;
+   struct pipe_rasterizer_state rs = {0};
+   struct pipe_query *query;
+   union pipe_query_result qresult;
+
+   cso = cso_create_context(ctx, 0);
+   cb = util_create_texture2d(ctx->screen, 256, 256,
+                              PIPE_FORMAT_R8G8B8A8_UNORM);
+   util_set_common_states_and_clear(cso, ctx, cb);
+
+   /* No rasterization. */
+   rs.rasterizer_discard = 1;
+   cso_set_rasterizer(cso, &rs);
+
+   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+
+   query = ctx->create_query(ctx, PIPE_QUERY_PRIMITIVES_GENERATED, 0);
+   ctx->begin_query(ctx, query);
+   util_draw_fullscreen_quad(cso);
+   ctx->end_query(ctx, query);
+   ctx->get_query_result(ctx, query, true, &qresult);
+
+   /* Cleanup. */
+   cso_destroy_context(cso);
+   ctx->delete_vs_state(ctx, vs);
+   ctx->destroy_query(ctx, query);
+   pipe_resource_reference(&cb, NULL);
+
+   /* Check PRIMITIVES_GENERATED. */
+   util_report_result(qresult.u64 == 2);
+}
+
 /**
  * Run all tests. This should be run with a clean context after
  * context_create.
@@ -434,10 +496,12 @@ null_constant_buffer(struct pipe_context *ctx)
 void
 util_run_tests(struct pipe_screen *screen)
 {
-   struct pipe_context *ctx = screen->context_create(screen, NULL);
+   struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
 
+   null_fragment_shader(ctx);
    tgsi_vs_window_space_position(ctx);
-   null_sampler_view(ctx);
+   null_sampler_view(ctx, TGSI_TEXTURE_2D);
+   null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
    null_constant_buffer(ctx);
 
    ctx->destroy(ctx);