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 static const char *radeon_get_name(struct pipe_winsys
*ws
)
37 return "Radeon/GEM+KMS";
40 static struct pipe_buffer
*radeon_buffer_create(struct pipe_winsys
*ws
,
45 struct radeon_winsys
*radeon_ws
= (struct radeon_winsys
*)ws
;
46 struct radeon_pipe_buffer
*radeon_buffer
;
49 radeon_buffer
= CALLOC_STRUCT(radeon_pipe_buffer
);
50 if (radeon_buffer
== NULL
) {
54 pipe_reference_init(&radeon_buffer
->base
.reference
, 1);
55 radeon_buffer
->base
.alignment
= alignment
;
56 radeon_buffer
->base
.usage
= usage
;
57 radeon_buffer
->base
.size
= size
;
61 if (usage
& PIPE_BUFFER_USAGE_PIXEL
) {
62 domain
|= RADEON_GEM_DOMAIN_VRAM
;
64 if (usage
& PIPE_BUFFER_USAGE_VERTEX
) {
65 domain
|= RADEON_GEM_DOMAIN_GTT
;
67 if (usage
& PIPE_BUFFER_USAGE_INDEX
) {
68 domain
|= RADEON_GEM_DOMAIN_GTT
;
71 radeon_buffer
->bo
= radeon_bo_open(radeon_ws
->priv
->bom
, 0, size
,
72 alignment
, domain
, 0);
73 if (radeon_buffer
->bo
== NULL
) {
76 return &radeon_buffer
->base
;
79 static struct pipe_buffer
*radeon_buffer_user_create(struct pipe_winsys
*ws
,
83 struct radeon_pipe_buffer
*radeon_buffer
;
86 (struct radeon_pipe_buffer
*)radeon_buffer_create(ws
, 0, 0, bytes
);
87 if (radeon_buffer
== NULL
) {
90 radeon_bo_map(radeon_buffer
->bo
, 1);
91 memcpy(radeon_buffer
->bo
->ptr
, ptr
, bytes
);
92 radeon_bo_unmap(radeon_buffer
->bo
);
93 return &radeon_buffer
->base
;
96 static struct pipe_buffer
*radeon_surface_buffer_create(struct pipe_winsys
*ws
,
99 enum pipe_format format
,
103 struct pipe_format_block block
;
104 unsigned nblocksx
, nblocksy
, size
;
106 pf_get_block(format
, &block
);
108 nblocksx
= pf_get_nblocksx(&block
, width
);
109 nblocksy
= pf_get_nblocksy(&block
, height
);
111 /* Radeons enjoy things in multiples of 32. */
112 /* XXX this can be 32 when POT */
113 *stride
= (nblocksx
* block
.size
+ 63) & ~63;
114 size
= *stride
* nblocksy
;
116 return radeon_buffer_create(ws
, 64, usage
, size
);
119 static void radeon_buffer_del(struct pipe_buffer
*buffer
)
121 struct radeon_pipe_buffer
*radeon_buffer
=
122 (struct radeon_pipe_buffer
*)buffer
;
124 radeon_bo_unref(radeon_buffer
->bo
);
128 static void *radeon_buffer_map(struct pipe_winsys
*ws
,
129 struct pipe_buffer
*buffer
,
132 struct radeon_pipe_buffer
*radeon_buffer
=
133 (struct radeon_pipe_buffer
*)buffer
;
136 if (flags
& PIPE_BUFFER_USAGE_DONTBLOCK
) {
137 /* XXX Remove this when radeon_bo_map supports DONTBLOCK */
140 if (flags
& PIPE_BUFFER_USAGE_CPU_WRITE
) {
144 if (radeon_bo_map(radeon_buffer
->bo
, write
))
146 return radeon_buffer
->bo
->ptr
;
149 static void radeon_buffer_unmap(struct pipe_winsys
*ws
,
150 struct pipe_buffer
*buffer
)
152 struct radeon_pipe_buffer
*radeon_buffer
=
153 (struct radeon_pipe_buffer
*)buffer
;
155 radeon_bo_unmap(radeon_buffer
->bo
);
158 static void radeon_fence_reference(struct pipe_winsys
*ws
,
159 struct pipe_fence_handle
**ptr
,
160 struct pipe_fence_handle
*pfence
)
164 static int radeon_fence_signalled(struct pipe_winsys
*ws
,
165 struct pipe_fence_handle
*pfence
,
171 static int radeon_fence_finish(struct pipe_winsys
*ws
,
172 struct pipe_fence_handle
*pfence
,
178 static void radeon_flush_frontbuffer(struct pipe_winsys
*pipe_winsys
,
179 struct pipe_surface
*pipe_surface
,
180 void *context_private
)
182 /* XXX TODO: call dri2CopyRegion */
185 struct radeon_winsys
* radeon_pipe_winsys(int fd
)
187 struct radeon_winsys
* radeon_ws
;
188 struct radeon_bo_manager
* bom
;
190 radeon_ws
= CALLOC_STRUCT(radeon_winsys
);
191 if (radeon_ws
== NULL
) {
195 radeon_ws
->priv
= CALLOC_STRUCT(radeon_winsys_priv
);
196 if (radeon_ws
->priv
== NULL
) {
201 radeon_ws
->priv
->bom
= radeon_bo_manager_gem_ctor(fd
);
203 radeon_ws
->base
.flush_frontbuffer
= radeon_flush_frontbuffer
;
205 radeon_ws
->base
.buffer_create
= radeon_buffer_create
;
206 radeon_ws
->base
.user_buffer_create
= radeon_buffer_user_create
;
207 radeon_ws
->base
.surface_buffer_create
= radeon_surface_buffer_create
;
208 radeon_ws
->base
.buffer_map
= radeon_buffer_map
;
209 radeon_ws
->base
.buffer_unmap
= radeon_buffer_unmap
;
210 radeon_ws
->base
.buffer_destroy
= radeon_buffer_del
;
212 radeon_ws
->base
.fence_reference
= radeon_fence_reference
;
213 radeon_ws
->base
.fence_signalled
= radeon_fence_signalled
;
214 radeon_ws
->base
.fence_finish
= radeon_fence_finish
;
216 radeon_ws
->base
.get_name
= radeon_get_name
;
221 static struct pipe_buffer
*radeon_buffer_from_handle(struct radeon_screen
*radeon_screen
,
224 struct radeon_pipe_buffer
*radeon_buffer
;
225 struct radeon_bo
*bo
= NULL
;
227 bo
= radeon_bo_open(radeon_screen
->bom
, handle
, 0, 0, 0, 0);
231 radeon_buffer
= calloc(1, sizeof(struct radeon_pipe_buffer
));
232 if (radeon_buffer
== NULL
) {
236 pipe_reference_init(&radeon_buffer
->base
.reference
, 1);
237 radeon_buffer
->base
.usage
= PIPE_BUFFER_USAGE_PIXEL
;
238 radeon_buffer
->bo
= bo
;
239 return &radeon_buffer
->base
;
242 struct pipe_surface
*radeon_surface_from_handle(struct radeon_context
*radeon_context
,
244 enum pipe_format format
,
245 int w
, int h
, int pitch
)
247 struct pipe_screen
*pipe_screen
= radeon_context
->pipe_screen
;
248 struct pipe_winsys
*pipe_winsys
= radeon_context
->pipe_winsys
;
249 struct pipe_texture tmpl
;
250 struct pipe_surface
*ps
;
251 struct pipe_texture
*pt
;
252 struct pipe_buffer
*pb
;
254 pb
= radeon_buffer_from_handle(radeon_context
->radeon_screen
, handle
);
258 memset(&tmpl
, 0, sizeof(tmpl
));
259 tmpl
.tex_usage
= PIPE_TEXTURE_USAGE_DISPLAY_TARGET
;
260 tmpl
.target
= PIPE_TEXTURE_2D
;
264 tmpl
.format
= format
;
265 pf_get_block(tmpl
.format
, &tmpl
.block
);
266 tmpl
.nblocksx
[0] = pf_get_nblocksx(&tmpl
.block
, w
);
267 tmpl
.nblocksy
[0] = pf_get_nblocksy(&tmpl
.block
, h
);
269 pt
= pipe_screen
->texture_blanket(pipe_screen
, &tmpl
, &pitch
, pb
);
271 pipe_buffer_reference(&pb
, NULL
);
273 ps
= pipe_screen
->get_tex_surface(pipe_screen
, pt
, 0, 0, 0,
274 PIPE_BUFFER_USAGE_GPU_WRITE
);