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