i915g: Implement vertex textures.
authorStéphane Marchesin <marcheu@chromium.org>
Sun, 9 Oct 2011 06:54:53 +0000 (23:54 -0700)
committerStéphane Marchesin <marcheu@chromium.org>
Sun, 9 Oct 2011 06:54:53 +0000 (23:54 -0700)
src/gallium/drivers/i915/i915_context.c
src/gallium/drivers/i915/i915_context.h
src/gallium/drivers/i915/i915_screen.c
src/gallium/drivers/i915/i915_state.c

index 1b30309bb587c747dabeb883c86b41a269051c86..ff6d715b72ad532d2fa7da12e2265ccb81ea2a3f 100644 (file)
@@ -79,6 +79,11 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    else
       draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, NULL, 0);
 
+   if (i915->num_vertex_sampler_views > 0)
+      i915_prepare_vertex_sampling(i915,
+                                   i915->num_vertex_sampler_views,
+                                   i915->vertex_sampler_views);
+
    /*
     * Do the drawing
     */
@@ -86,6 +91,9 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 
    if (mapped_indices)
       draw_set_mapped_index_buffer(draw, NULL);
+
+   if (i915->num_vertex_sampler_views > 0)
+      i915_cleanup_vertex_sampling(i915);
 }
 
 
index dacd0a669c156324c8a5cb8fa7bf15bca30fc4ad..7f67f5f1340e98b0eaebb5f345b75e8046b7418e 100644 (file)
@@ -225,6 +225,7 @@ struct i915_context {
     */
    const struct i915_blend_state           *blend;
    const struct i915_sampler_state         *sampler[PIPE_MAX_SAMPLERS];
+   struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
    const struct i915_depth_stencil_state   *depth_stencil;
    const struct i915_rasterizer_state      *rasterizer;
 
@@ -238,13 +239,19 @@ struct i915_context {
    struct pipe_poly_stipple poly_stipple;
    struct pipe_scissor_state scissor;
    struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
+   struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_SAMPLERS];
    struct pipe_viewport_state viewport;
    struct pipe_index_buffer index_buffer;
 
    unsigned dirty;
 
+   struct pipe_resource *mapped_vs_tex[PIPE_MAX_VERTEX_SAMPLERS];
+   struct i915_winsys_buffer* mapped_vs_tex_buffer[PIPE_MAX_VERTEX_SAMPLERS];
+
    unsigned num_samplers;
    unsigned num_fragment_sampler_views;
+   unsigned num_vertex_samplers;
+   unsigned num_vertex_sampler_views;
 
    struct i915_winsys_batchbuffer *batch;
 
@@ -360,6 +367,16 @@ struct draw_stage *i915_draw_render_stage( struct i915_context *i915 );
 struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 );
 
 
+/***********************************************************************
+ * i915_state.c:
+ */
+void i915_prepare_vertex_sampling(struct i915_context *i915,
+                                  unsigned num,
+                                  struct pipe_sampler_view **views);
+void i915_cleanup_vertex_sampling(struct i915_context *i915);
+
+
+
 /***********************************************************************
  * i915_state_emit.c: 
  */
index cc818351577db5bbe80846ce38bdca0e1c87d574..7d9b8653ea664d38a7b40e5d80eb95083f1b88bc 100644 (file)
@@ -99,6 +99,69 @@ i915_get_name(struct pipe_screen *screen)
    return buffer;
 }
 
+static int
+i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap cap)
+{
+   switch(shader) {
+   case PIPE_SHADER_VERTEX:
+      switch (cap) {
+      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+         if (debug_get_bool_option("DRAW_USE_LLVM", TRUE))
+            return PIPE_MAX_VERTEX_SAMPLERS;
+         else
+            return 0;
+      default:
+         return draw_get_shader_param(shader, cap);
+      }
+   case PIPE_SHADER_FRAGMENT:
+      /* XXX: these are just shader model 2.0 values, fix this! */
+      switch(cap) {
+      case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+         return 96;
+      case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+         return 64;
+      case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+         return 32;
+      case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+         return 8;
+      case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+         return 0;
+      case PIPE_SHADER_CAP_MAX_INPUTS:
+         return 10;
+      case PIPE_SHADER_CAP_MAX_CONSTS:
+         return 32;
+      case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+         return 1;
+      case PIPE_SHADER_CAP_MAX_TEMPS:
+         return 12; /* XXX: 12 -> 32 ? */
+      case PIPE_SHADER_CAP_MAX_ADDRS:
+         return 0;
+      case PIPE_SHADER_CAP_MAX_PREDS:
+         return 0;
+      case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+         return 0;
+      case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+      case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+      case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+      case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+         return 1;
+      case PIPE_SHADER_CAP_SUBROUTINES:
+         return 0;
+      case PIPE_SHADER_CAP_INTEGERS:
+         return 0;
+      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+         return 8;
+      default:
+         debug_printf("%s: Unknown cap %u.\n", __FUNCTION__, cap);
+         return 0;
+      }
+      break;
+   default:
+      return 0;
+   }
+
+}
+
 static int
 i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
 {
@@ -143,7 +206,12 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
 
    /* Texturing. */
    case PIPE_CAP_MAX_COMBINED_SAMPLERS:
-      return 8;
+      return i915_get_shader_param(screen,
+                                   PIPE_SHADER_VERTEX,
+                                   PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) +
+             i915_get_shader_param(screen,
+                                   PIPE_SHADER_FRAGMENT,
+                                   PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       return I915_MAX_TEXTURE_2D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
@@ -172,65 +240,6 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
    }
 }
 
-static int
-i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap cap)
-{
-   switch(shader) {
-   case PIPE_SHADER_VERTEX:
-      switch (cap) {
-      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
-         return 0;
-      default:
-         return draw_get_shader_param(shader, cap);
-      }
-   case PIPE_SHADER_FRAGMENT:
-      /* XXX: these are just shader model 2.0 values, fix this! */
-      switch(cap) {
-      case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
-         return 96;
-      case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
-         return 64;
-      case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
-         return 32;
-      case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
-         return 8;
-      case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
-         return 0;
-      case PIPE_SHADER_CAP_MAX_INPUTS:
-         return 10;
-      case PIPE_SHADER_CAP_MAX_CONSTS:
-         return 32;
-      case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
-         return 1;
-      case PIPE_SHADER_CAP_MAX_TEMPS:
-         return 12; /* XXX: 12 -> 32 ? */
-      case PIPE_SHADER_CAP_MAX_ADDRS:
-         return 0;
-      case PIPE_SHADER_CAP_MAX_PREDS:
-         return 0;
-      case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
-         return 0;
-      case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
-      case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
-      case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
-      case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
-         return 1;
-      case PIPE_SHADER_CAP_SUBROUTINES:
-         return 0;
-      case PIPE_SHADER_CAP_INTEGERS:
-         return 0;
-      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
-         return 8;
-      default:
-         debug_printf("%s: Unknown cap %u.\n", __FUNCTION__, cap);
-         return 0;
-      }
-   default:
-      return 0;
-   }
-
-}
-
 static float
 i915_get_paramf(struct pipe_screen *screen, enum pipe_cap cap)
 {
index 345c109a995c7a561b817e7e1dca9ae2e6740627..f6e531062fe6800e781afc77cbfe450717af0fa8 100644 (file)
@@ -299,7 +299,38 @@ static void i915_fixup_bind_sampler_states(struct pipe_context *pipe,
    i915->saved_bind_sampler_states(pipe, num, sampler);
 }
 
-static void i915_bind_sampler_states(struct pipe_context *pipe,
+static void
+i915_bind_vertex_sampler_states(struct pipe_context *pipe,
+                                unsigned num_samplers,
+                                void **samplers)
+{
+   struct i915_context *i915 = i915_context(pipe);
+   unsigned i;
+
+   assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS);
+
+   /* Check for no-op */
+   if (num_samplers == i915->num_vertex_samplers &&
+       !memcmp(i915->vertex_samplers, samplers, num_samplers * sizeof(void *)))
+      return;
+
+   draw_flush(i915->draw);
+
+   for (i = 0; i < num_samplers; ++i)
+      i915->vertex_samplers[i] = samplers[i];
+   for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
+      i915->vertex_samplers[i] = NULL;
+
+   i915->num_vertex_samplers = num_samplers;
+
+   draw_set_samplers(i915->draw,
+                     i915->vertex_samplers,
+                     i915->num_vertex_samplers);
+}
+
+
+
+static void i915_bind_fragment_sampler_states(struct pipe_context *pipe,
                                      unsigned num, void **sampler)
 {
    struct i915_context *i915 = i915_context(pipe);
@@ -329,6 +360,76 @@ static void i915_delete_sampler_state(struct pipe_context *pipe,
 }
 
 
+/**
+ * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
+ */
+void
+i915_prepare_vertex_sampling(struct i915_context *i915,
+                             unsigned num,
+                             struct pipe_sampler_view **views)
+{
+   struct i915_winsys *iws = i915->iws;
+   unsigned i,j;
+   uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
+   uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
+   const void* data[PIPE_MAX_TEXTURE_LEVELS];
+
+   assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
+   if (!num)
+      return;
+
+   for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
+
+      if (view) {
+         struct pipe_resource *tex = view->texture;
+         struct i915_texture *i915_tex = i915_texture(tex);
+         void* addr;
+
+         /* We're referencing the texture's internal data, so save a
+          * reference to it.
+          */
+         pipe_resource_reference(&i915->mapped_vs_tex[i], tex);
+
+        i915->mapped_vs_tex_buffer[i] = i915_tex->buffer;
+         addr = iws->buffer_map(iws,
+                                i915_tex->buffer,
+                                FALSE /* read only */);
+
+         /* Setup array of mipmap level pointers */
+        /* FIXME: handle 3D textures? */
+         for (j = view->u.tex.first_level; j <= tex->last_level; j++) {
+            unsigned offset = i915_texture_offset(i915_tex, j , 0 /* FIXME depth */);
+            data[j] = addr + offset;
+            row_stride[j] = i915_tex->stride;
+            img_stride[j] = 0; /* FIXME */;
+         }
+
+         draw_set_mapped_texture(i915->draw,
+                                 i,
+                                 tex->width0, tex->height0, tex->depth0,
+                                 view->u.tex.first_level, tex->last_level,
+                                 row_stride, img_stride, data);
+      } else
+         i915->mapped_vs_tex[i] = NULL;
+   }
+}
+
+void
+i915_cleanup_vertex_sampling(struct i915_context *i915)
+{
+   struct i915_winsys *iws = i915->iws;
+   unsigned i;
+   for (i = 0; i < Elements(i915->mapped_vs_tex); i++) {
+      if (i915->mapped_vs_tex_buffer[i]) { 
+         iws->buffer_unmap(iws, i915->mapped_vs_tex_buffer[i]);
+         pipe_resource_reference(&i915->mapped_vs_tex[i], NULL);
+      }
+   }
+}
+
+
+
 /** XXX move someday?  Or consolidate all these simple state setters
  * into one file.
  */
@@ -652,6 +753,37 @@ static void i915_set_fragment_sampler_views(struct pipe_context *pipe,
    i915->dirty |= I915_NEW_SAMPLER_VIEW;
 }
 
+static void
+i915_set_vertex_sampler_views(struct pipe_context *pipe,
+                              unsigned num,
+                              struct pipe_sampler_view **views)
+{
+   struct i915_context *i915 = i915_context(pipe);
+   uint i;
+
+   assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
+
+   /* Check for no-op */
+   if (num == i915->num_vertex_sampler_views &&
+       !memcmp(i915->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
+      return;
+   }
+
+   draw_flush(i915->draw);
+
+   for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
+
+      pipe_sampler_view_reference(&i915->vertex_sampler_views[i], view);
+   }
+
+   i915->num_vertex_sampler_views = num;
+
+   draw_set_sampler_views(i915->draw,
+                          i915->vertex_sampler_views,
+                          i915->num_vertex_sampler_views);
+}
+
 
 static struct pipe_sampler_view *
 i915_create_sampler_view(struct pipe_context *pipe,
@@ -918,7 +1050,8 @@ i915_init_state_functions( struct i915_context *i915 )
    i915->base.delete_blend_state = i915_delete_blend_state;
 
    i915->base.create_sampler_state = i915_create_sampler_state;
-   i915->base.bind_fragment_sampler_states = i915_bind_sampler_states;
+   i915->base.bind_fragment_sampler_states = i915_bind_fragment_sampler_states;
+   i915->base.bind_vertex_sampler_states = i915_bind_vertex_sampler_states;
    i915->base.delete_sampler_state = i915_delete_sampler_state;
 
    i915->base.create_depth_stencil_alpha_state = i915_create_depth_stencil_state;
@@ -948,6 +1081,7 @@ i915_init_state_functions( struct i915_context *i915 )
    i915->base.set_polygon_stipple = i915_set_polygon_stipple;
    i915->base.set_scissor_state = i915_set_scissor_state;
    i915->base.set_fragment_sampler_views = i915_set_fragment_sampler_views;
+   i915->base.set_vertex_sampler_views = i915_set_vertex_sampler_views;
    i915->base.create_sampler_view = i915_create_sampler_view;
    i915->base.sampler_view_destroy = i915_sampler_view_destroy;
    i915->base.set_viewport_state = i915_set_viewport_state;