683710ee3c36a38381e5cd3f684d6ed2e9fd7195
[mesa.git] / src / gallium / winsys / drm / nouveau / common / nouveau_winsys_pipe.c
1 #include <pipe/p_winsys.h>
2 #include <pipe/p_defines.h>
3 #include <pipe/p_inlines.h>
4 #include <util/u_memory.h>
5 #include "nouveau_context.h"
6 #include "nouveau_local.h"
7 #include "nouveau_screen.h"
8 #include "nouveau_winsys_pipe.h"
9
10 static const char *
11 nouveau_get_name(struct pipe_winsys *pws)
12 {
13 return "Nouveau/DRI";
14 }
15
16 static uint32_t
17 nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage)
18 {
19 struct nouveau_device *dev = nv->nv_screen->device;
20 uint32_t flags = NOUVEAU_BO_LOCAL;
21
22 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
23 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
24 flags |= NOUVEAU_BO_GART;
25 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
26 flags |= NOUVEAU_BO_VRAM;
27
28 switch (dev->chipset & 0xf0) {
29 case 0x50:
30 case 0x80:
31 case 0x90:
32 flags |= NOUVEAU_BO_TILED;
33 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
34 flags |= NOUVEAU_BO_ZTILE;
35 break;
36 default:
37 break;
38 }
39 }
40
41 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
42 if (nv->cap.hw_vertex_buffer)
43 flags |= NOUVEAU_BO_GART;
44 }
45
46 if (usage & PIPE_BUFFER_USAGE_INDEX) {
47 if (nv->cap.hw_index_buffer)
48 flags |= NOUVEAU_BO_GART;
49 }
50
51 return flags;
52 }
53
54 static struct pipe_buffer *
55 nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
56 unsigned usage, unsigned size)
57 {
58 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
59 struct nouveau_context *nv = nvpws->nv;
60 struct nouveau_device *dev = nv->nv_screen->device;
61 struct nouveau_pipe_buffer *nvbuf;
62 uint32_t flags;
63
64 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
65 if (!nvbuf)
66 return NULL;
67 nvbuf->base.refcount = 1;
68 nvbuf->base.alignment = alignment;
69 nvbuf->base.usage = usage;
70 nvbuf->base.size = size;
71
72 flags = nouveau_flags_from_usage(nv, usage);
73
74 if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) {
75 FREE(nvbuf);
76 return NULL;
77 }
78
79 return &nvbuf->base;
80 }
81
82 static struct pipe_buffer *
83 nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
84 {
85 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
86 struct nouveau_device *dev = nvpws->nv->nv_screen->device;
87 struct nouveau_pipe_buffer *nvbuf;
88
89 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
90 if (!nvbuf)
91 return NULL;
92 nvbuf->base.refcount = 1;
93 nvbuf->base.size = bytes;
94
95 if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) {
96 FREE(nvbuf);
97 return NULL;
98 }
99
100 return &nvbuf->base;
101 }
102
103 static void
104 nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf)
105 {
106 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
107
108 nouveau_bo_del(&nvbuf->bo);
109 FREE(nvbuf);
110 }
111
112 static void *
113 nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
114 unsigned flags)
115 {
116 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
117 uint32_t map_flags = 0;
118
119 if (flags & PIPE_BUFFER_USAGE_CPU_READ)
120 map_flags |= NOUVEAU_BO_RD;
121 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
122 map_flags |= NOUVEAU_BO_WR;
123
124 if (nouveau_bo_map(nvbuf->bo, map_flags))
125 return NULL;
126 return nvbuf->bo->map;
127 }
128
129 static void
130 nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
131 {
132 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
133
134 nouveau_bo_unmap(nvbuf->bo);
135 }
136
137 static INLINE struct nouveau_fence *
138 nouveau_pipe_fence(struct pipe_fence_handle *pfence)
139 {
140 return (struct nouveau_fence *)pfence;
141 }
142
143 static void
144 nouveau_pipe_fence_reference(struct pipe_winsys *ws,
145 struct pipe_fence_handle **ptr,
146 struct pipe_fence_handle *pfence)
147 {
148 nouveau_fence_ref((void *)pfence, (void *)ptr);
149 }
150
151 static int
152 nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
153 struct pipe_fence_handle *pfence, unsigned flag)
154 {
155 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)ws;
156 struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
157
158 if (nouveau_fence(fence)->signalled == 0)
159 nouveau_fence_flush(nvpws->nv->nvc->channel);
160
161 return !nouveau_fence(fence)->signalled;
162 }
163
164 static int
165 nouveau_pipe_fence_finish(struct pipe_winsys *ws,
166 struct pipe_fence_handle *pfence, unsigned flag)
167 {
168 struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
169 struct nouveau_fence *ref = NULL;
170
171 nouveau_fence_ref(fence, &ref);
172 return nouveau_fence_wait(&ref);
173 }
174
175 static void
176 nouveau_destroy(struct pipe_winsys *pws)
177 {
178 FREE(pws);
179 }
180
181 struct pipe_winsys *
182 nouveau_create_pipe_winsys(struct nouveau_context *nv)
183 {
184 struct nouveau_pipe_winsys *nvpws;
185 struct pipe_winsys *pws;
186
187 nvpws = CALLOC_STRUCT(nouveau_pipe_winsys);
188 if (!nvpws)
189 return NULL;
190 nvpws->nv = nv;
191 pws = &nvpws->pws;
192
193 pws->flush_frontbuffer = nouveau_flush_frontbuffer;
194
195 pws->buffer_create = nouveau_pipe_bo_create;
196 pws->buffer_destroy = nouveau_pipe_bo_del;
197 pws->user_buffer_create = nouveau_pipe_bo_user_create;
198 pws->buffer_map = nouveau_pipe_bo_map;
199 pws->buffer_unmap = nouveau_pipe_bo_unmap;
200
201 pws->fence_reference = nouveau_pipe_fence_reference;
202 pws->fence_signalled = nouveau_pipe_fence_signalled;
203 pws->fence_finish = nouveau_pipe_fence_finish;
204
205 pws->get_name = nouveau_get_name;
206 pws->destroy = nouveau_destroy;
207
208 return &nvpws->pws;
209 }