Beispiel #1
0
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);
}
Beispiel #2
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);
}
Beispiel #3
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);
}
Beispiel #4
0
static inline void nv10ExtendPrimitive(struct nouveau_context* nmesa, int size)
{
	/* make sure there's enough room. if not, wait */
	if (RING_AVAILABLE()<size)
	{
		WAIT_RING(nmesa,size);
	}
}
Beispiel #5
0
static void
nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
{
    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 = nv50_query(pq);

    WAIT_RING (chan, 5);
    BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4);
    OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
    OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
    OUT_RING  (chan, 0x00000000);
    OUT_RING  (chan, 0x0100f002);
    FIRE_RING (chan);
}
Beispiel #6
0
static void
nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
{
	struct nv50_context *nv50 = nv50_context(pipe);
	struct nouveau_channel *chan = nv50->screen->nvws->channel;
	struct nouveau_grobj *tesla = nv50->screen->tesla;
	struct nv50_query *q = nv50_query(pq);
	struct nouveau_bo *bo = nv50->screen->nvws->get_bo(q->buffer);

	WAIT_RING (chan, 5);
	BEGIN_RING(chan, tesla, 0x1b00, 4);
	OUT_RELOCh(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
	OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
	OUT_RING  (chan, 0x00000000);
	OUT_RING  (chan, 0x0100f002);
	FIRE_RING (chan);
}
Beispiel #7
0
int
nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
		     int dx, int dy, struct pipe_surface *src, int sx, int sy,
		     int w, int h)
{
	struct nouveau_channel *chan = screen->eng2d->channel;
	struct nouveau_grobj *eng2d = screen->eng2d;
	int ret;

	WAIT_RING (chan, 32);

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

	ret = nv50_surface_set(screen, src, 0);
	if (ret)
		return ret;

	BEGIN_RING(chan, eng2d, 0x088c, 1);
	OUT_RING  (chan, 0);
	BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
	OUT_RING  (chan, dx);
	OUT_RING  (chan, dy);
	OUT_RING  (chan, w);
	OUT_RING  (chan, h);
	BEGIN_RING(chan, eng2d, 0x08c0, 4);
	OUT_RING  (chan, 0);
	OUT_RING  (chan, 1);
	OUT_RING  (chan, 0);
	OUT_RING  (chan, 1);
	BEGIN_RING(chan, eng2d, 0x08d0, 4);
	OUT_RING  (chan, 0);
	OUT_RING  (chan, sx);
	OUT_RING  (chan, 0);
	OUT_RING  (chan, sy);

	return 0;
}
void
nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	unsigned num_outputs = nvfx->vertprog->draw_elements;
	int elements = MAX2(num_outputs, nvfx->hw_vtxelt_nr);

	if (!elements)
		return;

	WAIT_RING(chan, (1 + 6 + 1 + 2) + elements * 2);

	OUT_RING(chan, RING_3D(NV30_3D_VTXFMT(0), elements));
	for(unsigned i = 0; i < num_outputs; ++i)
		OUT_RING(chan, (4 << NV30_3D_VTXFMT_SIZE__SHIFT) | NV30_3D_VTXFMT_TYPE_V32_FLOAT);
	for(unsigned i = num_outputs; i < elements; ++i)
		OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT);

	if(nvfx->is_nv4x) {
		unsigned i;
		/* seems to be some kind of cache flushing */
		for(i = 0; i < 3; ++i) {
			OUT_RING(chan, RING_3D(0x1718, 1));
			OUT_RING(chan, 0);
		}
	}

	OUT_RING(chan, RING_3D(NV30_3D_VTXBUF(0), elements));
	for (unsigned i = 0; i < elements; i++)
		OUT_RING(chan, 0);

	OUT_RING(chan, RING_3D(0x1710, 1));
	OUT_RING(chan, 0);

	nvfx->hw_vtxelt_nr = num_outputs;
	nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
}
Beispiel #9
0
void
NV40EXAComposite(PixmapPtr pdPix, int srcX , int srcY,
				  int maskX, int maskY,
				  int dstX , int dstY,
				  int width, int height)
{
	ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *curie = pNv->Nv3D;
	float sX0, sX1, sX2, sY0, sY1, sY2;
	float mX0, mX1, mX2, mY0, mY1, mY2;
	NV40EXA_STATE;

	WAIT_RING(chan, 64);

	/* We're drawing a triangle, we need to scissor it to a quad. */
	/* The scissors are here for a good reason, we don't get the full
	 * image, but just a part.
	 */
	/* Handling the cliprects is done for us already. */
	BEGIN_RING(chan, curie, NV40TCL_SCISSOR_HORIZ, 2);
	OUT_RING  (chan, (width << 16) | dstX);
	OUT_RING  (chan, (height << 16) | dstY);
	BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1);
	OUT_RING  (chan, NV40TCL_BEGIN_END_TRIANGLES);

	NV40EXATransformCoord(state->unit[0].transform, srcX, srcY - height,
			      state->unit[0].width, state->unit[0].height,
			      &sX0, &sY0);
	NV40EXATransformCoord(state->unit[0].transform, srcX, srcY + height,
			      state->unit[0].width, state->unit[0].height,
			      &sX1, &sY1);
	NV40EXATransformCoord(state->unit[0].transform,
			      srcX + 2*width, srcY + height,
			      state->unit[0].width,
			      state->unit[0].height, &sX2, &sY2);

	if (state->have_mask) {
		NV40EXATransformCoord(state->unit[1].transform,
				      maskX, maskY - height,
				      state->unit[1].width,
				      state->unit[1].height, &mX0, &mY0);
		NV40EXATransformCoord(state->unit[1].transform,
				      maskX, maskY + height,
				      state->unit[1].width,
				      state->unit[1].height, &mX1, &mY1);
		NV40EXATransformCoord(state->unit[1].transform,
				      maskX + 2*width, maskY + height,
				      state->unit[1].width,
				      state->unit[1].height, &mX2, &mY2);

		CV_OUTm(sX0, sY0, mX0, mY0, dstX, dstY - height);
		CV_OUTm(sX1, sY1, mX1, mY1, dstX, dstY + height);
		CV_OUTm(sX2, sY2, mX2, mY2, dstX + 2*width, dstY + height);
	} else {
		CV_OUT(sX0, sY0, dstX, dstY - height);
		CV_OUT(sX1, sY1, dstX, dstY + height);
		CV_OUT(sX2, sY2, dstX + 2*width, dstY + height);
	}

	BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1);
	OUT_RING  (chan, NV40TCL_BEGIN_END_STOP);
}
void
nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
	struct nvfx_context *nvfx = nvfx_context(pipe);
	struct nouveau_channel *chan = nvfx->screen->base.channel;
	struct push_context ctx;
	struct util_split_prim s;
	unsigned instances_left = info->instance_count;
	int vtx_value;
	unsigned hw_mode = nvgl_primitive(info->mode);
	int i;
	struct
	{
		uint8_t* map;
		unsigned step;
	} per_instance[16];
	unsigned p_overhead = 64 /* magic fix */
			+ 4 /* begin/end */
			+ 4; /* potential edgeflag enable/disable */

	ctx.chan = nvfx->screen->base.channel;
	ctx.translate = nvfx->vtxelt->translate;
	ctx.idxbuf = NULL;
	ctx.vertex_length = nvfx->vtxelt->vertex_length;
	ctx.max_vertices_per_packet = nvfx->vtxelt->max_vertices_per_packet;
	ctx.edgeflag = 0.5f;
	// TODO: figure out if we really want to handle this, and do so in that case
	ctx.edgeflag_attr = 0xff; // nvfx->vertprog->cfg.edgeflag_in;

	if(!nvfx->use_vertex_buffers)
	{
		for(i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
		{
			struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
			struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
			uint8_t* data = nvfx_buffer(vb->buffer)->data + vb->buffer_offset;
			if(info->indexed)
				data += info->index_bias * vb->stride;
			ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
		}

		if(ctx.edgeflag_attr < 16)
			vtx_value = -(ctx.vertex_length + 3);  /* vertex data and edgeflag header and value */
		else
		{
			p_overhead += 1; /* initial vertex_data header */
			vtx_value = -ctx.vertex_length;  /* vertex data and edgeflag header and value */
		}

		if (info->indexed) {
			// XXX: this case and is broken and probably need a new VTX_ATTR push path
			if (nvfx->idxbuf.index_size == 1)
				s.emit = emit_vertices_lookup8;
			else if (nvfx->idxbuf.index_size == 2)
				s.emit = emit_vertices_lookup16;
			else
				s.emit = emit_vertices_lookup32;
		} else
			s.emit = emit_vertices;
	}
	else
	{
		if(!info->indexed || nvfx->use_index_buffer)
		{
			s.emit = info->indexed ? emit_ib_ranges : emit_vb_ranges;
			p_overhead += 3;
			vtx_value = 0;
		}
		else if (nvfx->idxbuf.index_size == 4)
		{
			s.emit = emit_elt32;
			p_overhead += 1;
			vtx_value = 8;
		}
		else
		{
			s.emit = (nvfx->idxbuf.index_size == 2) ? emit_elt16 : emit_elt8;
			p_overhead += 3;
			vtx_value = 7;
		}
	}

	ctx.idxbias = info->index_bias;
	if(nvfx->use_vertex_buffers)
		ctx.idxbias -= nvfx->base_vertex;

	/* map index buffer, if present */
	if (info->indexed && !nvfx->use_index_buffer)
		ctx.idxbuf = nvfx_buffer(nvfx->idxbuf.buffer)->data + nvfx->idxbuf.offset;

	s.priv = &ctx;
	s.edge = emit_edgeflag;

	for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
	{
		struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
		struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
		float v[4];
		per_instance[i].step = info->start_instance % ve->instance_divisor;
		per_instance[i].map = nvfx_buffer(vb->buffer)->data + vb->buffer_offset + ve->base.src_offset;

		nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);

		WAIT_RING(chan, 5);
		nvfx_emit_vtx_attr(chan, nvfx->vtxelt->per_instance[i].base.idx, v, nvfx->vtxelt->per_instance[i].base.ncomp);
	}

	/* per-instance loop */
	while (instances_left--) {
		int max_verts;
		boolean done;

		util_split_prim_init(&s, info->mode, info->start, info->count);
		nvfx_state_emit(nvfx);
		for(;;) {
			max_verts  = AVAIL_RING(chan);
			max_verts -= p_overhead;

			/* if vtx_value < 0, each vertex is -vtx_value words long
			 * otherwise, each vertex is 2^(vtx_value) / 255 words long (this is an approximation)
			 */
			if(vtx_value < 0)
			{
				max_verts /= -vtx_value;
				max_verts -= (max_verts >> 10); /* vertex data headers */
			}
			else
			{
				if(max_verts >= (1 << 23)) /* avoid overflow here */
					max_verts = (1 << 23);
				max_verts = (max_verts * 255) >> vtx_value;
			}

			//printf("avail %u max_verts %u\n", AVAIL_RING(chan), max_verts);

			if(max_verts >= 16)
			{
				/* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
				/* this seems to cause issues on nv3x, and also be unneeded there */
				if(nvfx->is_nv4x)
				{
					int i;
					for(i = 0; i < 32; ++i)
					{
						OUT_RING(chan, RING_3D(0x1dac, 1));
						OUT_RING(chan, 0);
					}
				}

				OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
				OUT_RING(chan, hw_mode);
				done = util_split_prim_next(&s, max_verts);
				OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
				OUT_RING(chan, 0);

				if(done)
					break;
			}

			FIRE_RING(chan);
			nvfx_state_emit(nvfx);
		}
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;
	}
}