2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23 #include "radeon_r300.h"
24 #include "radeon_buffer.h"
26 #include "radeon_bo_gem.h"
27 #include "radeon_cs_gem.h"
28 #include "state_tracker/drm_driver.h"
30 #include "util/u_memory.h"
32 static unsigned get_pb_usage_from_create_flags(unsigned bind
, unsigned usage
,
33 enum r300_buffer_domain domain
)
37 if (bind
& (PIPE_BIND_DEPTH_STENCIL
| PIPE_BIND_RENDER_TARGET
|
38 PIPE_BIND_DISPLAY_TARGET
| PIPE_BIND_SCANOUT
))
39 res
|= PB_USAGE_GPU_WRITE
;
41 if (bind
& PIPE_BIND_SAMPLER_VIEW
)
42 res
|= PB_USAGE_GPU_READ
| PB_USAGE_GPU_WRITE
;
44 if (bind
& (PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_INDEX_BUFFER
))
45 res
|= PB_USAGE_GPU_READ
;
47 if (bind
& PIPE_BIND_TRANSFER_WRITE
)
48 res
|= PB_USAGE_CPU_WRITE
;
50 if (bind
& PIPE_BIND_TRANSFER_READ
)
51 res
|= PB_USAGE_CPU_READ
;
53 /* Is usage of any use for us? Probably not. */
55 /* Now add driver-specific usage flags. */
56 if (bind
& (PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_INDEX_BUFFER
))
57 res
|= RADEON_PB_USAGE_VERTEX
;
59 if (domain
& R300_DOMAIN_GTT
)
60 res
|= RADEON_PB_USAGE_DOMAIN_GTT
;
62 if (domain
& R300_DOMAIN_VRAM
)
63 res
|= RADEON_PB_USAGE_DOMAIN_VRAM
;
68 static struct r300_winsys_buffer
*
69 radeon_r300_winsys_buffer_create(struct r300_winsys_screen
*rws
,
74 enum r300_buffer_domain domain
)
76 struct radeon_libdrm_winsys
*ws
= radeon_libdrm_winsys(rws
);
78 struct pb_manager
*provider
;
79 struct pb_buffer
*buffer
;
81 memset(&desc
, 0, sizeof(desc
));
82 desc
.alignment
= alignment
;
83 desc
.usage
= get_pb_usage_from_create_flags(bind
, usage
, domain
);
85 /* Assign a buffer manager. */
86 if (bind
& (PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_INDEX_BUFFER
))
91 buffer
= provider
->create_buffer(provider
, size
, &desc
);
95 return radeon_libdrm_winsys_buffer(buffer
);
98 static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen
*rws
,
99 struct r300_winsys_buffer
**pdst
,
100 struct r300_winsys_buffer
*src
)
102 struct pb_buffer
*_src
= radeon_pb_buffer(src
);
103 struct pb_buffer
*_dst
= radeon_pb_buffer(*pdst
);
105 pb_reference(&_dst
, _src
);
107 *pdst
= radeon_libdrm_winsys_buffer(_dst
);
110 static struct r300_winsys_buffer
*radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen
*rws
,
111 struct winsys_handle
*whandle
,
115 struct radeon_libdrm_winsys
*ws
= radeon_libdrm_winsys(rws
);
116 struct pb_buffer
*_buf
;
118 _buf
= radeon_drm_bufmgr_create_buffer_from_handle(ws
->kman
, whandle
->handle
);
121 *stride
= whandle
->stride
;
123 *size
= _buf
->base
.size
;
125 return radeon_libdrm_winsys_buffer(_buf
);
128 static boolean
radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen
*rws
,
129 struct r300_winsys_buffer
*buffer
,
131 struct winsys_handle
*whandle
)
133 struct pb_buffer
*_buf
= radeon_pb_buffer(buffer
);
134 whandle
->stride
= stride
;
135 return radeon_drm_bufmgr_get_handle(_buf
, whandle
);
138 static void radeon_r300_winsys_cs_set_flush(struct r300_winsys_cs
*rcs
,
139 void (*flush
)(void *),
142 struct radeon_libdrm_cs
*cs
= radeon_libdrm_cs(rcs
);
143 cs
->flush_cs
= flush
;
144 cs
->flush_data
= user
;
145 radeon_cs_space_set_flush(cs
->cs
, flush
, user
);
148 static boolean
radeon_r300_winsys_cs_validate(struct r300_winsys_cs
*rcs
)
150 struct radeon_libdrm_cs
*cs
= radeon_libdrm_cs(rcs
);
152 return radeon_cs_space_check(cs
->cs
) >= 0;
155 static void radeon_r300_winsys_cs_reset_buffers(struct r300_winsys_cs
*rcs
)
157 struct radeon_libdrm_cs
*cs
= radeon_libdrm_cs(rcs
);
158 radeon_cs_space_reset_bos(cs
->cs
);
161 static void radeon_r300_winsys_cs_flush(struct r300_winsys_cs
*rcs
)
163 struct radeon_libdrm_cs
*cs
= radeon_libdrm_cs(rcs
);
166 /* Don't flush a zero-sized CS. */
171 cs
->cs
->cdw
= cs
->base
.cdw
;
173 radeon_drm_bufmgr_flush_maps(cs
->ws
->kman
);
176 retval
= radeon_cs_emit(cs
->cs
);
178 if (debug_get_bool_option("RADEON_DUMP_CS", FALSE
)) {
179 fprintf(stderr
, "radeon: The kernel rejected CS, dumping...\n");
180 radeon_cs_print(cs
->cs
, stderr
);
182 fprintf(stderr
, "radeon: The kernel rejected CS, "
183 "see dmesg for more information.\n");
188 * Someday, when we care about performance, we should really find a way
189 * to rotate between two or three CS objects so that the GPU can be
190 * spinning through one CS while another one is being filled. */
191 radeon_cs_erase(cs
->cs
);
193 cs
->base
.ptr
= cs
->cs
->packets
;
194 cs
->base
.cdw
= cs
->cs
->cdw
;
195 cs
->base
.ndw
= cs
->cs
->ndw
;
198 static uint32_t radeon_get_value(struct r300_winsys_screen
*rws
,
199 enum r300_value_id id
)
201 struct radeon_libdrm_winsys
*ws
= (struct radeon_libdrm_winsys
*)rws
;
204 case R300_VID_PCI_ID
:
206 case R300_VID_GB_PIPES
:
208 case R300_VID_Z_PIPES
:
210 case R300_VID_SQUARE_TILING_SUPPORT
:
211 return ws
->squaretiling
;
212 case R300_VID_DRM_2_3_0
:
213 return ws
->drm_2_3_0
;
214 case R300_VID_DRM_2_6_0
:
215 return ws
->drm_2_6_0
;
216 case R300_CAN_HYPERZ
:
222 static struct r300_winsys_cs
*radeon_r300_winsys_cs_create(struct r300_winsys_screen
*rws
)
224 struct radeon_libdrm_winsys
*ws
= radeon_libdrm_winsys(rws
);
225 struct radeon_libdrm_cs
*cs
= CALLOC_STRUCT(radeon_libdrm_cs
);
230 /* Size limit on IBs is 64 kibibytes. */
231 cs
->cs
= radeon_cs_create(ws
->csm
, 1024 * 64 / 4);
237 radeon_cs_set_limit(cs
->cs
,
238 RADEON_GEM_DOMAIN_GTT
, ws
->gart_size
);
239 radeon_cs_set_limit(cs
->cs
,
240 RADEON_GEM_DOMAIN_VRAM
, ws
->vram_size
);
243 cs
->base
.ptr
= cs
->cs
->packets
;
244 cs
->base
.cdw
= cs
->cs
->cdw
;
245 cs
->base
.ndw
= cs
->cs
->ndw
;
249 static void radeon_r300_winsys_cs_destroy(struct r300_winsys_cs
*rcs
)
251 struct radeon_libdrm_cs
*cs
= radeon_libdrm_cs(rcs
);
252 radeon_cs_destroy(cs
->cs
);
256 static void radeon_winsys_destroy(struct r300_winsys_screen
*rws
)
258 struct radeon_libdrm_winsys
*ws
= (struct radeon_libdrm_winsys
*)rws
;
260 ws
->cman
->destroy(ws
->cman
);
261 ws
->kman
->destroy(ws
->kman
);
263 radeon_bo_manager_gem_dtor(ws
->bom
);
264 radeon_cs_manager_gem_dtor(ws
->csm
);
269 boolean
radeon_setup_winsys(int fd
, struct radeon_libdrm_winsys
* ws
)
271 ws
->csm
= radeon_cs_manager_gem_ctor(fd
);
274 ws
->bom
= radeon_bo_manager_gem_ctor(fd
);
277 ws
->kman
= radeon_drm_bufmgr_create(ws
);
281 ws
->cman
= pb_cache_manager_create(ws
->kman
, 100000);
285 ws
->base
.destroy
= radeon_winsys_destroy
;
286 ws
->base
.get_value
= radeon_get_value
;
288 ws
->base
.buffer_create
= radeon_r300_winsys_buffer_create
;
289 ws
->base
.buffer_set_tiling
= radeon_drm_bufmgr_set_tiling
;
290 ws
->base
.buffer_get_tiling
= radeon_drm_bufmgr_get_tiling
;
291 ws
->base
.buffer_map
= radeon_drm_buffer_map
;
292 ws
->base
.buffer_unmap
= radeon_drm_buffer_unmap
;
293 ws
->base
.buffer_wait
= radeon_drm_bufmgr_wait
;
294 ws
->base
.buffer_reference
= radeon_r300_winsys_buffer_reference
;
295 ws
->base
.buffer_from_handle
= radeon_r300_winsys_buffer_from_handle
;
296 ws
->base
.buffer_get_handle
= radeon_r300_winsys_buffer_get_handle
;
298 ws
->base
.cs_create
= radeon_r300_winsys_cs_create
;
299 ws
->base
.cs_destroy
= radeon_r300_winsys_cs_destroy
;
300 ws
->base
.cs_add_buffer
= radeon_drm_bufmgr_add_buffer
;
301 ws
->base
.cs_validate
= radeon_r300_winsys_cs_validate
;
302 ws
->base
.cs_write_reloc
= radeon_drm_bufmgr_write_reloc
;
303 ws
->base
.cs_flush
= radeon_r300_winsys_cs_flush
;
304 ws
->base
.cs_reset_buffers
= radeon_r300_winsys_cs_reset_buffers
;
305 ws
->base
.cs_set_flush
= radeon_r300_winsys_cs_set_flush
;
306 ws
->base
.cs_is_buffer_referenced
= radeon_drm_bufmgr_is_buffer_referenced
;
311 radeon_cs_manager_gem_dtor(ws
->csm
);
314 radeon_bo_manager_gem_dtor(ws
->bom
);
317 ws
->cman
->destroy(ws
->cman
);
319 ws
->kman
->destroy(ws
->kman
);