Squashed commit of the following:
[profile/ivi/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_reference(struct r300_winsys_screen *rws,
102                                                 struct r300_winsys_buffer **pdst,
103                                                 struct r300_winsys_buffer *src)
104 {
105     struct pb_buffer *_src = radeon_pb_buffer(src);
106     struct pb_buffer *_dst = radeon_pb_buffer(*pdst);
107
108     pb_reference(&_dst, _src);
109
110     *pdst = radeon_libdrm_winsys_buffer(_dst);
111 }
112
113 static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws,
114                                                        struct r300_winsys_buffer *buf)
115 {
116     struct pb_buffer *_buf = radeon_pb_buffer(buf);
117
118     return radeon_drm_bufmgr_is_buffer_referenced(_buf);
119 }
120
121 static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
122                                                                         struct pipe_screen *screen,
123                                                                         struct winsys_handle *whandle,
124                                                                         unsigned *stride)
125 {
126     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
127     struct pb_buffer *_buf;
128
129     _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
130     *stride = whandle->stride;
131     return radeon_libdrm_winsys_buffer(_buf);
132 }
133
134 static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
135                                                     struct r300_winsys_buffer *buffer,
136                                                     unsigned stride,
137                                                     struct winsys_handle *whandle)
138 {
139     struct pb_buffer *_buf = radeon_pb_buffer(buffer);
140     boolean ret;
141     ret = radeon_drm_bufmgr_get_handle(_buf, whandle);
142     if (ret)
143         whandle->stride = stride;
144     return ret;
145 }
146
147 static void radeon_set_flush_cb(struct r300_winsys_screen *rws,
148                                 void (*flush_cb)(void *),
149                                 void *data)
150 {
151     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
152     ws->flush_cb = flush_cb;
153     ws->flush_data = data;
154     radeon_cs_space_set_flush(ws->cs, flush_cb, data);
155 }
156
157 static boolean radeon_add_buffer(struct r300_winsys_screen *rws,
158                                  struct r300_winsys_buffer *buf,
159                                  uint32_t rd,
160                                  uint32_t wd)
161 {
162     struct pb_buffer *_buf = radeon_pb_buffer(buf);
163
164     return radeon_drm_bufmgr_add_buffer(_buf, rd, wd);
165 }
166
167 static boolean radeon_validate(struct r300_winsys_screen *rws)
168 {
169     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
170     if (radeon_cs_space_check(ws->cs) < 0) {
171         return FALSE;
172     }
173
174     /* Things are fine, we can proceed as normal. */
175     return TRUE;
176 }
177
178 static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size)
179 {
180     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
181     struct radeon_cs *cs = ws->cs;
182
183     return radeon_validate(rws) && cs->cdw + size <= cs->ndw;
184 }
185
186 static void radeon_begin_cs(struct r300_winsys_screen *rws,
187                             int size,
188                             const char* file,
189                             const char* function,
190                             int line)
191 {
192     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
193     radeon_cs_begin(ws->cs, size, file, function, line);
194 }
195
196 static void radeon_write_cs_dword(struct r300_winsys_screen *rws,
197                                   uint32_t dword)
198 {
199     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
200     radeon_cs_write_dword(ws->cs, dword);
201 }
202
203 static void radeon_write_cs_reloc(struct r300_winsys_screen *rws,
204                                   struct r300_winsys_buffer *buf,
205                                   uint32_t rd,
206                                   uint32_t wd,
207                                   uint32_t flags)
208 {
209     struct pb_buffer *_buf = radeon_pb_buffer(buf);
210     radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags);
211 }
212
213 static void radeon_reset_bos(struct r300_winsys_screen *rws)
214 {
215     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
216     radeon_cs_space_reset_bos(ws->cs);
217 }
218
219 static void radeon_end_cs(struct r300_winsys_screen *rws,
220                           const char* file,
221                           const char* function,
222                           int line)
223 {
224     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
225     radeon_cs_end(ws->cs, file, function, line);
226 }
227
228 static void radeon_flush_cs(struct r300_winsys_screen *rws)
229 {
230     struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
231     int retval;
232
233     /* Don't flush a zero-sized CS. */
234     if (!ws->cs->cdw) {
235         return;
236     }
237
238     radeon_drm_bufmgr_flush_maps(ws->kman);
239     /* Emit the CS. */
240     retval = radeon_cs_emit(ws->cs);
241     if (retval) {
242         debug_printf("radeon: Bad CS, dumping...\n");
243         radeon_cs_print(ws->cs, stderr);
244     }
245
246     /* Reset CS.
247      * Someday, when we care about performance, we should really find a way
248      * to rotate between two or three CS objects so that the GPU can be
249      * spinning through one CS while another one is being filled. */
250     radeon_cs_erase(ws->cs);
251 }
252
253 static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
254                              enum r300_value_id id)
255 {
256     struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
257
258     switch(id) {
259     case R300_VID_PCI_ID:
260         return ws->pci_id;
261     case R300_VID_GB_PIPES:
262         return ws->gb_pipes;
263     case R300_VID_Z_PIPES:
264         return ws->z_pipes;
265     case R300_VID_SQUARE_TILING_SUPPORT:
266         return ws->squaretiling;
267     }
268     return 0;
269 }
270
271 static void
272 radeon_winsys_destroy(struct r300_winsys_screen *rws)
273 {
274     struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
275     radeon_cs_destroy(ws->cs);
276
277     ws->cman->destroy(ws->cman);
278     ws->kman->destroy(ws->kman);
279     ws->mman->destroy(ws->mman);
280
281     radeon_bo_manager_gem_dtor(ws->bom);
282     radeon_cs_manager_gem_dtor(ws->csm);
283 }
284
285 boolean
286 radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
287 {
288     
289     ws->csm = radeon_cs_manager_gem_ctor(fd);
290     if (!ws->csm)
291         goto fail;
292     ws->bom = radeon_bo_manager_gem_ctor(fd);
293     if (!ws->bom)
294         goto fail;
295     ws->kman = radeon_drm_bufmgr_create(ws);
296     if (!ws->kman)
297         goto fail;
298
299     ws->cman = pb_cache_manager_create(ws->kman, 100000);
300     if (!ws->cman)
301         goto fail;
302
303     ws->mman = pb_malloc_bufmgr_create();
304     if (!ws->mman)
305         goto fail;
306
307     /* Size limit on IBs is 64 kibibytes. */
308     ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
309     if (!ws->cs)
310         goto fail;
311     radeon_cs_set_limit(ws->cs,
312             RADEON_GEM_DOMAIN_GTT, ws->gart_size);
313     radeon_cs_set_limit(ws->cs,
314             RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
315
316     ws->base.add_buffer = radeon_add_buffer;
317     ws->base.validate = radeon_validate;
318     ws->base.destroy = radeon_winsys_destroy;
319     ws->base.check_cs = radeon_check_cs;
320     ws->base.begin_cs = radeon_begin_cs;
321     ws->base.write_cs_dword = radeon_write_cs_dword;
322     ws->base.write_cs_reloc = radeon_write_cs_reloc;
323     ws->base.end_cs = radeon_end_cs;
324     ws->base.flush_cs = radeon_flush_cs;
325     ws->base.reset_bos = radeon_reset_bos;
326     ws->base.set_flush_cb = radeon_set_flush_cb;
327     ws->base.get_value = radeon_get_value;
328
329     ws->base.buffer_create = radeon_r300_winsys_buffer_create;
330     ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy;
331     ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling;
332     ws->base.buffer_get_tiling = radeon_r300_winsys_buffer_get_tiling;
333     ws->base.buffer_map = radeon_r300_winsys_buffer_map;
334     ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
335     ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
336     ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
337     ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
338     ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced;
339     return TRUE;
340
341 fail:
342     if (ws->csm)
343         radeon_cs_manager_gem_dtor(ws->csm);
344
345     if (ws->bom)
346         radeon_bo_manager_gem_dtor(ws->bom);
347
348     if (ws->cman)
349         ws->cman->destroy(ws->cman);
350     if (ws->kman)
351         ws->kman->destroy(ws->kman);
352     if (ws->mman)
353         ws->mman->destroy(ws->mman);
354
355     if (ws->cs)
356         radeon_cs_destroy(ws->cs);
357     return FALSE;
358 }