849e38d22b6bdb2d4beb5e54007f783053f4d2cb
[mesa.git] / src / gallium / winsys / dri / nouveau / nouveau_winsys_pipe.c
1 #include "pipe/p_winsys.h"
2 #include "pipe/p_defines.h"
3 #include "pipe/p_util.h"
4 #include "pipe/p_inlines.h"
5
6 #include "nouveau_context.h"
7 #include "nouveau_device.h"
8 #include "nouveau_local.h"
9 #include "nouveau_screen.h"
10 #include "nouveau_swapbuffers.h"
11 #include "nouveau_winsys_pipe.h"
12
13 static void
14 nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf,
15 void *context_private)
16 {
17 struct nouveau_context *nv = context_private;
18 __DRIdrawablePrivate *dPriv = nv->dri_drawable;
19
20 nouveau_copy_buffer(dPriv, surf, NULL);
21 }
22
23 static const char *
24 nouveau_get_name(struct pipe_winsys *pws)
25 {
26 return "Nouveau/DRI";
27 }
28
29 static struct pipe_surface *
30 nouveau_surface_alloc(struct pipe_winsys *ws)
31 {
32 struct pipe_surface *surf;
33
34 surf = CALLOC_STRUCT(pipe_surface);
35 if (!surf)
36 return NULL;
37
38 surf->refcount = 1;
39 surf->winsys = ws;
40 return surf;
41 }
42
43 static int
44 nouveau_surface_alloc_storage(struct pipe_winsys *ws, struct pipe_surface *surf,
45 unsigned width, unsigned height,
46 enum pipe_format format, unsigned flags)
47 {
48 unsigned pitch = ((width * pf_get_size(format)) + 63) & ~63;
49
50 surf->format = format;
51 surf->width = width;
52 surf->height = height;
53 surf->cpp = pf_get_size(format);
54 surf->pitch = pitch / surf->cpp;
55
56 surf->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL,
57 pitch * height);
58 if (!surf->buffer)
59 return 1;
60
61 return 0;
62 }
63
64 static void
65 nouveau_surface_release(struct pipe_winsys *ws, struct pipe_surface **s)
66 {
67 struct pipe_surface *surf = *s;
68
69 *s = NULL;
70 if (--surf->refcount <= 0) {
71 if (surf->buffer)
72 pipe_buffer_reference(ws, &surf->buffer, NULL);
73 free(surf);
74 }
75 }
76
77 static struct pipe_buffer *
78 nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
79 unsigned usage, unsigned size)
80 {
81 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
82 struct nouveau_context *nv = nvpws->nv;
83 struct nouveau_device *dev = nv->nv_screen->device;
84 struct nouveau_pipe_buffer *nvbuf;
85 uint32_t flags;
86
87 nvbuf = calloc(1, sizeof(*nvbuf));
88 if (!nvbuf)
89 return NULL;
90 nvbuf->base.refcount = 1;
91 nvbuf->base.alignment = alignment;
92 nvbuf->base.usage = usage;
93 nvbuf->base.size = size;
94
95 flags = NOUVEAU_BO_LOCAL;
96
97 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
98 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
99 flags |= NOUVEAU_BO_GART;
100 flags |= NOUVEAU_BO_VRAM;
101 }
102
103 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
104 if (nv->cap.hw_vertex_buffer)
105 flags |= NOUVEAU_BO_GART;
106 }
107
108 if (usage & PIPE_BUFFER_USAGE_INDEX) {
109 if (nv->cap.hw_index_buffer)
110 flags |= NOUVEAU_BO_GART;
111 }
112
113 if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) {
114 free(nvbuf);
115 return NULL;
116 }
117
118 return &nvbuf->base;
119 }
120
121 static struct pipe_buffer *
122 nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
123 {
124 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
125 struct nouveau_device *dev = nvpws->nv->nv_screen->device;
126 struct nouveau_pipe_buffer *nvbuf;
127
128 nvbuf = calloc(1, sizeof(*nvbuf));
129 if (!nvbuf)
130 return NULL;
131 nvbuf->base.refcount = 1;
132 nvbuf->base.size = bytes;
133
134 if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) {
135 free(nvbuf);
136 return NULL;
137 }
138
139 return &nvbuf->base;
140 }
141
142 static void
143 nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf)
144 {
145 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
146
147 nouveau_bo_del(&nvbuf->bo);
148 free(nvbuf);
149 }
150
151 static void *
152 nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
153 unsigned flags)
154 {
155 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
156 uint32_t map_flags = 0;
157
158 if (flags & PIPE_BUFFER_USAGE_CPU_READ)
159 map_flags |= NOUVEAU_BO_RD;
160 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
161 map_flags |= NOUVEAU_BO_WR;
162
163 if (nouveau_bo_map(nvbuf->bo, map_flags))
164 return NULL;
165 return nvbuf->bo->map;
166 }
167
168 static void
169 nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
170 {
171 struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
172
173 nouveau_bo_unmap(nvbuf->bo);
174 }
175
176 static INLINE struct nouveau_fence *
177 nouveau_pipe_fence(struct pipe_fence_handle *pfence)
178 {
179 return (struct nouveau_fence *)pfence;
180 }
181
182 static void
183 nouveau_pipe_fence_reference(struct pipe_winsys *ws,
184 struct pipe_fence_handle **ptr,
185 struct pipe_fence_handle *pfence)
186 {
187 nouveau_fence_ref((void *)pfence, (void *)ptr);
188 }
189
190 static int
191 nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
192 struct pipe_fence_handle *pfence, unsigned flag)
193 {
194 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)ws;
195 struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
196
197 if (nouveau_fence(fence)->signalled == 0)
198 nouveau_fence_flush(nvpws->nv->nvc->channel);
199
200 return !nouveau_fence(fence)->signalled;
201 }
202
203 static int
204 nouveau_pipe_fence_finish(struct pipe_winsys *ws,
205 struct pipe_fence_handle *pfence, unsigned flag)
206 {
207 struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
208 struct nouveau_fence *ref = NULL;
209
210 nouveau_fence_ref(fence, &ref);
211 return nouveau_fence_wait(&ref);
212 }
213
214 struct pipe_winsys *
215 nouveau_create_pipe_winsys(struct nouveau_context *nv)
216 {
217 struct nouveau_pipe_winsys *nvpws;
218 struct pipe_winsys *pws;
219
220 nvpws = CALLOC_STRUCT(nouveau_pipe_winsys);
221 if (!nvpws)
222 return NULL;
223 nvpws->nv = nv;
224 pws = &nvpws->pws;
225
226 pws->flush_frontbuffer = nouveau_flush_frontbuffer;
227
228 pws->surface_alloc = nouveau_surface_alloc;
229 pws->surface_alloc_storage = nouveau_surface_alloc_storage;
230 pws->surface_release = nouveau_surface_release;
231
232 pws->buffer_create = nouveau_pipe_bo_create;
233 pws->buffer_destroy = nouveau_pipe_bo_del;
234 pws->user_buffer_create = nouveau_pipe_bo_user_create;
235 pws->buffer_map = nouveau_pipe_bo_map;
236 pws->buffer_unmap = nouveau_pipe_bo_unmap;
237
238 pws->fence_reference = nouveau_pipe_fence_reference;
239 pws->fence_signalled = nouveau_pipe_fence_signalled;
240 pws->fence_finish = nouveau_pipe_fence_finish;
241
242 pws->get_name = nouveau_get_name;
243
244 return &nvpws->pws;
245 }
246