ilo: hook up pipe context blit functions
authorChia-I Wu <olv@lunarg.com>
Wed, 12 Dec 2012 21:15:10 +0000 (05:15 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 26 Apr 2013 08:16:42 +0000 (16:16 +0800)
src/gallium/drivers/ilo/ilo_blit.c
src/gallium/drivers/ilo/ilo_context.c
src/gallium/drivers/ilo/ilo_context.h

index ce4801d46b69f2df67ed0ddb86343019203b34bc..20e09ae340bd4a9e9ebb6973b61ca658bde80945 100644 (file)
  *    Chia-I Wu <olv@lunarg.com>
  */
 
+#include "util/u_blitter.h"
+#include "util/u_clear.h"
+#include "util/u_pack_color.h"
+#include "util/u_surface.h"
+#include "intel_reg.h"
+
 #include "ilo_context.h"
+#include "ilo_cp.h"
+#include "ilo_resource.h"
+#include "ilo_screen.h"
 #include "ilo_blit.h"
 
+static bool
+blitter_xy_color_blt(struct pipe_context *pipe,
+                     struct pipe_resource *r,
+                     int16_t x1, int16_t y1,
+                     int16_t x2, int16_t y2,
+                     uint32_t color)
+{
+   const int cmd_len = 6;
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct ilo_resource *res = ilo_resource(r);
+   uint32_t cmd, br13;
+   int cpp, stride;
+   struct intel_bo *bo_check[2];
+
+   /* how to support Y-tiling? */
+   if (res->tiling == INTEL_TILING_Y)
+      return false;
+
+   /* nothing to clear */
+   if (x1 >= x2 || y1 >= y2)
+      return true;
+
+   cmd = XY_COLOR_BLT_CMD | (cmd_len - 2);
+   br13 = 0xf0 << 16;
+
+   cpp = util_format_get_blocksize(res->base.format);
+   switch (cpp) {
+   case 4:
+      cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
+      br13 |= BR13_8888;
+      break;
+   case 2:
+      br13 |= BR13_565;
+      break;
+   case 1:
+      br13 |= BR13_8;
+      break;
+   default:
+      return false;
+      break;
+   }
+
+   stride = res->bo_stride;
+   if (res->tiling != INTEL_TILING_NONE) {
+      assert(res->tiling == INTEL_TILING_X);
+
+      cmd |= XY_DST_TILED;
+      /* in dwords */
+      stride /= 4;
+   }
+
+   /* make room if necessary */
+   bo_check[0] = ilo->cp->bo;
+   bo_check[1] = res->bo;
+   if (ilo->winsys->check_aperture_space(ilo->winsys, bo_check, 2))
+      ilo_cp_flush(ilo->cp);
+
+   ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT);
+
+   ilo_cp_begin(ilo->cp, cmd_len);
+   ilo_cp_write(ilo->cp, cmd);
+   ilo_cp_write(ilo->cp, br13 | stride);
+   ilo_cp_write(ilo->cp, (y1 << 16) | x1);
+   ilo_cp_write(ilo->cp, (y2 << 16) | x2);
+   ilo_cp_write_bo(ilo->cp, 0, res->bo,
+                   INTEL_DOMAIN_RENDER,
+                   INTEL_DOMAIN_RENDER);
+   ilo_cp_write(ilo->cp, color);
+   ilo_cp_end(ilo->cp);
+
+   return true;
+}
+
+enum ilo_blitter_op {
+   ILO_BLITTER_CLEAR,
+   ILO_BLITTER_CLEAR_SURFACE,
+   ILO_BLITTER_BLIT,
+};
+
+static void
+ilo_blitter_begin(struct ilo_context *ilo, enum ilo_blitter_op op)
+{
+   /* as documented in util/u_blitter.h */
+   util_blitter_save_vertex_buffer_slot(ilo->blitter,
+         ilo->vertex_buffers.buffers);
+   util_blitter_save_vertex_elements(ilo->blitter, ilo->vertex_elements);
+   util_blitter_save_vertex_shader(ilo->blitter, ilo->vs);
+   util_blitter_save_geometry_shader(ilo->blitter, ilo->gs);
+   util_blitter_save_so_targets(ilo->blitter,
+         ilo->stream_output_targets.num_targets,
+         ilo->stream_output_targets.targets);
+
+   util_blitter_save_fragment_shader(ilo->blitter, ilo->fs);
+   util_blitter_save_depth_stencil_alpha(ilo->blitter,
+         ilo->depth_stencil_alpha);
+   util_blitter_save_blend(ilo->blitter, ilo->blend);
+
+   /* undocumented? */
+   util_blitter_save_viewport(ilo->blitter, &ilo->viewport);
+   util_blitter_save_stencil_ref(ilo->blitter, &ilo->stencil_ref);
+   util_blitter_save_sample_mask(ilo->blitter, ilo->sample_mask);
+
+   switch (op) {
+   case ILO_BLITTER_CLEAR:
+      util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
+      break;
+   case ILO_BLITTER_CLEAR_SURFACE:
+      util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
+      break;
+   case ILO_BLITTER_BLIT:
+      util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
+      util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
+
+      util_blitter_save_fragment_sampler_states(ilo->blitter,
+            ilo->samplers[PIPE_SHADER_FRAGMENT].num_samplers,
+            (void **) ilo->samplers[PIPE_SHADER_FRAGMENT].samplers);
+
+      util_blitter_save_fragment_sampler_views(ilo->blitter,
+            ilo->sampler_views[PIPE_SHADER_FRAGMENT].num_views,
+            ilo->sampler_views[PIPE_SHADER_FRAGMENT].views);
+
+      /* disable render condition? */
+      break;
+   default:
+      break;
+   }
+}
+
+static void
+ilo_blitter_end(struct ilo_context *ilo)
+{
+}
+
+static void
+ilo_clear(struct pipe_context *pipe,
+          unsigned buffers,
+          const union pipe_color_union *color,
+          double depth,
+          unsigned stencil)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+
+   /* TODO we should pause/resume some queries */
+   ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR);
+
+   util_blitter_clear(ilo->blitter,
+         ilo->framebuffer.width, ilo->framebuffer.height,
+         ilo->framebuffer.nr_cbufs, buffers,
+         (ilo->framebuffer.nr_cbufs) ? ilo->framebuffer.cbufs[0]->format :
+                                        PIPE_FORMAT_NONE,
+         color, depth, stencil);
+
+   ilo_blitter_end(ilo);
+}
+
+static void
+ilo_clear_render_target(struct pipe_context *pipe,
+                        struct pipe_surface *dst,
+                        const union pipe_color_union *color,
+                        unsigned dstx, unsigned dsty,
+                        unsigned width, unsigned height)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   union util_color packed;
+
+   if (!width || !height || dstx >= dst->width || dsty >= dst->height)
+      return;
+
+   if (dstx + width > dst->width)
+      width = dst->width - dstx;
+   if (dsty + height > dst->height)
+      height = dst->height - dsty;
+
+   util_pack_color(color->f, dst->format, &packed);
+
+   /* try HW blit first */
+   if (blitter_xy_color_blt(pipe, dst->texture,
+                            dstx, dsty,
+                            dstx + width, dsty + height,
+                            packed.ui))
+      return;
+
+   ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
+   util_blitter_clear_render_target(ilo->blitter,
+         dst, color, dstx, dsty, width, height);
+   ilo_blitter_end(ilo);
+}
+
+static void
+ilo_clear_depth_stencil(struct pipe_context *pipe,
+                        struct pipe_surface *dst,
+                        unsigned clear_flags,
+                        double depth,
+                        unsigned stencil,
+                        unsigned dstx, unsigned dsty,
+                        unsigned width, unsigned height)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+
+   /*
+    * The PRM claims that HW blit supports Y-tiling since GEN6, but it does
+    * not tell us how to program it.  Since depth buffers are always Y-tiled,
+    * HW blit will not work.
+    */
+   ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
+   util_blitter_clear_depth_stencil(ilo->blitter,
+         dst, clear_flags, depth, stencil, dstx, dsty, width, height);
+   ilo_blitter_end(ilo);
+}
+
+static void
+ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct pipe_blit_info skip_stencil;
+
+   if (util_try_blit_via_copy_region(pipe, info))
+      return;
+
+   if (!util_blitter_is_blit_supported(ilo->blitter, info)) {
+      /* try without stencil */
+      if (info->mask & PIPE_MASK_S) {
+         skip_stencil = *info;
+         skip_stencil.mask = info->mask & ~PIPE_MASK_S;
+
+         if (util_blitter_is_blit_supported(ilo->blitter, &skip_stencil))
+            info = &skip_stencil;
+      }
+
+      if (info == &skip_stencil) {
+         ilo_warn("ignore stencil buffer blitting\n");
+      }
+      else {
+         ilo_warn("failed to blit with the generic blitter\n");
+         return;
+      }
+   }
+
+   ilo_blitter_begin(ilo, ILO_BLITTER_BLIT);
+   util_blitter_blit(ilo->blitter, info);
+   ilo_blitter_end(ilo);
+}
+
 /**
  * Initialize blit-related functions.
  */
 void
 ilo_init_blit_functions(struct ilo_context *ilo)
 {
-   ilo->base.resource_copy_region = NULL;
-   ilo->base.blit = NULL;
+   ilo->base.resource_copy_region = util_resource_copy_region;
+   ilo->base.blit = ilo_blit;
 
-   ilo->base.clear = NULL;
-   ilo->base.clear_render_target = NULL;
-   ilo->base.clear_depth_stencil = NULL;
+   ilo->base.clear = ilo_clear;
+   ilo->base.clear_render_target = ilo_clear_render_target;
+   ilo->base.clear_depth_stencil = ilo_clear_depth_stencil;
 }
index d92b07811ea07fd120566db8d87d17bc657d1a52..82da56e71968b9302ab3ac7c75e16469fa996a8d 100644 (file)
@@ -25,6 +25,7 @@
  *    Chia-I Wu <olv@lunarg.com>
  */
 
+#include "util/u_blitter.h"
 #include "intel_chipset.h"
 
 #include "ilo_3d.h"
@@ -100,6 +101,8 @@ ilo_context_destroy(struct pipe_context *pipe)
    if (ilo->last_cp_bo)
       ilo->last_cp_bo->unreference(ilo->last_cp_bo);
 
+   if (ilo->blitter)
+      util_blitter_destroy(ilo->blitter);
    if (ilo->shader_cache)
       ilo_shader_cache_destroy(ilo->shader_cache);
    if (ilo->cp)
@@ -203,6 +206,13 @@ ilo_context_create(struct pipe_screen *screen, void *priv)
    ilo_init_video_functions(ilo);
    ilo_init_gpgpu_functions(ilo);
 
+   /* this must be called last as u_blitter is a client of the pipe context */
+   ilo->blitter = util_blitter_create(&ilo->base);
+   if (!ilo->blitter) {
+      ilo_context_destroy(&ilo->base);
+      return NULL;
+   }
+
    return &ilo->base;
 }
 
index 107961d57c6be6dc9e3e9d8abb754ba4dbfcb143..58fee1f1821ffa1a9d4e2cddf36ca1c1e2650994 100644 (file)
@@ -54,6 +54,7 @@
 #define ILO_WM_CONST_SURFACE(i)    (ILO_MAX_DRAW_BUFFERS + i)
 #define ILO_WM_TEXTURE_SURFACE(i)  (ILO_MAX_DRAW_BUFFERS + ILO_MAX_CONST_BUFFERS  + i)
 
+struct blitter_context;
 struct intel_winsys;
 struct intel_bo;
 struct ilo_cp;
@@ -86,6 +87,7 @@ struct ilo_context {
    struct intel_bo *last_cp_bo;
 
    struct ilo_shader_cache *shader_cache;
+   struct blitter_context *blitter;
 
    uint32_t dirty;