示例#1
0
static void
llvmpipe_resource_destroy(struct pipe_screen *pscreen,
                          struct pipe_resource *pt)
{
   struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);

   if (lpr->dt) {
      /* display target */
      struct sw_winsys *winsys = screen->winsys;
      winsys->displaytarget_destroy(winsys, lpr->dt);
   }
   else if (llvmpipe_resource_is_texture(pt)) {
      /* free linear image data */
      if (lpr->linear_img.data) {
         align_free(lpr->linear_img.data);
         lpr->linear_img.data = NULL;
      }
   }
   else if (!lpr->userBuffer) {
      assert(lpr->data);
      align_free(lpr->data);
   }

#ifdef DEBUG
   if (lpr->next)
      remove_from_list(lpr);
#endif

   FREE(lpr);
}
示例#2
0
void *
llvmpipe_resource_data(struct pipe_resource *resource)
{
   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);

   assert(!llvmpipe_resource_is_texture(resource));

   return lpr->data;
}
示例#3
0
/**
 * Map a resource for read/write.
 */
void *
llvmpipe_resource_map(struct pipe_resource *resource,
                      unsigned level,
                      unsigned layer,
                      enum lp_texture_usage tex_usage)
{
   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
   uint8_t *map;

   assert(level < LP_MAX_TEXTURE_LEVELS);
   assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));

   assert(tex_usage == LP_TEX_USAGE_READ ||
          tex_usage == LP_TEX_USAGE_READ_WRITE ||
          tex_usage == LP_TEX_USAGE_WRITE_ALL);

   if (lpr->dt) {
      /* display target */
      struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
      struct sw_winsys *winsys = screen->winsys;
      unsigned dt_usage;

      if (tex_usage == LP_TEX_USAGE_READ) {
         dt_usage = PIPE_TRANSFER_READ;
      }
      else {
         dt_usage = PIPE_TRANSFER_READ_WRITE;
      }

      assert(level == 0);
      assert(layer == 0);

      /* FIXME: keep map count? */
      map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);

      /* install this linear image in texture data structure */
      lpr->linear_img.data = map;

      return map;
   }
   else if (llvmpipe_resource_is_texture(resource)) {

      map = llvmpipe_get_texture_image(lpr, layer, level, tex_usage);
      return map;
   }
   else {
      return lpr->data;
   }
}
示例#4
0
void
lp_scene_begin_rasterization(struct lp_scene *scene)
{
   const struct pipe_framebuffer_state *fb = &scene->fb;
   int i;

   //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);

   for (i = 0; i < scene->fb.nr_cbufs; i++) {
      struct pipe_surface *cbuf = scene->fb.cbufs[i];
      if (llvmpipe_resource_is_texture(cbuf->texture)) {
         assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer);
         scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
                                                           cbuf->u.tex.level);

         scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
                                                     cbuf->u.tex.level,
                                                     cbuf->u.tex.first_layer,
                                                     LP_TEX_USAGE_READ_WRITE,
                                                     LP_TEX_LAYOUT_LINEAR);
      }
      else {
         struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
         unsigned pixstride = util_format_get_blocksize(cbuf->format);
         scene->cbufs[i].stride = cbuf->texture->width0;
         scene->cbufs[i].map = lpr->data;
         scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride;
      }
   }

   if (fb->zsbuf) {
      struct pipe_surface *zsbuf = scene->fb.zsbuf;
      assert(zsbuf->u.tex.first_layer == zsbuf->u.tex.last_layer);
      scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level);
      scene->zsbuf.blocksize = 
         util_format_get_blocksize(zsbuf->texture->format);

      scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture,
                                               zsbuf->u.tex.level,
                                               zsbuf->u.tex.first_layer,
                                               LP_TEX_USAGE_READ_WRITE,
                                               LP_TEX_LAYOUT_NONE);
   }
}
示例#5
0
/**
 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
 */
void
lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
                                    unsigned num,
                                    struct pipe_sampler_view **views)
{
   unsigned i, max_tex_num;

   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);

   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);

   max_tex_num = MAX2(num, setup->fs.current_tex_num);

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

      if (view) {
         struct pipe_resource *res = view->texture;
         struct llvmpipe_resource *lp_tex = llvmpipe_resource(res);
         struct lp_jit_texture *jit_tex;
         jit_tex = &setup->fs.current.jit_context.textures[i];

         /* We're referencing the texture's internal data, so save a
          * reference to it.
          */
         pipe_resource_reference(&setup->fs.current_tex[i], res);

         if (!lp_tex->dt) {
            /* regular texture - setup array of mipmap level offsets */
            int j;
            unsigned first_level = 0;
            unsigned last_level = 0;

            if (llvmpipe_resource_is_texture(res)) {
               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);
               jit_tex->base = lp_tex->tex_data;
            }
            else {
              jit_tex->base = lp_tex->data;
            }

            if (LP_PERF & PERF_TEX_MEM) {
               /* use dummy tile memory */
               jit_tex->base = lp_dummy_tile;
               jit_tex->width = TILE_SIZE/8;
               jit_tex->height = TILE_SIZE/8;
               jit_tex->depth = 1;
               jit_tex->first_level = 0;
               jit_tex->last_level = 0;
               jit_tex->mip_offsets[0] = 0;
               jit_tex->row_stride[0] = 0;
               jit_tex->img_stride[0] = 0;
            }
            else {
               jit_tex->width = res->width0;
               jit_tex->height = res->height0;
               jit_tex->depth = res->depth0;
               jit_tex->first_level = first_level;
               jit_tex->last_level = last_level;

               if (llvmpipe_resource_is_texture(res)) {
                  for (j = first_level; j <= last_level; j++) {
                     jit_tex->mip_offsets[j] = lp_tex->mip_offsets[j];
                     jit_tex->row_stride[j] = lp_tex->row_stride[j];
                     jit_tex->img_stride[j] = lp_tex->img_stride[j];
                  }

                  if (res->target == PIPE_TEXTURE_1D_ARRAY ||
                      res->target == PIPE_TEXTURE_2D_ARRAY ||
                      res->target == PIPE_TEXTURE_CUBE ||
                      res->target == PIPE_TEXTURE_CUBE_ARRAY) {
                     /*
                      * For array textures, we don't have first_layer, instead
                      * adjust last_layer (stored as depth) plus the mip level offsets
                      * (as we have mip-first layout can't just adjust base ptr).
                      * XXX For mip levels, could do something similar.
                      */
                     jit_tex->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1;
                     for (j = first_level; j <= last_level; j++) {
                        jit_tex->mip_offsets[j] += view->u.tex.first_layer *
                                                   lp_tex->img_stride[j];
                     }
                     if (view->target == PIPE_TEXTURE_CUBE ||
                         view->target == PIPE_TEXTURE_CUBE_ARRAY) {
                        assert(jit_tex->depth % 6 == 0);
                     }
                     assert(view->u.tex.first_layer <= view->u.tex.last_layer);
                     assert(view->u.tex.last_layer < res->array_size);
                  }
               }
               else {
                  /*
                   * For buffers, we don't have first_element, instead adjust
                   * last_element (stored as width) plus the base pointer.
                   */
                  unsigned view_blocksize = util_format_get_blocksize(view->format);
                  /* probably don't really need to fill that out */
                  jit_tex->mip_offsets[0] = 0;
                  jit_tex->row_stride[0] = 0;
                  jit_tex->img_stride[0] = 0;

                  /* everything specified in number of elements here. */
                  jit_tex->width = view->u.buf.last_element - view->u.buf.first_element + 1;
                  jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.first_element *
                                  view_blocksize;
                  /* XXX Unsure if we need to sanitize parameters? */
                  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 llvmpipe_screen *screen = llvmpipe_screen(res->screen);
            struct sw_winsys *winsys = screen->winsys;
            jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt,
                                                         PIPE_TRANSFER_READ);
            jit_tex->row_stride[0] = lp_tex->row_stride[0];
            jit_tex->img_stride[0] = lp_tex->img_stride[0];
            jit_tex->mip_offsets[0] = 0;
            jit_tex->width = res->width0;
            jit_tex->height = res->height0;
            jit_tex->depth = res->depth0;
            jit_tex->first_level = jit_tex->last_level = 0;
            assert(jit_tex->base);
         }
      }
      else {
         pipe_resource_reference(&setup->fs.current_tex[i], NULL);
      }
   }
   setup->fs.current_tex_num = num;

   setup->dirty |= LP_SETUP_NEW_FS;
}
static void
prepare_shader_sampling(
   struct llvmpipe_context *lp,
   unsigned num,
   struct pipe_sampler_view **views,
   unsigned shader_type)
{

   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 < num; i++) {
      struct pipe_sampler_view *view = i < num ? views[i] : NULL;

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

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

            if (llvmpipe_resource_is_texture(res)) {
               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 = lp_tex->tex_data;

               for (j = first_level; j <= last_level; j++) {
                  mip_offsets[j] = lp_tex->mip_offsets[j];
                  row_stride[j] = lp_tex->row_stride[j];
                  img_stride[j] = lp_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 *
                                       lp_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 = lp_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 llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
            struct sw_winsys *winsys = screen->winsys;
            addr = winsys->displaytarget_map(winsys, lp_tex->dt,
                                                PIPE_TRANSFER_READ);
            row_stride[0] = lp_tex->row_stride[0];
            img_stride[0] = lp_tex->img_stride[0];
            mip_offsets[0] = 0;
            assert(addr);
         }
         draw_set_mapped_texture(lp->draw,
                                 shader_type,
                                 i,
                                 width0, tex->height0, num_layers,
                                 first_level, last_level,
                                 addr,
                                 row_stride, img_stride, mip_offsets);
      }
   }
}
示例#7
0
/**
 * Free all the temporary data in a scene.
 */
void
lp_scene_end_rasterization(struct lp_scene *scene )
{
   int i, j;

   /* Unmap color buffers */
   for (i = 0; i < scene->fb.nr_cbufs; i++) {
      if (scene->cbufs[i].map) {
         struct pipe_surface *cbuf = scene->fb.cbufs[i];
         if (llvmpipe_resource_is_texture(cbuf->texture)) {
            llvmpipe_resource_unmap(cbuf->texture,
                                    cbuf->u.tex.level,
                                    cbuf->u.tex.first_layer);
         }
         scene->cbufs[i].map = NULL;
      }
   }

   /* Unmap z/stencil buffer */
   if (scene->zsbuf.map) {
      struct pipe_surface *zsbuf = scene->fb.zsbuf;
      llvmpipe_resource_unmap(zsbuf->texture,
                              zsbuf->u.tex.level,
                              zsbuf->u.tex.first_layer);
      scene->zsbuf.map = NULL;
   }

   /* Reset all command lists:
    */
   for (i = 0; i < scene->tiles_x; i++) {
      for (j = 0; j < scene->tiles_y; j++) {
         struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
         bin->head = NULL;
         bin->tail = NULL;
         bin->last_state = NULL;
      }
   }

   /* If there are any bins which weren't cleared by the loop above,
    * they will be caught (on debug builds at least) by this assert:
    */
   assert(lp_scene_is_empty(scene));

   /* Decrement texture ref counts
    */
   {
      struct resource_ref *ref;
      int i, j = 0;

      for (ref = scene->resources; ref; ref = ref->next) {
         for (i = 0; i < ref->count; i++) {
            if (LP_DEBUG & DEBUG_SETUP)
               debug_printf("resource %d: %p %dx%d sz %d\n",
                            j,
                            (void *) ref->resource[i],
                            ref->resource[i]->width0,
                            ref->resource[i]->height0,
                            llvmpipe_resource_size(ref->resource[i]));
            j++;
            pipe_resource_reference(&ref->resource[i], NULL);
         }
      }

      if (LP_DEBUG & DEBUG_SETUP)
         debug_printf("scene %d resources, sz %d\n",
                      j, scene->resource_reference_size);
   }

   /* Free all scene data blocks:
    */
   {
      struct data_block_list *list = &scene->data;
      struct data_block *block, *tmp;

      for (block = list->head->next; block; block = tmp) {
         tmp = block->next;
	 FREE(block);
      }

      list->head->next = NULL;
      list->head->used = 0;
   }

   lp_fence_reference(&scene->fence, NULL);

   scene->resources = NULL;
   scene->scene_size = 0;
   scene->resource_reference_size = 0;

   scene->has_depthstencil_clear = FALSE;
   scene->alloc_failed = FALSE;

   util_unreference_framebuffer_state( &scene->fb );
}
示例#8
0
static struct pipe_resource *
llvmpipe_resource_create(struct pipe_screen *_screen,
                         const struct pipe_resource *templat)
{
   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
   struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
   if (!lpr)
      return NULL;

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

   /* assert(lpr->base.bind); */

   if (llvmpipe_resource_is_texture(&lpr->base)) {
      if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
                            PIPE_BIND_SCANOUT |
                            PIPE_BIND_SHARED)) {
         /* displayable surface */
         if (!llvmpipe_displaytarget_layout(screen, lpr))
            goto fail;
      }
      else {
         /* texture map */
         if (!llvmpipe_texture_layout(screen, lpr))
            goto fail;
      }
   }
   else {
      /* other data (vertex buffer, const buffer, etc) */
      const uint bytes = templat->width0;
      assert(util_format_get_blocksize(templat->format) == 1);
      assert(templat->height0 == 1);
      assert(templat->depth0 == 1);
      assert(templat->last_level == 0);
      /*
       * Reserve some extra storage since if we'd render to a buffer we
       * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
       * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
       */
      lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64);
      /*
       * buffers don't really have stride but it's probably safer
       * (for code doing same calculations for buffers and textures)
       * to put something sane in there.
       */
      lpr->row_stride[0] = bytes;
      if (!lpr->data)
         goto fail;
      memset(lpr->data, 0, bytes);
   }

   lpr->id = id_counter++;

#ifdef DEBUG
   insert_at_tail(&resource_list, lpr);
#endif

   return &lpr->base;

 fail:
   FREE(lpr);
   return NULL;
}