Example #1
0
static int
nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
{
	struct nv50_miptree *mt = nv50_miptree(ps->texture);
	struct nouveau_channel *chan = screen->eng2d->channel;
	struct nouveau_grobj *eng2d = screen->eng2d;
	struct nouveau_bo *bo = nv50_miptree(ps->texture)->base.bo;
 	int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
 	int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);

 	format = nv50_format(ps->format);
 	if (format < 0)
 		return 1;

 	if (!bo->tile_flags) {
 		BEGIN_RING(chan, eng2d, mthd, 2);
 		OUT_RING  (chan, format);
 		OUT_RING  (chan, 1);
 		BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
		OUT_RING  (chan, mt->level[ps->level].pitch);
 		OUT_RING  (chan, ps->width);
 		OUT_RING  (chan, ps->height);
 		OUT_RELOCh(chan, bo, ps->offset, flags);
 		OUT_RELOCl(chan, bo, ps->offset, flags);
 	} else {
 		BEGIN_RING(chan, eng2d, mthd, 5);
 		OUT_RING  (chan, format);
 		OUT_RING  (chan, 0);
		OUT_RING  (chan, mt->level[ps->level].tile_mode << 4);
 		OUT_RING  (chan, 1);
 		OUT_RING  (chan, 0);
 		BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
 		OUT_RING  (chan, ps->width);
 		OUT_RING  (chan, ps->height);
 		OUT_RELOCh(chan, bo, ps->offset, flags);
 		OUT_RELOCl(chan, bo, ps->offset, flags);
 	}
 
#if 0
 	if (dst) {
 		BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
 		OUT_RING  (chan, 0);
 		OUT_RING  (chan, 0);
 		OUT_RING  (chan, surf->width);
 		OUT_RING  (chan, surf->height);
 	}
#endif
  
 	return 0;
}
Example #2
0
void
nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
                            struct pipe_transfer *transfer)
{
   struct nvc0_context *nvc0 = nvc0_context(pctx);
   struct nvc0_transfer *tx = (struct nvc0_transfer *)transfer;
   struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
   unsigned i;

   if (tx->base.usage & PIPE_TRANSFER_WRITE) {
      for (i = 0; i < tx->nlayers; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &tx->rect[0], &tx->rect[1],
                              tx->nblocksx, tx->nblocksy);
         if (mt->layout_3d)
            tx->rect[0].z++;
         else
            tx->rect[0].base += mt->layer_stride;
         tx->rect[1].base += tx->nblocksy * tx->base.stride;
      }
   }

   nouveau_bo_ref(NULL, &tx->rect[1].bo);
   pipe_resource_reference(&transfer->resource, NULL);

   FREE(tx);
}
Example #3
0
static void
nv50_emit_texture_relocs(struct nv50_context *nv50, int prog)
{
	struct nouveau_channel *chan = nv50->screen->base.channel;
	struct nouveau_bo *tic = nv50->screen->tic;
	int unit;

	for (unit = 0; unit < nv50->sampler_view_nr[prog]; unit++) {
		struct nv50_sampler_view *view;
		struct nv50_miptree *mt;
		const unsigned base = ((prog * 32) + unit) * 32;

		view = nv50_sampler_view(nv50->sampler_views[prog][unit]);
		if (!view)
			continue;
		mt = nv50_miptree(view->pipe.texture);

		nouveau_reloc_emit(chan, tic, base + 4, NULL, mt->base.bo, 0, 0,
				   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
				   NOUVEAU_BO_LOW, 0, 0);
		nouveau_reloc_emit(chan, tic, base + 8, NULL, mt->base.bo, 0, 0,
				   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
				   NOUVEAU_BO_HIGH, view->tic[2], view->tic[2]);
	}
}
Example #4
0
static struct pipe_surface *
nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
			 unsigned face, unsigned level, unsigned zslice,
			 unsigned flags)
{
	struct nv50_miptree *mt = nv50_miptree(pt);
	struct nv50_miptree_level *lvl = &mt->level[level];
	struct pipe_surface *ps;
	unsigned img = 0;

	if (pt->target == PIPE_TEXTURE_CUBE)
		img = face;

	ps = CALLOC_STRUCT(pipe_surface);
	if (!ps)
		return NULL;
	pipe_texture_reference(&ps->texture, pt);
	ps->format = pt->format;
	ps->width = u_minify(pt->width0, level);
	ps->height = u_minify(pt->height0, level);
	ps->usage = flags;
	pipe_reference_init(&ps->reference, 1);
	ps->face = face;
	ps->level = level;
	ps->zslice = zslice;
	ps->offset = lvl->image_offset[img];

	if (pt->target == PIPE_TEXTURE_3D) {
		unsigned nb_h = util_format_get_nblocksy(pt->format, ps->height);
		ps->offset += get_zslice_offset(lvl->tile_mode, zslice,
						lvl->pitch, nb_h);
	}

	return ps;
}
void
nv50_miptree_transfer_del(struct pipe_context *pcontext,
			  struct pipe_transfer *ptx)
{
	struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
	struct nv50_miptree *mt = nv50_miptree(ptx->resource);
	struct pipe_resource *pt = ptx->resource;

	unsigned nx = util_format_get_nblocksx(pt->format, tx->base.box.width);
	unsigned ny = util_format_get_nblocksy(pt->format, tx->base.box.height);

	if (ptx->usage & PIPE_TRANSFER_WRITE) {
		struct pipe_screen *pscreen = pcontext->screen;

		nv50_transfer_rect_m2mf(pscreen, tx->bo, 0,
					tx->base.stride, tx->bo->tile_mode,
					0, 0, 0,
					tx->nblocksx, tx->nblocksy, 1,
					mt->base.bo, tx->level_offset,
					tx->level_pitch, tx->level_tiling,
					tx->level_x, tx->level_y, tx->level_z,
					tx->nblocksx, tx->nblocksy,
					tx->level_depth,
					util_format_get_blocksize(pt->format), nx, ny,
					NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
					NOUVEAU_BO_GART);
	}

	nouveau_bo_ref(NULL, &tx->bo);
	pipe_resource_reference(&ptx->resource, NULL);
	FREE(ptx);
}
Example #6
0
static int
nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so,
		       unsigned p)
{
	struct nouveau_grobj *eng2d = nv50->screen->eng2d;
	struct nouveau_grobj *tesla = nv50->screen->tesla;
	unsigned unit, j;

	const unsigned rll = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW;
	const unsigned rlh = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH
		| NOUVEAU_BO_OR;

	nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM,
			  p * (32 * 8 * 4), nv50->sampler_view_nr[p] * 8 * 4);

	for (unit = 0; unit < nv50->sampler_view_nr[p]; ++unit) {
		struct nv50_sampler_view *view =
			nv50_sampler_view(nv50->sampler_views[p][unit]);

		so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
		if (view) {
			uint32_t tic2 = view->tic[2];
			struct nv50_miptree *mt =
				nv50_miptree(view->pipe.texture);

			tic2 &= ~NV50TIC_0_2_NORMALIZED_COORDS;
			if (nv50->sampler[p][unit]->normalized)
				tic2 |= NV50TIC_0_2_NORMALIZED_COORDS;
			view->tic[2] = tic2;

			so_data  (so, view->tic[0]);
			so_reloc (so, mt->base.bo, 0, rll, 0, 0);
			so_reloc (so, mt->base.bo, 0, rlh, tic2, tic2);
			so_datap (so, &view->tic[3], 5);

			/* Set TEX insn $t src binding $unit in program type p
			 * to TIC, TSC entry (32 * p + unit), mark valid (1).
			 */
			so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
			so_data  (so, ((32 * p + unit) << 9) | (unit << 1) | 1);
		} else {
			for (j = 0; j < 8; ++j)
				so_data(so, 0);
			so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
			so_data  (so, (unit << 1) | 0);
		}
	}

	for (; unit < nv50->state.sampler_view_nr[p]; unit++) {
		/* Make other bindings invalid. */
		so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
		so_data  (so, (unit << 1) | 0);
	}

	nv50->state.sampler_view_nr[p] = nv50->sampler_view_nr[p];
	return TRUE;
}
Example #7
0
static void
nv50_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 nv50_context *nv50 = nv50_context(pipe);
   struct nouveau_pushbuf *push = nv50->base.pushbuf;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;

   BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);
   PUSH_DATAf(push, color->f[0]);
   PUSH_DATAf(push, color->f[1]);
   PUSH_DATAf(push, color->f[2]);
   PUSH_DATAf(push, color->f[3]);
#if 0
   if (MARK_RING(chan, 18, 2))
      return;
#endif
   BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
   PUSH_DATA (push, 1);
   BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);
   PUSH_DATAh(push, bo->offset + sf->offset);
   PUSH_DATA (push, bo->offset + sf->offset);
   PUSH_DATA (push, nv50_format_table[dst->format].rt);
   PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);
   if (nouveau_bo_memtype(bo))
      PUSH_DATA(push, sf->width);
   else
      PUSH_DATA(push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);
   PUSH_DATA (push, sf->height);
   BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
   PUSH_DATA (push, 1);

   if (!nouveau_bo_memtype(bo)) {
      BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
      PUSH_DATA (push, 0);
   }

   /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */

   BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
   PUSH_DATA (push, (width << 16) | dstx);
   PUSH_DATA (push, (height << 16) | dsty);

   BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);
   PUSH_DATA (push, 0x3c);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
Example #8
0
static void
nv50_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 nv50_context *nv50 = nv50_context(pipe);
   struct nouveau_pushbuf *push = nv50->base.pushbuf;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;
   uint32_t mode = 0;

   assert(nouveau_bo_memtype(bo)); /* ZETA cannot be linear */

   if (clear_flags & PIPE_CLEAR_DEPTH) {
      BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1);
      PUSH_DATAf(push, depth);
      mode |= NV50_3D_CLEAR_BUFFERS_Z;
   }

   if (clear_flags & PIPE_CLEAR_STENCIL) {
      BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1);
      PUSH_DATA (push, stencil & 0xff);
      mode |= NV50_3D_CLEAR_BUFFERS_S;
   }
#if 0
   if (MARK_RING(chan, 17, 2))
      return;
#endif
   BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);
   PUSH_DATAh(push, bo->offset + sf->offset);
   PUSH_DATA (push, bo->offset + sf->offset);
   PUSH_DATA (push, nv50_format_table[dst->format].rt);
   PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
   PUSH_DATA (push, 1);
   BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);
   PUSH_DATA (push, sf->width);
   PUSH_DATA (push, sf->height);
   PUSH_DATA (push, (1 << 16) | 1);

   BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
   PUSH_DATA (push, (width << 16) | dstx);
   PUSH_DATA (push, (height << 16) | dsty);

   BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);
   PUSH_DATA (push, mode);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
Example #9
0
static void
nv50_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 nv50_context *nv50 = nv50_context(pipe);
   struct nv50_screen *screen = nv50->screen;
   struct nouveau_channel *chan = screen->base.channel;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;
   uint32_t mode = 0;

   if (clear_flags & PIPE_CLEAR_DEPTH) {
      BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
      OUT_RINGf (chan, depth);
      mode |= NV50_3D_CLEAR_BUFFERS_Z;
   }

   if (clear_flags & PIPE_CLEAR_STENCIL) {
      BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
      OUT_RING  (chan, stencil & 0xff);
      mode |= NV50_3D_CLEAR_BUFFERS_S;
   }

   if (MARK_RING(chan, 17, 2))
      return;

   BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
   OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RING  (chan, nv50_format_table[dst->format].rt);
   OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
   OUT_RING  (chan, 0);
   BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
   OUT_RING  (chan, 1);
   BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
   OUT_RING  (chan, sf->width);
   OUT_RING  (chan, sf->height);
   OUT_RING  (chan, (1 << 16) | 1);

   BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
   OUT_RING  (chan, (width << 16) | dstx);
   OUT_RING  (chan, (height << 16) | dsty);

   BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
   OUT_RING  (chan, mode);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
Example #10
0
static void
nv50_miptree_destroy(struct pipe_texture *pt)
{
	struct nv50_miptree *mt = nv50_miptree(pt);
	unsigned l;

	for (l = 0; l <= pt->last_level; ++l)
		FREE(mt->level[l].image_offset);

	nouveau_bo_ref(NULL, &mt->base.bo);
	FREE(mt);
}
Example #11
0
static void
nv50_clear_render_target(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         const float *rgba,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct nv50_screen *screen = nv50->screen;
   struct nouveau_channel *chan = screen->base.channel;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;

   BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
   OUT_RINGf (chan, rgba[0]);
   OUT_RINGf (chan, rgba[1]);
   OUT_RINGf (chan, rgba[2]);
   OUT_RINGf (chan, rgba[3]);

   if (MARK_RING(chan, 18, 2))
      return;

   BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
   OUT_RING  (chan, 1);
   BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 5);
   OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RING  (chan, nv50_format_table[dst->format].rt);
   OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
   OUT_RING  (chan, 0);
   BEGIN_RING(chan, RING_3D(RT_HORIZ(0)), 2);
   OUT_RING  (chan, sf->width);
   OUT_RING  (chan, sf->height);
   BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
   OUT_RING  (chan, 1);

   /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */

   BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
   OUT_RING  (chan, (width << 16) | dstx);
   OUT_RING  (chan, (height << 16) | dsty);

   BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
   OUT_RING  (chan, 0x3c);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
Example #12
0
static void
nvc0_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 nvc0_context *nvc0 = nvc0_context(pipe);
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nv50_surface *sf = nv50_surface(dst);
   struct nv04_resource *res = nv04_resource(sf->base.texture);
   unsigned z;

   if (!PUSH_SPACE(push, 32 + sf->depth))
      return;

   PUSH_REFN (push, res->bo, res->domain | NOUVEAU_BO_WR);

   BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
   PUSH_DATAf(push, color->f[0]);
   PUSH_DATAf(push, color->f[1]);
   PUSH_DATAf(push, color->f[2]);
   PUSH_DATAf(push, color->f[3]);

   BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
   PUSH_DATA (push, ( width << 16) | dstx);
   PUSH_DATA (push, (height << 16) | dsty);

   BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
   PUSH_DATA (push, 1);
   BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);
   PUSH_DATAh(push, res->address + sf->offset);
   PUSH_DATA (push, res->address + sf->offset);
   if (likely(nouveau_bo_memtype(res->bo))) {
      struct nv50_miptree *mt = nv50_miptree(dst->texture);

      PUSH_DATA(push, sf->width);
      PUSH_DATA(push, sf->height);
      PUSH_DATA(push, nvc0_format_table[dst->format].rt);
      PUSH_DATA(push, (mt->layout_3d << 16) |
               mt->level[sf->base.u.tex.level].tile_mode);
      PUSH_DATA(push, dst->u.tex.first_layer + sf->depth);
      PUSH_DATA(push, mt->layer_stride >> 2);
      PUSH_DATA(push, dst->u.tex.first_layer);
   } else {
      if (res->base.target == PIPE_BUFFER) {
Example #13
0
void
nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
                            struct pipe_transfer *transfer)
{
   struct nvc0_context *nvc0 = nvc0_context(pctx);
   struct nvc0_transfer *tx = (struct nvc0_transfer *)transfer;
   struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
   unsigned i;

   if (tx->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) {
      pipe_resource_reference(&transfer->resource, NULL);

      FREE(tx);
      return;
   }

   if (tx->base.usage & PIPE_TRANSFER_WRITE) {
      for (i = 0; i < tx->nlayers; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &tx->rect[0], &tx->rect[1],
                              tx->nblocksx, tx->nblocksy);
         if (mt->layout_3d)
            tx->rect[0].z++;
         else
            tx->rect[0].base += mt->layer_stride;
         tx->rect[1].base += tx->nblocksy * tx->base.stride;
      }
      NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_wr, 1);

      /* Allow the copies above to finish executing before freeing the source */
      nouveau_fence_work(nvc0->screen->base.fence.current,
                         nouveau_fence_unref_bo, tx->rect[1].bo);
   } else {
      nouveau_bo_ref(NULL, &tx->rect[1].bo);
   }
   if (tx->base.usage & PIPE_TRANSFER_READ)
      NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_rd, 1);

   pipe_resource_reference(&transfer->resource, NULL);

   FREE(tx);
}
Example #14
0
static void
nv50_resource_resolve(struct pipe_context *pipe,
                      const struct pipe_resolve_info *info)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct nv50_screen *screen = nv50->screen;
   struct nv50_blitctx *blit = screen->blitctx;
   struct nouveau_channel *chan = screen->base.channel;
   struct pipe_resource *src = info->src.res;
   struct pipe_resource *dst = info->dst.res;
   float x0, x1, y0, y1, z;
   float x_range, y_range;

   nv50_blitctx_get_color_mask_and_fp(blit, dst->format, info->mask);

   blit->filter = util_format_is_depth_or_stencil(dst->format) ? 0 : 1;

   nv50_blitctx_pre_blit(blit, nv50);

   nv50_blit_set_dst(nv50, dst, info->dst.level, info->dst.layer);
   nv50_blit_set_src(nv50, src, 0,               info->src.layer);

   nv50_blitctx_prepare_state(blit);

   nv50_state_validate(nv50, 36);

   x_range =
      (float)(info->src.x1 - info->src.x0) /
      (float)(info->dst.x1 - info->dst.x0);
   y_range =
      (float)(info->src.y1 - info->src.y0) /
      (float)(info->dst.y1 - info->dst.y0);

   x0 = (float)info->src.x0 - x_range * (float)info->dst.x0;
   y0 = (float)info->src.y0 - y_range * (float)info->dst.y0;

   x1 = x0 + 16384.0f * x_range;
   y1 = y0 + 16384.0f * y_range;

   x0 *= (float)(1 << nv50_miptree(src)->ms_x);
   x1 *= (float)(1 << nv50_miptree(src)->ms_x);
   y0 *= (float)(1 << nv50_miptree(src)->ms_y);
   y1 *= (float)(1 << nv50_miptree(src)->ms_y);

   z = (float)info->src.layer;

   BEGIN_RING(chan, RING_3D(FP_START_ID), 1);
   OUT_RING  (chan,
              blit->fp.code_base + blit->fp_offset);

   BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 1);
   OUT_RING  (chan, 0);

   /* Draw a large triangle in screen coordinates covering the whole
    * render target, with scissors defining the destination region.
    * The vertex is supplied with non-normalized texture coordinates
    * arranged in a way to yield the desired offset and scale.
    */

   BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
   OUT_RING  (chan, (info->dst.x1 << 16) | info->dst.x0);
   OUT_RING  (chan, (info->dst.y1 << 16) | info->dst.y0);

   BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);
   OUT_RING  (chan, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_3F_X(1)), 3);
   OUT_RINGf (chan, x0);
   OUT_RINGf (chan, y0);
   OUT_RINGf (chan, z);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_2F_X(0)), 2);
   OUT_RINGf (chan, 0.0f);
   OUT_RINGf (chan, 0.0f);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_3F_X(1)), 3);
   OUT_RINGf (chan, x1);
   OUT_RINGf (chan, y0);
   OUT_RINGf (chan, z);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_2F_X(0)), 2);
   OUT_RINGf (chan, 16384 << nv50_miptree(dst)->ms_x);
   OUT_RINGf (chan, 0.0f);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_3F_X(1)), 3);
   OUT_RINGf (chan, x0);
   OUT_RINGf (chan, y1);
   OUT_RINGf (chan, z);
   BEGIN_RING(chan, RING_3D(VTX_ATTR_2F_X(0)), 2);
   OUT_RINGf (chan, 0.0f);
   OUT_RINGf (chan, 16384 << nv50_miptree(dst)->ms_y);
   BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);
   OUT_RING  (chan, 0);

   /* re-enable normally constant state */

   BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 1);
   OUT_RING  (chan, 1);

   nv50_blitctx_post_blit(nv50, blit);
}
Example #15
0
static void
nv50_resource_copy_region(struct pipe_context *pipe,
                          struct pipe_resource *dst, unsigned dst_level,
                          unsigned dstx, unsigned dsty, unsigned dstz,
                          struct pipe_resource *src, unsigned src_level,
                          const struct pipe_box *src_box)
{
   struct nv50_screen *screen = nv50_context(pipe)->screen;
   int ret;
   boolean m2mf;
   unsigned dst_layer = dstz, src_layer = src_box->z;

   /* Fallback for buffers. */
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                                src, src_level, src_box);
      return;
   }

   assert(src->nr_samples == dst->nr_samples);

   m2mf = (src->format == dst->format) ||
      (util_format_get_blocksizebits(src->format) ==
       util_format_get_blocksizebits(dst->format));

   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;

   if (m2mf) {
      struct nv50_m2mf_rect drect, srect;
      unsigned i;
      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);

      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
      nv50_m2mf_rect_setup(&srect, src, src_level,
                           src_box->x, src_box->y, src_box->z);

      for (i = 0; i < src_box->depth; ++i) {
         nv50_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny);

         if (nv50_miptree(dst)->layout_3d)
            drect.z++;
         else
            drect.base += nv50_miptree(dst)->layer_stride;

         if (nv50_miptree(src)->layout_3d)
            srect.z++;
         else
            srect.base += nv50_miptree(src)->layer_stride;
      }
      return;
   }

   assert((src->format == dst->format) ||
          (nv50_2d_format_faithful(src->format) &&
           nv50_2d_format_faithful(dst->format)));

   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
      ret = nv50_2d_texture_do_copy(screen->base.channel,
                                    nv50_miptree(dst), dst_level,
                                    dstx, dsty, dst_layer,
                                    nv50_miptree(src), src_level,
                                    src_box->x, src_box->y, src_layer,
                                    src_box->width, src_box->height);
      if (ret)
         return;
   }
}
Example #16
0
struct pipe_sampler_view *
nv50_create_texture_view(struct pipe_context *pipe,
                         struct pipe_resource *texture,
                         const struct pipe_sampler_view *templ,
                         uint32_t flags,
                         enum pipe_texture_target target)
{
   const struct util_format_description *desc;
   uint64_t addr;
   uint32_t *tic;
   uint32_t swz[4];
   uint32_t depth;
   struct nv50_tic_entry *view;
   struct nv50_miptree *mt = nv50_miptree(texture);
   boolean tex_int;

   view = MALLOC_STRUCT(nv50_tic_entry);
   if (!view)
      return NULL;

   view->pipe = *templ;
   view->pipe.reference.count = 1;
   view->pipe.texture = NULL;
   view->pipe.context = pipe;

   view->id = -1;

   pipe_resource_reference(&view->pipe.texture, texture);

   tic = &view->tic[0];

   desc = util_format_description(view->pipe.format);

   /* TIC[0] */

   tic[0] = nv50_format_table[view->pipe.format].tic;

   tex_int = util_format_is_pure_integer(view->pipe.format);

   swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int);
   swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int);
   swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int);
   swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int);
   tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
      (swz[0] << NV50_TIC_0_MAPR__SHIFT) |
      (swz[1] << NV50_TIC_0_MAPG__SHIFT) |
      (swz[2] << NV50_TIC_0_MAPB__SHIFT) |
      (swz[3] << NV50_TIC_0_MAPA__SHIFT);

   addr = mt->base.address;

   if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY ||
       mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) {
      addr += view->pipe.u.tex.first_layer * mt->layer_stride;
      depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
   } else {
      depth = mt->base.base.depth0;
   }

   tic[2] = 0x10001000 | NV50_TIC_2_NO_BORDER;

   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
      tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;

   if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
      tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;

   if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
      if (target == PIPE_BUFFER) {
         addr += view->pipe.u.buf.first_element * desc->block.bits / 8;
         tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_BUFFER;
         tic[3] = 0;
         tic[4] = /* width */
            view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
         tic[5] = 0;
      } else {
         tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_RECT;
         tic[3] = mt->level[0].pitch;
         tic[4] = mt->base.base.width0;
         tic[5] = (1 << 16) | (mt->base.base.height0);
      }
      tic[6] =
      tic[7] = 0;
      tic[1] = addr;
      tic[2] |= addr >> 32;
      return &view->pipe;
   }

   tic[1] = addr;
   tic[2] |= (addr >> 32) & 0xff;

   tic[2] |=
      ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
      ((mt->level[0].tile_mode & 0xf00) << (25 - 8));

   switch (target) {
   case PIPE_TEXTURE_1D:
      tic[2] |= NV50_TIC_2_TARGET_1D;
      break;
   case PIPE_TEXTURE_2D:
      tic[2] |= NV50_TIC_2_TARGET_2D;
      break;
   case PIPE_TEXTURE_RECT:
      tic[2] |= NV50_TIC_2_TARGET_RECT;
      break;
   case PIPE_TEXTURE_3D:
      tic[2] |= NV50_TIC_2_TARGET_3D;
      break;
   case PIPE_TEXTURE_CUBE:
      depth /= 6;
      tic[2] |= NV50_TIC_2_TARGET_CUBE;
      break;
   case PIPE_TEXTURE_1D_ARRAY:
      tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
      break;
   case PIPE_TEXTURE_2D_ARRAY:
      tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
      break;
   case PIPE_TEXTURE_CUBE_ARRAY:
      depth /= 6;
      tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
      break;
   case PIPE_BUFFER:
      assert(0); /* should be linear and handled above ! */
      tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR;
      break;
   default:
      NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
      return FALSE;
   }

   tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;

   tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);

   tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
   tic[5] |= depth << 16;
   tic[5] |= mt->base.base.last_level << NV50_TIC_5_LAST_LEVEL__SHIFT;

   tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */

   tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;

   if (unlikely(!(tic[2] & NV50_TIC_2_NORMALIZED_COORDS)))
      if (mt->base.base.last_level)
         tic[5] &= ~NV50_TIC_5_LAST_LEVEL__MASK;

   return &view->pipe;
}
Example #17
0
boolean
nv50_tex_construct(struct nv50_sampler_view *view)
{
	const struct util_format_description *desc;
	struct nv50_miptree *mt = nv50_miptree(view->pipe.texture);
	uint32_t swz[4], *tic = view->tic;

	tic[0] = nv50_format_table[view->pipe.format].tic;

	swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r);
	swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g);
	swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b);
	swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a);
	view->tic[0] = (tic[0] &  ~NV50TIC_0_0_SWIZZLE_MASK) |
		(swz[0] << NV50TIC_0_0_MAPR_SHIFT) |
		(swz[1] << NV50TIC_0_0_MAPG_SHIFT) |
		(swz[2] << NV50TIC_0_0_MAPB_SHIFT) |
		(swz[3] << NV50TIC_0_0_MAPA_SHIFT);

	tic[2] = 0x50001000;
	tic[2] |= ((mt->base.bo->tile_mode & 0x0f) << 22) |
		  ((mt->base.bo->tile_mode & 0xf0) << 21);

	desc = util_format_description(mt->base.base.format);
	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
		tic[2] |= NV50TIC_0_2_COLORSPACE_SRGB;

	switch (mt->base.base.target) {
	case PIPE_TEXTURE_1D:
		tic[2] |= NV50TIC_0_2_TARGET_1D;
		break;
	case PIPE_TEXTURE_2D:
		tic[2] |= NV50TIC_0_2_TARGET_2D;
		break;
	case PIPE_TEXTURE_RECT:
		tic[2] |= NV50TIC_0_2_TARGET_RECT;
		break;
	case PIPE_TEXTURE_3D:
		tic[2] |= NV50TIC_0_2_TARGET_3D;
		break;
	case PIPE_TEXTURE_CUBE:
		tic[2] |= NV50TIC_0_2_TARGET_CUBE;
		break;
	default:
		NOUVEAU_ERR("invalid texture target: %d\n",
			    mt->base.base.target);
		return FALSE;
	}

	tic[3] = 0x00300000;

	tic[4] = (1 << 31) | mt->base.base.width0;
	tic[5] = (mt->base.base.last_level << 28) |
		(mt->base.base.depth0 << 16) | mt->base.base.height0;

	tic[6] = 0x03000000;

	tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;

	return TRUE;
}
Example #18
0
static struct pipe_sampler_view *
gm107_create_texture_view(struct pipe_context *pipe,
                          struct pipe_resource *texture,
                          const struct pipe_sampler_view *templ,
                          uint32_t flags,
                          enum pipe_texture_target target)
{
   const struct util_format_description *desc;
   const struct nvc0_format *fmt;
   uint64_t address;
   uint32_t *tic;
   uint32_t swz[4];
   uint32_t width, height;
   uint32_t depth;
   struct nv50_tic_entry *view;
   struct nv50_miptree *mt;
   bool tex_int;

   view = MALLOC_STRUCT(nv50_tic_entry);
   if (!view)
      return NULL;
   mt = nv50_miptree(texture);

   view->pipe = *templ;
   view->pipe.reference.count = 1;
   view->pipe.texture = NULL;
   view->pipe.context = pipe;

   view->id = -1;

   pipe_resource_reference(&view->pipe.texture, texture);

   tic = &view->tic[0];

   desc = util_format_description(view->pipe.format);
   tex_int = util_format_is_pure_integer(view->pipe.format);

   fmt = &nvc0_format_table[view->pipe.format];
   swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int);
   swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int);
   swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int);
   swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int);

   tic[0]  = fmt->tic.format << GM107_TIC2_0_COMPONENTS_SIZES__SHIFT;
   tic[0] |= fmt->tic.type_r << GM107_TIC2_0_R_DATA_TYPE__SHIFT;
   tic[0] |= fmt->tic.type_g << GM107_TIC2_0_G_DATA_TYPE__SHIFT;
   tic[0] |= fmt->tic.type_b << GM107_TIC2_0_B_DATA_TYPE__SHIFT;
   tic[0] |= fmt->tic.type_a << GM107_TIC2_0_A_DATA_TYPE__SHIFT;
   tic[0] |= swz[0] << GM107_TIC2_0_X_SOURCE__SHIFT;
   tic[0] |= swz[1] << GM107_TIC2_0_Y_SOURCE__SHIFT;
   tic[0] |= swz[2] << GM107_TIC2_0_Z_SOURCE__SHIFT;
   tic[0] |= swz[3] << GM107_TIC2_0_W_SOURCE__SHIFT;

   address = mt->base.address;

   tic[3]  = GM107_TIC2_3_LOD_ANISO_QUALITY_2;
   tic[4]  = GM107_TIC2_4_SECTOR_PROMOTION_PROMOTE_TO_2_V;
   tic[4] |= GM107_TIC2_4_BORDER_SIZE_SAMPLER_COLOR;

   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
      tic[4] |= GM107_TIC2_4_SRGB_CONVERSION;

   if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
      tic[5] = GM107_TIC2_5_NORMALIZED_COORDS;
   else
      tic[5] = 0;

   /* check for linear storage type */
   if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
      if (texture->target == PIPE_BUFFER) {
         assert(!(tic[5] & GM107_TIC2_5_NORMALIZED_COORDS));
         width = view->pipe.u.buf.last_element - view->pipe.u.buf.first_element;
         address +=
            view->pipe.u.buf.first_element * desc->block.bits / 8;
         tic[2]  = GM107_TIC2_2_HEADER_VERSION_ONE_D_BUFFER;
         tic[3] |= width >> 16;
         tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_BUFFER;
         tic[4] |= width & 0xffff;
      } else {
Example #19
0
static boolean
nv50_validate_tic(struct nv50_context *nv50, int s)
{
   struct nouveau_pushbuf *push = nv50->base.pushbuf;
   struct nouveau_bo *txc = nv50->screen->txc;
   unsigned i;
   boolean need_flush = FALSE;

   assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
   for (i = 0; i < nv50->num_textures[s]; ++i) {
      struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
      struct nv04_resource *res;

      if (!tic) {
         BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
         PUSH_DATA (push, (i << 1) | 0);
         continue;
      }
      res = &nv50_miptree(tic->pipe.texture)->base;

      if (tic->id < 0) {
         tic->id = nv50_screen_tic_alloc(nv50->screen, tic);

         BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
         PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
         PUSH_DATA (push, 1);
         BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
         PUSH_DATA (push, 262144);
         PUSH_DATA (push, 65536);
         PUSH_DATA (push, 1);
         PUSH_DATAh(push, txc->offset);
         PUSH_DATA (push, txc->offset);
         BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
         PUSH_DATA (push, 0);
         PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);
         BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
         PUSH_DATA (push, 32);
         PUSH_DATA (push, 1);
         PUSH_DATA (push, 0);
         PUSH_DATA (push, 1);
         PUSH_DATA (push, 0);
         PUSH_DATA (push, 1);
         PUSH_DATA (push, 0);
         PUSH_DATA (push, tic->id * 32);
         PUSH_DATA (push, 0);
         PUSH_DATA (push, 0);
         BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8);
         PUSH_DATAp(push, &tic->tic[0], 8);

         need_flush = TRUE;
      } else
      if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
         BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
         PUSH_DATA (push, 0x20);
      }

      nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);

      res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
      res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;

      BCTX_REFN(nv50->bufctx_3d, TEXTURES, res, RD);

      BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
      PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1);
   }
   for (; i < nv50->state.num_textures[s]; ++i) {
      BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
      PUSH_DATA (push, (i << 1) | 0);
   }
   if (nv50->num_textures[s]) {
      BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
      PUSH_DATA (push, (NV50_CB_AUX_TEX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX);
      BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2);
      for (i = 0; i < nv50->num_textures[s]; i++) {
         struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
         struct nv50_miptree *res;

         if (!tic) {
            PUSH_DATA (push, 0);
            PUSH_DATA (push, 0);
            continue;
         }
         res = nv50_miptree(tic->pipe.texture);
         PUSH_DATA (push, res->ms_x);
         PUSH_DATA (push, res->ms_y);
      }
   }
   nv50->state.num_textures[s] = nv50->num_textures[s];

   return need_flush;
}
Example #20
0
void *
nvc0_miptree_transfer_map(struct pipe_context *pctx,
                          struct pipe_resource *res,
                          unsigned level,
                          unsigned usage,
                          const struct pipe_box *box,
                          struct pipe_transfer **ptransfer)
{
   struct nvc0_context *nvc0 = nvc0_context(pctx);
   struct nouveau_device *dev = nvc0->screen->base.device;
   struct nv50_miptree *mt = nv50_miptree(res);
   struct nvc0_transfer *tx;
   uint32_t size;
   int ret;
   unsigned flags = 0;

   if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
      return NULL;

   tx = CALLOC_STRUCT(nvc0_transfer);
   if (!tx)
      return NULL;

   pipe_resource_reference(&tx->base.resource, res);

   tx->base.level = level;
   tx->base.usage = usage;
   tx->base.box = *box;

   if (util_format_is_plain(res->format)) {
      tx->nblocksx = box->width << mt->ms_x;
      tx->nblocksy = box->height << mt->ms_y;
   } else {
      tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
      tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
   }
   tx->nlayers = box->depth;

   tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
   tx->base.layer_stride = tx->nblocksy * tx->base.stride;

   nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z);

   size = tx->base.layer_stride;

   ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
                        size * tx->nlayers, NULL, &tx->rect[1].bo);
   if (ret) {
      pipe_resource_reference(&tx->base.resource, NULL);
      FREE(tx);
      return NULL;
   }

   tx->rect[1].cpp = tx->rect[0].cpp;
   tx->rect[1].width = tx->nblocksx;
   tx->rect[1].height = tx->nblocksy;
   tx->rect[1].depth = 1;
   tx->rect[1].pitch = tx->base.stride;
   tx->rect[1].domain = NOUVEAU_BO_GART;

   if (usage & PIPE_TRANSFER_READ) {
      unsigned base = tx->rect[0].base;
      unsigned z = tx->rect[0].z;
      unsigned i;
      for (i = 0; i < tx->nlayers; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &tx->rect[1], &tx->rect[0],
                              tx->nblocksx, tx->nblocksy);
         if (mt->layout_3d)
            tx->rect[0].z++;
         else
            tx->rect[0].base += mt->layer_stride;
         tx->rect[1].base += size;
      }
      tx->rect[0].z = z;
      tx->rect[0].base = base;
      tx->rect[1].base = 0;
   }

   if (tx->rect[1].bo->map) {
      *ptransfer = &tx->base;
      return tx->rect[1].bo->map;
   }

   if (usage & PIPE_TRANSFER_READ)
      flags = NOUVEAU_BO_RD;
   if (usage & PIPE_TRANSFER_WRITE)
      flags |= NOUVEAU_BO_WR;

   ret = nouveau_bo_map(tx->rect[1].bo, flags, nvc0->screen->base.client);
   if (ret) {
      pipe_resource_reference(&tx->base.resource, NULL);
      nouveau_bo_ref(NULL, &tx->rect[1].bo);
      FREE(tx);
      return NULL;
   }

   *ptransfer = &tx->base;
   return tx->rect[1].bo->map;
}
Example #21
0
static void
nvc0_resource_copy_region(struct pipe_context *pipe,
                          struct pipe_resource *dst, unsigned dst_level,
                          unsigned dstx, unsigned dsty, unsigned dstz,
                          struct pipe_resource *src, unsigned src_level,
                          const struct pipe_box *src_box)
{
   struct nvc0_context *nvc0 = nvc0_context(pipe);
   int ret;
   boolean m2mf;
   unsigned dst_layer = dstz, src_layer = src_box->z;

   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
      nouveau_copy_buffer(&nvc0->base,
                          nv04_resource(dst), dstx,
                          nv04_resource(src), src_box->x, src_box->width);
      NOUVEAU_DRV_STAT(&nvc0->screen->base, buf_copy_bytes, src_box->width);
      return;
   }
   NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_copy_count, 1);

   /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
   assert((src->nr_samples | 1) == (dst->nr_samples | 1));

   m2mf = (src->format == dst->format) ||
      (util_format_get_blocksizebits(src->format) ==
       util_format_get_blocksizebits(dst->format));

   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;

   if (m2mf) {
      struct nv50_m2mf_rect drect, srect;
      unsigned i;
      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);

      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
      nv50_m2mf_rect_setup(&srect, src, src_level,
                           src_box->x, src_box->y, src_box->z);

      for (i = 0; i < src_box->depth; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);

         if (nv50_miptree(dst)->layout_3d)
            drect.z++;
         else
            drect.base += nv50_miptree(dst)->layer_stride;

         if (nv50_miptree(src)->layout_3d)
            srect.z++;
         else
            srect.base += nv50_miptree(src)->layer_stride;
      }
      return;
   }

   assert(nv50_2d_dst_format_faithful(dst->format));
   assert(nv50_2d_src_format_faithful(src->format));

   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
   nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
   nouveau_pushbuf_validate(nvc0->base.pushbuf);

   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
      ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
                                    nv50_miptree(dst), dst_level,
                                    dstx, dsty, dst_layer,
                                    nv50_miptree(src), src_level,
                                    src_box->x, src_box->y, src_layer,
                                    src_box->width, src_box->height);
      if (ret)
         break;
   }
   nouveau_bufctx_reset(nvc0->bufctx, 0);
}
Example #22
0
struct pipe_sampler_view *
nvc0_create_texture_view(struct pipe_context *pipe,
                         struct pipe_resource *texture,
                         const struct pipe_sampler_view *templ,
                         uint32_t flags,
                         enum pipe_texture_target target)
{
   const struct util_format_description *desc;
   uint64_t address;
   uint32_t *tic;
   uint32_t swz[4];
   uint32_t depth;
   struct nv50_tic_entry *view;
   struct nv50_miptree *mt;
   boolean tex_int;

   view = MALLOC_STRUCT(nv50_tic_entry);
   if (!view)
      return NULL;
   mt = nv50_miptree(texture);

   view->pipe = *templ;
   view->pipe.reference.count = 1;
   view->pipe.texture = NULL;
   view->pipe.context = pipe;

   view->id = -1;

   pipe_resource_reference(&view->pipe.texture, texture);

   tic = &view->tic[0];

   desc = util_format_description(view->pipe.format);

   tic[0] = nvc0_format_table[view->pipe.format].tic;

   tex_int = util_format_is_pure_integer(view->pipe.format);

   swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int);
   swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int);
   swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int);
   swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int);
   tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
      (swz[0] << NV50_TIC_0_MAPR__SHIFT) |
      (swz[1] << NV50_TIC_0_MAPG__SHIFT) |
      (swz[2] << NV50_TIC_0_MAPB__SHIFT) |
      (swz[3] << NV50_TIC_0_MAPA__SHIFT);

   address = mt->base.address;

   tic[2] = 0x10001000 | NV50_TIC_2_NO_BORDER;

   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
      tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;

   /* check for linear storage type */
   if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
      if (texture->target == PIPE_BUFFER) {
         address +=
            view->pipe.u.buf.first_element * desc->block.bits / 8;
         tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_BUFFER;
         tic[3] = 0;
         tic[4] = /* width */
            view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
         tic[5] = 0;
      } else {
         /* must be 2D texture without mip maps */
         tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_RECT;
         if (texture->target != PIPE_TEXTURE_RECT)
            tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
         tic[3] = mt->level[0].pitch;
         tic[4] = mt->base.base.width0;
         tic[5] = (1 << 16) | mt->base.base.height0;
      }
      tic[6] =
      tic[7] = 0;
      tic[1] = address;
      tic[2] |= address >> 32;
      return &view->pipe;
   }

   if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
      tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;

   tic[2] |=
      ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
      ((mt->level[0].tile_mode & 0xf00) << (25 - 8));

   depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);

   if (mt->base.base.array_size > 1) {
      /* there doesn't seem to be a base layer field in TIC */
      address += view->pipe.u.tex.first_layer * mt->layer_stride;
      depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
   }
   tic[1] = address;
   tic[2] |= address >> 32;

   switch (target) {
   case PIPE_TEXTURE_1D:
      tic[2] |= NV50_TIC_2_TARGET_1D;
      break;
/* case PIPE_TEXTURE_2D_MS: */
   case PIPE_TEXTURE_2D:
      tic[2] |= NV50_TIC_2_TARGET_2D;
      break;
   case PIPE_TEXTURE_RECT:
      tic[2] |= NV50_TIC_2_TARGET_RECT;
      break;
   case PIPE_TEXTURE_3D:
      tic[2] |= NV50_TIC_2_TARGET_3D;
      break;
   case PIPE_TEXTURE_CUBE:
      depth /= 6;
      tic[2] |= NV50_TIC_2_TARGET_CUBE;
      break;
   case PIPE_TEXTURE_1D_ARRAY:
      tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
      break;
/* case PIPE_TEXTURE_2D_ARRAY_MS: */
   case PIPE_TEXTURE_2D_ARRAY:
      tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
      break;
   case PIPE_TEXTURE_CUBE_ARRAY:
      depth /= 6;
      tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
      break;
   default:
      NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
      return FALSE;
   }

   if (mt->base.base.target == PIPE_BUFFER)
      tic[3] = mt->base.base.width0;
   else
      tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;

   tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);

   tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
   tic[5] |= depth << 16;
   tic[5] |= mt->base.base.last_level << 28;

   tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */

   tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;

   /*
   if (mt->base.base.target == PIPE_TEXTURE_2D_MS ||
       mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS)
      tic[7] |= mt->ms_mode << 12;
   */

   return &view->pipe;
}
struct pipe_transfer *
nv50_miptree_transfer_new(struct pipe_context *pcontext,
			  struct pipe_resource *pt,
			  struct pipe_subresource sr,
			  unsigned usage,
			  const struct pipe_box *box)
{
        struct pipe_screen *pscreen = pcontext->screen;
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nv50_miptree *mt = nv50_miptree(pt);
	struct nv50_miptree_level *lvl = &mt->level[sr.level];
	struct nv50_transfer *tx;
	unsigned nx, ny, image = 0;
	int ret;

	if (pt->target == PIPE_TEXTURE_CUBE)
		image = sr.face;

	tx = CALLOC_STRUCT(nv50_transfer);
	if (!tx)
		return NULL;

	/* Don't handle 3D transfers yet.
	 */
	assert(box->depth == 1);


	pipe_resource_reference(&tx->base.resource, pt);
	tx->base.sr = sr;
	tx->base.usage = usage;
	tx->base.box = *box;
	tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, sr.level));
	tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, sr.level));
	tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format);
	tx->base.usage = usage;

	tx->level_pitch = lvl->pitch;
	tx->level_width = u_minify(mt->base.base.width0, sr.level);
	tx->level_height = u_minify(mt->base.base.height0, sr.level);
	tx->level_depth = u_minify(mt->base.base.depth0, sr.level);
	tx->level_offset = lvl->image_offset[image];
	tx->level_tiling = lvl->tile_mode;
	tx->level_z = box->z;
	tx->level_x = util_format_get_nblocksx(pt->format, box->x);
	tx->level_y = util_format_get_nblocksy(pt->format, box->y);
	ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
			     tx->nblocksy * tx->base.stride, &tx->bo);
	if (ret) {
		FREE(tx);
		return NULL;
	}

	if (usage & PIPE_TRANSFER_READ) {
		nx = util_format_get_nblocksx(pt->format, box->width);
		ny = util_format_get_nblocksy(pt->format, box->height);

		nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
					tx->level_pitch, tx->level_tiling,
					box->x, box->y, box->z,
					tx->nblocksx, tx->nblocksy,
					tx->level_depth,
					tx->bo, 0,
					tx->base.stride, tx->bo->tile_mode,
					0, 0, 0,
					tx->nblocksx, tx->nblocksy, 1,
					util_format_get_blocksize(pt->format), nx, ny,
					NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
					NOUVEAU_BO_GART);
	}

	return &tx->base;
}