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