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