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