r300g: store own copy of flush_cb and flush data.
[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_math.h"
39 #include <X11/Xutil.h>
40
41 struct radeon_vl_context
42 {
43 Display *display;
44 int screen;
45 Drawable drawable;
46 };
47
48 static const char *radeon_get_name(struct pipe_winsys *ws)
49 {
50 return "Radeon/GEM+KMS";
51 }
52
53 static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws,
54 unsigned alignment,
55 unsigned usage,
56 unsigned size)
57 {
58 struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws;
59 struct radeon_pipe_buffer *radeon_buffer;
60 uint32_t domain;
61
62 radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
63 if (radeon_buffer == NULL) {
64 return NULL;
65 }
66
67 pipe_reference_init(&radeon_buffer->base.reference, 1);
68 radeon_buffer->base.alignment = alignment;
69 radeon_buffer->base.usage = usage;
70 radeon_buffer->base.size = size;
71
72 domain = 0;
73
74 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
75 domain |= RADEON_GEM_DOMAIN_VRAM;
76 }
77 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
78 domain |= RADEON_GEM_DOMAIN_GTT;
79 }
80 if (usage & PIPE_BUFFER_USAGE_INDEX) {
81 domain |= RADEON_GEM_DOMAIN_GTT;
82 }
83
84 radeon_buffer->ws = radeon_ws;
85 radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size,
86 alignment, domain, 0);
87 if (radeon_buffer->bo == NULL) {
88 FREE(radeon_buffer);
89 return NULL;
90 }
91 return &radeon_buffer->base;
92 }
93
94 static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws,
95 void *ptr,
96 unsigned bytes)
97 {
98 struct radeon_pipe_buffer *radeon_buffer;
99
100 radeon_buffer =
101 (struct radeon_pipe_buffer*)radeon_buffer_create(ws, 0, 0, bytes);
102 if (radeon_buffer == NULL) {
103 return NULL;
104 }
105 radeon_bo_map(radeon_buffer->bo, 1);
106 memcpy(radeon_buffer->bo->ptr, ptr, bytes);
107 radeon_bo_unmap(radeon_buffer->bo);
108 return &radeon_buffer->base;
109 }
110
111 static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws,
112 unsigned width,
113 unsigned height,
114 enum pipe_format format,
115 unsigned usage,
116 unsigned tex_usage,
117 unsigned *stride)
118 {
119 /* Radeons enjoy things in multiples of 32. */
120 /* XXX this can be 32 when POT */
121 const unsigned alignment = 64;
122 unsigned nblocksy, size;
123
124 nblocksy = pf_get_nblocksy(format, height);
125 *stride = align(pf_get_stride(format, width), alignment);
126 size = *stride * nblocksy;
127
128 return radeon_buffer_create(ws, 64, usage, size);
129 }
130
131 static void radeon_buffer_del(struct pipe_buffer *buffer)
132 {
133 struct radeon_pipe_buffer *radeon_buffer =
134 (struct radeon_pipe_buffer*)buffer;
135 struct radeon_winsys_priv *priv = radeon_buffer->ws->priv;
136
137 if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
138 priv->flush_cb(priv->flush_data);
139 }
140
141 radeon_bo_unref(radeon_buffer->bo);
142 free(radeon_buffer);
143 }
144
145 static void *radeon_buffer_map(struct pipe_winsys *ws,
146 struct pipe_buffer *buffer,
147 unsigned flags)
148 {
149 struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv;
150 struct radeon_pipe_buffer *radeon_buffer =
151 (struct radeon_pipe_buffer*)buffer;
152 int write = 0;
153
154 if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
155 priv->flush_cb(priv->flush_data);
156 }
157
158 if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
159 uint32_t domain;
160
161 if (radeon_bo_is_busy(radeon_buffer->bo, &domain))
162 return NULL;
163 }
164 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
165 write = 1;
166 }
167
168 if (radeon_bo_map(radeon_buffer->bo, write)) {
169 return NULL;
170 }
171
172 return radeon_buffer->bo->ptr;
173 }
174
175 static void radeon_buffer_unmap(struct pipe_winsys *ws,
176 struct pipe_buffer *buffer)
177 {
178 struct radeon_pipe_buffer *radeon_buffer =
179 (struct radeon_pipe_buffer*)buffer;
180
181 radeon_bo_unmap(radeon_buffer->bo);
182 }
183
184 static void radeon_fence_reference(struct pipe_winsys *ws,
185 struct pipe_fence_handle **ptr,
186 struct pipe_fence_handle *pfence)
187 {
188 }
189
190 static int radeon_fence_signalled(struct pipe_winsys *ws,
191 struct pipe_fence_handle *pfence,
192 unsigned flag)
193 {
194 return 1;
195 }
196
197 static int radeon_fence_finish(struct pipe_winsys *ws,
198 struct pipe_fence_handle *pfence,
199 unsigned flag)
200 {
201 return 0;
202 }
203
204 static void radeon_display_surface(struct pipe_winsys *pws,
205 struct pipe_surface *psurf,
206 struct radeon_vl_context *rvl_ctx)
207 {
208 struct r300_texture *r300tex = (struct r300_texture *)(psurf->texture);
209 XImage *ximage;
210 void *data;
211
212 ximage = XCreateImage(rvl_ctx->display,
213 XDefaultVisual(rvl_ctx->display, rvl_ctx->screen),
214 XDefaultDepth(rvl_ctx->display, rvl_ctx->screen),
215 ZPixmap, 0, /* format, offset */
216 NULL, /* data */
217 0, 0, /* size */
218 32, /* bitmap_pad */
219 0); /* bytes_per_line */
220
221 assert(ximage->format);
222 assert(ximage->bitmap_unit);
223
224 data = pws->buffer_map(pws, r300tex->buffer, 0);
225
226 /* update XImage's fields */
227 ximage->data = data;
228 ximage->width = psurf->width;
229 ximage->height = psurf->height;
230 ximage->bytes_per_line = psurf->width * (ximage->bits_per_pixel >> 3);
231
232 XPutImage(rvl_ctx->display, rvl_ctx->drawable,
233 XDefaultGC(rvl_ctx->display, rvl_ctx->screen),
234 ximage, 0, 0, 0, 0, psurf->width, psurf->height);
235
236 XSync(rvl_ctx->display, 0);
237
238 ximage->data = NULL;
239 XDestroyImage(ximage);
240
241 pws->buffer_unmap(pws, r300tex->buffer);
242 }
243
244 static void radeon_flush_frontbuffer(struct pipe_winsys *pipe_winsys,
245 struct pipe_surface *pipe_surface,
246 void *context_private)
247 {
248 struct radeon_vl_context *rvl_ctx;
249 rvl_ctx = (struct radeon_vl_context *) context_private;
250 radeon_display_surface(pipe_winsys, pipe_surface, rvl_ctx);
251 }
252
253 struct radeon_winsys* radeon_pipe_winsys(int fd)
254 {
255 struct radeon_winsys* radeon_ws;
256
257 radeon_ws = CALLOC_STRUCT(radeon_winsys);
258 if (radeon_ws == NULL) {
259 return NULL;
260 }
261
262 radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv);
263 if (radeon_ws->priv == NULL) {
264 FREE(radeon_ws);
265 return NULL;
266 }
267
268 radeon_ws->priv->fd = fd;
269 radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd);
270
271 radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer;
272
273 radeon_ws->base.buffer_create = radeon_buffer_create;
274 radeon_ws->base.user_buffer_create = radeon_buffer_user_create;
275 radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create;
276 radeon_ws->base.buffer_map = radeon_buffer_map;
277 radeon_ws->base.buffer_unmap = radeon_buffer_unmap;
278 radeon_ws->base.buffer_destroy = radeon_buffer_del;
279
280 radeon_ws->base.fence_reference = radeon_fence_reference;
281 radeon_ws->base.fence_signalled = radeon_fence_signalled;
282 radeon_ws->base.fence_finish = radeon_fence_finish;
283
284 radeon_ws->base.get_name = radeon_get_name;
285
286 return radeon_ws;
287 }
288 #if 0
289 static struct pipe_buffer *radeon_buffer_from_handle(struct radeon_screen *radeon_screen,
290 uint32_t handle)
291 {
292 struct radeon_pipe_buffer *radeon_buffer;
293 struct radeon_bo *bo = NULL;
294
295 bo = radeon_bo_open(radeon_screen->bom, handle, 0, 0, 0, 0);
296 if (bo == NULL) {
297 return NULL;
298 }
299 radeon_buffer = calloc(1, sizeof(struct radeon_pipe_buffer));
300 if (radeon_buffer == NULL) {
301 radeon_bo_unref(bo);
302 return NULL;
303 }
304 pipe_reference_init(&radeon_buffer->base.reference, 1);
305 radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL;
306 radeon_buffer->bo = bo;
307 return &radeon_buffer->base;
308 }
309
310 struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context,
311 uint32_t handle,
312 enum pipe_format format,
313 int w, int h, int pitch)
314 {
315 struct pipe_screen *pipe_screen = radeon_context->pipe_screen;
316 struct pipe_winsys *pipe_winsys = radeon_context->pipe_winsys;
317 struct pipe_texture tmpl;
318 struct pipe_surface *ps;
319 struct pipe_texture *pt;
320 struct pipe_buffer *pb;
321
322 pb = radeon_buffer_from_handle(radeon_context->radeon_screen, handle);
323 if (pb == NULL) {
324 return NULL;
325 }
326 memset(&tmpl, 0, sizeof(tmpl));
327 tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
328 tmpl.target = PIPE_TEXTURE_2D;
329 tmpl.width0 = w;
330 tmpl.height0 = h;
331 tmpl.depth0 = 1;
332 tmpl.format = format;
333
334 pt = pipe_screen->texture_blanket(pipe_screen, &tmpl, &pitch, pb);
335 if (pt == NULL) {
336 pipe_buffer_reference(&pb, NULL);
337 }
338 ps = pipe_screen->get_tex_surface(pipe_screen, pt, 0, 0, 0,
339 PIPE_BUFFER_USAGE_GPU_WRITE);
340 return ps;
341 }
342 #endif