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