diff options
| author | Dave Airlie <airlied@redhat.com> | 2010-10-21 19:11:23 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-10-21 19:58:09 +1000 | 
| commit | f39e6c9c816b603a4ed8fd8cda8569b7e13c1f68 (patch) | |
| tree | 88d4070cccf84a78f8ef93290cc9f0a1a899fa81 /src/gallium | |
| parent | e68c83a5a01a8a659857310cfcc785c7e028d3f0 (diff) | |
r600g: start splitting out common code from eg/r600.
no point duplicating code that doesn't touch hw, also make it easier
to spot mistakes
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/drivers/r600/Makefile | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 66 | ||||
| -rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 20 | ||||
| -rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 282 | ||||
| -rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 123 | ||||
| -rw-r--r-- | src/gallium/drivers/r600/r600_translate.c | 211 | 
6 files changed, 367 insertions, 339 deletions
| diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile index ede0bb2ec4..a484f38e9f 100644 --- a/src/gallium/drivers/r600/Makefile +++ b/src/gallium/drivers/r600/Makefile @@ -19,6 +19,8 @@ C_SOURCES = \  	r600_texture.c \  	r700_asm.c \  	evergreen_state.c \ -	eg_asm.c +	eg_asm.c \ +	r600_translate.c \ +	r600_state_common.c  include ../../Makefile.template diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 0b54c2c716..f394527edf 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -377,19 +377,6 @@ static void *evergreen_create_sampler_state(struct pipe_context *ctx,  	return rstate;  } -static void *evergreen_create_vertex_elements(struct pipe_context *ctx, -				unsigned count, -				const struct pipe_vertex_element *elements) -{ -	struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element); - -	assert(count < 32); -	v->count = count; -	v->refcount = 1; -	memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element)); -	return v; -} -  static void evergreen_sampler_view_destroy(struct pipe_context *ctx,  				      struct pipe_sampler_view *state)  { @@ -935,40 +922,6 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,  	r600_context_pipe_state_set(&rctx->ctx, rstate);  } -static void evergreen_set_index_buffer(struct pipe_context *ctx, -				  const struct pipe_index_buffer *ib) -{ -	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - -	if (ib) { -		pipe_resource_reference(&rctx->index_buffer.buffer, ib->buffer); -		memcpy(&rctx->index_buffer, ib, sizeof(rctx->index_buffer)); -	} else { -		pipe_resource_reference(&rctx->index_buffer.buffer, NULL); -		memset(&rctx->index_buffer, 0, sizeof(rctx->index_buffer)); -	} - -	/* TODO make this more like a state */ -} - -static void evergreen_set_vertex_buffers(struct pipe_context *ctx, unsigned count, -					const struct pipe_vertex_buffer *buffers) -{ -	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - -	for (int i = 0; i < rctx->nvertex_buffer; i++) { -		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL); -	} -	memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); -	for (int i = 0; i < count; i++) { -		rctx->vertex_buffer[i].buffer = NULL; -		if (r600_buffer_is_user_buffer(buffers[i].buffer)) -			rctx->any_user_vbs = TRUE; -		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); -	} -	rctx->nvertex_buffer = count; -} -  static void evergreen_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,  					struct pipe_resource *buffer)  { @@ -1065,7 +1018,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx)  	rctx->context.create_rasterizer_state = evergreen_create_rs_state;  	rctx->context.create_sampler_state = evergreen_create_sampler_state;  	rctx->context.create_sampler_view = evergreen_create_sampler_view; -	rctx->context.create_vertex_elements_state = evergreen_create_vertex_elements; +	rctx->context.create_vertex_elements_state = r600_create_vertex_elements;  	rctx->context.create_vs_state = evergreen_create_shader_state;  	rctx->context.bind_blend_state = evergreen_bind_blend_state;  	rctx->context.bind_depth_stencil_alpha_state = evergreen_bind_state; @@ -1091,8 +1044,8 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx)  	rctx->context.set_sample_mask = evergreen_set_sample_mask;  	rctx->context.set_scissor_state = evergreen_set_scissor_state;  	rctx->context.set_stencil_ref = evergreen_set_stencil_ref; -	rctx->context.set_vertex_buffers = evergreen_set_vertex_buffers; -	rctx->context.set_index_buffer = evergreen_set_index_buffer; +	rctx->context.set_vertex_buffers = r600_set_vertex_buffers; +	rctx->context.set_index_buffer = r600_set_index_buffer;  	rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;  	rctx->context.set_viewport_state = evergreen_set_viewport_state;  	rctx->context.sampler_view_destroy = evergreen_sampler_view_destroy; @@ -1378,6 +1331,12 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info)  	struct r600_draw rdraw;  	struct r600_pipe_state vgt;  	struct r600_drawl draw; +	boolean translate = FALSE; + +	if (rctx->vertex_elements->incompatible_layout) { +		r600_begin_vertex_translate(rctx); +		translate = TRUE; +	}  	if (rctx->any_user_vbs) {  		r600_upload_user_buffers(rctx); @@ -1454,11 +1413,11 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info)  			vertex_buffer->buffer_offset +  			r600_bo_offset(rbuffer->bo); -		format = r600_translate_vertex_data_type(rctx->vertex_elements->elements[i].src_format); +		format = r600_translate_vertex_data_type(rctx->vertex_elements->hw_format[i]);  		word2 = format | S_030008_STRIDE(vertex_buffer->stride); -		word3 = r600_translate_vertex_data_swizzle(rctx->vertex_elements->elements[i].src_format); +		word3 = r600_translate_vertex_data_swizzle(rctx->vertex_elements->hw_format[i]);  		r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, offset, 0xFFFFFFFF, rbuffer->bo);  		r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, rbuffer->size - offset - 1, 0xFFFFFFFF, NULL); @@ -1539,6 +1498,9 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info)  	}  	evergreen_context_draw(&rctx->ctx, &rdraw); +	if (translate) +		r600_end_vertex_translate(rctx); +  	pipe_resource_reference(&draw.index_buffer, NULL);  } diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 7fb47b608e..11410f17c7 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -216,10 +216,6 @@ int r600_find_vs_semantic_index(struct r600_shader *vs,  void r600_init_state_functions(struct r600_pipe_context *rctx);  void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info);  void r600_init_config(struct r600_pipe_context *rctx); -void r600_translate_index_buffer(struct r600_pipe_context *r600, -					struct pipe_resource **index_buffer, -					unsigned *index_size, -					unsigned *start, unsigned count);  void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx);  /* r600_helper.h */  int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); @@ -230,6 +226,22 @@ uint32_t r600_translate_texformat(enum pipe_format format,  				  const unsigned char *swizzle_view,   				  uint32_t *word4_p, uint32_t *yuv_format_p); +/* r600_translate.c */ +void r600_begin_vertex_translate(struct r600_pipe_context *rctx); +void r600_end_vertex_translate(struct r600_pipe_context *rctx); +void r600_translate_index_buffer(struct r600_pipe_context *r600, +				 struct pipe_resource **index_buffer, +				 unsigned *index_size, +				 unsigned *start, unsigned count); + +/* r600_state_common.c */ +void r600_set_index_buffer(struct pipe_context *ctx, +			   const struct pipe_index_buffer *ib); +void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count, +			     const struct pipe_vertex_buffer *buffers); +void *r600_create_vertex_elements(struct pipe_context *ctx, +				  unsigned count, +				  const struct pipe_vertex_element *elements);  /*   * common helpers   */ diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 5cc4b3044b..df2c05ea13 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -37,10 +37,7 @@  #include <util/u_memory.h>  #include <util/u_inlines.h>  #include <util/u_upload_mgr.h> -#include <util/u_index_modify.h>  #include <util/u_framebuffer.h> -#include "translate/translate_cache.h" -#include "translate/translate.h"  #include <pipebuffer/pb_buffer.h>  #include "r600.h"  #include "r600d.h" @@ -184,195 +181,6 @@ static void r600_draw_common(struct r600_drawl *draw)  	r600_context_draw(&rctx->ctx, &rdraw);  } -static void r600_begin_vertex_translate(struct r600_pipe_context *rctx) -{ -	struct pipe_context *pipe = &rctx->context; -	struct translate_key key = {0}; -	struct translate_element *te; -	unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; -	struct translate *tr; -	struct r600_vertex_element *ve = rctx->vertex_elements; -	boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; -	void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; -	struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; -	struct pipe_resource *out_buffer; -	unsigned i, num_verts; - -	/* Initialize the translate key, i.e. the recipe how vertices should be -	 * translated. */ -	for (i = 0; i < ve->count; i++) { -		struct pipe_vertex_buffer *vb = -			&rctx->vertex_buffer[ve->elements[i].vertex_buffer_index]; -		enum pipe_format output_format = ve->hw_format[i]; -		unsigned output_format_size = ve->hw_format_size[i]; - -		/* Check for support. */ -		if (ve->elements[i].src_format == ve->hw_format[i] && -		    (vb->buffer_offset + ve->elements[i].src_offset) % 4 == 0 && -		    vb->stride % 4 == 0) { -			continue; -		} - -		/* Workaround for translate: output floats instead of halfs. */ -		switch (output_format) { -		case PIPE_FORMAT_R16_FLOAT: -			output_format = PIPE_FORMAT_R32_FLOAT; -			output_format_size = 4; -			break; -		case PIPE_FORMAT_R16G16_FLOAT: -			output_format = PIPE_FORMAT_R32G32_FLOAT; -			output_format_size = 8; -			break; -		case PIPE_FORMAT_R16G16B16_FLOAT: -			output_format = PIPE_FORMAT_R32G32B32_FLOAT; -			output_format_size = 12; -			break; -		case PIPE_FORMAT_R16G16B16A16_FLOAT: -			output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; -			output_format_size = 16; -			break; -		default:; -		} - -		/* Add this vertex element. */ -		te = &key.element[key.nr_elements]; -		/*te->type; -		  te->instance_divisor;*/ -		te->input_buffer = ve->elements[i].vertex_buffer_index; -		te->input_format = ve->elements[i].src_format; -		te->input_offset = vb->buffer_offset + ve->elements[i].src_offset; -		te->output_format = output_format; -		te->output_offset = key.output_stride; - -		key.output_stride += output_format_size; -		vb_translated[ve->elements[i].vertex_buffer_index] = TRUE; -		tr_elem_index[i] = key.nr_elements; -		key.nr_elements++; -	} - -	/* Get a translate object. */ -	tr = translate_cache_find(rctx->tran.translate_cache, &key); - -	/* Map buffers we want to translate. */ -	for (i = 0; i < rctx->nvertex_buffer; i++) { -		if (vb_translated[i]) { -			struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; - -			vb_map[i] = pipe_buffer_map(pipe, vb->buffer, -						    PIPE_TRANSFER_READ, &vb_transfer[i]); - -			tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index); -		} -	} - -	/* Create and map the output buffer. */ -	num_verts = rctx->vb_max_index + 1; - -	out_buffer = pipe_buffer_create(&rctx->screen->screen, -					PIPE_BIND_VERTEX_BUFFER, -					key.output_stride * num_verts); - -	out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, -				  &out_transfer); - -	/* Translate. */ -	tr->run(tr, 0, num_verts, 0, out_map); - -	/* Unmap all buffers. */ -	for (i = 0; i < rctx->nvertex_buffer; i++) { -		if (vb_translated[i]) { -			pipe_buffer_unmap(pipe, rctx->vertex_buffer[i].buffer, -					  vb_transfer[i]); -		} -	} - -	{ -		float *flt = out_map; -		fprintf(stderr,"num verts is %d\n", num_verts); -		for (i = 0; i < num_verts; i++) { -			fprintf(stderr,"%f %f\n", flt[i*2], flt[i*2+1]); -		} -	} -	pipe_buffer_unmap(pipe, out_buffer, out_transfer); - -	/* Setup the new vertex buffer in the first free slot. */ -	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { -		struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; - -		if (!vb->buffer) { -			pipe_resource_reference(&vb->buffer, out_buffer); -			vb->buffer_offset = 0; -			vb->max_index = num_verts - 1; -			vb->stride = key.output_stride; -			rctx->tran.vb_slot = i; -			break; -		} -	} - -	/* Save and replace vertex elements. */ -	{ -		struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - -		rctx->tran.saved_velems = rctx->vertex_elements; - -		for (i = 0; i < ve->count; i++) { -			if (vb_translated[ve->elements[i].vertex_buffer_index]) { -				te = &key.element[tr_elem_index[i]]; -				new_velems[i].instance_divisor = ve->elements[i].instance_divisor; -				new_velems[i].src_format = te->output_format; -				new_velems[i].src_offset = te->output_offset; -				new_velems[i].vertex_buffer_index = rctx->tran.vb_slot; -			} else { -				memcpy(&new_velems[i], &ve->elements[i], -				       sizeof(struct pipe_vertex_element)); -			} -		} - -		rctx->tran.new_velems = -			pipe->create_vertex_elements_state(pipe, ve->count, new_velems); -		pipe->bind_vertex_elements_state(pipe, rctx->tran.new_velems); -	} - -	pipe_resource_reference(&out_buffer, NULL); -} - -static void r600_end_vertex_translate(struct r600_pipe_context *rctx) -{ -	struct pipe_context *pipe = &rctx->context; - -	/* Restore vertex elements. */ -	pipe->bind_vertex_elements_state(pipe, rctx->tran.saved_velems); -	pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems); - -	/* Delete the now-unused VBO. */ -	pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, -				NULL); -} - -void r600_translate_index_buffer(struct r600_pipe_context *r600, -					struct pipe_resource **index_buffer, -					unsigned *index_size, -					unsigned *start, unsigned count) -{ -	switch (*index_size) { -	case 1: -		util_shorten_ubyte_elts(&r600->context, index_buffer, 0, *start, count); -		*index_size = 2; -		*start = 0; -		break; - -	case 2: -		if (*start % 2 != 0) { -			util_rebuild_ushort_elts(&r600->context, index_buffer, 0, *start, count); -			*start = 0; -		} -		break; - -	case 4: -		break; -	} -} -  void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)  {  	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; @@ -757,47 +565,6 @@ static void *r600_create_sampler_state(struct pipe_context *ctx,  	return rstate;  } -#define FORMAT_REPLACE(what, withwhat) \ -	case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break - -static void *r600_create_vertex_elements(struct pipe_context *ctx, -				unsigned count, -				const struct pipe_vertex_element *elements) -{ -	struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element); -	int i; -	enum pipe_format *format; - -	assert(count < 32); -	if (!v) -		return NULL; - -	v->count = count; -	memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element)); - -	for (i = 0; i < count; i++) { -		v->hw_format[i] = v->elements[i].src_format; -		format = &v->hw_format[i]; - -		switch (*format) { -                    FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT); -                    FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT); -                    FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT); -                    FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT); -		default:; -		} -		v->incompatible_layout = -			v->incompatible_layout || -			v->elements[i].src_format != v->hw_format[i] || -			v->elements[i].src_offset % 4 != 0; - -                v->hw_format_size[i] = -			align(util_format_get_blocksize(v->hw_format[i]), 4); -	} - -	v->refcount = 1; -	return v; -}  static void r600_sampler_view_destroy(struct pipe_context *ctx,  				      struct pipe_sampler_view *state) @@ -1348,55 +1115,6 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,  	r600_context_pipe_state_set(&rctx->ctx, rstate);  } -static void r600_set_index_buffer(struct pipe_context *ctx, -				  const struct pipe_index_buffer *ib) -{ -	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - -	if (ib) { -		pipe_resource_reference(&rctx->index_buffer.buffer, ib->buffer); -		memcpy(&rctx->index_buffer, ib, sizeof(rctx->index_buffer)); -	} else { -		pipe_resource_reference(&rctx->index_buffer.buffer, NULL); -		memset(&rctx->index_buffer, 0, sizeof(rctx->index_buffer)); -	} - -	/* TODO make this more like a state */ -} - -static void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count, -					const struct pipe_vertex_buffer *buffers) -{ -	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; -	struct pipe_vertex_buffer *vbo; -	unsigned max_index = (unsigned)-1, vbo_max_index; - -	for (int i = 0; i < rctx->nvertex_buffer; i++) { -		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL); -	} -	memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); - -	for (int i = 0; i < count; i++) { -		vbo = (struct pipe_vertex_buffer*)&buffers[i]; - -		rctx->vertex_buffer[i].buffer = NULL; -		if (r600_buffer_is_user_buffer(buffers[i].buffer)) -			rctx->any_user_vbs = TRUE; -		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); - -		if (vbo->max_index == ~0) { -			if (!vbo->stride) -				vbo->max_index = 1; -			else -				vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; -		} -	 -		max_index = MIN2(vbo->max_index, max_index); -	} -	rctx->nvertex_buffer = count; -	rctx->vb_max_index = max_index; -} -  static void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,  					struct pipe_resource *buffer)  { diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c new file mode 100644 index 0000000000..722ce32263 --- /dev/null +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -0,0 +1,123 @@ +/* + * Copyright 2010 Red Hat Inc. + *           2010 Jerome Glisse + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie <airlied@redhat.com> + *          Jerome Glisse <jglisse@redhat.com> + */ +#include <util/u_memory.h> +#include <util/u_format.h> +#include <pipebuffer/pb_buffer.h> +#include "r600_pipe.h" + +/* common state between evergreen and r600 */ + +void r600_set_index_buffer(struct pipe_context *ctx, +			   const struct pipe_index_buffer *ib) +{ +	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + +	if (ib) { +		pipe_resource_reference(&rctx->index_buffer.buffer, ib->buffer); +		memcpy(&rctx->index_buffer, ib, sizeof(rctx->index_buffer)); +	} else { +		pipe_resource_reference(&rctx->index_buffer.buffer, NULL); +		memset(&rctx->index_buffer, 0, sizeof(rctx->index_buffer)); +	} + +	/* TODO make this more like a state */ +} + +void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count, +			     const struct pipe_vertex_buffer *buffers) +{ +	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; +	struct pipe_vertex_buffer *vbo; +	unsigned max_index = (unsigned)-1; + +	for (int i = 0; i < rctx->nvertex_buffer; i++) { +		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL); +	} +	memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); + +	for (int i = 0; i < count; i++) { +		vbo = (struct pipe_vertex_buffer*)&buffers[i]; + +		rctx->vertex_buffer[i].buffer = NULL; +		if (r600_buffer_is_user_buffer(buffers[i].buffer)) +			rctx->any_user_vbs = TRUE; +		pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); + +		if (vbo->max_index == ~0) { +			if (!vbo->stride) +				vbo->max_index = 1; +			else +				vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; +		} +		max_index = MIN2(vbo->max_index, max_index); +	} +	rctx->nvertex_buffer = count; +	rctx->vb_max_index = max_index; +} + + +#define FORMAT_REPLACE(what, withwhat) \ +	case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break + +void *r600_create_vertex_elements(struct pipe_context *ctx, +				  unsigned count, +				  const struct pipe_vertex_element *elements) +{ +	struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element); +	int i; +	enum pipe_format *format; + +	assert(count < 32); +	if (!v) +		return NULL; + +	v->count = count; +	memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element)); + +	for (i = 0; i < count; i++) { +		v->hw_format[i] = v->elements[i].src_format; +		format = &v->hw_format[i]; + +		switch (*format) { +                    FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT); +                    FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT); +                    FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT); +                    FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT); +		default:; +		} +		v->incompatible_layout = +			v->incompatible_layout || +			v->elements[i].src_format != v->hw_format[i] || +			v->elements[i].src_offset % 4 != 0; + +                v->hw_format_size[i] = +			align(util_format_get_blocksize(v->hw_format[i]), 4); +	} + +	v->refcount = 1; +	return v; +} diff --git a/src/gallium/drivers/r600/r600_translate.c b/src/gallium/drivers/r600/r600_translate.c new file mode 100644 index 0000000000..9a07cf2073 --- /dev/null +++ b/src/gallium/drivers/r600/r600_translate.c @@ -0,0 +1,211 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie <airlied@redhat.com> + */ +#include "translate/translate_cache.h" +#include "translate/translate.h" +#include <pipebuffer/pb_buffer.h> +#include <util/u_index_modify.h> +#include "r600_pipe.h" + +void r600_begin_vertex_translate(struct r600_pipe_context *rctx) +{ +	struct pipe_context *pipe = &rctx->context; +	struct translate_key key = {0}; +	struct translate_element *te; +	unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; +	struct translate *tr; +	struct r600_vertex_element *ve = rctx->vertex_elements; +	boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; +	void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; +	struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; +	struct pipe_resource *out_buffer; +	unsigned i, num_verts; + +	/* Initialize the translate key, i.e. the recipe how vertices should be +	 * translated. */ +	for (i = 0; i < ve->count; i++) { +		struct pipe_vertex_buffer *vb = +			&rctx->vertex_buffer[ve->elements[i].vertex_buffer_index]; +		enum pipe_format output_format = ve->hw_format[i]; +		unsigned output_format_size = ve->hw_format_size[i]; + +		/* Check for support. */ +		if (ve->elements[i].src_format == ve->hw_format[i] && +		    (vb->buffer_offset + ve->elements[i].src_offset) % 4 == 0 && +		    vb->stride % 4 == 0) { +			continue; +		} + +		/* Workaround for translate: output floats instead of halfs. */ +		switch (output_format) { +		case PIPE_FORMAT_R16_FLOAT: +			output_format = PIPE_FORMAT_R32_FLOAT; +			output_format_size = 4; +			break; +		case PIPE_FORMAT_R16G16_FLOAT: +			output_format = PIPE_FORMAT_R32G32_FLOAT; +			output_format_size = 8; +			break; +		case PIPE_FORMAT_R16G16B16_FLOAT: +			output_format = PIPE_FORMAT_R32G32B32_FLOAT; +			output_format_size = 12; +			break; +		case PIPE_FORMAT_R16G16B16A16_FLOAT: +			output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; +			output_format_size = 16; +			break; +		default:; +		} + +		/* Add this vertex element. */ +		te = &key.element[key.nr_elements]; +		/*te->type; +		  te->instance_divisor;*/ +		te->input_buffer = ve->elements[i].vertex_buffer_index; +		te->input_format = ve->elements[i].src_format; +		te->input_offset = vb->buffer_offset + ve->elements[i].src_offset; +		te->output_format = output_format; +		te->output_offset = key.output_stride; + +		key.output_stride += output_format_size; +		vb_translated[ve->elements[i].vertex_buffer_index] = TRUE; +		tr_elem_index[i] = key.nr_elements; +		key.nr_elements++; +	} + +	/* Get a translate object. */ +	tr = translate_cache_find(rctx->tran.translate_cache, &key); + +	/* Map buffers we want to translate. */ +	for (i = 0; i < rctx->nvertex_buffer; i++) { +		if (vb_translated[i]) { +			struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; + +			vb_map[i] = pipe_buffer_map(pipe, vb->buffer, +						    PIPE_TRANSFER_READ, &vb_transfer[i]); + +			tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index); +		} +	} + +	/* Create and map the output buffer. */ +	num_verts = rctx->vb_max_index + 1; + +	out_buffer = pipe_buffer_create(&rctx->screen->screen, +					PIPE_BIND_VERTEX_BUFFER, +					key.output_stride * num_verts); + +	out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, +				  &out_transfer); + +	/* Translate. */ +	tr->run(tr, 0, num_verts, 0, out_map); + +	/* Unmap all buffers. */ +	for (i = 0; i < rctx->nvertex_buffer; i++) { +		if (vb_translated[i]) { +			pipe_buffer_unmap(pipe, rctx->vertex_buffer[i].buffer, +					  vb_transfer[i]); +		} +	} + +	pipe_buffer_unmap(pipe, out_buffer, out_transfer); + +	/* Setup the new vertex buffer in the first free slot. */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; + +		if (!vb->buffer) { +			pipe_resource_reference(&vb->buffer, out_buffer); +			vb->buffer_offset = 0; +			vb->max_index = num_verts - 1; +			vb->stride = key.output_stride; +			rctx->tran.vb_slot = i; +			break; +		} +	} + +	/* Save and replace vertex elements. */ +	{ +		struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + +		rctx->tran.saved_velems = rctx->vertex_elements; + +		for (i = 0; i < ve->count; i++) { +			if (vb_translated[ve->elements[i].vertex_buffer_index]) { +				te = &key.element[tr_elem_index[i]]; +				new_velems[i].instance_divisor = ve->elements[i].instance_divisor; +				new_velems[i].src_format = te->output_format; +				new_velems[i].src_offset = te->output_offset; +				new_velems[i].vertex_buffer_index = rctx->tran.vb_slot; +			} else { +				memcpy(&new_velems[i], &ve->elements[i], +				       sizeof(struct pipe_vertex_element)); +			} +		} + +		rctx->tran.new_velems = +			pipe->create_vertex_elements_state(pipe, ve->count, new_velems); +		pipe->bind_vertex_elements_state(pipe, rctx->tran.new_velems); +	} + +	pipe_resource_reference(&out_buffer, NULL); +} + +void r600_end_vertex_translate(struct r600_pipe_context *rctx) +{ +	struct pipe_context *pipe = &rctx->context; + +	/* Restore vertex elements. */ +	pipe->bind_vertex_elements_state(pipe, rctx->tran.saved_velems); +	pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems); + +	/* Delete the now-unused VBO. */ +	pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, +				NULL); +} + +void r600_translate_index_buffer(struct r600_pipe_context *r600, +					struct pipe_resource **index_buffer, +					unsigned *index_size, +					unsigned *start, unsigned count) +{ +	switch (*index_size) { +	case 1: +		util_shorten_ubyte_elts(&r600->context, index_buffer, 0, *start, count); +		*index_size = 2; +		*start = 0; +		break; + +	case 2: +		if (*start % 2 != 0) { +			util_rebuild_ushort_elts(&r600->context, index_buffer, 0, *start, count); +			*start = 0; +		} +		break; + +	case 4: +		break; +	} +} | 
