Merge commit 'origin/graw-tests'
[mesa.git] / src / gallium / winsys / radeon / drm / radeon_r300.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@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 #include "radeon_r300.h"
24 #include "radeon_buffer.h"
25
26 #include "radeon_bo_gem.h"
27 #include "radeon_cs_gem.h"
28 #include "state_tracker/drm_api.h"
29
30 static struct r300_winsys_buffer *
31 radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
32 unsigned alignment,
33 unsigned usage,
34 unsigned size)
35 {
36 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
37 struct pb_desc desc;
38 struct pb_manager *provider;
39 struct pb_buffer *buffer;
40
41 memset(&desc, 0, sizeof(desc));
42 desc.alignment = alignment;
43 desc.usage = usage;
44
45 if (usage & PIPE_BIND_CONSTANT_BUFFER)
46 provider = ws->mman;
47 else if ((usage & PIPE_BIND_VERTEX_BUFFER) ||
48 (usage & PIPE_BIND_INDEX_BUFFER))
49 provider = ws->cman;
50 else
51 provider = ws->kman;
52 buffer = provider->create_buffer(provider, size, &desc);
53 if (!buffer)
54 return NULL;
55
56 return radeon_libdrm_winsys_buffer(buffer);
57 }
58
59 static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf)
60 {
61 struct pb_buffer *_buf = radeon_pb_buffer(buf);
62
63 pb_destroy(_buf);
64 }
65 static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws,
66 struct r300_winsys_buffer *buf,
67 uint32_t pitch,
68 enum r300_buffer_tiling microtiled,
69 enum r300_buffer_tiling macrotiled)
70 {
71 struct pb_buffer *_buf = radeon_pb_buffer(buf);
72 radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch);
73 }
74
75 static void radeon_r300_winsys_buffer_get_tiling(struct r300_winsys_screen *rws,
76 struct r300_winsys_buffer *buf,
77 enum r300_buffer_tiling *microtiled,
78 enum r300_buffer_tiling *macrotiled)
79 {
80 struct pb_buffer *_buf = radeon_pb_buffer(buf);
81 radeon_drm_bufmgr_get_tiling(_buf, microtiled, macrotiled);
82 }
83
84 static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws,
85 struct r300_winsys_buffer *buf,
86 unsigned usage)
87 {
88 struct pb_buffer *_buf = radeon_pb_buffer(buf);
89
90 return pb_map(_buf, usage);
91 }
92
93 static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws,
94 struct r300_winsys_buffer *buf)
95 {
96 struct pb_buffer *_buf = radeon_pb_buffer(buf);
97
98 pb_unmap(_buf);
99 }
100
101 static void radeon_r300_winsys_buffer_wait(struct r300_winsys_screen *ws,
102 struct r300_winsys_buffer *buf)
103 {
104 struct pb_buffer *_buf = radeon_pb_buffer(buf);
105 radeon_drm_bufmgr_wait(_buf);
106 }
107
108 static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
109 struct r300_winsys_buffer **pdst,
110 struct r300_winsys_buffer *src)
111 {
112 struct pb_buffer *_src = radeon_pb_buffer(src);
113 struct pb_buffer *_dst = radeon_pb_buffer(*pdst);
114
115 pb_reference(&_dst, _src);
116
117 *pdst = radeon_libdrm_winsys_buffer(_dst);
118 }
119
120 static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws,
121 struct r300_winsys_buffer *buf,
122 enum r300_reference_domain domain)
123 {
124 struct pb_buffer *_buf = radeon_pb_buffer(buf);
125
126 return radeon_drm_bufmgr_is_buffer_referenced(_buf, domain);
127 }
128
129 static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
130 struct pipe_screen *screen,
131 struct winsys_handle *whandle,
132 unsigned *stride)
133 {
134 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
135 struct pb_buffer *_buf;
136
137 _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
138 *stride = whandle->stride;
139 return radeon_libdrm_winsys_buffer(_buf);
140 }
141
142 static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
143 struct r300_winsys_buffer *buffer,
144 unsigned stride,
145 struct winsys_handle *whandle)
146 {
147 struct pb_buffer *_buf = radeon_pb_buffer(buffer);
148 boolean ret;
149 ret = radeon_drm_bufmgr_get_handle(_buf, whandle);
150 if (ret)
151 whandle->stride = stride;
152 return ret;
153 }
154
155 static void radeon_set_flush_cb(struct r300_winsys_screen *rws,
156 void (*flush_cb)(void *),
157 void *data)
158 {
159 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
160 ws->flush_cb = flush_cb;
161 ws->flush_data = data;
162 radeon_cs_space_set_flush(ws->cs, flush_cb, data);
163 }
164
165 static boolean radeon_add_buffer(struct r300_winsys_screen *rws,
166 struct r300_winsys_buffer *buf,
167 uint32_t rd,
168 uint32_t wd)
169 {
170 struct pb_buffer *_buf = radeon_pb_buffer(buf);
171
172 return radeon_drm_bufmgr_add_buffer(_buf, rd, wd);
173 }
174
175 static boolean radeon_validate(struct r300_winsys_screen *rws)
176 {
177 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
178 if (radeon_cs_space_check(ws->cs) < 0) {
179 return FALSE;
180 }
181
182 /* Things are fine, we can proceed as normal. */
183 return TRUE;
184 }
185
186 static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size)
187 {
188 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
189 struct radeon_cs *cs = ws->cs;
190
191 return cs->cdw + size <= cs->ndw;
192 }
193
194 static void radeon_begin_cs(struct r300_winsys_screen *rws,
195 int size,
196 const char* file,
197 const char* function,
198 int line)
199 {
200 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
201 radeon_cs_begin(ws->cs, size, file, function, line);
202 }
203
204 static void radeon_write_cs_dword(struct r300_winsys_screen *rws,
205 uint32_t dword)
206 {
207 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
208 radeon_cs_write_dword(ws->cs, dword);
209 }
210
211 static void radeon_write_cs_table(struct r300_winsys_screen *rws,
212 const void *table, unsigned count)
213 {
214 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
215 radeon_cs_write_table(ws->cs, table, count);
216 }
217
218 static void radeon_write_cs_reloc(struct r300_winsys_screen *rws,
219 struct r300_winsys_buffer *buf,
220 uint32_t rd,
221 uint32_t wd,
222 uint32_t flags)
223 {
224 struct pb_buffer *_buf = radeon_pb_buffer(buf);
225 radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags);
226 }
227
228 static void radeon_reset_bos(struct r300_winsys_screen *rws)
229 {
230 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
231 radeon_cs_space_reset_bos(ws->cs);
232 }
233
234 static void radeon_end_cs(struct r300_winsys_screen *rws,
235 const char* file,
236 const char* function,
237 int line)
238 {
239 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
240 radeon_cs_end(ws->cs, file, function, line);
241 }
242
243 static void radeon_flush_cs(struct r300_winsys_screen *rws)
244 {
245 struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
246 int retval;
247
248 /* Don't flush a zero-sized CS. */
249 if (!ws->cs->cdw) {
250 return;
251 }
252
253 radeon_drm_bufmgr_flush_maps(ws->kman);
254 /* Emit the CS. */
255 retval = radeon_cs_emit(ws->cs);
256 if (retval) {
257 debug_printf("radeon: Bad CS, dumping...\n");
258 radeon_cs_print(ws->cs, stderr);
259 }
260
261 /* Reset CS.
262 * Someday, when we care about performance, we should really find a way
263 * to rotate between two or three CS objects so that the GPU can be
264 * spinning through one CS while another one is being filled. */
265 radeon_cs_erase(ws->cs);
266 }
267
268 static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
269 enum r300_value_id id)
270 {
271 struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
272
273 switch(id) {
274 case R300_VID_PCI_ID:
275 return ws->pci_id;
276 case R300_VID_GB_PIPES:
277 return ws->gb_pipes;
278 case R300_VID_Z_PIPES:
279 return ws->z_pipes;
280 case R300_VID_SQUARE_TILING_SUPPORT:
281 return ws->squaretiling;
282 case R300_VID_DRM_2_3_0:
283 return ws->drm_2_3_0;
284 }
285 return 0;
286 }
287
288 static void
289 radeon_winsys_destroy(struct r300_winsys_screen *rws)
290 {
291 struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
292 radeon_cs_destroy(ws->cs);
293
294 ws->cman->destroy(ws->cman);
295 ws->kman->destroy(ws->kman);
296 ws->mman->destroy(ws->mman);
297
298 radeon_bo_manager_gem_dtor(ws->bom);
299 radeon_cs_manager_gem_dtor(ws->csm);
300 }
301
302 boolean
303 radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
304 {
305
306 ws->csm = radeon_cs_manager_gem_ctor(fd);
307 if (!ws->csm)
308 goto fail;
309 ws->bom = radeon_bo_manager_gem_ctor(fd);
310 if (!ws->bom)
311 goto fail;
312 ws->kman = radeon_drm_bufmgr_create(ws);
313 if (!ws->kman)
314 goto fail;
315
316 ws->cman = pb_cache_manager_create(ws->kman, 100000);
317 if (!ws->cman)
318 goto fail;
319
320 ws->mman = pb_malloc_bufmgr_create();
321 if (!ws->mman)
322 goto fail;
323
324 /* Size limit on IBs is 64 kibibytes. */
325 ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
326 if (!ws->cs)
327 goto fail;
328 radeon_cs_set_limit(ws->cs,
329 RADEON_GEM_DOMAIN_GTT, ws->gart_size);
330 radeon_cs_set_limit(ws->cs,
331 RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
332
333 ws->base.add_buffer = radeon_add_buffer;
334 ws->base.validate = radeon_validate;
335 ws->base.destroy = radeon_winsys_destroy;
336 ws->base.check_cs = radeon_check_cs;
337 ws->base.begin_cs = radeon_begin_cs;
338 ws->base.write_cs_dword = radeon_write_cs_dword;
339 ws->base.write_cs_table = radeon_write_cs_table;
340 ws->base.write_cs_reloc = radeon_write_cs_reloc;
341 ws->base.end_cs = radeon_end_cs;
342 ws->base.flush_cs = radeon_flush_cs;
343 ws->base.reset_bos = radeon_reset_bos;
344 ws->base.set_flush_cb = radeon_set_flush_cb;
345 ws->base.get_value = radeon_get_value;
346
347 ws->base.buffer_create = radeon_r300_winsys_buffer_create;
348 ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy;
349 ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling;
350 ws->base.buffer_get_tiling = radeon_r300_winsys_buffer_get_tiling;
351 ws->base.buffer_map = radeon_r300_winsys_buffer_map;
352 ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
353 ws->base.buffer_wait = radeon_r300_winsys_buffer_wait;
354 ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
355 ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
356 ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
357 ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced;
358 return TRUE;
359
360 fail:
361 if (ws->csm)
362 radeon_cs_manager_gem_dtor(ws->csm);
363
364 if (ws->bom)
365 radeon_bo_manager_gem_dtor(ws->bom);
366
367 if (ws->cman)
368 ws->cman->destroy(ws->cman);
369 if (ws->kman)
370 ws->kman->destroy(ws->kman);
371 if (ws->mman)
372 ws->mman->destroy(ws->mman);
373
374 if (ws->cs)
375 radeon_cs_destroy(ws->cs);
376 return FALSE;
377 }