Exemple #1
0
static void
nv50_dac_disconnect(struct drm_encoder *encoder)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	int ret;

	if (!nv_encoder->crtc)
		return;
	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);

	NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);

	ret = RING_SPACE(evo, 4);
	if (ret) {
		NV_ERROR(dev, "no space while disconnecting DAC\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
	OUT_RING  (evo, 0);
	BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
	OUT_RING  (evo, 0);

	nv_encoder->crtc = NULL;
}
Exemple #2
0
static void
nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
{
	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	struct drm_device *dev = nv_crtc->base.dev;
	int ret;

	NV_DEBUG_KMS(dev, "\n");

	if (update && !nv_crtc->cursor.visible)
		return;

	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
	if (ret) {
		NV_ERROR(dev, "no space while hiding cursor\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE);
	OUT_RING(evo, 0);
	if (dev_priv->chipset != 0x50) {
		BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE);
	}

	if (update) {
		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
		OUT_RING(evo, 0);
		FIRE_RING(evo);
		nv_crtc->cursor.visible = false;
	}
}
Exemple #3
0
void
nvfx_state_viewport_validate(struct nvfx_context *nvfx)
{
	struct nouveau_channel *chan = nvfx->screen->base.channel;
	struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
	struct pipe_viewport_state *vpt = &nvfx->viewport;

	if(nvfx->render_mode == HW) {
		BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_TRANSLATE_X, 8);
		OUT_RINGf(chan, vpt->translate[0]);
		OUT_RINGf(chan, vpt->translate[1]);
		OUT_RINGf(chan, vpt->translate[2]);
		OUT_RINGf(chan, vpt->translate[3]);
		OUT_RINGf(chan, vpt->scale[0]);
		OUT_RINGf(chan, vpt->scale[1]);
		OUT_RINGf(chan, vpt->scale[2]);
		OUT_RINGf(chan, vpt->scale[3]);
		BEGIN_RING(chan, eng3d, 0x1d78, 1);
		OUT_RING(chan, 1);
	} else {
		BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_TRANSLATE_X, 8);
		OUT_RINGf(chan, 0.0f);
		OUT_RINGf(chan, 0.0f);
		OUT_RINGf(chan, 0.0f);
		OUT_RINGf(chan, 0.0f);
		OUT_RINGf(chan, 1.0f);
		OUT_RINGf(chan, 1.0f);
		OUT_RINGf(chan, 1.0f);
		OUT_RINGf(chan, 1.0f);
		BEGIN_RING(chan, eng3d, 0x1d78, 1);
		OUT_RING(chan, nvfx->is_nv4x ? 0x110 : 1);
	}
}
Exemple #4
0
boolean
nv30_draw_arrays(struct pipe_context *pipe,
		 unsigned mode, unsigned start, unsigned count)
{
	struct nv30_context *nv30 = nv30_context(pipe);
	struct nouveau_channel *chan = nv30->screen->base.channel;
	unsigned restart = 0;

	nv30_vbo_set_idxbuf(nv30, NULL, 0);
	if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
		/*return nv30_draw_elements_swtnl(pipe, NULL, 0,
						mode, start, count);*/
		return FALSE;
	}

	while (count) {
		unsigned vc, nr;

		nv30_state_emit(nv30);

		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
					mode, start, count, &restart);
		if (!vc) {
			FIRE_RING(NULL);
			continue;
		}

		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
		OUT_RING  (nvgl_primitive(mode));

		nr = (vc & 0xff);
		if (nr) {
			BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
			OUT_RING  (((nr - 1) << 24) | start);
			start += nr;
		}

		nr = vc >> 8;
		while (nr) {
			unsigned push = nr > 2047 ? 2047 : nr;

			nr -= push;

			BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
			while (push--) {
				OUT_RING(((0x100 - 1) << 24) | start);
				start += 0x100;
			}
		}

		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
		OUT_RING  (0);

		count -= vc;
		start = restart;
	}

	pipe->flush(pipe, 0, NULL);
	return TRUE;
}
Exemple #5
0
static void
nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
{
	struct nv40_context *nv40 = nv40_context(pipe);
	struct nv40_query *q = nv40_query(pq);

	assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);

	/* Happens when end_query() is called, then another begin_query()
	 * without querying the result in-between.  For now we'll wait for
	 * the existing query to notify completion, but it could be better.
	 */
	if (q->object) {
		uint64_t tmp;
		pipe->get_query_result(pipe, pq, 1, &tmp);
	}

	if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object))
		assert(0);
	nv40->nvws->notifier_reset(nv40->screen->query, q->object->start);

	BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1);
	OUT_RING  (1);
	BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1);
	OUT_RING  (1);

	q->ready = FALSE;
}
Exemple #6
0
static void
nvfx_ucp_validate(struct nvfx_context* nvfx)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
	unsigned enables[7] =
	{
			0,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE4,
			NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE4 | NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE5,
	};

	if(!nvfx->use_vp_clipping)
	{
		BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANES_ENABLE, 1);
		OUT_RING(chan, 0);

		BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANE(0, 0),
			   nvfx->clip.nr * 4);
		OUT_RINGp(chan, &nvfx->clip.ucp[0][0], nvfx->clip.nr * 4);
	}

	BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANES_ENABLE, 1);
	OUT_RING(chan, enables[nvfx->clip.nr]);
}
Exemple #7
0
static void
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
	struct nouveau_fbcon_par *par = info->par;
	struct drm_device *dev = par->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->channel;

	if (info->state != FBINFO_STATE_RUNNING)
		return;

	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
		nouveau_fbcon_gpu_lockup(info);
	}

	if (info->flags & FBINFO_HWACCEL_DISABLED) {
		cfb_fillrect(info, rect);
		return;
	}

	BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
	OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
	BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1);
	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
		OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
	else
		OUT_RING(chan, rect->color);
	BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2);
	OUT_RING(chan, (rect->dx << 16) | rect->dy);
	OUT_RING(chan, (rect->width << 16) | rect->height);
	FIRE_RING(chan);
}
Exemple #8
0
static void
nv17_zclear(struct gl_context *ctx, GLbitfield *buffers)
{
	struct nouveau_context *nctx = to_nouveau_context(ctx);
	struct nouveau_channel *chan = context_chan(ctx);
	struct nouveau_grobj *celsius = context_eng3d(ctx);
	struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(
		ctx->DrawBuffer);
	struct nouveau_surface *s = &to_nouveau_renderbuffer(
		nfb->base.Attachment[BUFFER_DEPTH].Renderbuffer)->surface;

	/* Clear the hierarchical depth buffer */
	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_FILL_VALUE, 1);
	OUT_RING(chan, pack_zs_f(s->format, ctx->Depth.Clear, 0));
	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_BUFFER_CLEAR, 1);
	OUT_RING(chan, 1);

	/* Mark the depth buffer as cleared */
	if (use_fast_zclear(ctx, *buffers)) {
		if (nctx->hierz.clear_seq)
			*buffers &= ~BUFFER_BIT_DEPTH;

		nfb->hierz.clear_value =
			pack_zs_f(s->format, ctx->Depth.Clear, 0);
		nctx->hierz.clear_seq++;

		context_dirty(ctx, ZCLEAR);
	}
}
static void
nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
		  unsigned destx, unsigned desty, unsigned width,
		  unsigned height, unsigned value)
{
	struct nv50_context *nv50 = nv50_context(pipe);
	struct nv50_screen *screen = nv50->screen;
	struct nouveau_channel *chan = screen->eng2d->channel;
	struct nouveau_grobj *eng2d = screen->eng2d;
	int format, ret;

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

	WAIT_RING (chan, 32);

	ret = nv50_surface_set(screen, dest, 1);
	if (ret)
		return;

	BEGIN_RING(chan, eng2d, 0x0580, 3);
	OUT_RING  (chan, 4);
	OUT_RING  (chan, format);
	OUT_RING  (chan, value);
	BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
	OUT_RING  (chan, destx);
	OUT_RING  (chan, desty);
	OUT_RING  (chan, width);
	OUT_RING  (chan, height);
}
Exemple #10
0
void
nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
{
    struct nouveau_channel* chan = nvfx->screen->base.channel;
    struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
    struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
    struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
    struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
    unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
    unsigned txf;
    unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
    unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod);

    txf = sv->u.nv40.fmt[ps->compare] | ps->fmt;

    MARK_RING(chan, 11, 2);
    BEGIN_RING(chan, eng3d, NV30_3D_TEX_OFFSET(unit), 8);
    OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
    OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
              NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
    OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
    OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7));
    OUT_RING(chan, sv->swizzle);
    OUT_RING(chan, ps->filt | sv->filt);
    OUT_RING(chan, sv->npot_size);
    OUT_RING(chan, ps->bcol);
    BEGIN_RING(chan, eng3d, NV40_3D_TEX_SIZE1(unit), 1);
    OUT_RING(chan, sv->u.nv40.npot_size2);

    nvfx->hw_txf[unit] = txf;
    nvfx->hw_samplers |= (1 << unit);
}
void
nvc0_vertprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *vp = nvc0->vertprog;

   if (nvc0->clip.nr > vp->vp.num_ucps) {
      assert(nvc0->clip.nr <= 6);
      vp->vp.num_ucps = 6;

      if (vp->translated)
         nvc0_program_destroy(nvc0, vp);
   }

   if (!nvc0_program_validate(nvc0, vp))
         return;
   nvc0_program_update_context_state(nvc0, vp, 0);

   BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2);
   OUT_RING  (chan, 0x11);
   OUT_RING  (chan, vp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(1)), 1);
   OUT_RING  (chan, vp->max_gpr);

   if (!nvc0->gmtyprog && !nvc0->tevlprog)
      nvc0_program_validate_clip(nvc0, vp);

   // BEGIN_RING(chan, RING_3D_(0x163c), 1);
   // OUT_RING  (chan, 0);
}
static INLINE void
nvc0_program_update_context_state(struct nvc0_context *nvc0,
                                  struct nvc0_program *prog, int stage)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;

   if (prog->hdr[1])
      nvc0->state.tls_required |= 1 << stage;
   else
      nvc0->state.tls_required &= ~(1 << stage);

   if (prog->immd_size) {
      const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

      BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
      /* NOTE: may overlap code of a different shader */
      OUT_RING  (chan, align(prog->immd_size, 0x100));
      OUT_RELOCh(chan, nvc0->screen->text, prog->immd_base, rl);
      OUT_RELOCl(chan, nvc0->screen->text, prog->immd_base, rl);
      BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
      OUT_RING  (chan, (14 << 4) | 1);

      nvc0->state.c14_bound |= 1 << stage;
   } else
   if (nvc0->state.c14_bound & (1 << stage)) {
      BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
      OUT_RING  (chan, (14 << 4) | 0);

      nvc0->state.c14_bound &= ~(1 << stage);
   }
}
void
nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *gp = nvc0->gmtyprog;

   if (gp)
      nvc0_program_validate(nvc0, gp);
   /* we allow GPs with no code for specifying stream output state only */
   if (!gp || !gp->code_size) {
      BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
      OUT_RING  (chan, 0x40);
      IMMED_RING(chan, RING_3D(LAYER), 0);
      return;
   }
   nvc0_program_update_context_state(nvc0, gp, 3);

   BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
   OUT_RING  (chan, 0x41);
   BEGIN_RING(chan, RING_3D(SP_START_ID(4)), 1);
   OUT_RING  (chan, gp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
   OUT_RING  (chan, gp->max_gpr);
   BEGIN_RING(chan, RING_3D(LAYER), 1);
   OUT_RING  (chan, (gp->hdr[13] & (1 << 9)) ? NVC0_3D_LAYER_USE_GP : 0);

   nvc0_program_validate_clip(nvc0, gp);
}
void
nvc0_tevlprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *tp = nvc0->tevlprog;

   if (!tp) {
      BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
      OUT_RING  (chan, 0x30);
      return;
   }
   if (!nvc0_program_validate(nvc0, tp))
         return;
   nvc0_program_update_context_state(nvc0, tp, 2);

   if (tp->tp.tess_mode != ~0) {
      BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
      OUT_RING  (chan, tp->tp.tess_mode);
   }
   BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
   OUT_RING  (chan, 0x31);
   BEGIN_RING(chan, RING_3D(SP_START_ID(3)), 1);
   OUT_RING  (chan, tp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(3)), 1);
   OUT_RING  (chan, tp->max_gpr);

   if (!nvc0->gmtyprog)
      nvc0_program_validate_clip(nvc0, tp);
}
Exemple #15
0
void
nvc0_m2mf_copy_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
                      struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
                      unsigned size)
{
   struct nouveau_channel *chan = nv->screen->channel;

   while (size) {
      unsigned bytes = MIN2(size, 1 << 17);

      MARK_RING (chan, 11, 4);

      BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
      OUT_RELOCh(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
      OUT_RELOCl(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
      BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2);
      OUT_RELOCh(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
      OUT_RELOCl(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
      BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
      OUT_RING  (chan, bytes);
      OUT_RING  (chan, 1);
      BEGIN_RING(chan, RING_MF(EXEC), 1);
      OUT_RING  (chan, (1 << NVC0_M2MF_EXEC_INC__SHIFT) |
                 NVC0_M2MF_EXEC_LINEAR_IN | NVC0_M2MF_EXEC_LINEAR_OUT);

      srcoff += bytes;
      dstoff += bytes;
      size -= bytes;
   }
}
Exemple #16
0
void
NV10EXAComposite(PixmapPtr pix_dst,
		 int srcX, int srcY,
		 int maskX, int maskY,
		 int dstX, int dstY,
		 int width, int height)
{
	ScrnInfoPtr pScrn = xf86Screens[pix_dst->drawable.pScreen->myNum];
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *celsius = pNv->Nv3D;
	PicturePtr mask = pNv->pmpict,
		src = pNv->pspict;
	PictVector dstq[4] = QUAD(dstX, dstY, width, height),
		maskq[4] = QUAD(maskX, maskY, width, height),
		srcq[4] = QUAD(srcX, srcY, width, height);

	MAP(transform_vertex, src->transform, srcq);
	if (mask)
		MAP(transform_vertex, mask->transform, maskq);

	WAIT_RING (chan, 64);
	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
	OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_QUADS);

	MAP(emit_vertex, pNv, dstq, srcq, mask ? maskq : NULL);

	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
	OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_STOP);
}
void
nvc0_tctlprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *tp = nvc0->tctlprog;

   if (!tp) {
      BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 1);
      OUT_RING  (chan, 0x20);
      return;
   }
   if (!nvc0_program_validate(nvc0, tp))
         return;
   nvc0_program_update_context_state(nvc0, tp, 1);

   if (tp->tp.tess_mode != ~0) {
      BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
      OUT_RING  (chan, tp->tp.tess_mode);
   }
   BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2);
   OUT_RING  (chan, 0x21);
   OUT_RING  (chan, tp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(2)), 1);
   OUT_RING  (chan, tp->max_gpr);

   if (tp->tp.input_patch_size <= 32)
      IMMED_RING(chan, RING_3D(PATCH_VERTICES), tp->tp.input_patch_size);
}
void
nv50_gp_linkage_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct nv50_program *vp = nv50->vertprog;
   struct nv50_program *gp = nv50->gmtyprog;
   int m = 0;
   int n;
   uint8_t map[64];

   if (!gp)
      return;
   memset(map, 0, sizeof(map));

   m = nv50_vp_gp_mapping(map, m, vp, gp);

   n = (m + 3) / 4;

   BEGIN_RING(chan, RING_3D(VP_GP_BUILTIN_ATTR_EN), 1);
   OUT_RING  (chan, vp->vp.attrs[2] | gp->vp.attrs[2]);

   BEGIN_RING(chan, RING_3D(VP_RESULT_MAP_SIZE), 1);
   OUT_RING  (chan, m);
   BEGIN_RING(chan, RING_3D(VP_RESULT_MAP(0)), n);
   OUT_RINGp (chan, map, n);
}
Exemple #19
0
static void
setup_blend_function(NVPtr pNv)
{
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *celsius = pNv->Nv3D;
	struct pict_op *op = &nv10_pict_op[pNv->alu];
	int src_factor = op->src;
	int dst_factor = op->dst;

	if (src_factor == SF(ONE_MINUS_DST_ALPHA) &&
	    !PICT_FORMAT_A(pNv->pdpict->format))
		/* ONE_MINUS_DST_ALPHA doesn't always do the right thing for
		 * framebuffers without alpha channel. But it's the same as
		 * ZERO in that case.
		 */
		src_factor = SF(ZERO);

	if (effective_component_alpha(pNv->pmpict)) {
		if (dst_factor == DF(SRC_ALPHA))
			dst_factor = DF(SRC_COLOR);
		else if (dst_factor == DF(ONE_MINUS_SRC_ALPHA))
			dst_factor = DF(ONE_MINUS_SRC_COLOR);
	}

	BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 2);
	OUT_RING  (chan, src_factor);
	OUT_RING  (chan, dst_factor);
	BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
	OUT_RING  (chan, 1);
}
void
nv20_emit_tex_gen(GLcontext *ctx, int emit)
{
	const int i = emit - NOUVEAU_STATE_TEX_GEN0;
	struct nouveau_context *nctx = to_nouveau_context(ctx);
	struct nouveau_channel *chan = context_chan(ctx);
	struct nouveau_grobj *kelvin = context_eng3d(ctx);
	struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
	int j;

	for (j = 0; j < 4; j++) {
		if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
			struct gl_texgen *coord = get_texgen_coord(unit, j);
			float *k = get_texgen_coeff(coord);

			if (k) {
				BEGIN_RING(chan, kelvin, TX_GEN_COEFF(i, j), 4);
				OUT_RINGp(chan, k, 4);
			}

			BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1);
			OUT_RING(chan, nvgl_texgen_mode(coord->Mode));

		} else {
			BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1);
			OUT_RING(chan, 0);
		}
	}
}
Exemple #21
0
static void
setup_hierz_buffer(struct gl_context *ctx)
{
	struct nouveau_channel *chan = context_chan(ctx);
	struct nouveau_grobj *celsius = context_eng3d(ctx);
	struct nouveau_bo_context *bctx = context_bctx(ctx, HIERZ);
	struct gl_framebuffer *fb = ctx->DrawBuffer;
	struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
	unsigned pitch = align(fb->Width, 128),
		height = align(fb->Height, 2),
		size = pitch * height;

	if (!nfb->hierz.bo || nfb->hierz.bo->size != size) {
		nouveau_bo_ref(NULL, &nfb->hierz.bo);
		nouveau_bo_new_tile(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size,
				    0, NOUVEAU_BO_TILE_ZETA, &nfb->hierz.bo);
	}

	nouveau_bo_markl(bctx, celsius, NV17_3D_HIERZ_OFFSET,
			 nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);

	WAIT_RING(chan, 9);
	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_WINDOW_X, 4);
	OUT_RINGf(chan, - 1792);
	OUT_RINGf(chan, - 2304 + fb->Height);
	OUT_RINGf(chan, fb->_DepthMaxF / 2);
	OUT_RINGf(chan, 0);

	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_PITCH, 1);
	OUT_RING(chan, pitch);

	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_ENABLE, 1);
	OUT_RING(chan, 1);
}
/* Validate state derived from shaders and the rasterizer cso. */
void
nv50_validate_derived_rs(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   uint32_t color, psize;

   nv50_sprite_coords_validate(nv50);

   if (nv50->dirty & NV50_NEW_FRAGPROG)
      return;
   psize = nv50->state.semantic_psize & ~NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK;
   color = nv50->state.semantic_color & ~NV50_3D_MAP_SEMANTIC_0_CLMP_EN;

   if (nv50->rast->pipe.clamp_vertex_color)
      color |= NV50_3D_MAP_SEMANTIC_0_CLMP_EN;

   if (color != nv50->state.semantic_color) {
      nv50->state.semantic_color = color;
      BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_0), 1);
      OUT_RING  (chan, color);
   }

   if (nv50->rast->pipe.point_size_per_vertex)
      psize |= NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK;

   if (psize != nv50->state.semantic_psize) {
      nv50->state.semantic_psize = psize;
      BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_3), 1);
      OUT_RING  (chan, psize);
   }
}
Exemple #23
0
void
nv10_emit_viewport(struct gl_context *ctx, int emit)
{
	struct nouveau_channel *chan = context_chan(ctx);
	struct nouveau_grobj *celsius = context_eng3d(ctx);
	struct gl_viewport_attrib *vp = &ctx->Viewport;
	struct gl_framebuffer *fb = ctx->DrawBuffer;
	float a[4] = {};

	get_viewport_translate(ctx, a);
	a[0] -= 2048;
	a[1] -= 2048;
	if (nv10_use_viewport_zclear(ctx))
		a[2] = nv10_transform_depth(ctx, (vp->Far + vp->Near) / 2);

	BEGIN_RING(chan, celsius, NV10_3D_VIEWPORT_TRANSLATE_X, 4);
	OUT_RINGp(chan, a, 4);

	BEGIN_RING(chan, celsius, NV10_3D_VIEWPORT_CLIP_HORIZ(0), 1);
	OUT_RING(chan, (fb->Width - 1) << 16 | 0x08000800);
	BEGIN_RING(chan, celsius, NV10_3D_VIEWPORT_CLIP_VERT(0), 1);
	OUT_RING(chan, (fb->Height - 1) << 16 | 0x08000800);

	context_dirty(ctx, PROJECTION);
}
Exemple #24
0
static void
nv50_render_condition(struct pipe_context *pipe,
		      struct pipe_query *pq, uint mode)
{
	struct nv50_context *nv50 = nv50_context(pipe);
	struct nouveau_channel *chan = nv50->screen->base.channel;
	struct nouveau_grobj *tesla = nv50->screen->tesla;
	struct nv50_query *q;

	if (!pq) {
		BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1);
		OUT_RING  (chan, NV50TCL_COND_MODE_ALWAYS);
		return;
	}
	q = nv50_query(pq);

	if (mode == PIPE_RENDER_COND_WAIT ||
	    mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
		/* XXX: big fence, FIFO semaphore might be better */
		BEGIN_RING(chan, tesla, 0x0110, 1);
		OUT_RING  (chan, 0);
	}

	BEGIN_RING(chan, tesla, NV50TCL_COND_ADDRESS_HIGH, 3);
	OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
	OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
	OUT_RING  (chan, NV50TCL_COND_MODE_RES);
}
Exemple #25
0
static int
nouveau_card_channel_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan;
	int ret, oclass;

	ret = nouveau_channel_alloc(dev, &chan, NULL, NvDmaFB, NvDmaTT);
	dev_priv->channel = chan;
	if (ret)
		return ret;

	mutex_unlock(&dev_priv->channel->mutex);

	if (dev_priv->card_type <= NV_50) {
		if (dev_priv->card_type < NV_50)
			oclass = 0x0039;
		else
			oclass = 0x5039;

		ret = nouveau_gpuobj_gr_new(chan, NvM2MF, oclass);
		if (ret)
			goto error;

		ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000,
					     &chan->m2mf_ntfy);
		if (ret)
			goto error;

		ret = RING_SPACE(chan, 6);
		if (ret)
			goto error;

		BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
		OUT_RING  (chan, NvM2MF);
		BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
		OUT_RING  (chan, NvNotify0);
		OUT_RING  (chan, chan->vram_handle);
		OUT_RING  (chan, chan->gart_handle);
	} else
	if (dev_priv->card_type <= NV_D0) {
		ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
		if (ret)
			goto error;

		ret = RING_SPACE(chan, 2);
		if (ret)
			goto error;

		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
		OUT_RING  (chan, 0x00009039);
	}

	FIRE_RING (chan);
error:
	if (ret)
		nouveau_card_channel_fini(dev);
	return ret;
}
Exemple #26
0
static int
nouveau_fbcon_sync(struct fb_info *info)
{
	struct nouveau_fbdev *nfbdev = info->par;
	struct drm_device *dev = nfbdev->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->channel;
	int ret, i;

	if (!chan || !chan->accel_done || in_interrupt() ||
	    info->state != FBINFO_STATE_RUNNING ||
	    info->flags & FBINFO_HWACCEL_DISABLED)
		return 0;

	if (!mutex_trylock(&chan->mutex))
		return 0;

	ret = RING_SPACE(chan, 4);
	if (ret) {
		mutex_unlock(&chan->mutex);
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	if (dev_priv->card_type >= NV_C0) {
		BEGIN_NVC0(chan, 2, NvSub2D, 0x010c, 1);
		OUT_RING  (chan, 0);
		BEGIN_NVC0(chan, 2, NvSub2D, 0x0100, 1);
		OUT_RING  (chan, 0);
	} else {
		BEGIN_RING(chan, 0, 0x0104, 1);
		OUT_RING  (chan, 0);
		BEGIN_RING(chan, 0, 0x0100, 1);
		OUT_RING  (chan, 0);
	}

	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3, 0xffffffff);
	FIRE_RING(chan);
	mutex_unlock(&chan->mutex);

	ret = -EBUSY;
	for (i = 0; i < 100000; i++) {
		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3)) {
			ret = 0;
			break;
		}
		DRM_UDELAY(1);
	}

	if (ret) {
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	chan->accel_done = false;
	return 0;
}
static void
nv50_sprite_coords_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   uint32_t pntc[8], mode;
   struct nv50_program *fp = nv50->fragprog;
   unsigned i, c;
   unsigned m = (nv50->state.interpolant_ctrl >> 8) & 0xff;

   if (!nv50->rast->pipe.point_quad_rasterization) {
      if (nv50->state.point_sprite) {
         BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8);
         for (i = 0; i < 8; ++i)
            OUT_RING(chan, 0);

         nv50->state.point_sprite = FALSE;
      }
      return;
   } else {
      nv50->state.point_sprite = TRUE;
   }

   memset(pntc, 0, sizeof(pntc));

   for (i = 0; i < fp->in_nr; i++) {
      unsigned n = util_bitcount(fp->in[i].mask);

      if (fp->in[i].sn != TGSI_SEMANTIC_GENERIC) {
         m += n;
         continue;
      }
      if (!(nv50->rast->pipe.sprite_coord_enable & (1 << fp->in[i].si))) {
         m += n;
         continue;
      }

      for (c = 0; c < 4; ++c) {
         if (fp->in[i].mask & (1 << c)) {
            pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
            ++m;
         }
      }
   }

   if (nv50->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
      mode = 0x00;
   else
      mode = 0x10;

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

   BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8);
   OUT_RINGp (chan, pntc, 8);
}
Exemple #28
0
static void
nvc0_m2mf_push_rect(struct pipe_screen *pscreen,
                    const struct nv50_m2mf_rect *dst,
                    const void *data,
                    unsigned nblocksx, unsigned nblocksy)
{
   struct nouveau_channel *chan;
   const uint8_t *src = (const uint8_t *)data;
   const int cpp = dst->cpp;
   const int line_len = nblocksx * cpp;
   int dy = dst->y;

   assert(nouveau_bo_tile_layout(dst->bo));

   BEGIN_RING(chan, RING_MF(TILING_MODE_OUT), 5);
   OUT_RING  (chan, dst->tile_mode);
   OUT_RING  (chan, dst->width * cpp);
   OUT_RING  (chan, dst->height);
   OUT_RING  (chan, dst->depth);
   OUT_RING  (chan, dst->z);

   while (nblocksy) {
      int line_count, words;
      int size = MIN2(AVAIL_RING(chan), NV04_PFIFO_MAX_PACKET_LEN);

      if (size < (12 + words)) {
         FIRE_RING(chan);
         continue;
      }
      line_count = (size * 4) / line_len;
      words = (line_count * line_len + 3) / 4;

      BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
      OUT_RELOCh(chan, dst->bo, dst->base, dst->domain | NOUVEAU_BO_WR);
      OUT_RELOCl(chan, dst->bo, dst->base, dst->domain | NOUVEAU_BO_WR);

      BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT_X), 2);
      OUT_RING  (chan, dst->x * cpp);
      OUT_RING  (chan, dy);
      BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
      OUT_RING  (chan, line_len);
      OUT_RING  (chan, line_count);
      BEGIN_RING(chan, RING_MF(EXEC), 1);
      OUT_RING  (chan, (1 << NVC0_M2MF_EXEC_INC__SHIFT) |
                 NVC0_M2MF_EXEC_PUSH | NVC0_M2MF_EXEC_LINEAR_IN);

      BEGIN_RING_NI(chan, RING_MF(DATA), words);
      OUT_RINGp (chan, src, words);

      dy += line_count;
      src += line_len * line_count;
      nblocksy -= line_count;
   }
}
Exemple #29
0
static void
setup_combiners(NVPtr pNv, PicturePtr src, PicturePtr mask)
{
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *celsius = pNv->Nv3D;
	uint32_t rc_in_alpha = 0, rc_in_rgb = 0;

	if (PICT_FORMAT_A(src->format))
		rc_in_alpha |= RC_IN_TEX(A, ALPHA, 0);
	else
		rc_in_alpha |= RC_IN_ONE(A);

	if (mask && PICT_FORMAT_A(mask->format))
		rc_in_alpha |= RC_IN_TEX(B, ALPHA, 1);
	else
		rc_in_alpha |= RC_IN_ONE(B);

	if (effective_component_alpha(mask)) {
		if (!needs_src_alpha(pNv->alu)) {
			/* The alpha channels won't be used for blending. Drop
			 * them, as our pixels only have 4 components...
			 * output_i = src_i * mask_i
			 */
			if (PICT_FORMAT_RGB(src->format))
				rc_in_rgb |= RC_IN_TEX(A, RGB, 0);
		} else {
			/* The RGB channels won't be used for blending. Drop
			 * them.
			 * output_i = src_alpha * mask_i
			 */
			if (PICT_FORMAT_A(src->format))
				rc_in_rgb |= RC_IN_TEX(A, ALPHA, 0);
			else
				rc_in_rgb |= RC_IN_ONE(A);
		}

		rc_in_rgb |= RC_IN_TEX(B, RGB, 1);

	} else {
		if (PICT_FORMAT_RGB(src->format))
			rc_in_rgb |= RC_IN_TEX(A, RGB, 0);

		if (mask && PICT_FORMAT_A(mask->format))
			rc_in_rgb |= RC_IN_TEX(B, ALPHA, 1);
		else
			rc_in_rgb |= RC_IN_ONE(B);
	}

	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 1);
	OUT_RING  (chan, rc_in_alpha);
	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(0), 1);
	OUT_RING  (chan, rc_in_rgb);
}
Exemple #30
0
static int
nv50_2d_texture_do_copy(struct nouveau_channel *chan,
                        struct nv50_miptree *dst, unsigned dst_level,
                        unsigned dx, unsigned dy, unsigned dz,
                        struct nv50_miptree *src, unsigned src_level,
                        unsigned sx, unsigned sy, unsigned sz,
                        unsigned w, unsigned h)
{
   static const uint32_t duvdxy[5] =
   {
      0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
   };

   int ret;
   uint32_t ctrl;

   ret = MARK_RING(chan, 2 * 16 + 32, 4);
   if (ret)
      return ret;

   ret = nv50_2d_texture_set(chan, 1, dst, dst_level, dz);
   if (ret)
      return ret;

   ret = nv50_2d_texture_set(chan, 0, src, src_level, sz);
   if (ret)
      return ret;

   /* NOTE: 2D engine doesn't work for MS8 */
   if (src->ms_x)
      ctrl = 0x11;

   /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
   BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1);
   OUT_RING  (chan, ctrl);
   BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4);
   OUT_RING  (chan, dx << dst->ms_x);
   OUT_RING  (chan, dy << dst->ms_y);
   OUT_RING  (chan, w << dst->ms_x);
   OUT_RING  (chan, h << dst->ms_y);
   BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4);
   OUT_RING  (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000);
   OUT_RING  (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f);
   OUT_RING  (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000);
   OUT_RING  (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f);
   BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4);
   OUT_RING  (chan, 0);
   OUT_RING  (chan, sx << src->ms_x);
   OUT_RING  (chan, 0);
   OUT_RING  (chan, sy << src->ms_y);

   return 0;
}