From: Marek Olšák Date: Tue, 13 Jul 2010 23:59:57 +0000 (+0200) Subject: r300g: rebuild winsys and command submission to support multiple contexts X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fe3caa91d3f637bf9cf9f9e7adb992aa8c7ef8e4;p=mesa.git r300g: rebuild winsys and command submission to support multiple contexts --- diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h index 61b28330b0b..9d3d4fc1b19 100644 --- a/src/gallium/drivers/r300/r300_cb.h +++ b/src/gallium/drivers/r300/r300_cb.h @@ -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", \ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 1beab7628a0..0f7deca2826 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index df4299b7ea3..55cec881490 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -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); diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 1db7da642bd..3beb625d430 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -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,49 +66,39 @@ #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_TABLE(values, count) do { \ - cs_winsys->write_cs_table(cs_winsys, values, count); \ - CS_DEBUG(cs_count -= count;) \ -} while (0) +#define OUT_CS_ONE_REG(register, count) \ + OUT_CS(CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR) -#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) \ + OUT_CS(CP_PACKET3(op, count)) -#define OUT_CS_PKT3(op, count) do { \ - cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \ - CS_DEBUG(cs_count--;) \ +#define OUT_CS_TABLE(values, count) do { \ + memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \ + cs_copy->cdw += count; \ + CS_DEBUG(cs_count -= count;) \ } while (0) @@ -116,26 +106,26 @@ * 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 */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index daae6dd510c..10d9e675ac0 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -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. */ diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 6f31ba159ac..9e5bfebe245 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -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. */ diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 10086ee9256..5b0121ce9e1 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 970cb688378..d30de1a4217 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index a3b08555cde..f28b05506e3 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -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; -} diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index c6b4b57c3bd..58270230e1d 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -30,6 +30,8 @@ #include +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. */ /** diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index f49f36b6264..15d3f25c776 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index ff355858704..4f7c0ec87e5 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -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 diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index f4c6a262d4a..8214bcc2464 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -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; } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index e8b1d670070..5750bc4329f 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -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; } diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 2eb93e19111..3cc4c8c9582 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -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) { diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 7687eac53eb..7e115c2d624 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson + * Copyright 2010 Marek Olšák * * 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 { + /** + * 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...). + *************************************************************************/ + + /** + * Create a buffer object. * - * 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. + * \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. */ struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws, - unsigned alignment, - unsigned usage, - enum r300_buffer_domain domain, - unsigned size); + unsigned size, + unsigned alignment, + unsigned bind, + unsigned usage, + enum r300_buffer_domain domain); /** - * 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. + * 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_map)( struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, - unsigned usage); + void (*buffer_reference)(struct r300_winsys_screen *ws, + struct r300_winsys_buffer **pdst, + struct r300_winsys_buffer *src); - void (*buffer_unmap)( struct r300_winsys_screen *ws, - 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); - void (*buffer_destroy)( struct r300_winsys_buffer *buf ); + /** + * 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); + /** + * 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); - void (*buffer_reference)(struct r300_winsys_screen *rws, - struct r300_winsys_buffer **pdst, - struct r300_winsys_buffer *src); + /** + * 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); - void (*buffer_wait)(struct r300_winsys_screen *rws, - struct r300_winsys_buffer *buf); + /** + * 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); - /* Add a pipe_resource to the list of buffer objects to validate. */ - boolean (*add_buffer)(struct r300_winsys_screen *winsys, - struct r300_winsys_buffer *buf, - enum r300_buffer_domain rd, - enum r300_buffer_domain wd); + /** + * 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); - /* Revalidate all currently setup pipe_buffers. - * Returns TRUE if a flush is required. */ - boolean (*validate)(struct r300_winsys_screen* winsys); + /************************************************************************** + * Command submission. + * + * Each pipe context should create its own command stream and submit + * commands independently of other contexts. + *************************************************************************/ - /* Return the number of free dwords in CS. */ - unsigned (*get_cs_free_dwords)(struct r300_winsys_screen *winsys); + /** + * Create a command stream. + * + * \param ws The winsys this function is called from. + */ + struct r300_winsys_cs *(*cs_create)(struct r300_winsys_screen *ws); - /* 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); + /** + * Destroy a command stream. + * + * \param cs A command stream to destroy. + */ + void (*cs_destroy)(struct r300_winsys_cs *cs); - /* Write a dword to the command buffer. */ - void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword); + /** + * 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); - /* Write a table of dwords to the command buffer. */ - void (*write_cs_table)(struct r300_winsys_screen* winsys, - const void *dwords, unsigned count); + /** + * 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); - /* 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); - - /* winsys flush - callback from winsys when flush required */ - void (*set_flush_cb)(struct r300_winsys_screen *winsys, - void (*flush_cb)(void *), void *data); - - void (*reset_bos)(struct r300_winsys_screen *winsys); - - 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); + /** + * Flush a command stream. + * + * \param cs A command stream to flush. + */ + void (*cs_flush)(struct r300_winsys_cs *cs); - struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys, - struct winsys_handle *whandle, - unsigned *stride); + /** + * 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); - boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys, - struct r300_winsys_buffer *buffer, - struct winsys_handle *whandle, - unsigned stride); + /** + * 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); - 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 */ diff --git a/src/gallium/winsys/radeon/drm/radeon_buffer.h b/src/gallium/winsys/radeon/drm/radeon_buffer.h index 73cb6a579b4..a8137d85e83 100644 --- a/src/gallium/winsys/radeon/drm/radeon_buffer.h +++ b/src/gallium/winsys/radeon/drm/radeon_buffer.h @@ -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 diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c index c5f133e7b28..5ea5912089e 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c @@ -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); } diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c index af35497fd7c..4e89c070831 100644 --- a/src/gallium/winsys/radeon/drm/radeon_r300.c +++ b/src/gallium/winsys/radeon/drm/radeon_r300.c @@ -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) -{ - 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); -} - -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) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buf); - - return radeon_drm_bufmgr_add_buffer(_buf, rd, wd); -} - -static boolean radeon_validate(struct r300_winsys_screen *rws) +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); - 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); + cs->flush_cs = flush; + cs->flush_data = user; + radeon_cs_space_set_flush(cs->cs, flush, user); } -static unsigned radeon_get_cs_free_dwords(struct r300_winsys_screen *rws) +static boolean radeon_r300_winsys_cs_validate(struct r300_winsys_cs *rcs) { - struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); - struct radeon_cs *cs = ws->cs; + struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs); - return cs->ndw - cs->cdw; + return radeon_cs_space_check(cs->cs) >= 0; } -static uint32_t *radeon_get_cs_pointer(struct r300_winsys_screen *rws, - unsigned count) +static void radeon_r300_winsys_cs_reset_buffers(struct r300_winsys_cs *rcs) { - 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; + struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs); + radeon_cs_space_reset_bos(cs->cs); } -static void radeon_write_cs_dword(struct r300_winsys_screen *rws, - uint32_t dword) +static void radeon_r300_winsys_cs_flush(struct r300_winsys_cs *rcs) { - 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; } diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index ca789be8e93..9a25e7679c9 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -75,19 +75,32 @@ struct radeon_libdrm_winsys { /* Radeon CS manager. */ struct radeon_cs_manager *csm; +}; + +struct radeon_libdrm_cs { + struct r300_winsys_cs base; + + /* The winsys. */ + struct radeon_libdrm_winsys *ws; - /* Current CS. */ + /* 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_cs * +radeon_libdrm_cs(struct r300_winsys_cs *base) +{ + return (struct radeon_libdrm_cs*)base; +} + static INLINE struct radeon_libdrm_winsys * -radeon_winsys_screen(struct r300_winsys_screen *base) +radeon_libdrm_winsys(struct r300_winsys_screen *base) { - return (struct radeon_libdrm_winsys *)base; + return (struct radeon_libdrm_winsys*)base; } #endif