Merge branch 'mesa_7_5_branch'
[mesa.git] / src / gallium / drivers / nouveau / nouveau_screen.c
1 #include <pipe/p_defines.h>
2 #include <pipe/p_screen.h>
3 #include <pipe/p_state.h>
4
5 #include <util/u_memory.h>
6
7 #include "nouveau/nouveau_bo.h"
8 #include "nouveau_winsys.h"
9 #include "nouveau_screen.h"
10
11 static const char *
12 nouveau_screen_get_name(struct pipe_screen *pscreen)
13 {
14 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
15 static char buffer[128];
16
17 snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
18 return buffer;
19 }
20
21 static const char *
22 nouveau_screen_get_vendor(struct pipe_screen *pscreen)
23 {
24 return "nouveau";
25 }
26
27 static struct pipe_buffer *
28 nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo,
29 unsigned alignment, unsigned usage, unsigned size)
30 {
31 struct pipe_buffer *pb;
32
33 pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *));
34 if (!pb) {
35 nouveau_bo_ref(NULL, &bo);
36 return NULL;
37 }
38
39 pipe_reference_init(&pb->reference, 1);
40 pb->screen = pscreen;
41 pb->alignment = alignment;
42 pb->usage = usage;
43 pb->size = size;
44 *(struct nouveau_bo **)(pb + 1) = bo;
45 return pb;
46 }
47
48 static struct pipe_buffer *
49 nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
50 unsigned usage, unsigned size)
51 {
52 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
53 struct nouveau_bo *bo = NULL;
54 uint32_t flags = NOUVEAU_BO_MAP;
55 int ret;
56
57 if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER)
58 flags |= NOUVEAU_BO_GART;
59 else
60 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
61 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
62 flags |= NOUVEAU_BO_GART;
63 } else
64 if (usage & PIPE_BUFFER_USAGE_INDEX) {
65 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
66 flags |= NOUVEAU_BO_GART;
67 }
68
69 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
70 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
71 flags |= NOUVEAU_BO_GART;
72 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
73 flags |= NOUVEAU_BO_VRAM;
74
75 if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
76 flags |= NOUVEAU_BO_TILED;
77 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
78 flags |= NOUVEAU_BO_ZTILE;
79 }
80 }
81
82 ret = nouveau_bo_new(dev, flags, alignment, size, &bo);
83 if (ret)
84 return NULL;
85
86 return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size);
87 }
88
89 static struct pipe_buffer *
90 nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes)
91 {
92 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
93 struct nouveau_bo *bo = NULL;
94 int ret;
95
96 ret = nouveau_bo_user(dev, ptr, bytes, &bo);
97 if (ret)
98 return NULL;
99
100 return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes);
101 }
102
103 static inline uint32_t
104 nouveau_screen_map_flags(unsigned pipe)
105 {
106 uint32_t flags = 0;
107
108 if (pipe & PIPE_BUFFER_USAGE_CPU_READ)
109 flags |= NOUVEAU_BO_RD;
110 if (pipe & PIPE_BUFFER_USAGE_CPU_WRITE)
111 flags |= NOUVEAU_BO_WR;
112 if (pipe & PIPE_BUFFER_USAGE_DISCARD)
113 flags |= NOUVEAU_BO_INVAL;
114 if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK)
115 flags |= NOUVEAU_BO_NOWAIT;
116 else
117 if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/)
118 flags |= NOUVEAU_BO_NOSYNC;
119
120 return flags;
121 }
122
123 static void *
124 nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
125 unsigned usage)
126 {
127 struct nouveau_bo *bo = nouveau_bo(pb);
128 int ret;
129
130 ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
131 if (ret) {
132 debug_printf("map failed: %d\n", ret);
133 return NULL;
134 }
135
136 return bo->map;
137 }
138
139 static void *
140 nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb,
141 unsigned offset, unsigned length, unsigned usage)
142 {
143 struct nouveau_bo *bo = nouveau_bo(pb);
144 int ret;
145
146 ret = nouveau_bo_map_range(bo, offset, length,
147 nouveau_screen_map_flags(usage));
148 if (ret) {
149 debug_printf("map_range failed: %d\n", ret);
150 return NULL;
151 }
152
153 return (char *)bo->map - offset; /* why gallium? why? */
154 }
155
156 static void
157 nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb,
158 unsigned offset, unsigned length)
159 {
160 struct nouveau_bo *bo = nouveau_bo(pb);
161
162 nouveau_bo_map_flush(bo, offset, length);
163 }
164
165 static void
166 nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb)
167 {
168 struct nouveau_bo *bo = nouveau_bo(pb);
169
170 nouveau_bo_unmap(bo);
171 }
172
173 static void
174 nouveau_screen_bo_del(struct pipe_buffer *pb)
175 {
176 struct nouveau_bo *bo = nouveau_bo(pb);
177
178 nouveau_bo_ref(NULL, &bo);
179 FREE(pb);
180 }
181
182 static void
183 nouveau_screen_fence_ref(struct pipe_screen *pscreen,
184 struct pipe_fence_handle **ptr,
185 struct pipe_fence_handle *pfence)
186 {
187 *ptr = pfence;
188 }
189
190 static int
191 nouveau_screen_fence_signalled(struct pipe_screen *screen,
192 struct pipe_fence_handle *pfence,
193 unsigned flags)
194 {
195 return 0;
196 }
197
198 static int
199 nouveau_screen_fence_finish(struct pipe_screen *screen,
200 struct pipe_fence_handle *pfence,
201 unsigned flags)
202 {
203 return 0;
204 }
205
206 int
207 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
208 {
209 struct pipe_screen *pscreen = &screen->base;
210 int ret;
211
212 ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
213 &screen->channel);
214 if (ret)
215 return ret;
216 screen->device = dev;
217
218 pscreen->get_name = nouveau_screen_get_name;
219 pscreen->get_vendor = nouveau_screen_get_vendor;
220
221 pscreen->buffer_create = nouveau_screen_bo_new;
222 pscreen->user_buffer_create = nouveau_screen_bo_user;
223 pscreen->buffer_map = nouveau_screen_bo_map;
224 pscreen->buffer_map_range = nouveau_screen_bo_map_range;
225 pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush;
226 pscreen->buffer_unmap = nouveau_screen_bo_unmap;
227 pscreen->buffer_destroy = nouveau_screen_bo_del;
228
229 pscreen->fence_reference = nouveau_screen_fence_ref;
230 pscreen->fence_signalled = nouveau_screen_fence_signalled;
231 pscreen->fence_finish = nouveau_screen_fence_finish;
232
233 return 0;
234 }
235
236 void
237 nouveau_screen_fini(struct nouveau_screen *screen)
238 {
239 }
240