r600g: Make some more things static.
[mesa.git] / src / gallium / drivers / r600 / r600_buffer.c
1 /*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
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:
24 * Jerome Glisse
25 * Corbin Simpson <MostAwesomeDude@gmail.com>
26 */
27 #include <pipe/p_screen.h>
28 #include <util/u_format.h>
29 #include <util/u_math.h>
30 #include <util/u_inlines.h>
31 #include <util/u_memory.h>
32 #include "util/u_upload_mgr.h"
33
34 #include "state_tracker/drm_driver.h"
35
36 #include <xf86drm.h>
37 #include "radeon_drm.h"
38
39 #include "r600.h"
40 #include "r600_pipe.h"
41
42 static void r600_buffer_destroy(struct pipe_screen *screen,
43 struct pipe_resource *buf)
44 {
45 struct r600_resource_buffer *rbuffer = r600_buffer(buf);
46
47 if (rbuffer->r.bo) {
48 r600_bo_reference((struct radeon*)screen->winsys, &rbuffer->r.bo, NULL);
49 }
50 rbuffer->r.bo = NULL;
51 FREE(rbuffer);
52 }
53
54 static unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
55 struct pipe_resource *buf,
56 unsigned level, int layer)
57 {
58 /* FIXME */
59 return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
60 }
61
62 static void *r600_buffer_transfer_map(struct pipe_context *pipe,
63 struct pipe_transfer *transfer)
64 {
65 struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource);
66 int write = 0;
67 uint8_t *data;
68
69 if (rbuffer->user_buffer)
70 return (uint8_t*)rbuffer->user_buffer + transfer->box.x;
71
72 if (transfer->usage & PIPE_TRANSFER_DONTBLOCK) {
73 /* FIXME */
74 }
75 if (transfer->usage & PIPE_TRANSFER_WRITE) {
76 write = 1;
77 }
78 data = r600_bo_map((struct radeon*)pipe->winsys, rbuffer->r.bo, transfer->usage, pipe);
79 if (!data)
80 return NULL;
81
82 return (uint8_t*)data + transfer->box.x;
83 }
84
85 static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
86 struct pipe_transfer *transfer)
87 {
88 struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource);
89
90 if (rbuffer->user_buffer)
91 return;
92
93 if (rbuffer->r.bo)
94 r600_bo_unmap((struct radeon*)pipe->winsys, rbuffer->r.bo);
95 }
96
97 static void r600_buffer_transfer_flush_region(struct pipe_context *pipe,
98 struct pipe_transfer *transfer,
99 const struct pipe_box *box)
100 {
101 }
102
103 static const struct u_resource_vtbl r600_buffer_vtbl =
104 {
105 u_default_resource_get_handle, /* get_handle */
106 r600_buffer_destroy, /* resource_destroy */
107 r600_buffer_is_referenced_by_cs, /* is_buffer_referenced */
108 u_default_get_transfer, /* get_transfer */
109 u_default_transfer_destroy, /* transfer_destroy */
110 r600_buffer_transfer_map, /* transfer_map */
111 r600_buffer_transfer_flush_region, /* transfer_flush_region */
112 r600_buffer_transfer_unmap, /* transfer_unmap */
113 u_default_transfer_inline_write /* transfer_inline_write */
114 };
115
116 struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
117 const struct pipe_resource *templ)
118 {
119 struct r600_resource_buffer *rbuffer;
120 struct r600_bo *bo;
121 /* XXX We probably want a different alignment for buffers and textures. */
122 unsigned alignment = 4096;
123
124 rbuffer = CALLOC_STRUCT(r600_resource_buffer);
125 if (rbuffer == NULL)
126 return NULL;
127
128 rbuffer->magic = R600_BUFFER_MAGIC;
129 rbuffer->user_buffer = NULL;
130 rbuffer->r.base.b = *templ;
131 pipe_reference_init(&rbuffer->r.base.b.reference, 1);
132 rbuffer->r.base.b.screen = screen;
133 rbuffer->r.base.vtbl = &r600_buffer_vtbl;
134 rbuffer->r.size = rbuffer->r.base.b.width0;
135 rbuffer->r.bo_size = rbuffer->r.size;
136 bo = r600_bo((struct radeon*)screen->winsys, rbuffer->r.base.b.width0, alignment, rbuffer->r.base.b.bind, rbuffer->r.base.b.usage);
137 if (bo == NULL) {
138 FREE(rbuffer);
139 return NULL;
140 }
141 rbuffer->r.bo = bo;
142 return &rbuffer->r.base.b;
143 }
144
145 struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
146 void *ptr, unsigned bytes,
147 unsigned bind)
148 {
149 struct r600_resource_buffer *rbuffer;
150
151 rbuffer = CALLOC_STRUCT(r600_resource_buffer);
152 if (rbuffer == NULL)
153 return NULL;
154
155 rbuffer->magic = R600_BUFFER_MAGIC;
156 pipe_reference_init(&rbuffer->r.base.b.reference, 1);
157 rbuffer->r.base.vtbl = &r600_buffer_vtbl;
158 rbuffer->r.base.b.screen = screen;
159 rbuffer->r.base.b.target = PIPE_BUFFER;
160 rbuffer->r.base.b.format = PIPE_FORMAT_R8_UNORM;
161 rbuffer->r.base.b.usage = PIPE_USAGE_IMMUTABLE;
162 rbuffer->r.base.b.bind = bind;
163 rbuffer->r.base.b.width0 = bytes;
164 rbuffer->r.base.b.height0 = 1;
165 rbuffer->r.base.b.depth0 = 1;
166 rbuffer->r.base.b.array_size = 1;
167 rbuffer->r.base.b.flags = 0;
168 rbuffer->r.bo = NULL;
169 rbuffer->r.bo_size = 0;
170 rbuffer->user_buffer = ptr;
171 return &rbuffer->r.base.b;
172 }
173
174 struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
175 struct winsys_handle *whandle)
176 {
177 struct radeon *rw = (struct radeon*)screen->winsys;
178 struct r600_resource *rbuffer;
179 struct r600_bo *bo = NULL;
180
181 bo = r600_bo_handle(rw, whandle->handle, NULL);
182 if (bo == NULL) {
183 return NULL;
184 }
185
186 rbuffer = CALLOC_STRUCT(r600_resource);
187 if (rbuffer == NULL) {
188 r600_bo_reference(rw, &bo, NULL);
189 return NULL;
190 }
191
192 pipe_reference_init(&rbuffer->base.b.reference, 1);
193 rbuffer->base.b.target = PIPE_BUFFER;
194 rbuffer->base.b.screen = screen;
195 rbuffer->base.vtbl = &r600_buffer_vtbl;
196 rbuffer->bo = bo;
197 return &rbuffer->base.b;
198 }
199
200 void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw)
201 {
202 struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer);
203 boolean flushed;
204
205 u_upload_data(rctx->upload_vb, 0,
206 draw->info.count * draw->index_size,
207 rbuffer->user_buffer,
208 &draw->index_buffer_offset,
209 &draw->index_buffer, &flushed);
210 }
211
212 void r600_upload_user_buffers(struct r600_pipe_context *rctx,
213 int min_index, int max_index)
214 {
215 int i, nr = rctx->vertex_elements->count;
216 unsigned count = max_index + 1 - min_index;
217 boolean flushed;
218 boolean uploaded[32] = {0};
219
220 for (i = 0; i < nr; i++) {
221 unsigned index = rctx->vertex_elements->elements[i].vertex_buffer_index;
222 struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[index];
223 struct r600_resource_buffer *userbuf = r600_buffer(vb->buffer);
224
225 if (userbuf && userbuf->user_buffer && !uploaded[index]) {
226 unsigned first, size;
227
228 if (vb->stride) {
229 first = vb->stride * min_index;
230 size = vb->stride * count;
231 } else {
232 first = 0;
233 size = rctx->vertex_elements->hw_format_size[i];
234 }
235
236 u_upload_data(rctx->upload_vb, first, size,
237 (uint8_t*)userbuf->user_buffer + first,
238 &vb->buffer_offset,
239 &rctx->real_vertex_buffer[index],
240 &flushed);
241
242 vb->buffer_offset -= first;
243
244 /* vertex_arrays_dirty = TRUE; */
245 uploaded[index] = TRUE;
246 } else {
247 assert(rctx->real_vertex_buffer[index]);
248 }
249 }
250 }
251
252 void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resource_buffer **rbuffer,
253 uint32_t *const_offset)
254 {
255 if ((*rbuffer)->user_buffer) {
256 uint8_t *ptr = (*rbuffer)->user_buffer;
257 unsigned size = (*rbuffer)->r.base.b.width0;
258 boolean flushed;
259
260 *rbuffer = NULL;
261
262 u_upload_data(rctx->upload_const, 0, size, ptr, const_offset,
263 (struct pipe_resource**)rbuffer, &flushed);
264 } else {
265 *const_offset = 0;
266 }
267 }