2
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
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:
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
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. */
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.
30
#include "r300_context.h"
31
#include "translate/translate.h"
33
void r300_begin_vertex_translate(struct r300_context *r300)
35
struct pipe_context *pipe = &r300->context;
36
struct translate_key key = {0};
37
struct translate_element *te;
38
unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
40
struct r300_vertex_element_state *ve = r300->velems;
41
boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
42
void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
43
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
44
struct pipe_resource *out_buffer;
45
unsigned i, num_verts;
47
/* Initialize the translate key, i.e. the recipe how vertices should be
49
for (i = 0; i < ve->count; i++) {
50
struct pipe_vertex_buffer *vb =
51
&r300->vertex_buffer[ve->velem[i].vertex_buffer_index];
52
enum pipe_format output_format = ve->hw_format[i];
53
unsigned output_format_size = ve->hw_format_size[i];
55
/* Check for support. */
56
if (ve->velem[i].src_format == ve->hw_format[i] &&
57
(vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 &&
58
vb->stride % 4 == 0) {
62
/* Workaround for translate: output floats instead of halfs. */
63
switch (output_format) {
64
case PIPE_FORMAT_R16_FLOAT:
65
output_format = PIPE_FORMAT_R32_FLOAT;
66
output_format_size = 4;
68
case PIPE_FORMAT_R16G16_FLOAT:
69
output_format = PIPE_FORMAT_R32G32_FLOAT;
70
output_format_size = 8;
72
case PIPE_FORMAT_R16G16B16_FLOAT:
73
output_format = PIPE_FORMAT_R32G32B32_FLOAT;
74
output_format_size = 12;
76
case PIPE_FORMAT_R16G16B16A16_FLOAT:
77
output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
78
output_format_size = 16;
83
/* Add this vertex element. */
84
te = &key.element[key.nr_elements];
86
te->instance_divisor;*/
87
te->input_buffer = ve->velem[i].vertex_buffer_index;
88
te->input_format = ve->velem[i].src_format;
89
te->input_offset = vb->buffer_offset + ve->velem[i].src_offset;
90
te->output_format = output_format;
91
te->output_offset = key.output_stride;
93
key.output_stride += output_format_size;
94
vb_translated[ve->velem[i].vertex_buffer_index] = TRUE;
95
tr_elem_index[i] = key.nr_elements;
99
/* Get a translate object. */
100
tr = translate_cache_find(r300->tran.translate_cache, &key);
102
/* Map buffers we want to translate. */
103
for (i = 0; i < r300->vertex_buffer_count; i++) {
104
if (vb_translated[i]) {
105
struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
107
vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
108
PIPE_TRANSFER_READ, &vb_transfer[i]);
110
tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index);
114
/* Create and map the output buffer. */
115
num_verts = r300->vertex_buffer_max_index + 1;
117
out_buffer = pipe_buffer_create(&r300->screen->screen,
118
PIPE_BIND_VERTEX_BUFFER,
119
key.output_stride * num_verts);
121
out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
125
tr->run(tr, 0, num_verts, 0, out_map);
127
/* Unmap all buffers. */
128
for (i = 0; i < r300->vertex_buffer_count; i++) {
129
if (vb_translated[i]) {
130
pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
135
pipe_buffer_unmap(pipe, out_buffer, out_transfer);
137
/* Setup the new vertex buffer in the first free slot. */
138
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
139
struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
142
pipe_resource_reference(&vb->buffer, out_buffer);
143
vb->buffer_offset = 0;
144
vb->max_index = num_verts - 1;
145
vb->stride = key.output_stride;
146
r300->tran.vb_slot = i;
151
/* Save and replace vertex elements. */
153
struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
155
r300->tran.saved_velems = r300->velems;
157
for (i = 0; i < ve->count; i++) {
158
if (vb_translated[ve->velem[i].vertex_buffer_index]) {
159
te = &key.element[tr_elem_index[i]];
160
new_velems[i].instance_divisor = ve->velem[i].instance_divisor;
161
new_velems[i].src_format = te->output_format;
162
new_velems[i].src_offset = te->output_offset;
163
new_velems[i].vertex_buffer_index = r300->tran.vb_slot;
165
memcpy(&new_velems[i], &ve->velem[i],
166
sizeof(struct pipe_vertex_element));
170
r300->tran.new_velems =
171
pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
172
pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems);
175
pipe_resource_reference(&out_buffer, NULL);
178
void r300_end_vertex_translate(struct r300_context *r300)
180
struct pipe_context *pipe = &r300->context;
182
/* Restore vertex elements. */
183
pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems);
184
pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems);
186
/* Delete the now-unused VBO. */
187
pipe_resource_reference(&r300->vertex_buffer[r300->tran.vb_slot].buffer,
191
static void r300_shorten_ubyte_elts(struct r300_context* r300,
192
struct pipe_resource** elts,
197
struct pipe_context* context = &r300->context;
198
struct pipe_screen* screen = r300->context.screen;
199
struct pipe_resource* new_elts;
200
unsigned char *in_map;
201
unsigned short *out_map;
202
struct pipe_transfer *src_transfer, *dst_transfer;
205
new_elts = pipe_buffer_create(screen,
206
PIPE_BIND_INDEX_BUFFER,
209
in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
210
out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
214
for (i = 0; i < count; i++) {
215
*out_map = (unsigned short)(*in_map + index_bias);
220
pipe_buffer_unmap(context, *elts, src_transfer);
221
pipe_buffer_unmap(context, new_elts, dst_transfer);
226
static void r300_rebuild_ushort_elts(struct r300_context *r300,
227
struct pipe_resource **elts,
229
unsigned start, unsigned count)
231
struct pipe_context *context = &r300->context;
232
struct pipe_transfer *in_transfer = NULL;
233
struct pipe_transfer *out_transfer = NULL;
234
struct pipe_resource *new_elts;
235
unsigned short *in_map;
236
unsigned short *out_map;
239
new_elts = pipe_buffer_create(context->screen,
240
PIPE_BIND_INDEX_BUFFER,
243
in_map = pipe_buffer_map(context, *elts,
244
PIPE_TRANSFER_READ, &in_transfer);
245
out_map = pipe_buffer_map(context, new_elts,
246
PIPE_TRANSFER_WRITE, &out_transfer);
249
for (i = 0; i < count; i++) {
250
*out_map = (unsigned short)(*in_map + index_bias);
255
pipe_buffer_unmap(context, *elts, in_transfer);
256
pipe_buffer_unmap(context, new_elts, out_transfer);
261
static void r300_rebuild_uint_elts(struct r300_context *r300,
262
struct pipe_resource **elts,
264
unsigned start, unsigned count)
266
struct pipe_context *context = &r300->context;
267
struct pipe_transfer *in_transfer = NULL;
268
struct pipe_transfer *out_transfer = NULL;
269
struct pipe_resource *new_elts;
270
unsigned int *in_map;
271
unsigned int *out_map;
274
new_elts = pipe_buffer_create(context->screen,
275
PIPE_BIND_INDEX_BUFFER,
278
in_map = pipe_buffer_map(context, *elts,
279
PIPE_TRANSFER_READ, &in_transfer);
280
out_map = pipe_buffer_map(context, new_elts,
281
PIPE_TRANSFER_WRITE, &out_transfer);
284
for (i = 0; i < count; i++) {
285
*out_map = (unsigned int)(*in_map + index_bias);
290
pipe_buffer_unmap(context, *elts, in_transfer);
291
pipe_buffer_unmap(context, new_elts, out_transfer);
296
void r300_translate_index_buffer(struct r300_context *r300,
297
struct pipe_resource **index_buffer,
298
unsigned *index_size, unsigned index_offset,
299
unsigned *start, unsigned count)
301
switch (*index_size) {
303
r300_shorten_ubyte_elts(r300, index_buffer, index_offset, *start, count);
309
if (*start % 2 != 0 || index_offset) {
310
r300_rebuild_ushort_elts(r300, index_buffer, index_offset, *start, count);
317
r300_rebuild_uint_elts(r300, index_buffer, index_offset, *start, count);