r600g: only set depth bit for hw accessible depth buffers.
[mesa.git] / src / gallium / drivers / r600 / r600_translate.c
1 /*
2 * Copyright 2010 Red Hat Inc.
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 * Authors: Dave Airlie <airlied@redhat.com>
24 */
25
26 #include "translate/translate_cache.h"
27 #include "translate/translate.h"
28 #include <pipebuffer/pb_buffer.h>
29 #include <util/u_index_modify.h>
30 #include "util/u_upload_mgr.h"
31 #include "r600_pipe.h"
32
33 void r600_begin_vertex_translate(struct r600_pipe_context *rctx,
34 int min_index, int max_index)
35 {
36 struct pipe_context *pipe = &rctx->context;
37 struct translate_key key = {0};
38 struct translate_element *te;
39 unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
40 struct translate *tr;
41 struct r600_vertex_element *ve = rctx->vertex_elements;
42 boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
43 uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
44 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
45 struct pipe_resource *out_buffer = NULL;
46 unsigned i, num_verts, out_offset;
47 struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
48 boolean flushed;
49
50 /* Initialize the translate key, i.e. the recipe how vertices should be
51 * translated. */
52 for (i = 0; i < ve->count; i++) {
53 enum pipe_format output_format = ve->hw_format[i];
54 unsigned output_format_size = ve->hw_format_size[i];
55
56 /* Check for support. */
57 if (ve->elements[i].src_format == ve->hw_format[i]) {
58 continue;
59 }
60
61 /* Workaround for translate: output floats instead of halfs. */
62 switch (output_format) {
63 case PIPE_FORMAT_R16_FLOAT:
64 output_format = PIPE_FORMAT_R32_FLOAT;
65 output_format_size = 4;
66 break;
67 case PIPE_FORMAT_R16G16_FLOAT:
68 output_format = PIPE_FORMAT_R32G32_FLOAT;
69 output_format_size = 8;
70 break;
71 case PIPE_FORMAT_R16G16B16_FLOAT:
72 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
73 output_format_size = 12;
74 break;
75 case PIPE_FORMAT_R16G16B16A16_FLOAT:
76 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
77 output_format_size = 16;
78 break;
79 default:;
80 }
81
82 /* Add this vertex element. */
83 te = &key.element[key.nr_elements];
84 /*te->type;
85 te->instance_divisor;*/
86 te->input_buffer = ve->elements[i].vertex_buffer_index;
87 te->input_format = ve->elements[i].src_format;
88 te->input_offset = ve->elements[i].src_offset;
89 te->output_format = output_format;
90 te->output_offset = key.output_stride;
91
92 key.output_stride += output_format_size;
93 vb_translated[ve->elements[i].vertex_buffer_index] = TRUE;
94 tr_elem_index[i] = key.nr_elements;
95 key.nr_elements++;
96 }
97
98 /* Get a translate object. */
99 tr = translate_cache_find(rctx->tran.translate_cache, &key);
100
101 /* Map buffers we want to translate. */
102 for (i = 0; i < rctx->nvertex_buffers; i++) {
103 if (vb_translated[i]) {
104 struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i];
105
106 vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
107 PIPE_TRANSFER_READ, &vb_transfer[i]);
108
109 tr->set_buffer(tr, i,
110 vb_map[i] + vb->buffer_offset + vb->stride * min_index,
111 vb->stride, ~0);
112 }
113 }
114
115 /* Create and map the output buffer. */
116 num_verts = max_index + 1 - min_index;
117
118 u_upload_alloc(rctx->upload_vb,
119 key.output_stride * min_index,
120 key.output_stride * num_verts,
121 &out_offset, &out_buffer, &flushed,
122 (void**)&out_map);
123
124 out_offset -= key.output_stride * min_index;
125
126 /* Translate. */
127 tr->run(tr, 0, num_verts, 0, out_map);
128
129 /* Unmap all buffers. */
130 for (i = 0; i < rctx->nvertex_buffers; i++) {
131 if (vb_translated[i]) {
132 pipe_buffer_unmap(pipe, vb_transfer[i]);
133 }
134 }
135
136 /* Find the first free slot. */
137 rctx->tran.vb_slot = ~0;
138 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
139 if (!rctx->vertex_buffer[i].buffer) {
140 rctx->tran.vb_slot = i;
141
142 if (i >= rctx->nvertex_buffers) {
143 rctx->nreal_vertex_buffers = i+1;
144 }
145 break;
146 }
147 }
148
149 if (rctx->tran.vb_slot != ~0) {
150 /* Setup the new vertex buffer. */
151 pipe_resource_reference(&rctx->real_vertex_buffer[rctx->tran.vb_slot], out_buffer);
152 rctx->vertex_buffer[rctx->tran.vb_slot].buffer_offset = out_offset;
153 rctx->vertex_buffer[rctx->tran.vb_slot].stride = key.output_stride;
154
155 /* Setup new vertex elements. */
156 for (i = 0; i < ve->count; i++) {
157 if (vb_translated[ve->elements[i].vertex_buffer_index]) {
158 te = &key.element[tr_elem_index[i]];
159 new_velems[i].instance_divisor = ve->elements[i].instance_divisor;
160 new_velems[i].src_format = te->output_format;
161 new_velems[i].src_offset = te->output_offset;
162 new_velems[i].vertex_buffer_index = rctx->tran.vb_slot;
163 } else {
164 memcpy(&new_velems[i], &ve->elements[i],
165 sizeof(struct pipe_vertex_element));
166 }
167 }
168
169 rctx->tran.saved_velems = rctx->vertex_elements;
170 rctx->tran.new_velems =
171 pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
172 pipe->bind_vertex_elements_state(pipe, rctx->tran.new_velems);
173 }
174
175 pipe_resource_reference(&out_buffer, NULL);
176 }
177
178 void r600_end_vertex_translate(struct r600_pipe_context *rctx)
179 {
180 struct pipe_context *pipe = &rctx->context;
181
182 if (rctx->tran.new_velems == NULL) {
183 return;
184 }
185
186 /* Restore vertex elements. */
187 pipe->bind_vertex_elements_state(pipe, rctx->tran.saved_velems);
188 rctx->tran.saved_velems = NULL;
189 pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems);
190 rctx->tran.new_velems = NULL;
191
192 /* Delete the now-unused VBO. */
193 pipe_resource_reference(&rctx->real_vertex_buffer[rctx->tran.vb_slot], NULL);
194 rctx->nreal_vertex_buffers = rctx->nvertex_buffers;
195 }
196
197 void r600_translate_index_buffer(struct r600_pipe_context *r600,
198 struct pipe_resource **index_buffer,
199 unsigned *index_size,
200 unsigned *start, unsigned count)
201 {
202 struct pipe_resource *out_buffer = NULL;
203 unsigned out_offset;
204 void *ptr;
205 boolean flushed;
206
207 switch (*index_size) {
208 case 1:
209 u_upload_alloc(r600->upload_vb, 0, count * 2,
210 &out_offset, &out_buffer, &flushed, &ptr);
211
212 util_shorten_ubyte_elts_to_userptr(
213 &r600->context, *index_buffer, 0, *start, count, ptr);
214
215 pipe_resource_reference(index_buffer, out_buffer);
216 *index_size = 2;
217 *start = out_offset / 2;
218 break;
219 }
220 }