Beispiel #1
0
static boolean
nv50_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   if (sample_count > 8)
      return FALSE;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return FALSE;
   if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128)
      return FALSE;

   if (!util_format_is_supported(format, bindings))
      return FALSE;

   switch (format) {
   case PIPE_FORMAT_Z16_UNORM:
      if (nv50_screen(pscreen)->tesla->oclass < NVA0_3D_CLASS)
         return FALSE;
      break;
   default:
      break;
   }

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_SHARED);

   return (nv50_format_table[format].usage & bindings) == bindings;
}
Beispiel #2
0
static void
nv50_screen_destroy(struct pipe_screen *pscreen)
{
	struct nv50_screen *screen = nv50_screen(pscreen);
	unsigned i;

	for (i = 0; i < 3; i++) {
		if (screen->constbuf_parm[i])
			nouveau_bo_ref(NULL, &screen->constbuf_parm[i]);
	}

	if (screen->constbuf_misc[0])
		nouveau_bo_ref(NULL, &screen->constbuf_misc[0]);
	if (screen->tic)
		nouveau_bo_ref(NULL, &screen->tic);
	if (screen->tsc)
		nouveau_bo_ref(NULL, &screen->tsc);
	if (screen->static_init)
		so_ref(NULL, &screen->static_init);

	nouveau_notifier_free(&screen->sync);
	nouveau_grobj_free(&screen->tesla);
	nouveau_grobj_free(&screen->eng2d);
	nouveau_grobj_free(&screen->m2mf);
	nouveau_resource_destroy(&screen->immd_heap[0]);
	nouveau_resource_destroy(&screen->parm_heap[0]);
	nouveau_resource_destroy(&screen->parm_heap[1]);
	nouveau_screen_fini(&screen->base);
	FREE(screen);
}
Beispiel #3
0
static int
nv50_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
                             enum pipe_shader_cap param)
{
   switch (shader) {
   case PIPE_SHADER_VERTEX:
   case PIPE_SHADER_GEOMETRY:
   case PIPE_SHADER_FRAGMENT:
      break;
   default:
      return 0;
   }

   switch (param) {
   case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
      return 16384;
   case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
      return 4;
   case PIPE_SHADER_CAP_MAX_INPUTS:
      if (shader == PIPE_SHADER_VERTEX)
         return 32;
      return 15;
   case PIPE_SHADER_CAP_MAX_CONSTS:
      return 65536 / 16;
   case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
      return NV50_MAX_PIPE_CONSTBUFS;
   case PIPE_SHADER_CAP_MAX_ADDRS:
      return 1;
   case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
   case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
      return shader != PIPE_SHADER_FRAGMENT;
   case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
   case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
      return 1;
   case PIPE_SHADER_CAP_MAX_PREDS:
      return 0;
   case PIPE_SHADER_CAP_MAX_TEMPS:
      return nv50_screen(pscreen)->max_tls_space / ONE_TEMP_SIZE;
   case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
      return 1;
   case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
      return 0;
   case PIPE_SHADER_CAP_SUBROUTINES:
      return 0; /* please inline, or provide function declarations */
   case PIPE_SHADER_CAP_INTEGERS:
      return 1;
   case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
      /* The chip could handle more sampler views than samplers */
   case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
      return MIN2(32, PIPE_MAX_SAMPLERS);
   default:
      NOUVEAU_ERR("unknown PIPE_SHADER_CAP %d\n", param);
      return 0;
   }
}
Beispiel #4
0
static void
nv50_screen_destroy(struct pipe_screen *pscreen)
{
   struct nv50_screen *screen = nv50_screen(pscreen);

   if (!nouveau_drm_screen_unref(&screen->base))
      return;

   if (screen->base.fence.current) {
      struct nouveau_fence *current = NULL;

      /* nouveau_fence_wait will create a new current fence, so wait on the
       * _current_ one, and remove both.
       */
      nouveau_fence_ref(screen->base.fence.current, &current);
      nouveau_fence_wait(current, NULL);
      nouveau_fence_ref(NULL, &current);
      nouveau_fence_ref(NULL, &screen->base.fence.current);
   }
   if (screen->base.pushbuf)
      screen->base.pushbuf->user_priv = NULL;

   if (screen->blitter)
      nv50_blitter_destroy(screen);
   if (screen->pm.prog) {
      screen->pm.prog->code = NULL; /* hardcoded, don't FREE */
      nv50_program_destroy(NULL, screen->pm.prog);
      FREE(screen->pm.prog);
   }

   nouveau_bo_ref(NULL, &screen->code);
   nouveau_bo_ref(NULL, &screen->tls_bo);
   nouveau_bo_ref(NULL, &screen->stack_bo);
   nouveau_bo_ref(NULL, &screen->txc);
   nouveau_bo_ref(NULL, &screen->uniforms);
   nouveau_bo_ref(NULL, &screen->fence.bo);

   nouveau_heap_destroy(&screen->vp_code_heap);
   nouveau_heap_destroy(&screen->gp_code_heap);
   nouveau_heap_destroy(&screen->fp_code_heap);

   FREE(screen->tic.entries);

   nouveau_object_del(&screen->tesla);
   nouveau_object_del(&screen->eng2d);
   nouveau_object_del(&screen->m2mf);
   nouveau_object_del(&screen->compute);
   nouveau_object_del(&screen->sync);

   nouveau_screen_fini(&screen->base);

   FREE(screen);
}
Beispiel #5
0
int
nv50_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
                                        unsigned id,
                                        struct pipe_driver_query_group_info *info)
{
   struct nv50_screen *screen = nv50_screen(pscreen);
   int count = 0;

   if (screen->compute)
      if (screen->base.class_3d >= NV84_3D_CLASS)
         count += 2;

   if (!info)
      return count;

   if (id == NV50_HW_SM_QUERY_GROUP) {
      if (screen->compute) {
         if (screen->base.class_3d >= NV84_3D_CLASS) {
            info->name = "MP counters";

            /* Expose the maximum number of hardware counters available,
             * although some queries use more than one counter. Expect failures
             * in that case but as performance counters are for developers,
             * this should not have a real impact. */
            info->max_active_queries = 4;
            info->num_queries = NV50_HW_SM_QUERY_COUNT;
            return 1;
         }
      }
   } else
   if (id == NV50_HW_METRIC_QUERY_GROUP) {
      if (screen->compute) {
         if (screen->base.class_3d >= NV84_3D_CLASS) {
            info->name = "Performance metrics";
            info->max_active_queries = 2; /* A metric uses at least 2 queries */
            info->num_queries = NV50_HW_METRIC_QUERY_COUNT;
            return 1;
         }
      }
   }

   /* user asked for info about non-existing query group */
   info->name = "this_is_not_the_query_group_you_are_looking_for";
   info->max_active_queries = 0;
   info->num_queries = 0;
   return 0;
}
Beispiel #6
0
static int
nv50_screen_get_compute_param(struct pipe_screen *pscreen,
                              enum pipe_shader_ir ir_type,
                              enum pipe_compute_cap param, void *data)
{
   struct nv50_screen *screen = nv50_screen(pscreen);

#define RET(x) do {                  \
   if (data)                         \
      memcpy(data, x, sizeof(x));    \
   return sizeof(x);                 \
} while (0)

   switch (param) {
   case PIPE_COMPUTE_CAP_GRID_DIMENSION:
      RET((uint64_t []) { 2 });
   case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
      RET(((uint64_t []) { 65535, 65535 }));
   case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
      RET(((uint64_t []) { 512, 512, 64 }));
   case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
      RET((uint64_t []) { 512 });
   case PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE: /* g0-15[] */
      RET((uint64_t []) { 1ULL << 32 });
   case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE: /* s[] */
      RET((uint64_t []) { 16 << 10 });
   case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE: /* l[] */
      RET((uint64_t []) { 16 << 10 });
   case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE: /* c[], arbitrary limit */
      RET((uint64_t []) { 4096 });
   case PIPE_COMPUTE_CAP_SUBGROUP_SIZE:
      RET((uint32_t []) { 32 });
   case PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE:
      RET((uint64_t []) { 1ULL << 40 });
   case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:
      RET((uint32_t []) { 0 });
   case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:
      RET((uint32_t []) { screen->mp_count });
   case PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY:
      RET((uint32_t []) { 512 }); /* FIXME: arbitrary limit */
   default:
      return 0;
   }

#undef RET
}
Beispiel #7
0
static boolean
nv50_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   if (sample_count > 8)
      return false;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return false;
   if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128)
      return false;

   if (!util_format_is_supported(format, bindings))
      return false;

   switch (format) {
   case PIPE_FORMAT_Z16_UNORM:
      if (nv50_screen(pscreen)->tesla->oclass < NVA0_3D_CLASS)
         return false;
      break;
   default:
      break;
   }

   if (bindings & PIPE_BIND_LINEAR)
      if (util_format_is_depth_or_stencil(format) ||
          (target != PIPE_TEXTURE_1D &&
           target != PIPE_TEXTURE_2D &&
           target != PIPE_TEXTURE_RECT) ||
          sample_count > 1)
         return false;

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_LINEAR |
                 PIPE_BIND_SHARED);

   return (( nv50_format_table[format].usage |
            nv50_vertex_format[format].usage) & bindings) == bindings;
}
Beispiel #8
0
static void
nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
{
   struct nv50_screen *screen = nv50_screen(pscreen);
   struct nouveau_pushbuf *push = screen->base.pushbuf;

   /* we need to do it after possible flush in MARK_RING */
   *sequence = ++screen->base.fence.sequence;

   PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4));
   PUSH_DATAh(push, screen->fence.bo->offset);
   PUSH_DATA (push, screen->fence.bo->offset);
   PUSH_DATA (push, *sequence);
   PUSH_DATA (push, NV50_3D_QUERY_GET_MODE_WRITE_UNK0 |
                    NV50_3D_QUERY_GET_UNK4 |
                    NV50_3D_QUERY_GET_UNIT_CROP |
                    NV50_3D_QUERY_GET_TYPE_QUERY |
                    NV50_3D_QUERY_GET_QUERY_SELECT_ZERO |
                    NV50_3D_QUERY_GET_SHORT);
}
Beispiel #9
0
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
	struct pipe_winsys *pipe_winsys = pscreen->winsys;
	struct nv50_screen *screen = nv50_screen(pscreen);
	struct nv50_context *nv50;

	nv50 = CALLOC_STRUCT(nv50_context);
	if (!nv50)
		return NULL;
	nv50->screen = screen;
	nv50->pctx_id = pctx_id;

	nv50->pipe.winsys = pipe_winsys;
	nv50->pipe.screen = pscreen;

	nv50->pipe.destroy = nv50_destroy;

	nv50->pipe.set_edgeflags = nv50_set_edgeflags;
	nv50->pipe.draw_arrays = nv50_draw_arrays;
	nv50->pipe.draw_elements = nv50_draw_elements;
	nv50->pipe.clear = nv50_clear;

	nv50->pipe.flush = nv50_flush;

	nv50->pipe.is_texture_referenced = nouveau_is_texture_referenced;
	nv50->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;

	screen->base.channel->user_private = nv50;
	screen->base.channel->flush_notify = nv50_state_flush_notify;

	nv50_init_surface_functions(nv50);
	nv50_init_state_functions(nv50);
	nv50_init_query_functions(nv50);

	nv50->draw = draw_create();
	assert(nv50->draw);
	draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));

	return &nv50->pipe;
}
Beispiel #10
0
static int
nv50_pre_pipebuffer_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
	unsigned usage)
{
	struct nv50_screen *screen = nv50_screen(pscreen);
	struct nv50_context *ctx = screen->cur_ctx;

	if (!(pb->usage & PIPE_BUFFER_USAGE_VERTEX))
		return 0;

	/* Our vtxbuf got mapped, it can no longer be considered part of current
	 * state, remove it to avoid emitting reloc markers.
	 */
	if (ctx && ctx->state.vtxbuf && so_bo_is_reloc(ctx->state.vtxbuf,
			nouveau_bo(pb))) {
		so_ref(NULL, &ctx->state.vtxbuf);
		ctx->dirty |= NV50_NEW_ARRAYS;
	}

	return 0;
}
Beispiel #11
0
static void
nv50_screen_destroy(struct pipe_screen *pscreen)
{
   struct nv50_screen *screen = nv50_screen(pscreen);

   if (screen->base.fence.current) {
      nouveau_fence_wait(screen->base.fence.current);
      nouveau_fence_ref (NULL, &screen->base.fence.current);
   }
   if (screen->base.pushbuf)
      screen->base.pushbuf->user_priv = NULL;

   if (screen->blitctx)
      FREE(screen->blitctx);

   nouveau_bo_ref(NULL, &screen->code);
   nouveau_bo_ref(NULL, &screen->tls_bo);
   nouveau_bo_ref(NULL, &screen->stack_bo);
   nouveau_bo_ref(NULL, &screen->txc);
   nouveau_bo_ref(NULL, &screen->uniforms);
   nouveau_bo_ref(NULL, &screen->fence.bo);

   nouveau_heap_destroy(&screen->vp_code_heap);
   nouveau_heap_destroy(&screen->gp_code_heap);
   nouveau_heap_destroy(&screen->fp_code_heap);

   if (screen->tic.entries)
      FREE(screen->tic.entries);

   nouveau_object_del(&screen->tesla);
   nouveau_object_del(&screen->eng2d);
   nouveau_object_del(&screen->m2mf);
   nouveau_object_del(&screen->sync);

   nouveau_screen_fini(&screen->base);

   FREE(screen);
}
Beispiel #12
0
int
nv50_screen_get_driver_query_info(struct pipe_screen *pscreen,
                                  unsigned id,
                                  struct pipe_driver_query_info *info)
{
   struct nv50_screen *screen = nv50_screen(pscreen);
   int num_hw_queries = 0;

   num_hw_queries = nv50_hw_get_driver_query_info(screen, 0, NULL);

   if (!info)
      return num_hw_queries;

   /* Init default values. */
   info->name = "this_is_not_the_query_you_are_looking_for";
   info->query_type = 0xdeadd01d;
   info->max_value.u64 = 0;
   info->type = PIPE_DRIVER_QUERY_TYPE_UINT64;
   info->group_id = -1;
   info->flags = 0;

   return nv50_hw_get_driver_query_info(screen, id, info);
}
Beispiel #13
0
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
{
   struct nv50_screen *screen = nv50_screen(pscreen);
   struct nv50_context *nv50;
   struct pipe_context *pipe;
   int ret;
   uint32_t flags;

   nv50 = CALLOC_STRUCT(nv50_context);
   if (!nv50)
      return NULL;
   pipe = &nv50->base.pipe;

   if (!nv50_blitctx_create(nv50))
      goto out_err;

   nv50->base.pushbuf = screen->base.pushbuf;
   nv50->base.client = screen->base.client;

   ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
   if (!ret)
      ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_3D_COUNT,
                               &nv50->bufctx_3d);
   if (!ret)
      ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_CP_COUNT,
                               &nv50->bufctx_cp);
   if (ret)
      goto out_err;

   nv50->base.screen    = &screen->base;
   nv50->base.copy_data = nv50_m2mf_copy_linear;
   nv50->base.push_data = nv50_sifc_linear_u8;
   /* FIXME: Make it possible to use this again. The problem is that there is
    * some clever logic in the card that allows for multiple renders to happen
    * when there are only constbuf changes. However that relies on the
    * constbuf updates happening to the right constbuf slots. Currently
    * implementation just makes it go through a separate slot which doesn't
    * properly update the right constbuf data.
   nv50->base.push_cb   = nv50_cb_push;
    */

   nv50->screen = screen;
   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nv50_destroy;

   pipe->draw_vbo = nv50_draw_vbo;
   pipe->clear = nv50_clear;
   pipe->launch_grid = nv50_launch_grid;

   pipe->flush = nv50_flush;
   pipe->texture_barrier = nv50_texture_barrier;
   pipe->memory_barrier = nv50_memory_barrier;
   pipe->get_sample_position = nv50_context_get_sample_position;

   if (!screen->cur_ctx) {
      /* Restore the last context's state here, normally handled during
       * context switch
       */
      nv50->state = screen->save_state;
      screen->cur_ctx = nv50;
      nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
   }
   nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;

   nouveau_context_init(&nv50->base);
   nv50_init_query_functions(nv50);
   nv50_init_surface_functions(nv50);
   nv50_init_state_functions(nv50);
   nv50_init_resource_functions(pipe);

   nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;

   if (screen->base.device->chipset < 0x84 ||
       debug_get_bool_option("NOUVEAU_PMPEG", false)) {
      /* PMPEG */
      nouveau_context_init_vdec(&nv50->base);
   } else if (screen->base.device->chipset < 0x98 ||
              screen->base.device->chipset == 0xa0) {
      /* VP2 */
      pipe->create_video_codec = nv84_create_decoder;
      pipe->create_video_buffer = nv84_video_buffer_create;
   } else {
      /* VP3/4 */
      pipe->create_video_codec = nv98_create_decoder;
      pipe->create_video_buffer = nv98_video_buffer_create;
   }

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->code);
   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->uniforms);
   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->txc);
   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->stack_bo);
   if (screen->compute) {
      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->code);
      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->txc);
      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->stack_bo);
   }

   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->fence.bo);
   BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
   if (screen->compute)
      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);

   nv50->base.scratch.bo_size = 2 << 20;

   util_dynarray_init(&nv50->global_residents);

   return pipe;

out_err:
   if (nv50->bufctx_3d)
      nouveau_bufctx_del(&nv50->bufctx_3d);
   if (nv50->bufctx_cp)
      nouveau_bufctx_del(&nv50->bufctx_cp);
   if (nv50->bufctx)
      nouveau_bufctx_del(&nv50->bufctx);
   FREE(nv50->blit);
   FREE(nv50);
   return NULL;
}
Beispiel #14
0
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, void *priv)
{
   struct nv50_screen *screen = nv50_screen(pscreen);
   struct nv50_context *nv50;
   struct pipe_context *pipe;
   int ret;
   uint32_t flags;

   nv50 = CALLOC_STRUCT(nv50_context);
   if (!nv50)
      return NULL;
   pipe = &nv50->base.pipe;

   if (!nv50_blitctx_create(nv50))
      goto out_err;

   nv50->base.pushbuf = screen->base.pushbuf;
   nv50->base.client = screen->base.client;

   ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
                            &nv50->bufctx_3d);
   if (!ret)
      ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
   if (ret)
      goto out_err;

   nv50->base.screen    = &screen->base;
   nv50->base.copy_data = nv50_m2mf_copy_linear;
   nv50->base.push_data = nv50_sifc_linear_u8;
   nv50->base.push_cb   = nv50_cb_push;

   nv50->screen = screen;
   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nv50_destroy;

   pipe->draw_vbo = nv50_draw_vbo;
   pipe->clear = nv50_clear;

   pipe->flush = nv50_flush;
   pipe->texture_barrier = nv50_texture_barrier;

   if (!screen->cur_ctx) {
      screen->cur_ctx = nv50;
      nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
   }

   nv50_init_query_functions(nv50);
   nv50_init_surface_functions(nv50);
   nv50_init_state_functions(nv50);
   nv50_init_resource_functions(pipe);

   nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;

#ifdef NV50_WITH_DRAW_MODULE
   /* no software fallbacks implemented */
   nv50->draw = draw_create(pipe);
   assert(nv50->draw);
   draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
#endif

   nouveau_context_init_vdec(&nv50->base);

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

   BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->code);
   BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->uniforms);
   BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->txc);
   BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->stack_bo);

   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

   BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->fence.bo);
   BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);

   nv50->base.scratch.bo_size = 2 << 20;

   return pipe;

out_err:
   if (nv50) {
      if (nv50->bufctx_3d)
         nouveau_bufctx_del(&nv50->bufctx_3d);
      if (nv50->bufctx)
         nouveau_bufctx_del(&nv50->bufctx);
      if (nv50->blit)
         FREE(nv50->blit);
      FREE(nv50);
   }
   return NULL;
}
Beispiel #15
0
static int
nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
   const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;

   switch (param) {
   case PIPE_CAP_MAX_COMBINED_SAMPLERS:
      return 64;
   case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
      return 14;
   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
      return 12;
   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
      return 14;
   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
      return 512;
   case PIPE_CAP_MIN_TEXEL_OFFSET:
      return -8;
   case PIPE_CAP_MAX_TEXEL_OFFSET:
      return 7;
   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
   case PIPE_CAP_TEXTURE_SWIZZLE:
   case PIPE_CAP_TEXTURE_SHADOW_MAP:
   case PIPE_CAP_NPOT_TEXTURES:
   case PIPE_CAP_ANISOTROPIC_FILTER:
   case PIPE_CAP_SCALED_RESOLVE:
   case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
      return 1;
   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
      return 65536;
   case PIPE_CAP_SEAMLESS_CUBE_MAP:
      return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS;
   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
      return 0;
   case PIPE_CAP_CUBE_MAP_ARRAY:
      return 0;
      /*
      return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS;
      */
   case PIPE_CAP_TWO_SIDED_STENCIL:
   case PIPE_CAP_DEPTH_CLIP_DISABLE:
   case PIPE_CAP_POINT_SPRITE:
      return 1;
   case PIPE_CAP_SM3:
      return 1;
   case PIPE_CAP_GLSL_FEATURE_LEVEL:
      return 140;
   case PIPE_CAP_MAX_RENDER_TARGETS:
      return 8;
   case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
      return 1;
   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
   case PIPE_CAP_VERTEX_COLOR_CLAMPED:
      return 1;
   case PIPE_CAP_QUERY_TIMESTAMP:
   case PIPE_CAP_QUERY_TIME_ELAPSED:
   case PIPE_CAP_OCCLUSION_QUERY:
      return 1;
   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
      return 4;
   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
      return 64;
   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
      return (class_3d >= NVA0_3D_CLASS) ? 1 : 0;
   case PIPE_CAP_BLEND_EQUATION_SEPARATE:
   case PIPE_CAP_INDEP_BLEND_ENABLE:
      return 1;
   case PIPE_CAP_INDEP_BLEND_FUNC:
      return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS;
   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
      return 1;
   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
      return 0;
   case PIPE_CAP_SHADER_STENCIL_EXPORT:
      return 0;
   case PIPE_CAP_PRIMITIVE_RESTART:
   case PIPE_CAP_TGSI_INSTANCEID:
   case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
   case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
   case PIPE_CAP_CONDITIONAL_RENDER:
   case PIPE_CAP_TEXTURE_BARRIER:
   case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
   case PIPE_CAP_START_INSTANCE:
      return 1;
   case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
      return 0; /* state trackers will know better */
   case PIPE_CAP_USER_CONSTANT_BUFFERS:
   case PIPE_CAP_USER_INDEX_BUFFERS:
   case PIPE_CAP_USER_VERTEX_BUFFERS:
      return 1;
   case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
      return 256;
   case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
      return 1; /* 256 for binding as RT, but that's not possible in GL */
   case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
      return NOUVEAU_MIN_BUFFER_MAP_ALIGN;
   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
   case PIPE_CAP_TGSI_TEXCOORD:
   case PIPE_CAP_TEXTURE_MULTISAMPLE:
      return 0;
   case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
      return 1;
   case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
      return 0;
   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
      return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
   case PIPE_CAP_ENDIANNESS:
      return PIPE_ENDIAN_LITTLE;
   default:
      NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
      return 0;
   }
}
Beispiel #16
0
static u32
nv50_screen_fence_update(struct pipe_screen *pscreen)
{
   return nv50_screen(pscreen)->fence.map[0];
}
Beispiel #17
0
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
{
    struct nv50_screen *screen = nv50_screen(pscreen);
    struct nv50_context *nv50;
    struct pipe_context *pipe;
    int ret;
    uint32_t flags;

    nv50 = CALLOC_STRUCT(nv50_context);
    if (!nv50)
        return NULL;
    pipe = &nv50->base.pipe;

    if (!nv50_blitctx_create(nv50))
        goto out_err;

    nv50->base.pushbuf = screen->base.pushbuf;
    nv50->base.client = screen->base.client;

    ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
    if (!ret)
        ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_3D_COUNT,
                                 &nv50->bufctx_3d);
    if (!ret)
        ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_CP_COUNT,
                                 &nv50->bufctx_cp);
    if (ret)
        goto out_err;

    nv50->base.screen    = &screen->base;
    nv50->base.copy_data = nv50_m2mf_copy_linear;
    nv50->base.push_data = nv50_sifc_linear_u8;
    nv50->base.push_cb   = nv50_cb_push;

    nv50->screen = screen;
    pipe->screen = pscreen;
    pipe->priv = priv;

    pipe->destroy = nv50_destroy;

    pipe->draw_vbo = nv50_draw_vbo;
    pipe->clear = nv50_clear;
    pipe->launch_grid = nv50_launch_grid;

    pipe->flush = nv50_flush;
    pipe->texture_barrier = nv50_texture_barrier;
    pipe->memory_barrier = nv50_memory_barrier;
    pipe->get_sample_position = nv50_context_get_sample_position;
    pipe->emit_string_marker = nv50_emit_string_marker;

    if (!screen->cur_ctx) {
        /* Restore the last context's state here, normally handled during
         * context switch
         */
        nv50->state = screen->save_state;
        screen->cur_ctx = nv50;
        nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
    }
    nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;

    nouveau_context_init(&nv50->base);
    nv50_init_query_functions(nv50);
    nv50_init_surface_functions(nv50);
    nv50_init_state_functions(nv50);
    nv50_init_resource_functions(pipe);

    nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;

    if (screen->base.device->chipset < 0x84 ||
            debug_get_bool_option("NOUVEAU_PMPEG", false)) {
        /* PMPEG */
        nouveau_context_init_vdec(&nv50->base);
    } else if (screen->base.device->chipset < 0x98 ||
               screen->base.device->chipset == 0xa0) {
        /* VP2 */
        pipe->create_video_codec = nv84_create_decoder;
        pipe->create_video_buffer = nv84_video_buffer_create;
    } else {
        /* VP3/4 */
        pipe->create_video_codec = nv98_create_decoder;
        pipe->create_video_buffer = nv98_video_buffer_create;
    }

    flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

    BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->code);
    BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->uniforms);
    BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->txc);
    BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->stack_bo);
    if (screen->compute) {
        BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->code);
        BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->txc);
        BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->stack_bo);
    }

    flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

    BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->fence.bo);
    BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
    if (screen->compute)
        BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);

    nv50->base.scratch.bo_size = 2 << 20;

    util_dynarray_init(&nv50->global_residents);

    return pipe;

out_err:
    if (nv50->bufctx_3d)
        nouveau_bufctx_del(&nv50->bufctx_3d);
    if (nv50->bufctx_cp)
        nouveau_bufctx_del(&nv50->bufctx_cp);
    if (nv50->bufctx)
        nouveau_bufctx_del(&nv50->bufctx);
    FREE(nv50->blit);
    FREE(nv50);
    return NULL;
}
static void
nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
			struct nouveau_bo *src_bo, unsigned src_offset,
			int src_pitch, unsigned src_tile_mode,
			int sx, int sy, int sz, int sw, int sh, int sd,
			struct nouveau_bo *dst_bo, unsigned dst_offset,
			int dst_pitch, unsigned dst_tile_mode,
			int dx, int dy, int dz, int dw, int dh, int dd,
			int cpp, int width, int height,
			unsigned src_reloc, unsigned dst_reloc)
{
	struct nv50_screen *screen = nv50_screen(pscreen);
	struct nouveau_channel *chan = screen->m2mf->channel;
	struct nouveau_grobj *m2mf = screen->m2mf;

	src_reloc |= NOUVEAU_BO_RD;
	dst_reloc |= NOUVEAU_BO_WR;

	WAIT_RING (chan, 14);

	if (!src_bo->tile_flags) {
		BEGIN_RING(chan, m2mf,
			NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
		OUT_RING  (chan, 1);
		BEGIN_RING(chan, m2mf,
			NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN, 1);
		OUT_RING  (chan, src_pitch);
		src_offset += (sy * src_pitch) + (sx * cpp);
	} else {
		BEGIN_RING(chan, m2mf,
			NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 6);
		OUT_RING  (chan, 0);
		OUT_RING  (chan, src_tile_mode << 4);
		OUT_RING  (chan, sw * cpp);
		OUT_RING  (chan, sh);
		OUT_RING  (chan, sd);
		OUT_RING  (chan, sz); /* copying only 1 zslice per call */
	}

	if (!dst_bo->tile_flags) {
		BEGIN_RING(chan, m2mf,
			NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1);
		OUT_RING  (chan, 1);
		BEGIN_RING(chan, m2mf,
			NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT, 1);
		OUT_RING  (chan, dst_pitch);
		dst_offset += (dy * dst_pitch) + (dx * cpp);
	} else {
		BEGIN_RING(chan, m2mf,
			NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 6);
		OUT_RING  (chan, 0);
		OUT_RING  (chan, dst_tile_mode << 4);
		OUT_RING  (chan, dw * cpp);
		OUT_RING  (chan, dh);
		OUT_RING  (chan, dd);
		OUT_RING  (chan, dz); /* copying only 1 zslice per call */
	}

	while (height) {
		int line_count = height > 2047 ? 2047 : height;

		MARK_RING (chan, 15, 4); /* flush on lack of space or relocs */
		BEGIN_RING(chan, m2mf,
			NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
		OUT_RELOCh(chan, src_bo, src_offset, src_reloc);
		OUT_RELOCh(chan, dst_bo, dst_offset, dst_reloc);
		BEGIN_RING(chan, m2mf,
			NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 2);
		OUT_RELOCl(chan, src_bo, src_offset, src_reloc);
		OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc);
		if (src_bo->tile_flags) {
			BEGIN_RING(chan, m2mf,
				NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN, 1);
			OUT_RING  (chan, (sy << 16) | (sx * cpp));
		} else {
			src_offset += (line_count * src_pitch);
		}
		if (dst_bo->tile_flags) {
			BEGIN_RING(chan, m2mf,
				NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT, 1);
			OUT_RING  (chan, (dy << 16) | (dx * cpp));
		} else {
			dst_offset += (line_count * dst_pitch);
		}
		BEGIN_RING(chan, m2mf,
			NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN, 4);
		OUT_RING  (chan, width * cpp);
		OUT_RING  (chan, line_count);
		OUT_RING  (chan, 0x00000101);
		OUT_RING  (chan, 0);
		FIRE_RING (chan);

		height -= line_count;
		sy += line_count;
		dy += line_count;
	}
}