e3ee985afcd7f69a1c7839c17247493c4202706f
[mesa.git] / src / gallium / winsys / drm / nouveau / common / nouveau_winsys_pipe.c
1 #include "pipe/internal/p_winsys_screen.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 & NOUVEAU_BUFFER_USAGE_TRANSFER)
23 flags |= NOUVEAU_BO_GART;
24
25 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
26 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
27 flags |= NOUVEAU_BO_GART;
28 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
29 flags |= NOUVEAU_BO_VRAM;
30
31 switch (dev->chipset & 0xf0) {
32 case 0x50:
33 case 0x80:
34 case 0x90:
35 flags |= NOUVEAU_BO_TILED;
36 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
37 flags |= NOUVEAU_BO_ZTILE;
38 break;
39 default:
40 break;
41 }
42 }
43
44 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
45 if (nv->cap.hw_vertex_buffer)
46 flags |= NOUVEAU_BO_GART;
47 }
48
49 if (usage & PIPE_BUFFER_USAGE_INDEX) {
50 if (nv->cap.hw_index_buffer)
51 flags |= NOUVEAU_BO_GART;
52 }
53
54 return flags;
55 }
56
57 static struct pipe_buffer *
58 nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
59 unsigned usage, unsigned size)
60 {
61 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
62 struct nouveau_context *nv = nvpws->nv;
63 struct nouveau_device *dev = nv->nv_screen->device;
64 struct nouveau_pipe_buffer *nvbuf;
65 uint32_t flags;
66
67 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
68 if (!nvbuf)
69 return NULL;
70 nvbuf->base.refcount = 1;
71 nvbuf->base.alignment = alignment;
72 nvbuf->base.usage = usage;
73 nvbuf->base.size = size;
74
75 flags = nouveau_flags_from_usage(nv, usage);
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_STRUCT(nouveau_pipe_buffer);
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_pipe_buffer(buf);
110
111 nouveau_bo_ref(NULL, &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_pipe_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 0
128 if (flags & PIPE_BUFFER_USAGE_DISCARD &&
129 !(flags & PIPE_BUFFER_USAGE_CPU_READ) &&
130 nouveau_bo_busy(nvbuf->bo, map_flags)) {
131 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
132 struct nouveau_context *nv = nvpws->nv;
133 struct nouveau_device *dev = nv->nv_screen->device;
134 struct nouveau_bo *rename;
135 uint32_t flags = nouveau_flags_from_usage(nv, buf->usage);
136
137 if (!nouveau_bo_new(dev, flags, buf->alignment, buf->size, &rename)) {
138 nouveau_bo_ref(NULL, &nvbuf->bo);
139 nvbuf->bo = rename;
140 }
141 }
142 #endif
143
144 if (nouveau_bo_map(nvbuf->bo, map_flags))
145 return NULL;
146 return nvbuf->bo->map;
147 }
148
149 static void
150 nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
151 {
152 struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
153
154 nouveau_bo_unmap(nvbuf->bo);
155 }
156
157 static void
158 nouveau_pipe_fence_reference(struct pipe_winsys *ws,
159 struct pipe_fence_handle **ptr,
160 struct pipe_fence_handle *pfence)
161 {
162 *ptr = pfence;
163 }
164
165 static int
166 nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
167 struct pipe_fence_handle *pfence, unsigned flag)
168 {
169 return 0;
170 }
171
172 static int
173 nouveau_pipe_fence_finish(struct pipe_winsys *ws,
174 struct pipe_fence_handle *pfence, unsigned flag)
175 {
176 return 0;
177 }
178
179 struct pipe_surface *
180 nouveau_surface_buffer_ref(struct nouveau_context *nv, struct pipe_buffer *pb,
181 enum pipe_format format, int w, int h,
182 unsigned pitch, struct pipe_texture **ppt)
183 {
184 struct pipe_screen *pscreen = nv->nvc->pscreen;
185 struct pipe_texture tmpl, *pt;
186 struct pipe_surface *ps;
187
188 memset(&tmpl, 0, sizeof(tmpl));
189 tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
190 NOUVEAU_TEXTURE_USAGE_LINEAR;
191 tmpl.target = PIPE_TEXTURE_2D;
192 tmpl.width[0] = w;
193 tmpl.height[0] = h;
194 tmpl.depth[0] = 1;
195 tmpl.format = format;
196 pf_get_block(tmpl.format, &tmpl.block);
197 tmpl.nblocksx[0] = pf_get_nblocksx(&tmpl.block, w);
198 tmpl.nblocksy[0] = pf_get_nblocksy(&tmpl.block, h);
199
200 pt = pscreen->texture_blanket(pscreen, &tmpl, &pitch, pb);
201 if (!pt)
202 return NULL;
203
204 ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0,
205 PIPE_BUFFER_USAGE_GPU_WRITE);
206
207 *ppt = pt;
208 return ps;
209 }
210
211 static void
212 nouveau_destroy(struct pipe_winsys *pws)
213 {
214 FREE(pws);
215 }
216
217 struct pipe_winsys *
218 nouveau_create_pipe_winsys(struct nouveau_context *nv)
219 {
220 struct nouveau_pipe_winsys *nvpws;
221 struct pipe_winsys *pws;
222
223 nvpws = CALLOC_STRUCT(nouveau_pipe_winsys);
224 if (!nvpws)
225 return NULL;
226 nvpws->nv = nv;
227 pws = &nvpws->pws;
228
229 pws->flush_frontbuffer = nouveau_flush_frontbuffer;
230
231 pws->buffer_create = nouveau_pipe_bo_create;
232 pws->buffer_destroy = nouveau_pipe_bo_del;
233 pws->user_buffer_create = nouveau_pipe_bo_user_create;
234 pws->buffer_map = nouveau_pipe_bo_map;
235 pws->buffer_unmap = nouveau_pipe_bo_unmap;
236
237 pws->fence_reference = nouveau_pipe_fence_reference;
238 pws->fence_signalled = nouveau_pipe_fence_signalled;
239 pws->fence_finish = nouveau_pipe_fence_finish;
240
241 pws->get_name = nouveau_get_name;
242 pws->destroy = nouveau_destroy;
243
244 return &nvpws->pws;
245 }