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