Merge commit 'origin/gallium-master-merge'
[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 & PIPE_BUFFER_USAGE_PIXEL) {
23 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
24 flags |= NOUVEAU_BO_GART;
25 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
26 flags |= NOUVEAU_BO_VRAM;
27
28 switch (dev->chipset & 0xf0) {
29 case 0x50:
30 case 0x80:
31 case 0x90:
32 flags |= NOUVEAU_BO_TILED;
33 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
34 flags |= NOUVEAU_BO_ZTILE;
35 break;
36 default:
37 break;
38 }
39 }
40
41 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
42 if (nv->cap.hw_vertex_buffer)
43 flags |= NOUVEAU_BO_GART;
44 }
45
46 if (usage & PIPE_BUFFER_USAGE_INDEX) {
47 if (nv->cap.hw_index_buffer)
48 flags |= NOUVEAU_BO_GART;
49 }
50
51 return flags;
52 }
53
54 static struct pipe_buffer *
55 nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
56 unsigned usage, unsigned size)
57 {
58 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
59 struct nouveau_context *nv = nvpws->nv;
60 struct nouveau_device *dev = nv->nv_screen->device;
61 struct nouveau_pipe_buffer *nvbuf;
62 uint32_t flags;
63
64 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
65 if (!nvbuf)
66 return NULL;
67 nvbuf->base.refcount = 1;
68 nvbuf->base.alignment = alignment;
69 nvbuf->base.usage = usage;
70 nvbuf->base.size = size;
71
72 flags = nouveau_flags_from_usage(nv, usage);
73
74 if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) {
75 FREE(nvbuf);
76 return NULL;
77 }
78
79 return &nvbuf->base;
80 }
81
82 static struct pipe_buffer *
83 nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
84 {
85 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
86 struct nouveau_device *dev = nvpws->nv->nv_screen->device;
87 struct nouveau_pipe_buffer *nvbuf;
88
89 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
90 if (!nvbuf)
91 return NULL;
92 nvbuf->base.refcount = 1;
93 nvbuf->base.size = bytes;
94
95 if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) {
96 FREE(nvbuf);
97 return NULL;
98 }
99
100 return &nvbuf->base;
101 }
102
103 static void
104 nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf)
105 {
106 struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
107
108 nouveau_bo_ref(NULL, &nvbuf->bo);
109 FREE(nvbuf);
110 }
111
112 static void *
113 nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
114 unsigned flags)
115 {
116 struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
117 uint32_t map_flags = 0;
118
119 if (flags & PIPE_BUFFER_USAGE_CPU_READ)
120 map_flags |= NOUVEAU_BO_RD;
121 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
122 map_flags |= NOUVEAU_BO_WR;
123
124 #if 0
125 if (flags & PIPE_BUFFER_USAGE_DISCARD &&
126 !(flags & PIPE_BUFFER_USAGE_CPU_READ) &&
127 nouveau_bo_busy(nvbuf->bo, map_flags)) {
128 struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
129 struct nouveau_context *nv = nvpws->nv;
130 struct nouveau_device *dev = nv->nv_screen->device;
131 struct nouveau_bo *rename;
132 uint32_t flags = nouveau_flags_from_usage(nv, buf->usage);
133
134 if (!nouveau_bo_new(dev, flags, buf->alignment, buf->size, &rename)) {
135 nouveau_bo_ref(NULL, &nvbuf->bo);
136 nvbuf->bo = rename;
137 }
138 }
139 #endif
140
141 if (nouveau_bo_map(nvbuf->bo, map_flags))
142 return NULL;
143 return nvbuf->bo->map;
144 }
145
146 static void
147 nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
148 {
149 struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
150
151 nouveau_bo_unmap(nvbuf->bo);
152 }
153
154 static void
155 nouveau_pipe_fence_reference(struct pipe_winsys *ws,
156 struct pipe_fence_handle **ptr,
157 struct pipe_fence_handle *pfence)
158 {
159 *ptr = pfence;
160 }
161
162 static int
163 nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
164 struct pipe_fence_handle *pfence, unsigned flag)
165 {
166 return 0;
167 }
168
169 static int
170 nouveau_pipe_fence_finish(struct pipe_winsys *ws,
171 struct pipe_fence_handle *pfence, unsigned flag)
172 {
173 return 0;
174 }
175
176 struct pipe_surface *
177 nouveau_surface_buffer_ref(struct nouveau_context *nv, struct pipe_buffer *pb,
178 enum pipe_format format, int w, int h,
179 unsigned pitch, struct pipe_texture **ppt)
180 {
181 struct pipe_screen *pscreen = nv->nvc->pscreen;
182 struct pipe_texture tmpl, *pt;
183 struct pipe_surface *ps;
184
185 memset(&tmpl, 0, sizeof(tmpl));
186 tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
187 NOUVEAU_TEXTURE_USAGE_LINEAR;
188 tmpl.target = PIPE_TEXTURE_2D;
189 tmpl.width[0] = w;
190 tmpl.height[0] = h;
191 tmpl.depth[0] = 1;
192 tmpl.format = format;
193 pf_get_block(tmpl.format, &tmpl.block);
194 tmpl.nblocksx[0] = pf_get_nblocksx(&tmpl.block, w);
195 tmpl.nblocksy[0] = pf_get_nblocksy(&tmpl.block, h);
196
197 pt = pscreen->texture_blanket(pscreen, &tmpl, &pitch, pb);
198 if (!pt)
199 return NULL;
200
201 ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0,
202 PIPE_BUFFER_USAGE_GPU_WRITE);
203
204 *ppt = pt;
205 return ps;
206 }
207
208 static void
209 nouveau_destroy(struct pipe_winsys *pws)
210 {
211 FREE(pws);
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->buffer_create = nouveau_pipe_bo_create;
229 pws->buffer_destroy = nouveau_pipe_bo_del;
230 pws->user_buffer_create = nouveau_pipe_bo_user_create;
231 pws->buffer_map = nouveau_pipe_bo_map;
232 pws->buffer_unmap = nouveau_pipe_bo_unmap;
233
234 pws->fence_reference = nouveau_pipe_fence_reference;
235 pws->fence_signalled = nouveau_pipe_fence_signalled;
236 pws->fence_finish = nouveau_pipe_fence_finish;
237
238 pws->get_name = nouveau_get_name;
239 pws->destroy = nouveau_destroy;
240
241 return &nvpws->pws;
242 }