Merge branch 'draw-instanced'
[mesa.git] / src / gallium / drivers / r300 / r300_render_translate.c
1 /*
2 * Copyright 2010 Marek Olšák <maraeo@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 /**
24 * The functions below translate vertex and index buffers to the layout
25 * compatible with the hardware, so that all vertex and index fetches are
26 * DWORD-aligned and all used vertex and index formats are supported.
27 * For indices, an optional index offset is added to each index.
28 */
29
30 #include "r300_context.h"
31 #include "translate/translate.h"
32 #include "util/u_index_modify.h"
33
34 /* XXX Optimization: use min_index and translate only that range. */
35 /* XXX Use the uploader. */
36 void r300_begin_vertex_translate(struct r300_context *r300,
37 int min_index, int max_index)
38 {
39 struct pipe_context *pipe = &r300->context;
40 struct translate_key key = {0};
41 struct translate_element *te;
42 unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
43 struct translate *tr;
44 struct r300_vertex_element_state *ve = r300->velems;
45 boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
46 void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
47 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
48 struct pipe_resource *out_buffer;
49 unsigned i, num_verts;
50 unsigned slot;
51
52 /* Initialize the translate key, i.e. the recipe how vertices should be
53 * translated. */
54 for (i = 0; i < ve->count; i++) {
55 struct pipe_vertex_buffer *vb =
56 &r300->vertex_buffer[ve->velem[i].vertex_buffer_index];
57 enum pipe_format output_format = ve->hw_format[i];
58 unsigned output_format_size = ve->hw_format_size[i];
59
60 /* Check for support. */
61 if (ve->velem[i].src_format == ve->hw_format[i] &&
62 (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 &&
63 vb->stride % 4 == 0) {
64 continue;
65 }
66
67 /* Workaround for translate: output floats instead of halfs. */
68 switch (output_format) {
69 case PIPE_FORMAT_R16_FLOAT:
70 output_format = PIPE_FORMAT_R32_FLOAT;
71 output_format_size = 4;
72 break;
73 case PIPE_FORMAT_R16G16_FLOAT:
74 output_format = PIPE_FORMAT_R32G32_FLOAT;
75 output_format_size = 8;
76 break;
77 case PIPE_FORMAT_R16G16B16_FLOAT:
78 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
79 output_format_size = 12;
80 break;
81 case PIPE_FORMAT_R16G16B16A16_FLOAT:
82 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
83 output_format_size = 16;
84 break;
85 default:;
86 }
87
88 /* Add this vertex element. */
89 te = &key.element[key.nr_elements];
90 /*te->type;
91 te->instance_divisor;*/
92 te->input_buffer = ve->velem[i].vertex_buffer_index;
93 te->input_format = ve->velem[i].src_format;
94 te->input_offset = vb->buffer_offset + ve->velem[i].src_offset;
95 te->output_format = output_format;
96 te->output_offset = key.output_stride;
97
98 key.output_stride += output_format_size;
99 vb_translated[ve->velem[i].vertex_buffer_index] = TRUE;
100 tr_elem_index[i] = key.nr_elements;
101 key.nr_elements++;
102 }
103
104 /* Get a translate object. */
105 tr = translate_cache_find(r300->tran.translate_cache, &key);
106
107 /* Map buffers we want to translate. */
108 for (i = 0; i < r300->vertex_buffer_count; i++) {
109 if (vb_translated[i]) {
110 struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
111
112 vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
113 PIPE_TRANSFER_READ, &vb_transfer[i]);
114
115 tr->set_buffer(tr, i, vb_map[i], vb->stride, max_index);
116 }
117 }
118
119 /* Create and map the output buffer. */
120 num_verts = max_index + 1;
121
122 out_buffer = pipe_buffer_create(&r300->screen->screen,
123 PIPE_BIND_VERTEX_BUFFER,
124 key.output_stride * num_verts);
125
126 out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
127 &out_transfer);
128
129 /* Translate. */
130 tr->run(tr, 0, num_verts, 0, out_map);
131
132 /* Unmap all buffers. */
133 for (i = 0; i < r300->vertex_buffer_count; i++) {
134 if (vb_translated[i]) {
135 pipe_buffer_unmap(pipe, vb_transfer[i]);
136 }
137 }
138
139 pipe_buffer_unmap(pipe, out_transfer);
140
141 /* Setup the new vertex buffer in the first free slot. */
142 slot = ~0;
143 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
144 struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
145
146 if (!vb->buffer) {
147 pipe_resource_reference(&r300->valid_vertex_buffer[i], out_buffer);
148 vb->buffer_offset = 0;
149 vb->stride = key.output_stride;
150 slot = i;
151 /* XXX probably need to preserve the real count for u_blitter_save_*. */
152 r300->vertex_buffer_count = MAX2(r300->vertex_buffer_count, i+1);
153 r300->validate_buffers = TRUE;
154 break;
155 }
156 }
157 /* XXX This may fail. */
158 assert(slot != ~0);
159
160 /* Save and replace vertex elements. */
161 {
162 struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
163
164 r300->tran.saved_velems = r300->velems;
165
166 for (i = 0; i < ve->count; i++) {
167 if (vb_translated[ve->velem[i].vertex_buffer_index]) {
168 te = &key.element[tr_elem_index[i]];
169 new_velems[i].instance_divisor = ve->velem[i].instance_divisor;
170 new_velems[i].src_format = te->output_format;
171 new_velems[i].src_offset = te->output_offset;
172 new_velems[i].vertex_buffer_index = slot;
173 } else {
174 memcpy(&new_velems[i], &ve->velem[i],
175 sizeof(struct pipe_vertex_element));
176 }
177 }
178
179 r300->tran.new_velems =
180 pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
181 pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems);
182 }
183
184 pipe_resource_reference(&out_buffer, NULL);
185 }
186
187 void r300_end_vertex_translate(struct r300_context *r300)
188 {
189 struct pipe_context *pipe = &r300->context;
190
191 /* Restore vertex elements. */
192 pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems);
193 pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems);
194 }
195
196 /* XXX Use the uploader. */
197 void r300_translate_index_buffer(struct r300_context *r300,
198 struct pipe_resource **index_buffer,
199 unsigned *index_size, unsigned index_offset,
200 unsigned *start, unsigned count)
201 {
202 switch (*index_size) {
203 case 1:
204 util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count);
205 *index_size = 2;
206 *start = 0;
207 r300->validate_buffers = TRUE;
208 break;
209
210 case 2:
211 if (index_offset) {
212 util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count);
213 *start = 0;
214 r300->validate_buffers = TRUE;
215 }
216 break;
217
218 case 4:
219 if (index_offset) {
220 util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count);
221 *start = 0;
222 r300->validate_buffers = TRUE;
223 }
224 break;
225 }
226 }