Merge remote branch 'main/master' into radeon-rewrite
[mesa.git] / src / gallium / winsys / drm / nouveau / drm / 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
6 #include "nouveau_winsys_pipe.h"
7
8 #include "nouveau_drmif.h"
9 #include "nouveau_bo.h"
10
11 static const char *
12 nouveau_get_name(struct pipe_winsys *pws)
13 {
14 return "Nouveau/DRI";
15 }
16
17 static uint32_t
18 nouveau_flags_from_usage(struct pipe_winsys *ws, unsigned usage)
19 {
20 struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws);
21 struct pipe_screen *pscreen = nvpws->pscreen;
22 uint32_t flags = NOUVEAU_BO_LOCAL;
23
24 if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER)
25 flags |= NOUVEAU_BO_GART;
26
27 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
28 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
29 flags |= NOUVEAU_BO_GART;
30 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
31 flags |= NOUVEAU_BO_VRAM;
32
33 switch (nvpws->channel->device->chipset & 0xf0) {
34 case 0x50:
35 case 0x80:
36 case 0x90:
37 flags |= NOUVEAU_BO_TILED;
38 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
39 flags |= NOUVEAU_BO_ZTILE;
40 break;
41 default:
42 break;
43 }
44 }
45
46 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
47 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
48 flags |= NOUVEAU_BO_GART;
49 }
50
51 if (usage & PIPE_BUFFER_USAGE_INDEX) {
52 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
53 flags |= NOUVEAU_BO_GART;
54 }
55
56 return flags;
57 }
58
59 static struct pipe_buffer *
60 nouveau_pipe_bo_create(struct pipe_winsys *ws, unsigned alignment,
61 unsigned usage, unsigned size)
62 {
63 struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws);
64 struct nouveau_device *dev = nvpws->channel->device;
65 struct nouveau_pipe_buffer *nvbuf;
66 uint32_t flags;
67
68 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
69 if (!nvbuf)
70 return NULL;
71 pipe_reference_init(&nvbuf->base.reference, 1);
72 nvbuf->base.alignment = alignment;
73 nvbuf->base.usage = usage;
74 nvbuf->base.size = size;
75
76 flags = nouveau_flags_from_usage(ws, usage);
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 *ws, void *ptr, unsigned bytes)
87 {
88 struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws);
89 struct nouveau_device *dev = nvpws->channel->device;
90 struct nouveau_pipe_buffer *nvbuf;
91
92 nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer);
93 if (!nvbuf)
94 return NULL;
95 pipe_reference_init(&nvbuf->base.reference, 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_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 (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_pipe_buffer(buf);
136
137 nouveau_bo_unmap(nvbuf->bo);
138 }
139
140 static void
141 nouveau_pipe_fence_reference(struct pipe_winsys *ws,
142 struct pipe_fence_handle **ptr,
143 struct pipe_fence_handle *pfence)
144 {
145 *ptr = pfence;
146 }
147
148 static int
149 nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
150 struct pipe_fence_handle *pfence, unsigned flag)
151 {
152 return 0;
153 }
154
155 static int
156 nouveau_pipe_fence_finish(struct pipe_winsys *ws,
157 struct pipe_fence_handle *pfence, unsigned flag)
158 {
159 return 0;
160 }
161
162 static void
163 nouveau_destroy(struct pipe_winsys *ws)
164 {
165 struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws);
166
167 nouveau_device_close(&nvpws->channel->device);
168 FREE(nvpws);
169 }
170
171 struct pipe_winsys *
172 nouveau_pipe_winsys_new(struct nouveau_device *dev)
173 {
174 struct nouveau_pipe_winsys *nvpws;
175 int ret;
176
177 nvpws = CALLOC_STRUCT(nouveau_pipe_winsys);
178 if (!nvpws)
179 return NULL;
180
181 ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
182 &nvpws->channel);
183 if (ret) {
184 debug_printf("%s: error opening GPU channel: %d\n",
185 __func__, ret);
186 FREE(nvpws);
187 return NULL;
188 }
189 nvpws->next_handle = 0x77000000;
190
191 nvpws->base.buffer_create = nouveau_pipe_bo_create;
192 nvpws->base.buffer_destroy = nouveau_pipe_bo_del;
193 nvpws->base.user_buffer_create = nouveau_pipe_bo_user_create;
194 nvpws->base.buffer_map = nouveau_pipe_bo_map;
195 nvpws->base.buffer_unmap = nouveau_pipe_bo_unmap;
196
197 nvpws->base.fence_reference = nouveau_pipe_fence_reference;
198 nvpws->base.fence_signalled = nouveau_pipe_fence_signalled;
199 nvpws->base.fence_finish = nouveau_pipe_fence_finish;
200
201 nvpws->base.get_name = nouveau_get_name;
202 nvpws->base.destroy = nouveau_destroy;
203 return &nvpws->base;
204 }