b03582aac329052e4c8d96b1f5eab3fa917b0429
[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 buffers to the layout compatible
25 * with the hardware, so that all vertex fetches are be DWORD-aligned and all
26 * used vertex formats are supported.
27 */
28
29 #include "r300_context.h"
30 #include "translate/translate.h"
31
32 void r300_begin_vertex_translate(struct r300_context *r300)
33 {
34 struct pipe_context *pipe = &r300->context;
35 struct translate_key key = {0};
36 struct translate_element *te;
37 unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
38 struct translate *tr;
39 struct r300_vertex_element_state *ve = r300->velems;
40 boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
41 void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
42 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
43 struct pipe_resource *out_buffer;
44 unsigned i, num_verts;
45
46 /* Initialize the translate key, i.e. the recipe how vertices should be
47 * translated. */
48 for (i = 0; i < ve->count; i++) {
49 struct pipe_vertex_buffer *vb =
50 &r300->vertex_buffer[ve->velem[i].vertex_buffer_index];
51
52 /* Check for support. */
53 if (ve->velem[i].src_format == ve->hw_format[i] &&
54 (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 &&
55 vb->stride % 4 == 0) {
56 continue;
57 }
58
59 /* Add this vertex element. */
60 te = &key.element[key.nr_elements];
61 /*te->type;
62 te->instance_divisor;*/
63 te->input_buffer = ve->velem[i].vertex_buffer_index;
64 te->input_format = ve->velem[i].src_format;
65 te->input_offset = vb->buffer_offset + ve->velem[i].src_offset;
66 te->output_format = ve->hw_format[i];
67 te->output_offset = key.output_stride;
68
69 key.output_stride += ve->hw_format_size[i];
70 vb_translated[ve->velem[i].vertex_buffer_index] = TRUE;
71 tr_elem_index[i] = key.nr_elements;
72 key.nr_elements++;
73 }
74
75 /* Get a translate object. */
76 tr = translate_cache_find(r300->tran.translate_cache, &key);
77
78 /* Map buffers we want to translate. */
79 for (i = 0; i < r300->vertex_buffer_count; i++) {
80 if (vb_translated[i]) {
81 struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
82
83 vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
84 PIPE_TRANSFER_READ, &vb_transfer[i]);
85
86 tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index);
87 }
88 }
89
90 /* Create and map the output buffer. */
91 num_verts = r300->vertex_buffer_max_index + 1;
92
93 out_buffer = pipe_buffer_create(&r300->screen->screen,
94 PIPE_BIND_VERTEX_BUFFER,
95 key.output_stride * num_verts);
96
97 out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
98 &out_transfer);
99
100 /* Translate. */
101 tr->run(tr, 0, num_verts, 0, out_map);
102
103 /* Unmap all buffers. */
104 for (i = 0; i < r300->vertex_buffer_count; i++) {
105 if (vb_translated[i]) {
106 pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
107 vb_transfer[i]);
108 }
109 }
110
111 pipe_buffer_unmap(pipe, out_buffer, out_transfer);
112
113 /* Setup the new vertex buffer in the first free slot. */
114 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
115 struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
116
117 if (!vb->buffer) {
118 pipe_resource_reference(&vb->buffer, out_buffer);
119 vb->buffer_offset = 0;
120 vb->max_index = num_verts - 1;
121 vb->stride = key.output_stride;
122 r300->tran.vb_slot = i;
123 break;
124 }
125 }
126
127 /* Save and replace vertex elements. */
128 {
129 struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
130
131 r300->tran.saved_velems = r300->velems;
132
133 for (i = 0; i < ve->count; i++) {
134 if (vb_translated[ve->velem[i].vertex_buffer_index]) {
135 te = &key.element[tr_elem_index[i]];
136 new_velems[i].instance_divisor = ve->velem[i].instance_divisor;
137 new_velems[i].src_format = te->output_format;
138 new_velems[i].src_offset = te->output_offset;
139 new_velems[i].vertex_buffer_index = r300->tran.vb_slot;
140 } else {
141 memcpy(&new_velems[i], &ve->velem[i],
142 sizeof(struct pipe_vertex_element));
143 }
144 }
145
146 r300->tran.new_velems =
147 pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
148 pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems);
149 }
150
151 pipe_resource_reference(&out_buffer, NULL);
152 }
153
154 void r300_end_vertex_translate(struct r300_context *r300)
155 {
156 struct pipe_context *pipe = &r300->context;
157
158 /* Restore vertex elements. */
159 pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems);
160 pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems);
161
162 /* Delete the now-unused VBO. */
163 pipe_resource_reference(&r300->vertex_buffer[r300->tran.vb_slot].buffer,
164 NULL);
165 }