Ejemplo n.º 1
0
static struct pipe_resource *
softpipe_resource_from_handle(struct pipe_screen *screen,
                              const struct pipe_resource *templat,
                              struct winsys_handle *whandle)
{
   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
   struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
   if (!spr)
      return NULL;

   spr->base = *templat;
   pipe_reference_init(&spr->base.reference, 1);
   spr->base.screen = screen;

   spr->pot = (util_is_power_of_two(templat->width0) &&
               util_is_power_of_two(templat->height0) &&
               util_is_power_of_two(templat->depth0));

   spr->dt = winsys->displaytarget_from_handle(winsys,
                                               templat,
                                               whandle,
                                               &spr->stride[0]);
   if (!spr->dt)
      goto fail;

   return &spr->base;

 fail:
   FREE(spr);
   return NULL;
}
Ejemplo n.º 2
0
static int
softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
{
   struct softpipe_screen *sp_screen = softpipe_screen(screen);
   switch(shader)
   {
   case PIPE_SHADER_FRAGMENT:
      return tgsi_exec_get_shader_param(param);
   case PIPE_SHADER_VERTEX:
   case PIPE_SHADER_GEOMETRY:
      switch (param) {
      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
         if (sp_screen->use_llvm)
            /* Softpipe doesn't yet know how to tell draw/llvm about textures */
            return 0;
	 else
            return PIPE_MAX_SAMPLERS;
      default:
	 if (sp_screen->use_llvm)
            return draw_get_shader_param(shader, param);
         else
            return draw_get_shader_param_no_llvm(shader, param);
      }
   default:
      return 0;
   }
}
Ejemplo n.º 3
0
static void
gdi_present(struct pipe_screen *screen,
            struct pipe_resource *res,
            HDC hDC)
{
   /* This will fail if any interposing layer (trace, debug, etc) has
    * been introduced between the state-trackers and the pipe driver.
    *
    * Ideally this would get replaced with a call to
    * pipe_screen::flush_frontbuffer().
    *
    * Failing that, it may be necessary for intervening layers to wrap
    * other structs such as this stw_winsys as well...
    */

   struct sw_winsys *winsys = NULL;
   struct sw_displaytarget *dt = NULL;

#ifdef HAVE_LLVMPIPE
   if (use_llvmpipe) {
      winsys = llvmpipe_screen(screen)->winsys;
      dt = llvmpipe_resource(res)->dt;
      gdi_sw_display(winsys, dt, hDC);
      return;
   }
#endif

   winsys = softpipe_screen(screen)->winsys,
   dt = softpipe_resource(res)->dt,
   gdi_sw_display(winsys, dt, hDC);
}
Ejemplo n.º 4
0
static int
softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
{
#ifdef HAVE_LLVM
   struct softpipe_screen *sp_screen = softpipe_screen(screen);
#endif
   switch(shader)
   {
   case PIPE_SHADER_FRAGMENT:
      return tgsi_exec_get_shader_param(param);
   case PIPE_SHADER_VERTEX:
   case PIPE_SHADER_GEOMETRY:
      switch (param) {
      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
#ifdef HAVE_LLVM
         if (sp_screen->use_llvm)
            /* Softpipe doesn't yet know how to tell draw/llvm about textures */
            return 0;
#endif
         return PIPE_MAX_VERTEX_SAMPLERS;
      case PIPE_SHADER_CAP_INTEGERS:
#ifdef HAVE_LLVM /* gallivm doesn't support integers yet */
         if (sp_screen->use_llvm)
            return 0;
#endif
         /* fallthrough */
      default:
         return draw_get_shader_param(shader, param);
      }
   default:
      return 0;
   }
}
Ejemplo n.º 5
0
static void *
softpipe_surface_map( struct pipe_screen *screen,
                      struct pipe_surface *surface,
                      unsigned flags )
{
   ubyte *map;

   if (flags & ~surface->usage) {
      assert(0);
      return NULL;
   }

   map = pipe_buffer_map( screen, surface->buffer, flags );
   if (map == NULL)
      return NULL;

   /* May want to different things here depending on read/write nature
    * of the map:
    */
   if (surface->texture &&
       (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) 
   {
      /* Do something to notify sharing contexts of a texture change.
       * In softpipe, that would mean flushing the texture cache.
       */
      softpipe_screen(screen)->timestamp++;
   }
   
   return map + surface->offset;
}
Ejemplo n.º 6
0
/* Hopefully this will remain quite simple, otherwise need to pull in
 * something like the state tracker mechanism.
 */
void
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
   struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);

   /* Check for updated textures.
    */
   if (softpipe->tex_timestamp != sp_screen->timestamp) {
      softpipe->tex_timestamp = sp_screen->timestamp;
      softpipe->dirty |= SP_NEW_TEXTURE;
   }

#if DO_PSTIPPLE_IN_HELPER_MODULE
   if (softpipe->dirty & SP_NEW_STIPPLE)
      /* before updating samplers! */
      update_polygon_stipple_pattern(softpipe);
#endif

   if (softpipe->dirty & (SP_NEW_RASTERIZER |
                          SP_NEW_FS))
      update_fragment_shader(softpipe, prim);

#if DO_PSTIPPLE_IN_HELPER_MODULE
   if (softpipe->dirty & (SP_NEW_RASTERIZER |
                          SP_NEW_STIPPLE |
                          SP_NEW_FS))
      update_polygon_stipple_enable(softpipe, prim);
#endif

   /* TODO: this looks suboptimal */
   if (softpipe->dirty & (SP_NEW_SAMPLER |
                          SP_NEW_TEXTURE |
                          SP_NEW_FS | 
                          SP_NEW_VS))
      update_tgsi_samplers( softpipe );

   if (softpipe->dirty & (SP_NEW_RASTERIZER |
                          SP_NEW_FS |
                          SP_NEW_VS))
      invalidate_vertex_layout( softpipe );

   if (softpipe->dirty & (SP_NEW_SCISSOR |
                          SP_NEW_RASTERIZER |
                          SP_NEW_FRAMEBUFFER))
      compute_cliprect(softpipe);

   if (softpipe->dirty & (SP_NEW_BLEND |
                          SP_NEW_DEPTH_STENCIL_ALPHA |
                          SP_NEW_FRAMEBUFFER |
                          SP_NEW_STIPPLE |
                          SP_NEW_FS))
      sp_build_quad_pipeline(softpipe);

   softpipe->dirty = 0;
}
Ejemplo n.º 7
0
static void
softpipe_destroy_screen( struct pipe_screen *screen )
{
   struct softpipe_screen *sp_screen = softpipe_screen(screen);
   struct sw_winsys *winsys = sp_screen->winsys;

   if(winsys->destroy)
      winsys->destroy(winsys);

   FREE(screen);
}
Ejemplo n.º 8
0
/* This is often overriden by the co-state tracker.
 */
static void
softpipe_flush_frontbuffer(struct pipe_screen *_screen,
                           struct pipe_resource *resource,
                           unsigned level, unsigned layer,
                           void *context_private)
{
   struct softpipe_screen *screen = softpipe_screen(_screen);
   struct sw_winsys *winsys = screen->winsys;
   struct softpipe_resource *texture = softpipe_resource(resource);

   assert(texture->dt);
   if (texture->dt)
      winsys->displaytarget_display(winsys, texture->dt, context_private);
}
Ejemplo n.º 9
0
static boolean
softpipe_resource_get_handle(struct pipe_screen *screen,
                             struct pipe_resource *pt,
                             struct winsys_handle *whandle)
{
   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
   struct softpipe_resource *spr = softpipe_resource(pt);

   assert(spr->dt);
   if (!spr->dt)
      return FALSE;

   return winsys->displaytarget_get_handle(winsys, spr->dt, whandle);
}
Ejemplo n.º 10
0
/**
 * Texture layout for simple color buffers.
 */
static boolean
softpipe_displaytarget_layout(struct pipe_screen *screen,
                              struct softpipe_resource *spr)
{
   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;

   /* Round up the surface size to a multiple of the tile size?
    */
   spr->dt = winsys->displaytarget_create(winsys,
                                          spr->base.bind,
                                          spr->base.format,
                                          spr->base.width0, 
                                          spr->base.height0,
                                          16,
                                          &spr->stride[0] );

   return spr->dt != NULL;
}
Ejemplo n.º 11
0
static int
softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
{
   struct softpipe_screen *sp_screen = softpipe_screen(screen);
   switch(shader)
   {
   case PIPE_SHADER_FRAGMENT:
      return tgsi_exec_get_shader_param(param);
   case PIPE_SHADER_VERTEX:
   case PIPE_SHADER_GEOMETRY:
      if (sp_screen->use_llvm)
         return draw_get_shader_param(shader, param);
      else
         return draw_get_shader_param_no_llvm(shader, param);
   default:
      return 0;
   }
}
static void
gdi_softpipe_present(struct pipe_screen *screen,
                     struct pipe_surface *surface,
                     HDC hDC)
{
   /* This will fail if any interposing layer (trace, debug, etc) has
    * been introduced between the state-trackers and softpipe.
    *
    * Ideally this would get replaced with a call to
    * pipe_screen::flush_frontbuffer().
    *
    * Failing that, it may be necessary for intervening layers to wrap
    * other structs such as this stw_winsys as well...
    */
   gdi_sw_display(softpipe_screen(screen)->winsys,
                  softpipe_resource(surface->texture)->dt,
                  hDC);
}
Ejemplo n.º 13
0
static void
softpipe_resource_destroy(struct pipe_screen *pscreen,
			  struct pipe_resource *pt)
{
   struct softpipe_screen *screen = softpipe_screen(pscreen);
   struct softpipe_resource *spr = softpipe_resource(pt);

   if (spr->dt) {
      /* display target */
      struct sw_winsys *winsys = screen->winsys;
      winsys->displaytarget_destroy(winsys, spr->dt);
   }
   else if (!spr->userBuffer) {
      /* regular texture */
      align_free(spr->data);
   }

   FREE(spr);
}
Ejemplo n.º 14
0
/**
 * Unmap memory mapping for given pipe_transfer object.
 */
static void
softpipe_transfer_unmap(struct pipe_context *pipe,
                        struct pipe_transfer *transfer)
{
   struct softpipe_resource *spr;

   assert(transfer->resource);
   spr = softpipe_resource(transfer->resource);

   if (spr->dt) {
      /* display target */
      struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
      winsys->displaytarget_unmap(winsys, spr->dt);
   }

   if (transfer->usage & PIPE_TRANSFER_WRITE) {
      /* Mark the texture as dirty to expire the tile caches. */
      spr->timestamp++;
   }
}
Ejemplo n.º 15
0
static void *
softpipe_transfer_map( struct pipe_screen *screen,
                       struct pipe_transfer *transfer )
{
   ubyte *map, *xfer_map;
   struct softpipe_texture *spt;
   unsigned flags = 0;

   assert(transfer->texture);
   spt = softpipe_texture(transfer->texture);

   if (transfer->usage != PIPE_TRANSFER_READ) {
      flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
   }

   if (transfer->usage != PIPE_TRANSFER_WRITE) {
      flags |= PIPE_BUFFER_USAGE_CPU_READ;
   }

   map = pipe_buffer_map(screen, spt->buffer, flags);
   if (map == NULL)
      return NULL;

   /* May want to different things here depending on read/write nature
    * of the map:
    */
   if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) 
   {
      /* Do something to notify sharing contexts of a texture change.
       * In softpipe, that would mean flushing the texture cache.
       */
      softpipe_screen(screen)->timestamp++;
   }
   
   xfer_map = map + softpipe_transfer(transfer)->offset +
      transfer->y / transfer->block.height * transfer->stride +
      transfer->x / transfer->block.width * transfer->block.size;
   /*printf("map = %p  xfer map = %p\n", map, xfer_map);*/
   return xfer_map;
}
Ejemplo n.º 16
0
/**
 * Create memory mapping for given pipe_transfer object.
 */
static void *
softpipe_transfer_map(struct pipe_context *pipe,
                      struct pipe_transfer *transfer)
{
   struct softpipe_transfer *spt = softpipe_transfer(transfer);
   struct softpipe_resource *spr = softpipe_resource(transfer->resource);
   struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
   uint8_t *map;
   
   /* resources backed by display target treated specially:
    */
   if (spr->dt) {
      map = winsys->displaytarget_map(winsys, spr->dt, transfer->usage);
   }
   else {
      map = spr->data;
   }

   if (map == NULL)
      return NULL;
   else
      return map + spt->offset;
}
struct pipe_context *
softpipe_create_context( struct pipe_screen *screen,
			 void *priv )
{
   struct softpipe_screen *sp_screen = softpipe_screen(screen);
   struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
   uint i, sh;

   util_init_math();

   softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
   softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );

   softpipe->pipe.screen = screen;
   softpipe->pipe.destroy = softpipe_destroy;
   softpipe->pipe.priv = priv;

   /* state setters */
   softpipe_init_blend_funcs(&softpipe->pipe);
   softpipe_init_clip_funcs(&softpipe->pipe);
   softpipe_init_query_funcs( softpipe );
   softpipe_init_rasterizer_funcs(&softpipe->pipe);
   softpipe_init_sampler_funcs(&softpipe->pipe);
   softpipe_init_shader_funcs(&softpipe->pipe);
   softpipe_init_streamout_funcs(&softpipe->pipe);
   softpipe_init_texture_funcs( &softpipe->pipe );
   softpipe_init_vertex_funcs(&softpipe->pipe);

   softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;

   softpipe->pipe.draw_vbo = softpipe_draw_vbo;

   softpipe->pipe.clear = softpipe_clear;
   softpipe->pipe.flush = softpipe_flush_wrapped;

   softpipe->pipe.render_condition = softpipe_render_condition;
   
   softpipe->pipe.create_video_decoder = vl_create_decoder;
   softpipe->pipe.create_video_buffer = vl_video_buffer_create;

   /*
    * Alloc caches for accessing drawing surfaces and textures.
    * Must be before quad stage setup!
    */
   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
      softpipe->cbuf_cache[i] = sp_create_tile_cache( &softpipe->pipe );
   softpipe->zsbuf_cache = sp_create_tile_cache( &softpipe->pipe );

   /* Allocate texture caches */
   for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
      for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
         softpipe->tex_cache[sh][i] = sp_create_tex_tile_cache(&softpipe->pipe);
         if (!softpipe->tex_cache[sh][i])
            goto fail;
      }
   }

   softpipe->fs_machine = tgsi_exec_machine_create();

   /* setup quad rendering stages */
   softpipe->quad.shade = sp_quad_shade_stage(softpipe);
   softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
   softpipe->quad.blend = sp_quad_blend_stage(softpipe);
   softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe);


   /*
    * Create drawing context and plug our rendering stage into it.
    */
   if (sp_screen->use_llvm)
      softpipe->draw = draw_create(&softpipe->pipe);
   else
      softpipe->draw = draw_create_no_llvm(&softpipe->pipe);
   if (!softpipe->draw) 
      goto fail;

   draw_texture_samplers(softpipe->draw,
                         PIPE_SHADER_VERTEX,
                         PIPE_MAX_SAMPLERS,
                         (struct tgsi_sampler **)
                            softpipe->tgsi.samplers_list[PIPE_SHADER_VERTEX]);

   draw_texture_samplers(softpipe->draw,
                         PIPE_SHADER_GEOMETRY,
                         PIPE_MAX_SAMPLERS,
                         (struct tgsi_sampler **)
                            softpipe->tgsi.samplers_list[PIPE_SHADER_GEOMETRY]);

   if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
      softpipe->no_rast = TRUE;

   softpipe->vbuf_backend = sp_create_vbuf_backend(softpipe);
   if (!softpipe->vbuf_backend)
      goto fail;

   softpipe->vbuf = draw_vbuf_stage(softpipe->draw, softpipe->vbuf_backend);
   if (!softpipe->vbuf)
      goto fail;

   draw_set_rasterize_stage(softpipe->draw, softpipe->vbuf);
   draw_set_render(softpipe->draw, softpipe->vbuf_backend);


   /* plug in AA line/point stages */
   draw_install_aaline_stage(softpipe->draw, &softpipe->pipe);
   draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe);

   /* Do polygon stipple w/ texture map + frag prog? */
#if DO_PSTIPPLE_IN_DRAW_MODULE
   draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe);
#endif

   draw_wide_point_sprites(softpipe->draw, TRUE);

   sp_init_surface_functions(softpipe);

#if DO_PSTIPPLE_IN_HELPER_MODULE
   /* create the polgon stipple sampler */
   softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
#endif

   return &softpipe->pipe;

 fail:
   softpipe_destroy(&softpipe->pipe);
   return NULL;
}
Ejemplo n.º 18
0
/**
 * Query format support for creating a texture, drawing surface, etc.
 * \param format  the format to test
 * \param type  one of PIPE_TEXTURE, PIPE_SURFACE
 */
static boolean
softpipe_is_format_supported( struct pipe_screen *screen,
                              enum pipe_format format,
                              enum pipe_texture_target target,
                              unsigned sample_count,
                              unsigned bind)
{
   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
   const struct util_format_description *format_desc;

   assert(target == PIPE_BUFFER ||
          target == PIPE_TEXTURE_1D ||
          target == PIPE_TEXTURE_1D_ARRAY ||
          target == PIPE_TEXTURE_2D ||
          target == PIPE_TEXTURE_2D_ARRAY ||
          target == PIPE_TEXTURE_RECT ||
          target == PIPE_TEXTURE_3D ||
          target == PIPE_TEXTURE_CUBE ||
          target == PIPE_TEXTURE_CUBE_ARRAY);

   format_desc = util_format_description(format);
   if (!format_desc)
      return FALSE;

   if (sample_count > 1)
      return FALSE;

   if (bind & (PIPE_BIND_DISPLAY_TARGET |
               PIPE_BIND_SCANOUT |
               PIPE_BIND_SHARED)) {
      if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
         return FALSE;
   }

   if (bind & PIPE_BIND_RENDER_TARGET) {
      if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;

      /*
       * Although possible, it is unnatural to render into compressed or YUV
       * surfaces. So disable these here to avoid going into weird paths
       * inside the state trackers.
       */
      if (format_desc->block.width != 1 ||
          format_desc->block.height != 1)
         return FALSE;
   }

   if (bind & PIPE_BIND_DEPTH_STENCIL) {
      if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;
   }

   if (format_desc->layout == UTIL_FORMAT_LAYOUT_BPTC ||
       format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
      /* Software decoding is not hooked up. */
      return FALSE;
   }

   if ((bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) &&
       ((bind & PIPE_BIND_DISPLAY_TARGET) == 0) &&
       target != PIPE_BUFFER) {
      const struct util_format_description *desc =
         util_format_description(format);
      if (desc->nr_channels == 3 && desc->is_array) {
         /* Don't support any 3-component formats for rendering/texturing
          * since we don't support the corresponding 8-bit 3 channel UNORM
          * formats.  This allows us to support GL_ARB_copy_image between
          * GL_RGB8 and GL_RGB8UI, for example.  Otherwise, we may be asked to
          * do a resource copy between PIPE_FORMAT_R8G8B8_UINT and
          * PIPE_FORMAT_R8G8B8X8_UNORM, for example, which will not work
          * (different bpp).
          */
         return FALSE;
      }
   }

   if (format_desc->layout == UTIL_FORMAT_LAYOUT_ETC &&
       format != PIPE_FORMAT_ETC1_RGB8)
      return FALSE;

   /*
    * All other operations (sampling, transfer, etc).
    */

   /*
    * Everything else should be supported by u_format.
    */
   return TRUE;
}
Ejemplo n.º 19
0
/**
 * Query format support for creating a texture, drawing surface, etc.
 * \param format  the format to test
 * \param type  one of PIPE_TEXTURE, PIPE_SURFACE
 */
static boolean
softpipe_is_format_supported( struct pipe_screen *screen,
                              enum pipe_format format,
                              enum pipe_texture_target target,
                              unsigned sample_count,
                              unsigned bind)
{
   struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
   const struct util_format_description *format_desc;

   assert(target == PIPE_BUFFER ||
          target == PIPE_TEXTURE_1D ||
          target == PIPE_TEXTURE_1D_ARRAY ||
          target == PIPE_TEXTURE_2D ||
          target == PIPE_TEXTURE_2D_ARRAY ||
          target == PIPE_TEXTURE_RECT ||
          target == PIPE_TEXTURE_3D ||
          target == PIPE_TEXTURE_CUBE ||
          target == PIPE_TEXTURE_CUBE_ARRAY);

   format_desc = util_format_description(format);
   if (!format_desc)
      return FALSE;

   if (sample_count > 1)
      return FALSE;

   if (bind & (PIPE_BIND_DISPLAY_TARGET |
               PIPE_BIND_SCANOUT |
               PIPE_BIND_SHARED)) {
      if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
         return FALSE;
   }

   if (bind & PIPE_BIND_RENDER_TARGET) {
      if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;

      /*
       * Although possible, it is unnatural to render into compressed or YUV
       * surfaces. So disable these here to avoid going into weird paths
       * inside the state trackers.
       */
      if (format_desc->block.width != 1 ||
          format_desc->block.height != 1)
         return FALSE;
   }

   if (bind & PIPE_BIND_DEPTH_STENCIL) {
      if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
         return FALSE;
   }

   /*
    * All other operations (sampling, transfer, etc).
    */

   if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
      return util_format_s3tc_enabled;
   }

   /*
    * Everything else should be supported by u_format.
    */
   return TRUE;
}
Ejemplo n.º 20
0
static void
prepare_shader_sampling(
   struct softpipe_context *sp,
   unsigned num,
   struct pipe_sampler_view **views,
   unsigned shader_type,
   struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS])
{

   unsigned i;
   uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
   uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
   uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
   const void *addr;

   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
   if (!num)
      return;

   for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
      struct pipe_sampler_view *view = i < num ? views[i] : NULL;

      if (view) {
         struct pipe_resource *tex = view->texture;
         struct softpipe_resource *sp_tex = softpipe_resource(tex);
         unsigned width0 = tex->width0;
         unsigned num_layers = tex->depth0;
         unsigned first_level = 0;
         unsigned last_level = 0;

         /* We're referencing the texture's internal data, so save a
          * reference to it.
          */
         pipe_resource_reference(&mapped_tex[i], tex);

         if (!sp_tex->dt) {
            /* regular texture - setup array of mipmap level offsets */
            MAYBE_UNUSED struct pipe_resource *res = view->texture;
            int j;

            if (view->target != PIPE_BUFFER) {
               first_level = view->u.tex.first_level;
               last_level = view->u.tex.last_level;
               assert(first_level <= last_level);
               assert(last_level <= res->last_level);
               addr = sp_tex->data;

               for (j = first_level; j <= last_level; j++) {
                  mip_offsets[j] = sp_tex->level_offset[j];
                  row_stride[j] = sp_tex->stride[j];
                  img_stride[j] = sp_tex->img_stride[j];
               }
               if (tex->target == PIPE_TEXTURE_1D_ARRAY ||
                   tex->target == PIPE_TEXTURE_2D_ARRAY ||
                   tex->target == PIPE_TEXTURE_CUBE ||
                   tex->target == PIPE_TEXTURE_CUBE_ARRAY) {
                  num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
                  for (j = first_level; j <= last_level; j++) {
                     mip_offsets[j] += view->u.tex.first_layer *
                                       sp_tex->img_stride[j];
                  }
                  if (view->target == PIPE_TEXTURE_CUBE ||
                      view->target == PIPE_TEXTURE_CUBE_ARRAY) {
                     assert(num_layers % 6 == 0);
                  }
                  assert(view->u.tex.first_layer <= view->u.tex.last_layer);
                  assert(view->u.tex.last_layer < res->array_size);
               }
            }
            else {
               unsigned view_blocksize = util_format_get_blocksize(view->format);
               addr = sp_tex->data;
               /* probably don't really need to fill that out */
               mip_offsets[0] = 0;
               row_stride[0] = 0;
               img_stride[0] = 0;

               /* everything specified in number of elements here. */
               width0 = view->u.buf.last_element - view->u.buf.first_element + 1;
               addr = (uint8_t *)addr + view->u.buf.first_element *
                               view_blocksize;
               assert(view->u.buf.first_element <= view->u.buf.last_element);
               assert(view->u.buf.last_element * view_blocksize < res->width0);
            }
         }
         else {
            /* display target texture/surface */
            /*
             * XXX: Where should this be unmapped?
             */
            struct softpipe_screen *screen = softpipe_screen(tex->screen);
            struct sw_winsys *winsys = screen->winsys;
            addr = winsys->displaytarget_map(winsys, sp_tex->dt,
                                             PIPE_TRANSFER_READ);
            row_stride[0] = sp_tex->stride[0];
            img_stride[0] = sp_tex->img_stride[0];
            mip_offsets[0] = 0;
            assert(addr);
         }
         draw_set_mapped_texture(sp->draw,
                                 shader_type,
                                 i,
                                 width0, tex->height0, num_layers,
                                 first_level, last_level,
                                 addr,
                                 row_stride, img_stride, mip_offsets);
      }
   }
}
Ejemplo n.º 21
0
/**
 * Geta pipe_transfer object which is used for moving data in/out of
 * a resource object.
 * \param pipe  rendering context
 * \param resource  the resource to transfer in/out of
 * \param level  which mipmap level
 * \param usage  bitmask of PIPE_TRANSFER_x flags
 * \param box  the 1D/2D/3D region of interest
 */
static void *
softpipe_transfer_map(struct pipe_context *pipe,
                      struct pipe_resource *resource,
                      unsigned level,
                      unsigned usage,
                      const struct pipe_box *box,
                      struct pipe_transfer **transfer)
{
   struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
   struct softpipe_resource *spr = softpipe_resource(resource);
   struct softpipe_transfer *spt;
   struct pipe_transfer *pt;
   enum pipe_format format = resource->format;
   uint8_t *map;

   assert(resource);
   assert(level <= resource->last_level);

   /* make sure the requested region is in the image bounds */
   assert(box->x + box->width <= (int) u_minify(resource->width0, level));
   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
      assert(box->y + box->height <= (int) resource->array_size);
   }
   else {
      assert(box->y + box->height <= (int) u_minify(resource->height0, level));
      if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
         assert(box->z + box->depth <= (int) resource->array_size);
      }
      else if (resource->target == PIPE_TEXTURE_CUBE) {
         assert(box->z < 6);
      }
      else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
         assert(box->z <= (int) resource->array_size);
      }
      else {
         assert(box->z + box->depth <= (int) u_minify(resource->depth0, level));
      }
   }

   /*
    * Transfers, like other pipe operations, must happen in order, so flush the
    * context if necessary.
    */
   if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
      boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
      boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
      if (!softpipe_flush_resource(pipe, resource,
                                   level, box->depth > 1 ? -1 : box->z,
                                   0, /* flush_flags */
                                   read_only,
                                   TRUE, /* cpu_access */
                                   do_not_block)) {
         /*
          * It would have blocked, but state tracker requested no to.
          */
         assert(do_not_block);
         return NULL;
      }
   }

   spt = CALLOC_STRUCT(softpipe_transfer);
   if (!spt)
      return NULL;

   pt = &spt->base;

   pipe_resource_reference(&pt->resource, resource);
   pt->level = level;
   pt->usage = usage;
   pt->box = *box;
   pt->stride = spr->stride[level];
   pt->layer_stride = spr->img_stride[level];

   spt->offset = softpipe_get_tex_image_offset(spr, level, box->z);

   spt->offset +=
         box->y / util_format_get_blockheight(format) * spt->base.stride +
         box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);

   /* resources backed by display target treated specially:
    */
   if (spr->dt) {
      map = winsys->displaytarget_map(winsys, spr->dt, usage);
   }
   else {
      map = spr->data;
   }

   if (!map) {
      pipe_resource_reference(&pt->resource, NULL);
      FREE(spt);
      return NULL;
   }

   *transfer = pt;
   return map + spt->offset;
}