radeong: Clean up domain usages.
[mesa.git] / src / gallium / winsys / drm / radeon / core / radeon_buffer.c
1 /*
2 * Copyright © 2008 Jérôme Glisse
3 * 2009 Corbin Simpson
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
18 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * The above copyright notice and this permission notice (including the
24 * next paragraph) shall be included in all copies or substantial portions
25 * of the Software.
26 */
27 /*
28 * Authors:
29 * Jérôme Glisse <glisse@freedesktop.org>
30 * Corbin Simpson <MostAwesomeDude@gmail.com>
31 */
32
33 #include "radeon_buffer.h"
34
35 #include "radeon_bo_gem.h"
36 #include "softpipe/sp_texture.h"
37 #include "r300_context.h"
38 #include "util/u_format.h"
39 #include "util/u_math.h"
40 #include <X11/Xutil.h>
41
42 struct radeon_vl_context
43 {
44 Display *display;
45 int screen;
46 Drawable drawable;
47 };
48
49 static const char *radeon_get_name(struct pipe_winsys *ws)
50 {
51 return "Radeon/GEM+KMS";
52 }
53
54 static uint32_t radeon_domain_from_usage(unsigned usage)
55 {
56 uint32_t domain = 0;
57
58 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
59 domain |= RADEON_GEM_DOMAIN_VRAM;
60 }
61 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
62 domain |= RADEON_GEM_DOMAIN_GTT;
63 }
64 if (usage & PIPE_BUFFER_USAGE_INDEX) {
65 domain |= RADEON_GEM_DOMAIN_GTT;
66 }
67
68 return domain;
69 }
70
71 static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws,
72 unsigned alignment,
73 unsigned usage,
74 unsigned size)
75 {
76 struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws;
77 struct radeon_pipe_buffer *radeon_buffer;
78 struct pb_desc desc;
79 uint32_t domain;
80
81 radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
82 if (radeon_buffer == NULL) {
83 return NULL;
84 }
85
86 pipe_reference_init(&radeon_buffer->base.reference, 1);
87 radeon_buffer->base.alignment = alignment;
88 radeon_buffer->base.usage = usage;
89 radeon_buffer->base.size = size;
90
91 if (usage == PIPE_BUFFER_USAGE_CONSTANT && is_r3xx(radeon_ws->pci_id)) {
92 /* Don't bother allocating a BO, as it'll never get to the card. */
93 desc.alignment = alignment;
94 desc.usage = usage;
95 radeon_buffer->pb = pb_malloc_buffer_create(size, &desc);
96 return &radeon_buffer->base;
97 }
98
99 domain = radeon_domain_from_usage(usage);
100
101 radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size,
102 alignment, domain, 0);
103 if (radeon_buffer->bo == NULL) {
104 FREE(radeon_buffer);
105 return NULL;
106 }
107 return &radeon_buffer->base;
108 }
109
110 static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws,
111 void *ptr,
112 unsigned bytes)
113 {
114 struct radeon_pipe_buffer *radeon_buffer;
115
116 radeon_buffer =
117 (struct radeon_pipe_buffer*)radeon_buffer_create(ws, 0, 0, bytes);
118 if (radeon_buffer == NULL) {
119 return NULL;
120 }
121 radeon_bo_map(radeon_buffer->bo, 1);
122 memcpy(radeon_buffer->bo->ptr, ptr, bytes);
123 radeon_bo_unmap(radeon_buffer->bo);
124 return &radeon_buffer->base;
125 }
126
127 static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws,
128 unsigned width,
129 unsigned height,
130 enum pipe_format format,
131 unsigned usage,
132 unsigned tex_usage,
133 unsigned *stride)
134 {
135 /* Radeons enjoy things in multiples of 32. */
136 /* XXX this can be 32 when POT */
137 const unsigned alignment = 64;
138 unsigned nblocksy, size;
139
140 nblocksy = util_format_get_nblocksy(format, height);
141 *stride = align(util_format_get_stride(format, width), alignment);
142 size = *stride * nblocksy;
143
144 return radeon_buffer_create(ws, 64, usage, size);
145 }
146
147 static void radeon_buffer_del(struct pipe_buffer *buffer)
148 {
149 struct radeon_pipe_buffer *radeon_buffer =
150 (struct radeon_pipe_buffer*)buffer;
151
152 if (radeon_buffer->pb) {
153 pipe_reference_init(&radeon_buffer->pb->base.reference, 0);
154 pb_destroy(radeon_buffer->pb);
155 }
156
157 if (radeon_buffer->bo) {
158 radeon_bo_unref(radeon_buffer->bo);
159 }
160
161 FREE(radeon_buffer);
162 }
163
164 static void *radeon_buffer_map(struct pipe_winsys *ws,
165 struct pipe_buffer *buffer,
166 unsigned flags)
167 {
168 struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv;
169 struct radeon_pipe_buffer *radeon_buffer =
170 (struct radeon_pipe_buffer*)buffer;
171 int write = 0;
172
173 if (radeon_buffer->pb) {
174 return pb_map(radeon_buffer->pb, flags);
175 }
176
177 if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
178 uint32_t domain;
179
180 if (radeon_bo_is_busy(radeon_buffer->bo, &domain))
181 return NULL;
182 }
183
184 if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
185 priv->flush_cb(priv->flush_data);
186 }
187
188 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
189 write = 1;
190 }
191
192 if (radeon_bo_map(radeon_buffer->bo, write)) {
193 return NULL;
194 }
195
196 return radeon_buffer->bo->ptr;
197 }
198
199 static void radeon_buffer_unmap(struct pipe_winsys *ws,
200 struct pipe_buffer *buffer)
201 {
202 struct radeon_pipe_buffer *radeon_buffer =
203 (struct radeon_pipe_buffer*)buffer;
204
205 if (radeon_buffer->pb) {
206 pb_unmap(radeon_buffer->pb);
207 } else {
208 radeon_bo_unmap(radeon_buffer->bo);
209 }
210 }
211
212 static void radeon_buffer_set_tiling(struct radeon_winsys *ws,
213 struct pipe_buffer *buffer,
214 uint32_t pitch,
215 boolean microtiled,
216 boolean macrotiled)
217 {
218 struct radeon_pipe_buffer *radeon_buffer =
219 (struct radeon_pipe_buffer*)buffer;
220 uint32_t flags = 0;
221
222 if (microtiled) {
223 flags |= RADEON_BO_FLAGS_MICRO_TILE;
224 }
225 if (macrotiled) {
226 flags |= RADEON_BO_FLAGS_MACRO_TILE;
227 }
228
229 radeon_bo_set_tiling(radeon_buffer->bo, flags, pitch);
230 }
231
232 static void radeon_fence_reference(struct pipe_winsys *ws,
233 struct pipe_fence_handle **ptr,
234 struct pipe_fence_handle *pfence)
235 {
236 }
237
238 static int radeon_fence_signalled(struct pipe_winsys *ws,
239 struct pipe_fence_handle *pfence,
240 unsigned flag)
241 {
242 return 1;
243 }
244
245 static int radeon_fence_finish(struct pipe_winsys *ws,
246 struct pipe_fence_handle *pfence,
247 unsigned flag)
248 {
249 return 0;
250 }
251
252 static void radeon_display_surface(struct pipe_winsys *pws,
253 struct pipe_surface *psurf,
254 struct radeon_vl_context *rvl_ctx)
255 {
256 struct r300_texture *r300tex = (struct r300_texture *)(psurf->texture);
257 XImage *ximage;
258 void *data;
259
260 ximage = XCreateImage(rvl_ctx->display,
261 XDefaultVisual(rvl_ctx->display, rvl_ctx->screen),
262 XDefaultDepth(rvl_ctx->display, rvl_ctx->screen),
263 ZPixmap, 0, /* format, offset */
264 NULL, /* data */
265 0, 0, /* size */
266 32, /* bitmap_pad */
267 0); /* bytes_per_line */
268
269 assert(ximage->format);
270 assert(ximage->bitmap_unit);
271
272 data = pws->buffer_map(pws, r300tex->buffer, 0);
273
274 /* update XImage's fields */
275 ximage->data = data;
276 ximage->width = psurf->width;
277 ximage->height = psurf->height;
278 ximage->bytes_per_line = psurf->width * (ximage->bits_per_pixel >> 3);
279
280 XPutImage(rvl_ctx->display, rvl_ctx->drawable,
281 XDefaultGC(rvl_ctx->display, rvl_ctx->screen),
282 ximage, 0, 0, 0, 0, psurf->width, psurf->height);
283
284 XSync(rvl_ctx->display, 0);
285
286 ximage->data = NULL;
287 XDestroyImage(ximage);
288
289 pws->buffer_unmap(pws, r300tex->buffer);
290 }
291
292 static void radeon_flush_frontbuffer(struct pipe_winsys *pipe_winsys,
293 struct pipe_surface *pipe_surface,
294 void *context_private)
295 {
296 struct radeon_vl_context *rvl_ctx;
297 rvl_ctx = (struct radeon_vl_context *) context_private;
298 radeon_display_surface(pipe_winsys, pipe_surface, rvl_ctx);
299 }
300
301 struct radeon_winsys* radeon_pipe_winsys(int fd)
302 {
303 struct radeon_winsys* radeon_ws;
304
305 radeon_ws = CALLOC_STRUCT(radeon_winsys);
306 if (radeon_ws == NULL) {
307 return NULL;
308 }
309
310 radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv);
311 if (radeon_ws->priv == NULL) {
312 FREE(radeon_ws);
313 return NULL;
314 }
315
316 radeon_ws->priv->fd = fd;
317 radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd);
318
319 radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer;
320
321 radeon_ws->base.buffer_create = radeon_buffer_create;
322 radeon_ws->base.user_buffer_create = radeon_buffer_user_create;
323 radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create;
324 radeon_ws->base.buffer_map = radeon_buffer_map;
325 radeon_ws->base.buffer_unmap = radeon_buffer_unmap;
326 radeon_ws->base.buffer_destroy = radeon_buffer_del;
327
328 radeon_ws->base.fence_reference = radeon_fence_reference;
329 radeon_ws->base.fence_signalled = radeon_fence_signalled;
330 radeon_ws->base.fence_finish = radeon_fence_finish;
331
332 radeon_ws->base.get_name = radeon_get_name;
333
334 radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling;
335
336 return radeon_ws;
337 }