r300g: rebuild winsys and command submission to support multiple contexts

This commit is contained in:
Marek Olšák 2010-07-14 01:59:57 +02:00
parent 5f9d7bb242
commit fe3caa91d3
20 changed files with 671 additions and 564 deletions

View File

@ -89,9 +89,6 @@
CB_DEBUG(cs_count = size;) \
} while (0)
#define BEGIN_CS_AS_CB(r300, size) \
BEGIN_CB(r300->rws->get_cs_pointer(r300->rws, size), size)
#define END_CB do { \
CB_DEBUG(if (cs_count != 0) \
debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \

View File

@ -100,6 +100,8 @@ static void r300_destroy_context(struct pipe_context* context)
r300_release_referenced_objects(r300);
r300->rws->cs_destroy(r300->cs);
FREE(r300->aa_state.state);
FREE(r300->blend_color_state.state);
FREE(r300->clip_state.state);
@ -354,6 +356,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300->context.destroy = r300_destroy_context;
r300->cs = rws->cs_create(rws);
if (!r300screen->caps.has_tcl) {
/* Create a Draw. This is used for SW TCL. */
r300->draw = draw_create(&r300->context);
@ -381,7 +385,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
/* Render functions must be initialized after blitter. */
r300_init_render_functions(r300);
rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
rws->cs_set_flush(r300->cs, r300_flush_cb, r300);
r300->upload_ib = u_upload_create(&r300->context,
32 * 1024, 16,
@ -433,11 +437,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
return NULL;
}
boolean r300_check_cs(struct r300_context *r300, unsigned size)
{
return size <= r300->rws->get_cs_free_dwords(r300->rws);
}
void r300_finish(struct r300_context *r300)
{
struct pipe_framebuffer_state *fb;

View File

@ -416,6 +416,8 @@ struct r300_context {
/* The interface to the windowing system, etc. */
struct r300_winsys_screen *rws;
/* The command stream. */
struct r300_winsys_cs *cs;
/* Screen. */
struct r300_screen *screen;
/* Draw module. Used mostly for SW TCL. */
@ -570,7 +572,6 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
boolean r300_check_cs(struct r300_context *r300, unsigned size);
void r300_finish(struct r300_context *r300);
void r300_flush_cb(void *data);

View File

@ -46,12 +46,12 @@
*/
#define CS_LOCALS(context) \
struct r300_context* const cs_context_copy = (context); \
struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \
CS_DEBUG(int cs_count = 0; (void) cs_count;)
struct r300_winsys_cs *cs_copy = (context)->cs; \
struct r300_winsys_screen *cs_winsys = (context)->rws; \
int cs_count = 0; (void) cs_count; (void) cs_winsys;
#define BEGIN_CS(size) do { \
assert(r300_check_cs(cs_context_copy, (size))); \
assert(size <= (cs_copy->ndw - cs_copy->cdw)); \
CS_DEBUG(cs_count = size;) \
} while (0)
@ -66,76 +66,66 @@
#define END_CS
#endif
/**
* Writing pure DWORDs.
*/
#define OUT_CS(value) do { \
cs_winsys->write_cs_dword(cs_winsys, (value)); \
cs_copy->ptr[cs_copy->cdw++] = (value); \
CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_32F(value) do { \
cs_winsys->write_cs_dword(cs_winsys, fui(value)); \
CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_32F(value) \
OUT_CS(fui(value))
#define OUT_CS_REG(register, value) do { \
assert(register); \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0(register, 0)); \
cs_winsys->write_cs_dword(cs_winsys, value); \
CS_DEBUG(cs_count -= 2;) \
OUT_CS(CP_PACKET0(register, 0)); \
OUT_CS(value); \
} while (0)
/* Note: This expects count to be the number of registers,
* not the actual packet0 count! */
#define OUT_CS_REG_SEQ(register, count) do { \
assert(register); \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1))); \
CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_REG_SEQ(register, count) \
OUT_CS(CP_PACKET0((register), ((count) - 1)))
#define OUT_CS_ONE_REG(register, count) \
OUT_CS(CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR)
#define OUT_CS_PKT3(op, count) \
OUT_CS(CP_PACKET3(op, count))
#define OUT_CS_TABLE(values, count) do { \
cs_winsys->write_cs_table(cs_winsys, values, count); \
memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \
cs_copy->cdw += count; \
CS_DEBUG(cs_count -= count;) \
} while (0)
#define OUT_CS_ONE_REG(register, count) do { \
assert(register); \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \
CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_PKT3(op, count) do { \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \
CS_DEBUG(cs_count--;) \
} while (0)
/**
* Writing relocations.
*/
#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \
#define OUT_CS_RELOC(bo, offset, rd, wd) do { \
assert(bo); \
cs_winsys->write_cs_dword(cs_winsys, offset); \
cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
CS_DEBUG(cs_count -= 3;) \
OUT_CS(offset); \
cs_winsys->cs_write_reloc(cs_copy, bo, rd, wd); \
CS_DEBUG(cs_count -= 2;) \
} while (0)
#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \
#define OUT_CS_BUF_RELOC(bo, offset, rd, wd) do { \
assert(bo); \
OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd, flags); \
OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd); \
} while (0)
#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \
#define OUT_CS_TEX_RELOC(tex, offset, rd, wd) do { \
assert(tex); \
OUT_CS_RELOC(tex->buffer, offset, rd, wd, flags); \
OUT_CS_RELOC(tex->buffer, offset, rd, wd); \
} while (0)
#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd) do { \
assert(bo); \
cs_winsys->write_cs_reloc(cs_winsys, r300_buffer(bo)->buf, rd, wd, flags); \
cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->buf, rd, wd); \
CS_DEBUG(cs_count -= 2;) \
} while (0)
@ -146,7 +136,8 @@
#define WRITE_CS_TABLE(values, count) do { \
CS_DEBUG(assert(cs_count == 0);) \
cs_winsys->write_cs_table(cs_winsys, values, count); \
memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \
cs_copy->cdw += count; \
} while (0)
#endif /* R300_CS_H */

View File

@ -314,10 +314,10 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
if (aa->dest) {
OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1);
OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain, 0);
OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain);
OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1);
OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain, 0);
OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain);
}
OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl);
@ -347,10 +347,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
surf = r300_surface(fb->cbufs[i]);
OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain);
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain);
}
/* Set up the ZB part of the CBZB clear. */
@ -360,10 +360,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format);
OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
OUT_CS_RELOC(surf->buffer, surf->cbzb_midpoint_offset, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->cbzb_midpoint_offset, 0, surf->domain);
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain);
}
/* Set up a zbuffer. */
else if (fb->zsbuf) {
@ -372,10 +372,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG(R300_ZB_FORMAT, surf->format);
OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain);
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain);
/* HiZ RAM. */
if (r300->screen->caps.has_hiz) {
@ -512,13 +512,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 3) * 4,
0, query->domain, 0);
0, query->domain);
case 3:
/* pipe 2 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 2);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 2) * 4,
0, query->domain, 0);
0, query->domain);
case 2:
/* pipe 1 only */
/* As mentioned above, accomodate RV380 and older. */
@ -526,13 +526,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
1 << (caps->high_second_pipe ? 3 : 1));
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 1) * 4,
0, query->domain, 0);
0, query->domain);
case 1:
/* pipe 0 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 0) * 4,
0, query->domain, 0);
0, query->domain);
break;
default:
fprintf(stderr, "r300: Implementation error: Chipset reports %d"
@ -554,7 +554,7 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300,
BEGIN_CS(8);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain, 0);
OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
@ -568,10 +568,10 @@ static void rv530_emit_query_end_double_z(struct r300_context *r300,
BEGIN_CS(14);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain, 0);
OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain, 0);
OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
@ -731,7 +731,7 @@ void r300_emit_textures_state(struct r300_context *r300,
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
OUT_CS_TEX_RELOC(tex, texstate->format.tile_config, tex->domain,
0, 0);
0);
}
}
END_CS;
@ -774,7 +774,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
for (i = 0; i < aos_count; i++) {
buf = r300_buffer(vbuf[velem[i].vertex_buffer_index].buffer);
OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b, buf->domain, 0, 0);
OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b, buf->domain, 0);
}
END_CS;
}
@ -799,7 +799,7 @@ void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed)
OUT_CS(r300->vertex_info.size |
(r300->vertex_info.size << 8));
OUT_CS(r300->vbo_offset);
OUT_CS_BUF_RELOC(r300->vbo, 0, r300_buffer(r300->vbo)->domain, 0, 0);
OUT_CS_BUF_RELOC(r300->vbo, 0, r300_buffer(r300->vbo)->domain, 0);
END_CS;
}
@ -985,28 +985,22 @@ void r300_emit_buffer_validate(struct r300_context *r300,
}
/* Clean out BOs. */
r300->rws->reset_bos(r300->rws);
r300->rws->cs_reset_buffers(r300->cs);
validate:
/* Color buffers... */
for (i = 0; i < fb->nr_cbufs; i++) {
tex = r300_texture(fb->cbufs[i]->texture);
assert(tex && tex->buffer && "cbuf is marked, but NULL!");
if (!r300_add_texture(r300->rws, tex, 0,
r300_surface(fb->cbufs[i])->domain)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0,
r300_surface(fb->cbufs[i])->domain);
}
/* ...depth buffer... */
if (fb->zsbuf) {
tex = r300_texture(fb->zsbuf->texture);
assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
if (!r300_add_texture(r300->rws, tex, 0,
r300_surface(fb->zsbuf)->domain)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0,
r300_surface(fb->zsbuf)->domain);
}
/* ...textures... */
for (i = 0; i < texstate->count; i++) {
@ -1015,48 +1009,31 @@ validate:
}
tex = r300_texture(texstate->sampler_views[i]->base.texture);
if (!r300_add_texture(r300->rws, tex, tex->domain, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
r300->rws->cs_add_buffer(r300->cs, tex->buffer, tex->domain, 0);
}
/* ...occlusion query buffer... */
if (r300->query_current) {
if (!r300->rws->add_buffer(r300->rws, r300->query_current->buffer,
0, r300->query_current->domain)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
if (r300->query_current)
r300->rws->cs_add_buffer(r300->cs, r300->query_current->buffer,
0, r300->query_current->domain);
/* ...vertex buffer for SWTCL path... */
if (r300->vbo) {
if (!r300_add_buffer(r300->rws, r300->vbo,
r300_buffer(r300->vbo)->domain, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
if (r300->vbo)
r300->rws->cs_add_buffer(r300->cs, r300_buffer(r300->vbo)->buf,
r300_buffer(r300->vbo)->domain, 0);
/* ...vertex buffers for HWTCL path... */
if (do_validate_vertex_buffers) {
for (i = 0; i < r300->velems->count; i++) {
pbuf = vbuf[velem[i].vertex_buffer_index].buffer;
if (!r300_add_buffer(r300->rws, pbuf,
r300_buffer(pbuf)->domain, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
r300->rws->cs_add_buffer(r300->cs, r300_buffer(pbuf)->buf,
r300_buffer(pbuf)->domain, 0);
}
}
/* ...and index buffer for HWTCL path. */
if (index_buffer) {
if (!r300_add_buffer(r300->rws, index_buffer,
r300_buffer(index_buffer)->domain, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
if (!r300->rws->validate(r300->rws)) {
if (index_buffer)
r300->rws->cs_add_buffer(r300->cs, r300_buffer(index_buffer)->buf,
r300_buffer(index_buffer)->domain, 0);
if (!r300->rws->cs_validate(r300->cs)) {
r300->context.flush(&r300->context, 0, NULL);
if (invalid) {
/* Well, hell. */

View File

@ -52,7 +52,7 @@ static void r300_flush(struct pipe_context* pipe,
r300_emit_query_end(r300);
r300->flush_counter++;
r300->rws->flush_cs(r300->rws);
r300->rws->cs_flush(r300->cs);
r300->dirty_hw = 0;
/* New kitchen sink, baby. */

View File

@ -57,7 +57,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
insert_at_tail(&r300->query_list, q);
/* Open up the occlusion query buffer. */
q->buffer = r300->rws->buffer_create(r300->rws, 4096, 0, q->domain, q->buffer_size);
q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096,
PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM,
q->domain);
return (struct pipe_query*)q;
}
@ -134,7 +136,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0);
map = r300->rws->buffer_map(r300->rws, q->buffer, flags);
map = r300->rws->buffer_map(r300->rws, q->buffer, r300->cs, flags);
if (!map)
return FALSE;

View File

@ -229,7 +229,7 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
cs_dwords += end_dwords;
/* Reserve requested CS space. */
if (!r300_check_cs(r300, cs_dwords)) {
if (cs_dwords > (r300->cs->ndw - r300->cs->cdw)) {
r300->context.flush(&r300->context, 0, NULL);
flushed = TRUE;
}
@ -331,7 +331,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
uint32_t* mapelem[PIPE_MAX_ATTRIBS];
struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0};
CB_LOCALS;
CS_LOCALS(r300);
/* Calculate the vertex size, offsets, strides etc. and map the buffers. */
for (i = 0; i < vertex_element_count; i++) {
@ -356,24 +356,24 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
BEGIN_CS_AS_CB(r300, dwords);
OUT_CB_REG(R300_GA_COLOR_CONTROL,
BEGIN_CS(dwords);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
OUT_CB(count - 1);
OUT_CB(0);
OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
OUT_CS(count - 1);
OUT_CS(0);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
r300_translate_primitive(mode));
/* Emit vertices. */
for (v = 0; v < count; v++) {
for (i = 0; i < vertex_element_count; i++) {
OUT_CB_TABLE(&mapelem[i][stride[i] * v], size[i]);
OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]);
}
}
END_CB;
END_CS;
/* Unmap buffers. */
for (i = 0; i < vertex_element_count; i++) {
@ -474,7 +474,7 @@ static void r300_emit_draw_elements(struct r300_context *r300,
(0 << R300_INDX_BUFFER_SKIP_SHIFT));
OUT_CS(offset_dwords << 2);
OUT_CS_BUF_RELOC(indexBuffer, count_dwords,
r300_buffer(indexBuffer)->domain, 0, 0);
r300_buffer(indexBuffer)->domain, 0);
END_CS;
}
@ -929,7 +929,7 @@ static void r300_render_draw_elements(struct vbuf_render* render,
NULL, 256, 0, 0, &end_cs_dwords);
while (count) {
free_dwords = r300->rws->get_cs_free_dwords(r300->rws);
free_dwords = r300->cs->ndw - r300->cs->cdw;
short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2);
@ -1039,7 +1039,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
unsigned dwords = 13 + vertex_size +
(type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0);
const float zeros[4] = {0, 0, 0, 0};
CB_LOCALS;
CS_LOCALS(r300);
if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
r300->sprite_coord_enable = 1;
@ -1054,45 +1054,45 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");
BEGIN_CS_AS_CB(r300, dwords);
BEGIN_CS(dwords);
/* Set up GA. */
OUT_CB_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
/* Set up the GA to generate texcoords. */
OUT_CB_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
(R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT));
OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4);
OUT_CB_32F(attrib[0]);
OUT_CB_32F(attrib[3]);
OUT_CB_32F(attrib[2]);
OUT_CB_32F(attrib[1]);
OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
OUT_CS_32F(attrib[0]);
OUT_CS_32F(attrib[3]);
OUT_CS_32F(attrib[2]);
OUT_CS_32F(attrib[1]);
}
/* Set up VAP controls. */
OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
OUT_CB_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
OUT_CB(1);
OUT_CB(0);
OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
OUT_CS(1);
OUT_CS(0);
/* Draw. */
OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
R300_VAP_VF_CNTL__PRIM_POINTS);
OUT_CB_32F(x1 + width * 0.5f);
OUT_CB_32F(y1 + height * 0.5f);
OUT_CB_32F(depth);
OUT_CB_32F(1);
OUT_CS_32F(x1 + width * 0.5f);
OUT_CS_32F(y1 + height * 0.5f);
OUT_CS_32F(depth);
OUT_CS_32F(1);
if (vertex_size == 8) {
if (!attrib)
attrib = zeros;
OUT_CB_TABLE(attrib, 4);
OUT_CS_TABLE(attrib, 4);
}
END_CB;
END_CS;
/* Restore the state. */
r300->clip_state.dirty = TRUE;

View File

@ -420,9 +420,3 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws)
return &r300screen->screen;
}
struct r300_winsys_screen *
r300_winsys_screen(struct pipe_screen *screen)
{
return r300_screen(screen)->rws;
}

View File

@ -30,6 +30,8 @@
#include <stdio.h>
struct r300_winsys_screen;
struct r300_screen {
/* Parent class */
struct pipe_screen screen;
@ -44,11 +46,16 @@ struct r300_screen {
};
/* Convenience cast wrapper. */
/* Convenience cast wrappers. */
static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
return (struct r300_screen*)screen;
}
static INLINE struct r300_winsys_screen *
r300_winsys_screen(struct pipe_screen *screen) {
return r300_screen(screen)->rws;
}
/* Debug functionality. */
/**

View File

@ -43,7 +43,7 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context,
if (r300_buffer_is_user_buffer(buf))
return PIPE_UNREFERENCED;
if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf, domain))
if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->buf, domain))
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
return PIPE_UNREFERENCED;
@ -144,6 +144,7 @@ static void *
r300_buffer_transfer_map( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
struct r300_context *r300 = r300_context(pipe);
struct r300_screen *r300screen = r300_screen(pipe->screen);
struct r300_winsys_screen *rws = r300screen->rws;
struct r300_buffer *rbuf = r300_buffer(transfer->resource);
@ -170,23 +171,19 @@ r300_buffer_transfer_map( struct pipe_context *pipe,
rws->buffer_reference(rws, &rbuf->buf, NULL);
rbuf->num_ranges = 0;
rbuf->buf = r300screen->rws->buffer_create(r300screen->rws, 16,
rbuf->b.b.bind,
rbuf->domain,
rbuf->b.b.width0);
rbuf->buf =
r300screen->rws->buffer_create(r300screen->rws,
rbuf->b.b.width0, 16,
rbuf->b.b.bind,
rbuf->b.b.usage,
rbuf->domain);
break;
}
}
}
just_map:
/* XXX buffer_map might flush.
* We cannot flush here because there is a buffer manager between
* the context and winsys, and it does some magic to make the driver
* fast. This is a workaround for the case of multiple contexts. */
rws->set_flush_cb(rws, r300_flush_cb, pipe);
map = rws->buffer_map(rws, rbuf->buf, transfer->usage);
map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage);
if (map == NULL)
return NULL;
@ -273,11 +270,11 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
rbuf->b.b.screen = screen;
rbuf->domain = R300_DOMAIN_GTT;
rbuf->buf = r300screen->rws->buffer_create(r300screen->rws,
alignment,
rbuf->b.b.bind,
rbuf->domain,
rbuf->b.b.width0);
rbuf->buf =
r300screen->rws->buffer_create(r300screen->rws,
rbuf->b.b.width0, alignment,
rbuf->b.b.bind, rbuf->b.b.usage,
rbuf->domain);
if (!rbuf->buf)
goto error2;

View File

@ -97,23 +97,4 @@ static INLINE boolean r300_buffer_is_user_buffer(struct pipe_resource *buffer)
return r300_buffer(buffer)->user_buffer ? true : false;
}
static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws,
struct pipe_resource *buffer,
int rd, int wr)
{
struct r300_buffer *buf = r300_buffer(buffer);
if (!buf->buf)
return true;
return rws->add_buffer(rws, buf->buf, rd, wr);
}
static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws,
struct r300_texture *tex,
int rd, int wr)
{
return rws->add_buffer(rws, tex->buffer, rd, wr);
}
#endif

View File

@ -617,13 +617,13 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300,
if (tex->mip_macrotile[tex->surface_level] != tex->mip_macrotile[level]) {
/* Tiling determines how DRM treats the buffer data.
* We must flush CS when changing it if the buffer is referenced. */
if (r300->rws->is_buffer_referenced(r300->rws, tex->buffer, R300_REF_CS))
if (r300->rws->cs_is_buffer_referenced(r300->cs,
tex->buffer, R300_REF_CS))
r300->context.flush(&r300->context, 0, NULL);
r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
tex->microtile,
tex->mip_macrotile[level]);
tex->microtile, tex->mip_macrotile[level],
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
tex->surface_level = level;
}

View File

@ -908,7 +908,8 @@ static unsigned r300_texture_is_referenced(struct pipe_context *context,
struct r300_context *r300 = r300_context(context);
struct r300_texture *rtex = (struct r300_texture *)texture;
if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer, R300_REF_CS))
if (r300->rws->cs_is_buffer_referenced(r300->cs,
rtex->buffer, R300_REF_CS))
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
return PIPE_UNREFERENCED;
@ -935,8 +936,9 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen,
return FALSE;
}
return rws->buffer_get_handle(rws, tex->buffer, whandle,
r300_texture_get_stride(r300_screen(screen), tex, 0));
return rws->buffer_get_handle(rws, tex->buffer,
r300_texture_get_stride(r300_screen(screen), tex, 0),
whandle);
}
struct u_resource_vtbl r300_texture_vtbl =
@ -1005,8 +1007,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
R300_DOMAIN_GTT :
R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
tex->buffer = rws->buffer_create(rws, 2048, base->bind, tex->domain,
tex->size);
tex->buffer = rws->buffer_create(rws, tex->size, 2048, base->bind,
base->usage, tex->domain);
if (!tex->buffer) {
FREE(tex);
@ -1014,9 +1016,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
}
rws->buffer_set_tiling(rws, tex->buffer,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
tex->microtile,
tex->macrotile);
tex->microtile, tex->macrotile,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
return (struct pipe_resource*)tex;
}
@ -1176,9 +1177,8 @@ r300_texture_from_handle(struct pipe_screen* screen,
if (override_zb_flags) {
rws->buffer_set_tiling(rws, tex->buffer,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
tex->microtile,
tex->macrotile);
tex->microtile, tex->macrotile,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
}
return (struct pipe_resource*)tex;
}

View File

@ -91,19 +91,22 @@ r300_texture_get_transfer(struct pipe_context *ctx,
unsigned usage,
const struct pipe_box *box)
{
struct r300_context *r300 = r300_context(ctx);
struct r300_texture *tex = r300_texture(texture);
struct r300_screen *r300screen = r300_screen(ctx->screen);
struct r300_transfer *trans;
struct pipe_resource base;
boolean referenced_cs, referenced_hw, blittable;
referenced_cs = r300screen->rws->is_buffer_referenced(
r300screen->rws, tex->buffer, R300_REF_CS);
referenced_cs =
r300->rws->cs_is_buffer_referenced(r300->cs,
tex->buffer, R300_REF_CS);
if (referenced_cs) {
referenced_hw = TRUE;
} else {
referenced_hw = r300screen->rws->is_buffer_referenced(
r300screen->rws, tex->buffer, R300_REF_HW);
referenced_hw =
r300->rws->cs_is_buffer_referenced(r300->cs,
tex->buffer, R300_REF_HW);
}
blittable = ctx->screen->is_format_supported(
@ -231,6 +234,7 @@ void r300_texture_transfer_destroy(struct pipe_context *ctx,
void* r300_texture_transfer_map(struct pipe_context *ctx,
struct pipe_transfer *transfer)
{
struct r300_context *r300 = r300_context(ctx);
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
struct r300_transfer *r300transfer = r300_transfer(transfer);
struct r300_texture *tex = r300_texture(transfer->resource);
@ -242,10 +246,11 @@ void* r300_texture_transfer_map(struct pipe_context *ctx,
* (no offset needed). */
return rws->buffer_map(rws,
r300transfer->detiled_texture->buffer,
r300->cs,
transfer->usage);
} else {
/* Tiling is disabled. */
map = rws->buffer_map(rws, tex->buffer,
map = rws->buffer_map(rws, tex->buffer, r300->cs,
transfer->usage);
if (!map) {

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -23,17 +24,25 @@
#ifndef R300_WINSYS_H
#define R300_WINSYS_H
/* The public interface header for the r300 pipe driver.
* Any winsys hosting this pipe needs to implement r300_winsys and then
* call r300_create_screen to start things. */
/* The public winsys interface header for the r300 pipe driver.
* Any winsys hosting this pipe needs to implement r300_winsys_screen and then
* call r300_screen_create to start things. */
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "r300_defines.h"
struct r300_winsys_screen;
struct r300_winsys_buffer;
struct r300_winsys_cs {
uint32_t *ptr; /* Pointer to the beginning of the CS. */
unsigned cdw; /* Number of used dwords. */
unsigned ndw; /* Size of the CS in dwords. */
};
enum r300_value_id {
R300_VID_PCI_ID,
R300_VID_GB_PIPES,
@ -48,120 +57,250 @@ enum r300_reference_domain { /* bitfield */
};
struct r300_winsys_screen {
void (*destroy)(struct r300_winsys_screen *ws);
/**
* Destroy this winsys.
*
* \param ws The winsys this function is called from.
*/
void (*destroy)(struct r300_winsys_screen *ws);
/**
* Query a system value from a winsys.
*
* \param ws The winsys this function is called from.
* \param vid One of the R300_VID_* enums.
*/
uint32_t (*get_value)(struct r300_winsys_screen *ws,
enum r300_value_id vid);
/**************************************************************************
* Buffer management. Buffer attributes are mostly fixed over its lifetime.
*
* Remember that gallium gets to choose the interface it needs, and the
* window systems must then implement that interface (rather than the
* other way around...).
*
* usage is a bitmask of R300_WINSYS_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This
* usage argument is only an optimization hint, not a guarantee, therefore
* proper behavior must be observed in all circumstances.
*
* alignment indicates the client's alignment requirements, eg for
* SSE instructions.
*/
struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws,
unsigned alignment,
unsigned usage,
enum r300_buffer_domain domain,
unsigned size);
*************************************************************************/
/**
* Map the entire data store of a buffer object into the client's address.
* flags is bitmask of R300_WINSYS_BUFFER_USAGE_CPU_READ/WRITE flags.
* Create a buffer object.
*
* \param ws The winsys this function is called from.
* \param size The size to allocate.
* \param alignment An alignment of the buffer in memory.
* \param bind A bitmask of the PIPE_BIND_* flags.
* \param usage A bitmask of the PIPE_USAGE_* flags.
* \param domain A bitmask of the R300_DOMAIN_* flags.
* \return The created buffer object.
*/
void *(*buffer_map)( struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
unsigned usage);
struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws,
unsigned size,
unsigned alignment,
unsigned bind,
unsigned usage,
enum r300_buffer_domain domain);
void (*buffer_unmap)( struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf );
/**
* Reference a buffer object (assign with reference counting).
*
* \param ws The winsys this function is called from.
* \param pdst A destination pointer to set the source buffer to.
* \param src A source buffer object.
*/
void (*buffer_reference)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer **pdst,
struct r300_winsys_buffer *src);
void (*buffer_destroy)( struct r300_winsys_buffer *buf );
/**
* Map the entire data store of a buffer object into the client's address
* space.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to map.
* \param cs A command stream to flush if the buffer is referenced by it.
* \param usage A bitmask of the PIPE_TRANSFER_* flags.
* \return The pointer at the beginning of the buffer.
*/
void *(*buffer_map)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
struct r300_winsys_cs *cs,
enum pipe_transfer_usage usage);
/**
* Unmap a buffer object from the client's address space.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to unmap.
*/
void (*buffer_unmap)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf);
void (*buffer_reference)(struct r300_winsys_screen *rws,
struct r300_winsys_buffer **pdst,
struct r300_winsys_buffer *src);
void (*buffer_wait)(struct r300_winsys_screen *rws,
/**
* Wait for a buffer object until it is not used by a GPU. This is
* equivalent to a fence placed after the last command using the buffer,
* and synchronizing to the fence.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to wait for.
*/
void (*buffer_wait)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf);
/* Add a pipe_resource to the list of buffer objects to validate. */
boolean (*add_buffer)(struct r300_winsys_screen *winsys,
/**
* Return tiling flags describing a memory layout of a buffer object.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to get the flags from.
* \param macrotile A pointer to the return value of the microtile flag.
* \param microtile A pointer to the return value of the macrotile flag.
*
* \note microtile and macrotile are not bitmasks!
*/
void (*buffer_get_tiling)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
enum r300_buffer_tiling *microtile,
enum r300_buffer_tiling *macrotile);
/**
* Set tiling flags describing a memory layout of a buffer object.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to set the flags for.
* \param macrotile A macrotile flag.
* \param microtile A microtile flag.
* \param stride A stride of the buffer in bytes, for texturing.
*
* \note microtile and macrotile are not bitmasks!
*/
void (*buffer_set_tiling)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
enum r300_buffer_tiling microtile,
enum r300_buffer_tiling macrotile,
unsigned stride);
/**
* Get a winsys buffer from a winsys handle. The internal structure
* of the handle is platform-specific and only a winsys should access it.
*
* \param ws The winsys this function is called from.
* \param whandle A winsys handle pointer as was received from a state
* tracker.
* \param stride A pointer to the stride return variable.
* The stride is in bytes.
*/
struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws,
struct winsys_handle *whandle,
unsigned *stride);
/**
* Get a winsys handle from a winsys buffer. The internal structure
* of the handle is platform-specific and only a winsys should access it.
*
* \param ws The winsys this function is called from.
* \param buf A winsys buffer object to get the handle from.
* \param whandle A winsys handle pointer.
* \param stride A stride of the buffer in bytes, for texturing.
* \return TRUE on success.
*/
boolean (*buffer_get_handle)(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
unsigned stride,
struct winsys_handle *whandle);
/**************************************************************************
* Command submission.
*
* Each pipe context should create its own command stream and submit
* commands independently of other contexts.
*************************************************************************/
/**
* Create a command stream.
*
* \param ws The winsys this function is called from.
*/
struct r300_winsys_cs *(*cs_create)(struct r300_winsys_screen *ws);
/**
* Destroy a command stream.
*
* \param cs A command stream to destroy.
*/
void (*cs_destroy)(struct r300_winsys_cs *cs);
/**
* Add a buffer object to the list of buffers to validate.
*
* \param cs A command stream to add buffer for validation against.
* \param buf A winsys buffer to validate.
* \param rd A read domain containing a bitmask
* of the R300_DOMAIN_* flags.
* \param wd A write domain containing a bitmask
* of the R300_DOMAIN_* flags.
*/
void (*cs_add_buffer)(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd);
/**
* Revalidate all currently set up winsys buffers.
* Returns TRUE if a flush is required.
*
* \param cs A command stream to validate.
*/
boolean (*cs_validate)(struct r300_winsys_cs *cs);
/* Revalidate all currently setup pipe_buffers.
* Returns TRUE if a flush is required. */
boolean (*validate)(struct r300_winsys_screen* winsys);
/* Return the number of free dwords in CS. */
unsigned (*get_cs_free_dwords)(struct r300_winsys_screen *winsys);
/* Return the pointer to the first free dword in CS and assume a pipe
* driver wants to fill "count" dwords. */
uint32_t *(*get_cs_pointer)(struct r300_winsys_screen *winsys,
unsigned count);
/* Write a dword to the command buffer. */
void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword);
/* Write a table of dwords to the command buffer. */
void (*write_cs_table)(struct r300_winsys_screen* winsys,
const void *dwords, unsigned count);
/* Write a relocated dword to the command buffer. */
void (*write_cs_reloc)(struct r300_winsys_screen *winsys,
/**
* Write a relocated dword to a command buffer.
*
* \param cs A command stream the relocation is written to.
* \param buf A winsys buffer to write the relocation for.
* \param rd A read domain containing a bitmask of the R300_DOMAIN_* flags.
* \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags.
*/
void (*cs_write_reloc)(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
uint32_t flags);
enum r300_buffer_domain wd);
/* Flush the CS. */
void (*flush_cs)(struct r300_winsys_screen* winsys);
/**
* Flush a command stream.
*
* \param cs A command stream to flush.
*/
void (*cs_flush)(struct r300_winsys_cs *cs);
/* winsys flush - callback from winsys when flush required */
void (*set_flush_cb)(struct r300_winsys_screen *winsys,
void (*flush_cb)(void *), void *data);
/**
* Set a flush callback which is called from winsys when flush is
* required.
*
* \param cs A command stream to set the callback for.
* \param flush A flush callback function associated with the command stream.
* \param user A user pointer that will be passed to the flush callback.
*/
void (*cs_set_flush)(struct r300_winsys_cs *cs,
void (*flush)(void *),
void *user);
void (*reset_bos)(struct r300_winsys_screen *winsys);
/**
* Reset the list of buffer objects to validate, usually called
* prior to adding buffer objects for validation.
*
* \param cs A command stream to reset buffers for.
*/
void (*cs_reset_buffers)(struct r300_winsys_cs *cs);
void (*buffer_get_tiling)(struct r300_winsys_screen *winsys,
struct r300_winsys_buffer *buffer,
enum r300_buffer_tiling *microtiled,
enum r300_buffer_tiling *macrotiled);
void (*buffer_set_tiling)(struct r300_winsys_screen *winsys,
struct r300_winsys_buffer *buffer,
uint32_t pitch,
enum r300_buffer_tiling microtiled,
enum r300_buffer_tiling macrotiled);
uint32_t (*get_value)(struct r300_winsys_screen *winsys,
enum r300_value_id vid);
struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys,
struct winsys_handle *whandle,
unsigned *stride);
boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys,
struct r300_winsys_buffer *buffer,
struct winsys_handle *whandle,
unsigned stride);
boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys,
struct r300_winsys_buffer *buffer,
enum r300_reference_domain domain);
/**
* Return TRUE if a buffer is referenced by a command stream or by hardware
* (i.e. is busy), based on the domain parameter.
*
* \param cs A command stream.
* \param buf A winsys buffer.
* \param domain A bitmask of the R300_REF_* enums.
*/
boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_reference_domain domain);
};
struct r300_winsys_screen *
r300_winsys_screen(struct pipe_screen *screen);
#endif /* R300_WINSYS_H */

View File

@ -43,10 +43,9 @@
#include "radeon_winsys.h"
#define RADEON_USAGE_DOMAIN_GTT (1 << 29)
#define RADEON_USAGE_DOMAIN_VRAM (1 << 30)
#define RADEON_MAX_BOS 24
#define RADEON_PB_USAGE_VERTEX (1 << 28)
#define RADEON_PB_USAGE_DOMAIN_GTT (1 << 29)
#define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30)
static INLINE struct pb_buffer *
radeon_pb_buffer(struct r300_winsys_buffer *buffer)
@ -63,24 +62,26 @@ radeon_libdrm_winsys_buffer(struct pb_buffer *buffer)
struct pb_manager *
radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws);
boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd);
void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd);
void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
uint32_t flags);
enum r300_buffer_domain wd);
struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
uint32_t handle);
void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
void radeon_drm_bufmgr_get_tiling(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
enum r300_buffer_tiling *microtiled,
enum r300_buffer_tiling *macrotiled);
void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
void radeon_drm_bufmgr_set_tiling(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
enum r300_buffer_tiling microtiled,
enum r300_buffer_tiling macrotiled,
uint32_t pitch);
@ -90,9 +91,19 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr);
boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
struct winsys_handle *whandle);
boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
boolean radeon_drm_bufmgr_is_buffer_referenced(struct r300_winsys_cs *cs,
struct r300_winsys_buffer *buf,
enum r300_reference_domain domain);
void radeon_drm_bufmgr_wait(struct pb_buffer *_buf);
void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf);
void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
struct r300_winsys_cs *cs,
enum pipe_transfer_usage usage);
void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf);
#endif

View File

@ -20,6 +20,9 @@ struct radeon_drm_buffer {
struct radeon_bo *bo;
/* The CS associated with the last buffer_map. */
struct radeon_libdrm_cs *cs;
boolean flinked;
uint32_t flink;
@ -65,34 +68,53 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf)
FREE(buf);
}
static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
{
unsigned res = 0;
if (usage & PIPE_TRANSFER_READ)
res |= PB_USAGE_CPU_READ;
if (usage & PIPE_TRANSFER_WRITE)
res |= PB_USAGE_CPU_WRITE;
if (usage & PIPE_TRANSFER_DONTBLOCK)
res |= PB_USAGE_DONTBLOCK;
if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
res |= PB_USAGE_UNSYNCHRONIZED;
return res;
}
static void *
radeon_drm_buffer_map(struct pb_buffer *_buf,
radeon_drm_buffer_map_internal(struct pb_buffer *_buf,
unsigned flags)
{
struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
struct radeon_libdrm_cs *cs = buf->cs;
int write = 0;
if (flags & PIPE_TRANSFER_DONTBLOCK) {
if ((_buf->base.usage & PIPE_BIND_VERTEX_BUFFER) ||
(_buf->base.usage & PIPE_BIND_INDEX_BUFFER))
if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs))
if (flags & PB_USAGE_DONTBLOCK) {
if (_buf->base.usage & RADEON_PB_USAGE_VERTEX)
if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs))
return NULL;
}
if (buf->bo->ptr != NULL)
return buf->bo->ptr;
if (flags & PIPE_TRANSFER_DONTBLOCK) {
if (flags & PB_USAGE_DONTBLOCK) {
uint32_t domain;
if (radeon_bo_is_busy(buf->bo, &domain))
return NULL;
}
if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
cs->flush_cs(cs->flush_data);
}
if (flags & PIPE_TRANSFER_WRITE) {
if (flags & PB_USAGE_CPU_WRITE) {
write = 1;
}
@ -104,7 +126,7 @@ radeon_drm_buffer_map(struct pb_buffer *_buf,
}
static void
radeon_drm_buffer_unmap(struct pb_buffer *_buf)
radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf)
{
(void)_buf;
}
@ -136,8 +158,8 @@ radeon_drm_buffer_fence(struct pb_buffer *buf,
const struct pb_vtbl radeon_drm_buffer_vtbl = {
radeon_drm_buffer_destroy,
radeon_drm_buffer_map,
radeon_drm_buffer_unmap,
radeon_drm_buffer_map_internal,
radeon_drm_buffer_unmap_internal,
radeon_drm_buffer_validate,
radeon_drm_buffer_fence,
radeon_drm_buffer_get_base_buffer,
@ -166,7 +188,7 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
pipe_reference_init(&buf->base.base.reference, 1);
buf->base.base.alignment = 0;
buf->base.base.usage = PIPE_BIND_SAMPLER_VIEW;
buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
buf->base.base.size = 0;
buf->base.vtbl = &radeon_drm_buffer_vtbl;
buf->mgr = mgr;
@ -200,8 +222,8 @@ radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
make_empty_list(buf);
domain =
(desc->usage & RADEON_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) |
(desc->usage & RADEON_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
(desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) |
(desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
buf->bo = radeon_bo_open(rws->bom, 0, size,
desc->alignment, domain, 0);
@ -249,7 +271,8 @@ radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
{
struct radeon_drm_buffer *buf;
struct radeon_drm_buffer *buf = NULL;
if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
buf = radeon_drm_buffer(_buf);
} else {
@ -257,11 +280,35 @@ static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
pb_size offset;
pb_get_base_buffer(_buf, &base_buf, &offset);
buf = radeon_drm_buffer(base_buf);
if (base_buf->vtbl == &radeon_drm_buffer_vtbl)
buf = radeon_drm_buffer(base_buf);
}
return buf;
}
void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
struct r300_winsys_cs *cs,
enum pipe_transfer_usage usage)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
struct radeon_drm_buffer *rbuf = get_drm_buffer(_buf);
if (rbuf)
rbuf->cs = radeon_libdrm_cs(cs);
return pb_map(_buf, get_pb_usage_from_transfer_flags(usage));
}
void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
pb_unmap(_buf);
}
boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
struct winsys_handle *whandle)
{
@ -286,11 +333,12 @@ boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
return TRUE;
}
void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
void radeon_drm_bufmgr_get_tiling(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *_buf,
enum r300_buffer_tiling *microtiled,
enum r300_buffer_tiling *macrotiled)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
uint32_t flags = 0, pitch;
radeon_bo_get_tiling(buf->bo, &flags, &pitch);
@ -304,12 +352,13 @@ void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
*macrotiled = R300_BUFFER_TILED;
}
void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
void radeon_drm_bufmgr_set_tiling(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *_buf,
enum r300_buffer_tiling microtiled,
enum r300_buffer_tiling macrotiled,
uint32_t pitch)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
uint32_t flags = 0;
if (microtiled == R300_BUFFER_TILED)
flags |= RADEON_BO_FLAGS_MICRO_TILE;
@ -324,56 +373,60 @@ void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
radeon_bo_set_tiling(buf->bo, flags, pitch);
}
static uint32_t gem_domain(enum r300_buffer_domain dom)
static uint32_t get_gem_domain(enum r300_buffer_domain domain)
{
uint32_t res = 0;
if (dom & R300_DOMAIN_GTT)
if (domain & R300_DOMAIN_GTT)
res |= RADEON_GEM_DOMAIN_GTT;
if (dom & R300_DOMAIN_VRAM)
if (domain & R300_DOMAIN_VRAM)
res |= RADEON_GEM_DOMAIN_VRAM;
return res;
}
boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd)
void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *rcs,
struct r300_winsys_buffer *_buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
uint32_t gem_rd = gem_domain(rd);
uint32_t gem_wd = gem_domain(wd);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
uint32_t gem_rd = get_gem_domain(rd);
uint32_t gem_wd = get_gem_domain(wd);
radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
gem_rd, gem_wd);
return TRUE;
radeon_cs_space_add_persistent_bo(cs->cs, buf->bo, gem_rd, gem_wd);
}
void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *rcs,
struct r300_winsys_buffer *_buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
uint32_t flags)
enum r300_buffer_domain wd)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
int retval;
uint32_t gem_rd = gem_domain(rd);
uint32_t gem_wd = gem_domain(wd);
uint32_t gem_rd = get_gem_domain(rd);
uint32_t gem_wd = get_gem_domain(wd);
retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
buf->bo, gem_rd, gem_wd, flags);
cs->cs->cdw = cs->base.cdw;
retval = radeon_cs_write_reloc(cs->cs, buf->bo, gem_rd, gem_wd, 0);
cs->base.cdw = cs->cs->cdw;
if (retval) {
fprintf(stderr, "radeon: Relocation of %p (%d, %d, %d) failed!\n",
buf, gem_rd, gem_wd, flags);
buf, gem_rd, gem_wd, 0);
}
}
boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
boolean radeon_drm_bufmgr_is_buffer_referenced(struct r300_winsys_cs *rcs,
struct r300_winsys_buffer *_buf,
enum r300_reference_domain domain)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
uint32_t tmp;
if (domain & R300_REF_CS) {
if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
if (radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
return TRUE;
}
}
@ -387,7 +440,6 @@ boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
return FALSE;
}
void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
{
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
@ -402,9 +454,10 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
make_empty_list(&mgr->buffer_map_list);
}
void radeon_drm_bufmgr_wait(struct pb_buffer *_buf)
void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *_buf)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
radeon_bo_wait(buf->bo);
}

View File

@ -27,37 +27,69 @@
#include "radeon_cs_gem.h"
#include "state_tracker/drm_driver.h"
#include "util/u_memory.h"
static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
enum r300_buffer_domain domain)
{
unsigned res = 0;
if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT))
res |= PB_USAGE_GPU_WRITE;
if (bind & PIPE_BIND_SAMPLER_VIEW)
res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE;
if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
res |= PB_USAGE_GPU_READ;
if (bind & PIPE_BIND_TRANSFER_WRITE)
res |= PB_USAGE_CPU_WRITE;
if (bind & PIPE_BIND_TRANSFER_READ)
res |= PB_USAGE_CPU_READ;
/* Is usage of any use for us? Probably not. */
/* Now add driver-specific usage flags. */
if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
res |= RADEON_PB_USAGE_VERTEX;
if (domain & R300_DOMAIN_GTT)
res |= RADEON_PB_USAGE_DOMAIN_GTT;
if (domain & R300_DOMAIN_VRAM)
res |= RADEON_PB_USAGE_DOMAIN_VRAM;
return res;
}
static struct r300_winsys_buffer *
radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
unsigned alignment,
unsigned usage,
enum r300_buffer_domain domain,
unsigned size)
unsigned size,
unsigned alignment,
unsigned bind,
unsigned usage,
enum r300_buffer_domain domain)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
struct pb_desc desc;
struct pb_manager *provider;
struct pb_buffer *buffer;
/* XXX this is hackish, but it's the only way to pass these flags
* to the real create function. */
usage &= ~(RADEON_USAGE_DOMAIN_GTT | RADEON_USAGE_DOMAIN_VRAM);
if (domain & R300_DOMAIN_GTT)
usage |= RADEON_USAGE_DOMAIN_GTT;
if (domain & R300_DOMAIN_VRAM)
usage |= RADEON_USAGE_DOMAIN_VRAM;
memset(&desc, 0, sizeof(desc));
desc.alignment = alignment;
desc.usage = usage;
desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
if (usage & PIPE_BIND_CONSTANT_BUFFER)
/* Assign a buffer manager. */
if (bind & PIPE_BIND_CONSTANT_BUFFER)
provider = ws->mman;
else if ((usage & PIPE_BIND_VERTEX_BUFFER) ||
(usage & PIPE_BIND_INDEX_BUFFER))
else if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
provider = ws->cman;
else
provider = ws->kman;
buffer = provider->create_buffer(provider, size, &desc);
if (!buffer)
return NULL;
@ -65,55 +97,6 @@ radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
return radeon_libdrm_winsys_buffer(buffer);
}
static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
pb_destroy(_buf);
}
static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buf,
uint32_t pitch,
enum r300_buffer_tiling microtiled,
enum r300_buffer_tiling macrotiled)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch);
}
static void radeon_r300_winsys_buffer_get_tiling(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buf,
enum r300_buffer_tiling *microtiled,
enum r300_buffer_tiling *macrotiled)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
radeon_drm_bufmgr_get_tiling(_buf, microtiled, macrotiled);
}
static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf,
unsigned usage)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
return pb_map(_buf, usage);
}
static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
pb_unmap(_buf);
}
static void radeon_r300_winsys_buffer_wait(struct r300_winsys_screen *ws,
struct r300_winsys_buffer *buf)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
radeon_drm_bufmgr_wait(_buf);
}
static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
struct r300_winsys_buffer **pdst,
struct r300_winsys_buffer *src)
@ -126,20 +109,11 @@ static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
*pdst = radeon_libdrm_winsys_buffer(_dst);
}
static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buf,
enum r300_reference_domain domain)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
return radeon_drm_bufmgr_is_buffer_referenced(_buf, domain);
}
static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
struct winsys_handle *whandle,
unsigned *stride)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
struct pb_buffer *_buf;
*stride = whandle->stride;
@ -150,111 +124,57 @@ static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r
static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buffer,
struct winsys_handle *whandle,
unsigned stride)
unsigned stride,
struct winsys_handle *whandle)
{
struct pb_buffer *_buf = radeon_pb_buffer(buffer);
whandle->stride = stride;
return radeon_drm_bufmgr_get_handle(_buf, whandle);
}
static void radeon_set_flush_cb(struct r300_winsys_screen *rws,
void (*flush_cb)(void *),
void *data)
static void radeon_r300_winsys_cs_set_flush(struct r300_winsys_cs *rcs,
void (*flush)(void *),
void *user)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
ws->flush_cb = flush_cb;
ws->flush_data = data;
radeon_cs_space_set_flush(ws->cs, flush_cb, data);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
cs->flush_cs = flush;
cs->flush_data = user;
radeon_cs_space_set_flush(cs->cs, flush, user);
}
static boolean radeon_add_buffer(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd)
static boolean radeon_r300_winsys_cs_validate(struct r300_winsys_cs *rcs)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
return radeon_drm_bufmgr_add_buffer(_buf, rd, wd);
return radeon_cs_space_check(cs->cs) >= 0;
}
static boolean radeon_validate(struct r300_winsys_screen *rws)
static void radeon_r300_winsys_cs_reset_buffers(struct r300_winsys_cs *rcs)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
if (radeon_cs_space_check(ws->cs) < 0) {
return FALSE;
}
/* Things are fine, we can proceed as normal. */
return TRUE;
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
radeon_cs_space_reset_bos(cs->cs);
}
static unsigned radeon_get_cs_free_dwords(struct r300_winsys_screen *rws)
static void radeon_r300_winsys_cs_flush(struct r300_winsys_cs *rcs)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
struct radeon_cs *cs = ws->cs;
return cs->ndw - cs->cdw;
}
static uint32_t *radeon_get_cs_pointer(struct r300_winsys_screen *rws,
unsigned count)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
struct radeon_cs *cs = ws->cs;
uint32_t *ptr = cs->packets + cs->cdw;
cs->cdw += count;
return ptr;
}
static void radeon_write_cs_dword(struct r300_winsys_screen *rws,
uint32_t dword)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
radeon_cs_write_dword(ws->cs, dword);
}
static void radeon_write_cs_table(struct r300_winsys_screen *rws,
const void *table, unsigned count)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
radeon_cs_write_table(ws->cs, table, count);
}
static void radeon_write_cs_reloc(struct r300_winsys_screen *rws,
struct r300_winsys_buffer *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
uint32_t flags)
{
struct pb_buffer *_buf = radeon_pb_buffer(buf);
radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags);
}
static void radeon_reset_bos(struct r300_winsys_screen *rws)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
radeon_cs_space_reset_bos(ws->cs);
}
static void radeon_flush_cs(struct r300_winsys_screen *rws)
{
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
int retval;
/* Don't flush a zero-sized CS. */
if (!ws->cs->cdw) {
if (!cs->base.cdw) {
return;
}
radeon_drm_bufmgr_flush_maps(ws->kman);
cs->cs->cdw = cs->base.cdw;
radeon_drm_bufmgr_flush_maps(cs->ws->kman);
/* Emit the CS. */
retval = radeon_cs_emit(ws->cs);
retval = radeon_cs_emit(cs->cs);
if (retval) {
if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
radeon_cs_print(ws->cs, stderr);
radeon_cs_print(cs->cs, stderr);
} else {
fprintf(stderr, "radeon: The kernel rejected CS, "
"see dmesg for more information.\n");
@ -265,11 +185,15 @@ static void radeon_flush_cs(struct r300_winsys_screen *rws)
* Someday, when we care about performance, we should really find a way
* to rotate between two or three CS objects so that the GPU can be
* spinning through one CS while another one is being filled. */
radeon_cs_erase(ws->cs);
radeon_cs_erase(cs->cs);
cs->base.ptr = cs->cs->packets;
cs->base.cdw = cs->cs->cdw;
cs->base.ndw = cs->cs->ndw;
}
static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
enum r300_value_id id)
enum r300_value_id id)
{
struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
@ -288,11 +212,42 @@ static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
return 0;
}
static void
radeon_winsys_destroy(struct r300_winsys_screen *rws)
static struct r300_winsys_cs *radeon_r300_winsys_cs_create(struct r300_winsys_screen *rws)
{
struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
struct radeon_libdrm_cs *cs = CALLOC_STRUCT(radeon_libdrm_cs);
if (!cs)
return NULL;
/* Size limit on IBs is 64 kibibytes. */
cs->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
if (!cs->cs) {
FREE(cs);
return NULL;
}
radeon_cs_set_limit(cs->cs,
RADEON_GEM_DOMAIN_GTT, ws->gart_size);
radeon_cs_set_limit(cs->cs,
RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
cs->ws = ws;
cs->base.ptr = cs->cs->packets;
cs->base.cdw = cs->cs->cdw;
cs->base.ndw = cs->cs->ndw;
return &cs->base;
}
static void radeon_r300_winsys_cs_destroy(struct r300_winsys_cs *rcs)
{
struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
radeon_cs_destroy(cs->cs);
}
static void radeon_winsys_destroy(struct r300_winsys_screen *rws)
{
struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
radeon_cs_destroy(ws->cs);
ws->cman->destroy(ws->cman);
ws->kman->destroy(ws->kman);
@ -302,10 +257,8 @@ radeon_winsys_destroy(struct r300_winsys_screen *rws)
radeon_cs_manager_gem_dtor(ws->csm);
}
boolean
radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
boolean radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
{
ws->csm = radeon_cs_manager_gem_ctor(fd);
if (!ws->csm)
goto fail;
@ -324,39 +277,28 @@ radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
if (!ws->mman)
goto fail;
/* Size limit on IBs is 64 kibibytes. */
ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
if (!ws->cs)
goto fail;
radeon_cs_set_limit(ws->cs,
RADEON_GEM_DOMAIN_GTT, ws->gart_size);
radeon_cs_set_limit(ws->cs,
RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
ws->base.add_buffer = radeon_add_buffer;
ws->base.validate = radeon_validate;
ws->base.destroy = radeon_winsys_destroy;
ws->base.get_cs_free_dwords = radeon_get_cs_free_dwords;
ws->base.get_cs_pointer = radeon_get_cs_pointer;
ws->base.write_cs_dword = radeon_write_cs_dword;
ws->base.write_cs_table = radeon_write_cs_table;
ws->base.write_cs_reloc = radeon_write_cs_reloc;
ws->base.flush_cs = radeon_flush_cs;
ws->base.reset_bos = radeon_reset_bos;
ws->base.set_flush_cb = radeon_set_flush_cb;
ws->base.get_value = radeon_get_value;
ws->base.buffer_create = radeon_r300_winsys_buffer_create;
ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy;
ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling;
ws->base.buffer_get_tiling = radeon_r300_winsys_buffer_get_tiling;
ws->base.buffer_map = radeon_r300_winsys_buffer_map;
ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
ws->base.buffer_wait = radeon_r300_winsys_buffer_wait;
ws->base.buffer_set_tiling = radeon_drm_bufmgr_set_tiling;
ws->base.buffer_get_tiling = radeon_drm_bufmgr_get_tiling;
ws->base.buffer_map = radeon_drm_buffer_map;
ws->base.buffer_unmap = radeon_drm_buffer_unmap;
ws->base.buffer_wait = radeon_drm_bufmgr_wait;
ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced;
ws->base.cs_create = radeon_r300_winsys_cs_create;
ws->base.cs_destroy = radeon_r300_winsys_cs_destroy;
ws->base.cs_add_buffer = radeon_drm_bufmgr_add_buffer;
ws->base.cs_validate = radeon_r300_winsys_cs_validate;
ws->base.cs_write_reloc = radeon_drm_bufmgr_write_reloc;
ws->base.cs_flush = radeon_r300_winsys_cs_flush;
ws->base.cs_reset_buffers = radeon_r300_winsys_cs_reset_buffers;
ws->base.cs_set_flush = radeon_r300_winsys_cs_set_flush;
ws->base.cs_is_buffer_referenced = radeon_drm_bufmgr_is_buffer_referenced;
return TRUE;
fail:
@ -373,7 +315,5 @@ fail:
if (ws->mman)
ws->mman->destroy(ws->mman);
if (ws->cs)
radeon_cs_destroy(ws->cs);
return FALSE;
}

View File

@ -75,19 +75,32 @@ struct radeon_libdrm_winsys {
/* Radeon CS manager. */
struct radeon_cs_manager *csm;
};
/* Current CS. */
struct radeon_libdrm_cs {
struct r300_winsys_cs base;
/* The winsys. */
struct radeon_libdrm_winsys *ws;
/* The libdrm command stream. */
struct radeon_cs *cs;
/* Flush CB */
void (*flush_cb)(void *);
/* Flush CS. */
void (*flush_cs)(void *);
void *flush_data;
};
static INLINE struct radeon_libdrm_winsys *
radeon_winsys_screen(struct r300_winsys_screen *base)
static INLINE struct radeon_libdrm_cs *
radeon_libdrm_cs(struct r300_winsys_cs *base)
{
return (struct radeon_libdrm_winsys *)base;
return (struct radeon_libdrm_cs*)base;
}
static INLINE struct radeon_libdrm_winsys *
radeon_libdrm_winsys(struct r300_winsys_screen *base)
{
return (struct radeon_libdrm_winsys*)base;
}
#endif