Esempio n. 1
0
static void
fd_clear(struct pipe_context *pctx, unsigned buffers,
		const union pipe_color_union *color, double depth, unsigned stencil)
{
	struct fd_context *ctx = fd_context(pctx);
	struct pipe_framebuffer_state *pfb = &ctx->framebuffer;

	ctx->cleared |= buffers;
	ctx->resolve |= buffers;
	ctx->needs_flush = true;

	if (buffers & PIPE_CLEAR_COLOR)
		fd_resource(pfb->cbufs[0]->texture)->dirty = true;

	if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
		fd_resource(pfb->zsbuf->texture)->dirty = true;
		ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
	}

	DBG("%x depth=%f, stencil=%u (%s/%s)", buffers, depth, stencil,
		util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
		util_format_short_name(pipe_surface_format(pfb->zsbuf)));

	ctx->clear(ctx, buffers, color, depth, stencil);

	ctx->dirty |= FD_DIRTY_ZSA |
			FD_DIRTY_RASTERIZER |
			FD_DIRTY_SAMPLE_MASK |
			FD_DIRTY_PROG |
			FD_DIRTY_CONSTBUF |
			FD_DIRTY_BLEND;

	if (fd_mesa_debug & FD_DBG_DCLEAR)
		ctx->dirty = 0xffffffff;
}
Esempio n. 2
0
static void
draw_emit_indirect(struct fd_batch *batch, struct fd_ringbuffer *ring,
				   enum pc_di_primtype primtype,
				   enum pc_di_vis_cull_mode vismode,
				   const struct pipe_draw_info *info,
				   unsigned index_offset)
{
	struct fd_resource *ind = fd_resource(info->indirect->buffer);

	if (info->index_size) {
		struct pipe_resource *idx = info->index.resource;
		unsigned max_indicies = (idx->width0 - info->indirect->offset) /
			info->index_size;

		OUT_PKT7(ring, CP_DRAW_INDX_INDIRECT, 6);
		OUT_RINGP(ring, DRAW4(primtype, DI_SRC_SEL_DMA,
							  fd4_size2indextype(info->index_size), 0),
				  &batch->draw_patches);
		OUT_RELOC(ring, fd_resource(idx)->bo,
				  index_offset, 0, 0);
		// XXX: Check A5xx vs A6xx
		OUT_RING(ring, A5XX_CP_DRAW_INDX_INDIRECT_3_MAX_INDICES(max_indicies));
		OUT_RELOC(ring, ind->bo, info->indirect->offset, 0, 0);
	} else {
		OUT_PKT7(ring, CP_DRAW_INDIRECT, 3);
		OUT_RINGP(ring, DRAW4(primtype, DI_SRC_SEL_AUTO_INDEX, 0, 0),
				  &batch->draw_patches);
		OUT_RELOC(ring, ind->bo, info->indirect->offset, 0, 0);
	}
}
Esempio n. 3
0
static void
fd3_emit_const_bo(struct fd_ringbuffer *ring, enum shader_t type, boolean write,
		uint32_t regid, uint32_t num, struct pipe_resource **prscs, uint32_t *offsets)
{
	uint32_t i;

	debug_assert((regid % 4) == 0);
	debug_assert((num % 4) == 0);

	OUT_PKT3(ring, CP_LOAD_STATE, 2 + num);
	OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/2) |
			CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
			CP_LOAD_STATE_0_STATE_BLOCK(sb[type]) |
			CP_LOAD_STATE_0_NUM_UNIT(num/2));
	OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
			CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));

	for (i = 0; i < num; i++) {
		if (prscs[i]) {
			if (write) {
				OUT_RELOCW(ring, fd_resource(prscs[i])->bo, offsets[i], 0, 0);
			} else {
				OUT_RELOC(ring, fd_resource(prscs[i])->bo, offsets[i], 0, 0);
			}
		} else {
			OUT_RING(ring, 0xbad00000 | (i << 16));
		}
	}
}
Esempio n. 4
0
static void
fd_clear(struct pipe_context *pctx, unsigned buffers,
         const union pipe_color_union *color, double depth, unsigned stencil)
{
    struct fd_context *ctx = fd_context(pctx);
    struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
    struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
    unsigned cleared_buffers;

    /* for bookkeeping about which buffers have been cleared (and thus
     * can fully or partially skip mem2gmem) we need to ignore buffers
     * that have already had a draw, in case apps do silly things like
     * clear after draw (ie. if you only clear the color buffer, but
     * something like alpha-test causes side effects from the draw in
     * the depth buffer, etc)
     */
    cleared_buffers = buffers & (FD_BUFFER_ALL & ~ctx->restore);

    /* do we have full-screen scissor? */
    if (!memcmp(scissor, &ctx->disabled_scissor, sizeof(*scissor))) {
        ctx->cleared |= cleared_buffers;
    } else {
        ctx->partial_cleared |= cleared_buffers;
        if (cleared_buffers & PIPE_CLEAR_COLOR)
            ctx->cleared_scissor.color = *scissor;
        if (cleared_buffers & PIPE_CLEAR_DEPTH)
            ctx->cleared_scissor.depth = *scissor;
        if (cleared_buffers & PIPE_CLEAR_STENCIL)
            ctx->cleared_scissor.stencil = *scissor;
    }
    ctx->resolve |= buffers;
    ctx->needs_flush = true;

    if (buffers & PIPE_CLEAR_COLOR)
        fd_resource(pfb->cbufs[0]->texture)->dirty = true;

    if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
        fd_resource(pfb->zsbuf->texture)->dirty = true;
        ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
    }

    DBG("%x depth=%f, stencil=%u (%s/%s)", buffers, depth, stencil,
        util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
        util_format_short_name(pipe_surface_format(pfb->zsbuf)));

    fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_CLEAR);

    ctx->clear(ctx, buffers, color, depth, stencil);

    ctx->dirty |= FD_DIRTY_ZSA |
                  FD_DIRTY_VIEWPORT |
                  FD_DIRTY_RASTERIZER |
                  FD_DIRTY_SAMPLE_MASK |
                  FD_DIRTY_PROG |
                  FD_DIRTY_CONSTBUF |
                  FD_DIRTY_BLEND;

    if (fd_mesa_debug & FD_DBG_DCLEAR)
        ctx->dirty = 0xffffffff;
}
Esempio n. 5
0
/* emit accumulated render cmds, needed for example if render target has
 * changed, or for flush()
 */
void
fd_context_render(struct pipe_context *pctx)
{
	struct fd_context *ctx = fd_context(pctx);
	struct pipe_framebuffer_state *pfb = &ctx->framebuffer;

	DBG("needs_flush: %d", ctx->needs_flush);

	if (!ctx->needs_flush)
		return;

	fd_gmem_render_tiles(pctx);

	DBG("%p/%p/%p", ctx->ring->start, ctx->ring->cur, ctx->ring->end);

	/* if size in dwords is more than half the buffer size, then wait and
	 * wrap around:
	 */
	if ((ctx->ring->cur - ctx->ring->start) > ctx->ring->size/8)
		fd_context_next_rb(pctx);

	ctx->needs_flush = false;
	ctx->cleared = ctx->restore = ctx->resolve = 0;
	ctx->gmem_reason = 0;
	ctx->num_draws = 0;

	if (pfb->cbufs[0])
		fd_resource(pfb->cbufs[0]->texture)->dirty = false;
	if (pfb->zsbuf)
		fd_resource(pfb->zsbuf->texture)->dirty = false;
}
Esempio n. 6
0
static void
fd_clear(struct pipe_context *pctx, unsigned buffers,
		const union pipe_color_union *color, double depth, unsigned stencil)
{
	struct fd_context *ctx = fd_context(pctx);
	struct fd_ringbuffer *ring = ctx->ring;
	struct pipe_framebuffer_state *fb = &ctx->framebuffer.base;
	uint32_t reg, colr = 0;

	ctx->cleared |= buffers;
	ctx->resolve |= buffers;
	ctx->needs_flush = true;

	if (buffers & PIPE_CLEAR_COLOR)
		fd_resource(fb->cbufs[0]->texture)->dirty = true;

	if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))
		fd_resource(fb->zsbuf->texture)->dirty = true;

	DBG("depth=%f, stencil=%u", depth, stencil);

	if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs)
		colr  = pack_rgba(fb->cbufs[0]->format, color->f);

	/* emit generic state now: */
	fd_state_emit(pctx, ctx->dirty &
			(FD_DIRTY_BLEND | FD_DIRTY_VIEWPORT |
					FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR));

	fd_emit_vertex_bufs(ring, 0x9c, (struct fd_vertex_buf[]) {
			{ .prsc = ctx->solid_vertexbuf, .size = 48 },
		}, 1);
Esempio n. 7
0
static void
fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
	struct fd_context *ctx = fd_context(pctx);
	struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
	struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
	unsigned i, buffers = 0;

	/* if we supported transform feedback, we'd have to disable this: */
	if (((scissor->maxx - scissor->minx) *
			(scissor->maxy - scissor->miny)) == 0) {
		return;
	}

	ctx->needs_flush = true;

	/*
	 * Figure out the buffers/features we need:
	 */

	if (fd_depth_enabled(ctx)) {
		buffers |= FD_BUFFER_DEPTH;
		fd_resource(pfb->zsbuf->texture)->dirty = true;
		ctx->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
	}

	if (fd_stencil_enabled(ctx)) {
		buffers |= FD_BUFFER_STENCIL;
		fd_resource(pfb->zsbuf->texture)->dirty = true;
		ctx->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
	}

	if (fd_logicop_enabled(ctx))
		ctx->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;

	for (i = 0; i < pfb->nr_cbufs; i++) {
		struct pipe_resource *surf = pfb->cbufs[i]->texture;

		fd_resource(surf)->dirty = true;
		buffers |= FD_BUFFER_COLOR;

		if (surf->nr_samples > 1)
			ctx->gmem_reason |= FD_GMEM_MSAA_ENABLED;

		if (fd_blend_enabled(ctx, i))
			ctx->gmem_reason |= FD_GMEM_BLEND_ENABLED;
	}

	ctx->num_draws++;

	/* any buffers that haven't been cleared, we need to restore: */
	ctx->restore |= buffers & (FD_BUFFER_ALL & ~ctx->cleared);
	/* and any buffers used, need to be resolved: */
	ctx->resolve |= buffers;

	ctx->draw(ctx, info);
}
Esempio n. 8
0
/* regid:          base const register
 * prsc or dwords: buffer containing constant values
 * sizedwords:     size of const value buffer
 */
void
fd4_emit_constant(struct fd_ringbuffer *ring,
		enum adreno_state_block sb,
		uint32_t regid, uint32_t offset, uint32_t sizedwords,
		const uint32_t *dwords, struct pipe_resource *prsc)
{
	uint32_t i, sz;
	enum adreno_state_src src;

	if (prsc) {
		sz = 0;
		src = 0x2;  // TODO ??
	} else {
		sz = sizedwords;
		src = SS_DIRECT;
	}

	OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
	OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/4) |
			CP_LOAD_STATE_0_STATE_SRC(src) |
			CP_LOAD_STATE_0_STATE_BLOCK(sb) |
			CP_LOAD_STATE_0_NUM_UNIT(sizedwords/4));
	if (prsc) {
		struct fd_bo *bo = fd_resource(prsc)->bo;
		OUT_RELOC(ring, bo, offset,
				CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS), 0);
	} else {
		OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
				CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
		dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
	}
	for (i = 0; i < sz; i++) {
		OUT_RING(ring, dwords[i]);
	}
}
Esempio n. 9
0
static struct pipe_sampler_view *
fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
		const struct pipe_sampler_view *cso)
{
	struct fd3_pipe_sampler_view *so = CALLOC_STRUCT(fd3_pipe_sampler_view);
	struct fd_resource *rsc = fd_resource(prsc);

	if (!so)
		return NULL;

	so->base = *cso;
	pipe_reference(NULL, &prsc->reference);
	so->base.texture = prsc;
	so->base.reference.count = 1;
	so->base.context = pctx;

	so->tex_resource =  rsc;

	so->texconst0 =
			0x40000000 | /* ??? */
			A3XX_TEX_CONST_0_FMT(fd3_pipe2tex(cso->format)) |
			fd3_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
						cso->swizzle_b, cso->swizzle_a);
	so->texconst1 =
			A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
			A3XX_TEX_CONST_1_WIDTH(prsc->width0) |
			A3XX_TEX_CONST_1_HEIGHT(prsc->height0);
	/* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */
	so->texconst2 =
			A3XX_TEX_CONST_2_PITCH(rsc->pitch * rsc->cpp);
	so->texconst3 = 0x00000000;  /* ??? */

	return &so->base;
}
Esempio n. 10
0
static void
emit_vertexbufs(struct fd_context *ctx)
{
	struct fd_vertex_stateobj *vtx = ctx->vtx.vtx;
	struct fd_vertexbuf_stateobj *vertexbuf = &ctx->vtx.vertexbuf;
	struct fd2_vertex_buf bufs[PIPE_MAX_ATTRIBS];
	unsigned i;

	if (!vtx->num_elements)
		return;

	for (i = 0; i < vtx->num_elements; i++) {
		struct pipe_vertex_element *elem = &vtx->pipe[i];
		struct pipe_vertex_buffer *vb =
				&vertexbuf->vb[elem->vertex_buffer_index];
		bufs[i].offset = vb->buffer_offset;
		bufs[i].size = fd_bo_size(fd_resource(vb->buffer)->bo);
		bufs[i].prsc = vb->buffer;
	}

	// NOTE I believe the 0x78 (or 0x9c in solid_vp) relates to the
	// CONST(20,0) (or CONST(26,0) in soliv_vp)

	fd2_emit_vertex_bufs(ctx->ring, 0x78, bufs, vtx->num_elements);
}
Esempio n. 11
0
static void
fd_resource_transfer_unmap(struct pipe_context *pctx,
		struct pipe_transfer *ptrans)
{
	struct fd_context *ctx = fd_context(pctx);
	struct fd_resource *rsc = fd_resource(ptrans->resource);
	struct fd_transfer *trans = fd_transfer(ptrans);

	if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
		struct pipe_box box;
		u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box);
		fd_resource_flush(trans, &box);
	}

	if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
		fd_bo_cpu_fini(rsc->bo);
		if (rsc->stencil)
			fd_bo_cpu_fini(rsc->stencil->bo);
	}

	util_range_add(&rsc->valid_buffer_range,
				   ptrans->box.x,
				   ptrans->box.x + ptrans->box.width);

	pipe_resource_reference(&ptrans->resource, NULL);
	util_slab_free(&ctx->transfer_pool, ptrans);

	free(trans->staging);
}
Esempio n. 12
0
static void
fd_resource_flush_z32s8(struct fd_transfer *trans, const struct pipe_box *box)
{
	struct fd_resource *rsc = fd_resource(trans->base.resource);
	struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level);
	struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level);
	enum pipe_format format = trans->base.resource->format;

	float *depth = fd_bo_map(rsc->bo) + slice->offset +
		fd_resource_layer_offset(rsc, slice, trans->base.box.z) +
		(trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4;
	uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset +
		fd_resource_layer_offset(rsc->stencil, sslice, trans->base.box.z) +
		(trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x;

	if (format != PIPE_FORMAT_X32_S8X24_UINT)
		util_format_z32_float_s8x24_uint_unpack_z_float(
				depth, slice->pitch * 4,
				trans->staging, trans->base.stride,
				box->width, box->height);

	util_format_z32_float_s8x24_uint_unpack_s_8uint(
			stencil, sslice->pitch,
			trans->staging, trans->base.stride,
			box->width, box->height);
}
Esempio n. 13
0
static void
fd5_emit_tile_gmem2mem(struct fd_batch *batch, struct fd_tile *tile)
{
	struct fd_context *ctx = batch->ctx;
	struct fd_gmem_stateobj *gmem = &ctx->gmem;
	struct pipe_framebuffer_state *pfb = &batch->framebuffer;

	if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
		struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
		// XXX BLIT_ZS vs BLIT_Z32 .. need some more cmdstream traces
		// with z32_x24s8..
		if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH))
			emit_gmem2mem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf, BLIT_ZS);
		if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL))
			emit_gmem2mem_surf(batch, gmem->zsbuf_base[1], pfb->zsbuf, BLIT_ZS);
	}

	if (batch->resolve & FD_BUFFER_COLOR) {
		unsigned i;
		for (i = 0; i < pfb->nr_cbufs; i++) {
			if (!pfb->cbufs[i])
				continue;
			if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))
				continue;
			emit_gmem2mem_surf(batch, gmem->cbuf_base[i],
					pfb->cbufs[i], BLIT_MRT0 + i);
		}
	}
}
Esempio n. 14
0
static void
emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base,
		struct pipe_surface *psurf, enum a5xx_blit_buf buf)
{
	struct fd_ringbuffer *ring = batch->gmem;
	struct fd_resource *rsc = fd_resource(psurf->texture);
	struct fd_resource_slice *slice;
	uint32_t offset;

	slice = fd_resource_slice(rsc, psurf->u.tex.level);
	offset = fd_resource_offset(rsc, psurf->u.tex.level,
			psurf->u.tex.first_layer);

	debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);

	OUT_PKT4(ring, REG_A5XX_RB_BLIT_FLAG_DST_LO, 4);
	OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_LO */
	OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_HI */
	OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_PITCH */
	OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_ARRAY_PITCH */

	OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_3, 5);
	OUT_RING(ring, 0x00000004);   /* XXX RB_RESOLVE_CNTL_3 */
	OUT_RELOCW(ring, rsc->bo, offset, 0, 0);     /* RB_BLIT_DST_LO/HI */
	OUT_RING(ring, A5XX_RB_BLIT_DST_PITCH(slice->pitch * rsc->cpp));
	OUT_RING(ring, A5XX_RB_BLIT_DST_ARRAY_PITCH(slice->size0));

	OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
	OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf));

	fd5_emit_blit(batch->ctx, ring);
}
Esempio n. 15
0
static struct pipe_sampler_view *
fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
		const struct pipe_sampler_view *cso)
{
	struct fd4_pipe_sampler_view *so = CALLOC_STRUCT(fd4_pipe_sampler_view);
	struct fd_resource *rsc = fd_resource(prsc);
	unsigned lvl = fd_sampler_first_level(cso);
	unsigned miplevels = fd_sampler_last_level(cso) - lvl;

	if (!so)
		return NULL;

	so->base = *cso;
	pipe_reference(NULL, &prsc->reference);
	so->base.texture = prsc;
	so->base.reference.count = 1;
	so->base.context = pctx;

	so->texconst0 =
		A4XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) |
		A4XX_TEX_CONST_0_FMT(fd4_pipe2tex(cso->format)) |
		A4XX_TEX_CONST_0_MIPLVLS(miplevels) |
		fd4_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
				cso->swizzle_b, cso->swizzle_a);

	if (util_format_is_srgb(cso->format))
		so->texconst0 |= A4XX_TEX_CONST_0_SRGB;

	so->texconst1 =
		A4XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
		A4XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
	so->texconst2 =
		A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(cso->format)) |
		A4XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp);

	switch (prsc->target) {
	case PIPE_TEXTURE_1D_ARRAY:
	case PIPE_TEXTURE_2D_ARRAY:
		so->texconst3 =
			A4XX_TEX_CONST_3_DEPTH(prsc->array_size) |
			A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
		break;
	case PIPE_TEXTURE_CUBE:
	case PIPE_TEXTURE_CUBE_ARRAY:
		so->texconst3 =
			A4XX_TEX_CONST_3_DEPTH(prsc->array_size / 6) |
			A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
		break;
	case PIPE_TEXTURE_3D:
		so->texconst3 =
			A4XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) |
			A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0);
		break;
	default:
		so->texconst3 = 0x00000000;
		break;
	}

	return &so->base;
}
Esempio n. 16
0
static void
emit_gmem2mem_surf(struct fd_context *ctx,
		uint32_t base, struct pipe_surface *psurf)
{
	struct fd_ringbuffer *ring = ctx->ring;
	struct fd_resource *rsc = fd_resource(psurf->texture);
	struct fd_resource_slice *slice = &rsc->slices[psurf->u.tex.level];
	uint32_t offset = fd_resource_offset(rsc, psurf->u.tex.level,
			psurf->u.tex.first_layer);

	debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);

	OUT_PKT0(ring, REG_A4XX_RB_COPY_CONTROL, 4);
	OUT_RING(ring, A4XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
			A4XX_RB_COPY_CONTROL_MODE(RB_COPY_RESOLVE) |
			A4XX_RB_COPY_CONTROL_GMEM_BASE(base));
	OUT_RELOCW(ring, rsc->bo, offset, 0, 0);   /* RB_COPY_DEST_BASE */
	OUT_RING(ring, A4XX_RB_COPY_DEST_PITCH_PITCH(slice->pitch * rsc->cpp));
	OUT_RING(ring, A4XX_RB_COPY_DEST_INFO_TILE(TILE4_LINEAR) |
			A4XX_RB_COPY_DEST_INFO_FORMAT(fd4_pipe2color(psurf->format)) |
			A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
			A4XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |
			A4XX_RB_COPY_DEST_INFO_SWAP(fd4_pipe2swap(psurf->format)));

	fd4_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
			DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX_SIZE_IGN, 0, 0, NULL);
}
Esempio n. 17
0
static void
emit_gmem2mem_surf(struct fd_ringbuffer *ring, uint32_t swap, uint32_t base,
                   struct pipe_surface *psurf)
{
    struct fd_resource *rsc = fd_resource(psurf->texture);

    OUT_PKT3(ring, CP_SET_CONSTANT, 2);
    OUT_RING(ring, CP_REG(REG_RB_COLOR_INFO));
    OUT_RING(ring, RB_COLOR_INFO_COLOR_SWAP(swap) |
             RB_COLOR_INFO_COLOR_BASE(base / 1024) |
             RB_COLOR_INFO_COLOR_FORMAT(fd_pipe2color(psurf->format)));

    OUT_PKT3(ring, CP_SET_CONSTANT, 5);
    OUT_RING(ring, CP_REG(REG_RB_COPY_CONTROL));
    OUT_RING(ring, 0x00000000);             /* RB_COPY_CONTROL */
    OUT_RELOC(ring, rsc->bo, 0, 0);         /* RB_COPY_DEST_BASE */
    OUT_RING(ring, rsc->pitch >> 5);        /* RB_COPY_DEST_PITCH */
    OUT_RING(ring, RB_COPY_DEST_INFO_FORMAT(fd_pipe2color(psurf->format)) |
             RB_COPY_DEST_INFO_LINEAR |      /* RB_COPY_DEST_INFO */
             RB_COPY_DEST_INFO_SWAP(swap) |
             RB_COPY_DEST_INFO_WRITE_RED |
             RB_COPY_DEST_INFO_WRITE_GREEN |
             RB_COPY_DEST_INFO_WRITE_BLUE |
             RB_COPY_DEST_INFO_WRITE_ALPHA);

    OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
    OUT_RING(ring, 0x0000000);

    OUT_PKT3(ring, CP_DRAW_INDX, 3);
    OUT_RING(ring, 0x00000000);
    OUT_RING(ring, DRAW(DI_PT_RECTLIST, DI_SRC_SEL_AUTO_INDEX,
                        INDEX_SIZE_IGN, IGNORE_VISIBILITY));
    OUT_RING(ring, 3);					/* NumIndices */
}
Esempio n. 18
0
static void *
fd_resource_transfer_map(struct pipe_context *pctx,
		struct pipe_resource *prsc,
		unsigned level, unsigned usage,
		const struct pipe_box *box,
		struct pipe_transfer **pptrans)
{
	struct fd_context *ctx = fd_context(pctx);
	struct fd_resource *rsc = fd_resource(prsc);
	struct pipe_transfer *ptrans = util_slab_alloc(&ctx->transfer_pool);
	enum pipe_format format = prsc->format;
	char *buf;

	if (!ptrans)
		return NULL;

	ptrans->resource = prsc;
	ptrans->level = level;
	ptrans->usage = usage;
	ptrans->box = *box;
	ptrans->stride = rsc->pitch * rsc->cpp;
	ptrans->layer_stride = ptrans->stride;

	buf = fd_bo_map(rsc->bo);

	*pptrans = ptrans;

	return buf +
		box->y / util_format_get_blockheight(format) * ptrans->stride +
		box->x / util_format_get_blockwidth(format) * rsc->cpp;
}
Esempio n. 19
0
static struct pipe_stream_output_target *
fd_create_stream_output_target(struct pipe_context *pctx,
		struct pipe_resource *prsc, unsigned buffer_offset,
		unsigned buffer_size)
{
	struct pipe_stream_output_target *target;
	struct fd_resource *rsc = fd_resource(prsc);

	target = CALLOC_STRUCT(pipe_stream_output_target);
	if (!target)
		return NULL;

	pipe_reference_init(&target->reference, 1);
	pipe_resource_reference(&target->buffer, prsc);

	target->context = pctx;
	target->buffer_offset = buffer_offset;
	target->buffer_size = buffer_size;

	assert(rsc->base.target == PIPE_BUFFER);
	util_range_add(&rsc->valid_buffer_range,
		buffer_offset, buffer_offset + buffer_size);

	return target;
}
Esempio n. 20
0
static void
emit_gmem2mem_surf(struct fd_ringbuffer *ring,
		enum adreno_rb_copy_control_mode mode,
		uint32_t base, struct pipe_surface *psurf)
{
	struct fd_resource *rsc = fd_resource(psurf->texture);

	OUT_PKT0(ring, REG_A3XX_RB_COPY_CONTROL, 4);
	OUT_RING(ring, A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
			A3XX_RB_COPY_CONTROL_MODE(mode) |
			A3XX_RB_COPY_CONTROL_GMEM_BASE(base));
	OUT_RELOCW(ring, rsc->bo, 0, 0, -1);    /* RB_COPY_DEST_BASE */
	OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(rsc->pitch * rsc->cpp));
	OUT_RING(ring, A3XX_RB_COPY_DEST_INFO_TILE(LINEAR) |
			A3XX_RB_COPY_DEST_INFO_FORMAT(fd3_pipe2color(psurf->format)) |
			A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
			A3XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |
			A3XX_RB_COPY_DEST_INFO_SWAP(fd3_pipe2swap(psurf->format)));

	OUT_PKT3(ring, CP_DRAW_INDX, 3);
	OUT_RING(ring, 0x00000000);
	OUT_RING(ring, DRAW(DI_PT_RECTLIST, DI_SRC_SEL_AUTO_INDEX,
			INDEX_SIZE_IGN, IGNORE_VISIBILITY));
	OUT_RING(ring, 2);					/* NumIndices */
}
Esempio n. 21
0
/* this is same for a2xx/a3xx, so split into helper: */
void
fd_draw_emit(struct fd_context *ctx, struct fd_ringbuffer *ring,
		enum pc_di_vis_cull_mode vismode,
		const struct pipe_draw_info *info)
{
	struct pipe_index_buffer *idx = &ctx->indexbuf;
	struct fd_bo *idx_bo = NULL;
	enum pc_di_index_size idx_type = INDEX_SIZE_IGN;
	enum pc_di_src_sel src_sel;
	uint32_t idx_size, idx_offset;

	if (info->indexed) {
		assert(!idx->user_buffer);

		idx_bo = fd_resource(idx->buffer)->bo;
		idx_type = size2indextype(idx->index_size);
		idx_size = idx->index_size * info->count;
		idx_offset = idx->offset;
		src_sel = DI_SRC_SEL_DMA;
	} else {
		idx_bo = NULL;
		idx_type = INDEX_SIZE_IGN;
		idx_size = 0;
		idx_offset = 0;
		src_sel = DI_SRC_SEL_AUTO_INDEX;
	}

	fd_draw(ctx, ring, ctx->primtypes[info->mode], vismode, src_sel,
			info->count, idx_type, idx_size, idx_offset, idx_bo);
}
Esempio n. 22
0
static texmask
emit_texture(struct fd_ringbuffer *ring, struct fd_context *ctx,
		struct fd_texture_stateobj *tex, unsigned samp_id, texmask emitted)
{
	unsigned const_idx = fd2_get_const_idx(ctx, tex, samp_id);
	static const struct fd2_sampler_stateobj dummy_sampler = {};
	const struct fd2_sampler_stateobj *sampler;
	struct fd2_pipe_sampler_view *view;

	if (emitted & (1 << const_idx))
		return 0;

	sampler = tex->samplers[samp_id] ?
			fd2_sampler_stateobj(tex->samplers[samp_id]) :
			&dummy_sampler;
	view = fd2_pipe_sampler_view(tex->textures[samp_id]);

	OUT_PKT3(ring, CP_SET_CONSTANT, 7);
	OUT_RING(ring, 0x00010000 + (0x6 * const_idx));

	OUT_RING(ring, sampler->tex0 | view->tex0);
	OUT_RELOC(ring, fd_resource(view->base.texture)->bo, 0, view->fmt, 0);
	OUT_RING(ring, view->tex2);
	OUT_RING(ring, sampler->tex3 | view->tex3);
	OUT_RING(ring, sampler->tex4);
	OUT_RING(ring, sampler->tex5);

	return (1 << const_idx);
}
Esempio n. 23
0
static struct pipe_sampler_view *
fd_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
		const struct pipe_sampler_view *cso)
{
	struct fd_pipe_sampler_view *so = CALLOC_STRUCT(fd_pipe_sampler_view);
	struct fd_resource *rsc = fd_resource(prsc);

	if (!so)
		return NULL;

	so->base = *cso;
	pipe_reference(NULL, &prsc->reference);
	so->base.texture = prsc;
	so->base.reference.count = 1;
	so->base.context = pctx;

	so->tex_resource =  rsc;
	so->fmt = fd_pipe2surface(cso->format);

	so->tex0 = SQ_TEX0_PITCH(rsc->pitch);
	so->tex2 =
		SQ_TEX2_HEIGHT(prsc->height0) |
		SQ_TEX2_WIDTH(prsc->width0);
	so->tex3 = fd_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
			cso->swizzle_b, cso->swizzle_a);

	return &so->base;
}
Esempio n. 24
0
static void
emit_constants(struct fd_ringbuffer *ring, uint32_t base,
		struct fd_constbuf_stateobj *constbuf,
		struct fd2_shader_stateobj *shader)
{
	uint32_t enabled_mask = constbuf->enabled_mask;
	uint32_t start_base = base;
	unsigned i;

	/* emit user constants: */
	while (enabled_mask) {
		unsigned index = ffs(enabled_mask) - 1;
		struct pipe_constant_buffer *cb = &constbuf->cb[index];
		unsigned size = align(cb->buffer_size, 4) / 4; /* size in dwords */

		// I expect that size should be a multiple of vec4's:
		assert(size == align(size, 4));

		/* hmm, sometimes we still seem to end up with consts bound,
		 * even if shader isn't using them, which ends up overwriting
		 * const reg's used for immediates.. this is a hack to work
		 * around that:
		 */
		if (shader && ((base - start_base) >= (shader->first_immediate * 4)))
			break;

		const uint32_t *dwords;

		if (cb->user_buffer) {
			dwords = cb->user_buffer;
		} else {
			struct fd_resource *rsc = fd_resource(cb->buffer);
			dwords = fd_bo_map(rsc->bo);
		}

		dwords = (uint32_t *)(((uint8_t *)dwords) + cb->buffer_offset);

		OUT_PKT3(ring, CP_SET_CONSTANT, size + 1);
		OUT_RING(ring, base);
		for (i = 0; i < size; i++)
			OUT_RING(ring, *(dwords++));

		base += size;
		enabled_mask &= ~(1 << index);
	}

	/* emit shader immediates: */
	if (shader) {
		for (i = 0; i < shader->num_immediates; i++) {
			OUT_PKT3(ring, CP_SET_CONSTANT, 5);
			OUT_RING(ring, start_base + (4 * (shader->first_immediate + i)));
			OUT_RING(ring, shader->immediates[i].val[0]);
			OUT_RING(ring, shader->immediates[i].val[1]);
			OUT_RING(ring, shader->immediates[i].val[2]);
			OUT_RING(ring, shader->immediates[i].val[3]);
			base += 4;
		}
	}
}
Esempio n. 25
0
static void
fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
{
	struct fd_resource *rsc = fd_resource(prsc);

	if (rsc->dirty)
		fd_context_render(pctx);
}
static void
fd_resource_destroy(struct pipe_screen *pscreen,
		struct pipe_resource *prsc)
{
	struct fd_resource *rsc = fd_resource(prsc);
	fd_bo_del(rsc->bo);
	FREE(rsc);
}
Esempio n. 27
0
static void
fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
{
	struct fd_resource *rsc = fd_resource(prsc);

	if (pending(rsc, FD_PENDING_WRITE | FD_PENDING_READ))
		fd_context_render(pctx);
}
Esempio n. 28
0
/* used by clover to bind global objects, returning the bo address
 * via handles[n]
 */
static void
fd_set_global_binding(struct pipe_context *pctx,
		unsigned first, unsigned count, struct pipe_resource **prscs,
		uint32_t **handles)
{
	struct fd_context *ctx = fd_context(pctx);
	struct fd_global_bindings_stateobj *so = &ctx->global_bindings;
	unsigned mask = 0;

	if (prscs) {
		for (unsigned i = 0; i < count; i++) {
			unsigned n = i + first;

			mask |= BIT(n);

			pipe_resource_reference(&so->buf[n], prscs[i]);

			if (so->buf[n]) {
				struct fd_resource *rsc = fd_resource(so->buf[n]);
				uint64_t iova = fd_bo_get_iova(rsc->bo);
				// TODO need to scream if iova > 32b or fix gallium API..
				*handles[i] += iova;
			}

			if (prscs[i])
				so->enabled_mask |= BIT(n);
			else
				so->enabled_mask &= ~BIT(n);
		}
	} else {
		mask = (BIT(count) - 1) << first;

		for (unsigned i = 0; i < count; i++) {
			unsigned n = i + first;
			if (so->buf[n]) {
				struct fd_resource *rsc = fd_resource(so->buf[n]);
				fd_bo_put_iova(rsc->bo);
			}
			pipe_resource_reference(&so->buf[n], NULL);
		}

		so->enabled_mask &= ~mask;
	}

}
Esempio n. 29
0
static boolean
fd_resource_get_handle(struct pipe_screen *pscreen,
		struct pipe_resource *prsc,
		struct winsys_handle *handle)
{
	struct fd_resource *rsc = fd_resource(prsc);

	return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->pitch, handle);
}
Esempio n. 30
0
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
		struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w)
{
	enum a3xx_tile_mode tile_mode;
	unsigned i;

	if (bin_w) {
		tile_mode = TILE_32X32;
	} else {
		tile_mode = LINEAR;
	}

	for (i = 0; i < 4; i++) {
		enum a3xx_color_fmt format = 0;
		enum a3xx_color_swap swap = WZYX;
		struct fd_resource *rsc = NULL;
		struct fd_resource_slice *slice = NULL;
		uint32_t stride = 0;
		uint32_t base = 0;

		if ((i < nr_bufs) && bufs[i]) {
			struct pipe_surface *psurf = bufs[i];

			rsc = fd_resource(psurf->texture);
			slice = &rsc->slices[psurf->u.tex.level];
			format = fd3_pipe2color(psurf->format);
			swap = fd3_pipe2swap(psurf->format);

			if (bin_w) {
				stride = bin_w * rsc->cpp;

				if (bases) {
					base = bases[i];
				}
			} else {
				stride = slice->pitch * rsc->cpp;
			}
		}

		OUT_PKT0(ring, REG_A3XX_RB_MRT_BUF_INFO(i), 2);
		OUT_RING(ring, A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
				A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
				A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
				A3XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
		if (bin_w || (i >= nr_bufs)) {
			OUT_RING(ring, A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE(base));
		} else {
			OUT_RELOCW(ring, rsc->bo, slice->offset, 0, -1);
		}

		OUT_PKT0(ring, REG_A3XX_SP_FS_IMAGE_OUTPUT_REG(i), 1);
		OUT_RING(ring, A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT(format));
	}
}