2 * Copyright © 2008 Jérôme Glisse
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:
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.
23 * The above copyright notice and this permission notice (including the
24 * next paragraph) shall be included in all copies or substantial portions
29 * Jérôme Glisse <glisse@freedesktop.org>
30 * Corbin Simpson <MostAwesomeDude@gmail.com>
33 #include "radeon_buffer.h"
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>
42 struct radeon_vl_context
49 static const char *radeon_get_name(struct pipe_winsys
*ws
)
51 return "Radeon/GEM+KMS";
54 static struct pipe_buffer
*radeon_buffer_create(struct pipe_winsys
*ws
,
59 struct radeon_winsys
*radeon_ws
= (struct radeon_winsys
*)ws
;
60 struct radeon_pipe_buffer
*radeon_buffer
;
64 radeon_buffer
= CALLOC_STRUCT(radeon_pipe_buffer
);
65 if (radeon_buffer
== NULL
) {
69 pipe_reference_init(&radeon_buffer
->base
.reference
, 1);
70 radeon_buffer
->base
.alignment
= alignment
;
71 radeon_buffer
->base
.usage
= usage
;
72 radeon_buffer
->base
.size
= size
;
74 if (usage
== PIPE_BUFFER_USAGE_CONSTANT
&& is_r3xx(radeon_ws
->pci_id
)) {
75 /* Don't bother allocating a BO, as it'll never get to the card. */
76 desc
.alignment
= alignment
;
78 radeon_buffer
->pb
= pb_malloc_buffer_create(size
, &desc
);
79 return &radeon_buffer
->base
;
84 if (usage
& PIPE_BUFFER_USAGE_PIXEL
) {
85 domain
|= RADEON_GEM_DOMAIN_VRAM
;
87 if (usage
& PIPE_BUFFER_USAGE_VERTEX
) {
88 domain
|= RADEON_GEM_DOMAIN_GTT
;
90 if (usage
& PIPE_BUFFER_USAGE_INDEX
) {
91 domain
|= RADEON_GEM_DOMAIN_GTT
;
94 radeon_buffer
->bo
= radeon_bo_open(radeon_ws
->priv
->bom
, 0, size
,
95 alignment
, domain
, 0);
96 if (radeon_buffer
->bo
== NULL
) {
100 return &radeon_buffer
->base
;
103 static struct pipe_buffer
*radeon_buffer_user_create(struct pipe_winsys
*ws
,
107 struct radeon_pipe_buffer
*radeon_buffer
;
110 (struct radeon_pipe_buffer
*)radeon_buffer_create(ws
, 0, 0, bytes
);
111 if (radeon_buffer
== NULL
) {
114 radeon_bo_map(radeon_buffer
->bo
, 1);
115 memcpy(radeon_buffer
->bo
->ptr
, ptr
, bytes
);
116 radeon_bo_unmap(radeon_buffer
->bo
);
117 return &radeon_buffer
->base
;
120 static struct pipe_buffer
*radeon_surface_buffer_create(struct pipe_winsys
*ws
,
123 enum pipe_format format
,
128 /* Radeons enjoy things in multiples of 32. */
129 /* XXX this can be 32 when POT */
130 const unsigned alignment
= 64;
131 unsigned nblocksy
, size
;
133 nblocksy
= util_format_get_nblocksy(format
, height
);
134 *stride
= align(util_format_get_stride(format
, width
), alignment
);
135 size
= *stride
* nblocksy
;
137 return radeon_buffer_create(ws
, 64, usage
, size
);
140 static void radeon_buffer_del(struct pipe_buffer
*buffer
)
142 struct radeon_pipe_buffer
*radeon_buffer
=
143 (struct radeon_pipe_buffer
*)buffer
;
145 if (radeon_buffer
->pb
) {
146 pipe_reference_init(&radeon_buffer
->pb
->base
.reference
, 0);
147 pb_destroy(radeon_buffer
->pb
);
150 if (radeon_buffer
->bo
) {
151 radeon_bo_unref(radeon_buffer
->bo
);
157 static void *radeon_buffer_map(struct pipe_winsys
*ws
,
158 struct pipe_buffer
*buffer
,
161 struct radeon_winsys_priv
*priv
= ((struct radeon_winsys
*)ws
)->priv
;
162 struct radeon_pipe_buffer
*radeon_buffer
=
163 (struct radeon_pipe_buffer
*)buffer
;
166 if (radeon_buffer
->pb
) {
167 return pb_map(radeon_buffer
->pb
, flags
);
170 if (flags
& PIPE_BUFFER_USAGE_DONTBLOCK
) {
173 if (radeon_bo_is_busy(radeon_buffer
->bo
, &domain
))
177 if (radeon_bo_is_referenced_by_cs(radeon_buffer
->bo
, priv
->cs
)) {
178 priv
->flush_cb(priv
->flush_data
);
181 if (flags
& PIPE_BUFFER_USAGE_CPU_WRITE
) {
185 if (radeon_bo_map(radeon_buffer
->bo
, write
)) {
189 return radeon_buffer
->bo
->ptr
;
192 static void radeon_buffer_unmap(struct pipe_winsys
*ws
,
193 struct pipe_buffer
*buffer
)
195 struct radeon_pipe_buffer
*radeon_buffer
=
196 (struct radeon_pipe_buffer
*)buffer
;
198 if (radeon_buffer
->pb
) {
199 pb_unmap(radeon_buffer
->pb
);
201 radeon_bo_unmap(radeon_buffer
->bo
);
205 static void radeon_buffer_set_tiling(struct radeon_winsys
*ws
,
206 struct pipe_buffer
*buffer
,
211 struct radeon_pipe_buffer
*radeon_buffer
=
212 (struct radeon_pipe_buffer
*)buffer
;
216 flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
219 flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
222 radeon_bo_set_tiling(radeon_buffer
->bo
, flags
, pitch
);
225 static void radeon_fence_reference(struct pipe_winsys
*ws
,
226 struct pipe_fence_handle
**ptr
,
227 struct pipe_fence_handle
*pfence
)
231 static int radeon_fence_signalled(struct pipe_winsys
*ws
,
232 struct pipe_fence_handle
*pfence
,
238 static int radeon_fence_finish(struct pipe_winsys
*ws
,
239 struct pipe_fence_handle
*pfence
,
245 static void radeon_display_surface(struct pipe_winsys
*pws
,
246 struct pipe_surface
*psurf
,
247 struct radeon_vl_context
*rvl_ctx
)
249 struct r300_texture
*r300tex
= (struct r300_texture
*)(psurf
->texture
);
253 ximage
= XCreateImage(rvl_ctx
->display
,
254 XDefaultVisual(rvl_ctx
->display
, rvl_ctx
->screen
),
255 XDefaultDepth(rvl_ctx
->display
, rvl_ctx
->screen
),
256 ZPixmap
, 0, /* format, offset */
260 0); /* bytes_per_line */
262 assert(ximage
->format
);
263 assert(ximage
->bitmap_unit
);
265 data
= pws
->buffer_map(pws
, r300tex
->buffer
, 0);
267 /* update XImage's fields */
269 ximage
->width
= psurf
->width
;
270 ximage
->height
= psurf
->height
;
271 ximage
->bytes_per_line
= psurf
->width
* (ximage
->bits_per_pixel
>> 3);
273 XPutImage(rvl_ctx
->display
, rvl_ctx
->drawable
,
274 XDefaultGC(rvl_ctx
->display
, rvl_ctx
->screen
),
275 ximage
, 0, 0, 0, 0, psurf
->width
, psurf
->height
);
277 XSync(rvl_ctx
->display
, 0);
280 XDestroyImage(ximage
);
282 pws
->buffer_unmap(pws
, r300tex
->buffer
);
285 static void radeon_flush_frontbuffer(struct pipe_winsys
*pipe_winsys
,
286 struct pipe_surface
*pipe_surface
,
287 void *context_private
)
289 struct radeon_vl_context
*rvl_ctx
;
290 rvl_ctx
= (struct radeon_vl_context
*) context_private
;
291 radeon_display_surface(pipe_winsys
, pipe_surface
, rvl_ctx
);
294 struct radeon_winsys
* radeon_pipe_winsys(int fd
)
296 struct radeon_winsys
* radeon_ws
;
298 radeon_ws
= CALLOC_STRUCT(radeon_winsys
);
299 if (radeon_ws
== NULL
) {
303 radeon_ws
->priv
= CALLOC_STRUCT(radeon_winsys_priv
);
304 if (radeon_ws
->priv
== NULL
) {
309 radeon_ws
->priv
->fd
= fd
;
310 radeon_ws
->priv
->bom
= radeon_bo_manager_gem_ctor(fd
);
312 radeon_ws
->base
.flush_frontbuffer
= radeon_flush_frontbuffer
;
314 radeon_ws
->base
.buffer_create
= radeon_buffer_create
;
315 radeon_ws
->base
.user_buffer_create
= radeon_buffer_user_create
;
316 radeon_ws
->base
.surface_buffer_create
= radeon_surface_buffer_create
;
317 radeon_ws
->base
.buffer_map
= radeon_buffer_map
;
318 radeon_ws
->base
.buffer_unmap
= radeon_buffer_unmap
;
319 radeon_ws
->base
.buffer_destroy
= radeon_buffer_del
;
321 radeon_ws
->base
.fence_reference
= radeon_fence_reference
;
322 radeon_ws
->base
.fence_signalled
= radeon_fence_signalled
;
323 radeon_ws
->base
.fence_finish
= radeon_fence_finish
;
325 radeon_ws
->base
.get_name
= radeon_get_name
;
327 radeon_ws
->buffer_set_tiling
= radeon_buffer_set_tiling
;