This creates a cleaner winsys and drop the simple screen stuff. It makes r300g use pb_bufmgr structs. It also tries to avoid overheads from mapping too often. v5: clean warnings v6: break out of cache check on first buffer - since most likely the first busy one implies all after it are busy. v7: cleanup a bit v8-merged: drop cman for now to just get all the interface changes in first. rework to changes that happened upstream Signed-off-by: Dave Airlie <airlied@redhat.com>tags/mesa-7.9-rc1
@@ -14,6 +14,7 @@ C_SOURCES = \ | |||
r300_query.c \ | |||
r300_render.c \ | |||
r300_screen.c \ | |||
r300_screen_buffer.c \ | |||
r300_state.c \ | |||
r300_state_derived.c \ | |||
r300_state_invariant.c \ |
@@ -24,6 +24,7 @@ | |||
#include "util/u_memory.h" | |||
#include "util/u_simple_list.h" | |||
#include "util/u_upload_mgr.h" | |||
#include "r300_blit.h" | |||
#include "r300_context.h" | |||
@@ -55,6 +56,9 @@ static void r300_destroy_context(struct pipe_context* context) | |||
FREE(query); | |||
} | |||
u_upload_destroy(r300->upload_vb); | |||
u_upload_destroy(r300->upload_ib); | |||
FREE(r300->blend_color_state.state); | |||
FREE(r300->clip_state.state); | |||
FREE(r300->fb_state.state); | |||
@@ -72,8 +76,7 @@ r300_is_texture_referenced(struct pipe_context *pipe, | |||
struct pipe_texture *texture, | |||
unsigned face, unsigned level) | |||
{ | |||
return pipe->is_buffer_referenced(pipe, | |||
((struct r300_texture *)texture)->buffer); | |||
return 0; | |||
} | |||
static unsigned int | |||
@@ -157,14 +160,14 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, | |||
{ | |||
struct r300_context* r300 = CALLOC_STRUCT(r300_context); | |||
struct r300_screen* r300screen = r300_screen(screen); | |||
struct radeon_winsys* radeon_winsys = r300screen->radeon_winsys; | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
if (!r300) | |||
return NULL; | |||
r300->winsys = radeon_winsys; | |||
r300->rws = rws; | |||
r300->context.winsys = (struct pipe_winsys*)radeon_winsys; | |||
r300->context.winsys = (struct pipe_winsys*)rws; | |||
r300->context.screen = screen; | |||
r300->context.priv = priv; | |||
@@ -214,10 +217,29 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, | |||
r300->invariant_state.dirty = TRUE; | |||
r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); | |||
rws->set_flush_cb(r300->rws, r300_flush_cb, r300); | |||
r300->dirty_hw++; | |||
r300->blitter = util_blitter_create(&r300->context); | |||
r300->upload_ib = u_upload_create(screen, | |||
32 * 1024, 16, | |||
PIPE_BUFFER_USAGE_INDEX); | |||
if (r300->upload_ib == NULL) | |||
goto no_upload_ib; | |||
r300->upload_vb = u_upload_create(screen, | |||
128 * 1024, 16, | |||
PIPE_BUFFER_USAGE_VERTEX); | |||
if (r300->upload_vb == NULL) | |||
goto no_upload_vb; | |||
return &r300->context; | |||
no_upload_ib: | |||
u_upload_destroy(r300->upload_ib); | |||
no_upload_vb: | |||
FREE(r300); | |||
return NULL; | |||
} |
@@ -32,6 +32,7 @@ | |||
#include "r300_screen.h" | |||
struct u_upload_mgr; | |||
struct r300_context; | |||
struct r300_fragment_shader; | |||
@@ -268,7 +269,7 @@ struct r300_texture { | |||
boolean is_npot; | |||
/* Pipe buffer backing this texture. */ | |||
struct pipe_buffer* buffer; | |||
struct r300_winsys_buffer *buffer; | |||
/* Registers carrying texture format data. */ | |||
struct r300_texture_format_state state; | |||
@@ -302,7 +303,7 @@ struct r300_context { | |||
struct pipe_context context; | |||
/* The interface to the windowing system, etc. */ | |||
struct radeon_winsys* winsys; | |||
struct r300_winsys_screen *rws; | |||
/* Draw module. Used mostly for SW TCL. */ | |||
struct draw_context* draw; | |||
/* Accelerated blit support. */ | |||
@@ -368,6 +369,7 @@ struct r300_context { | |||
int vertex_buffer_max_index; | |||
/* Vertex elements for Gallium. */ | |||
struct r300_vertex_element_state *velems; | |||
bool any_user_vbs; | |||
/* Vertex info for Draw. */ | |||
struct vertex_info vertex_info; | |||
@@ -388,6 +390,9 @@ struct r300_context { | |||
uint32_t zbuffer_bpp; | |||
/* Whether scissor is enabled. */ | |||
boolean scissor_enabled; | |||
/* upload managers */ | |||
struct u_upload_mgr *upload_vb; | |||
struct u_upload_mgr *upload_ib; | |||
}; | |||
/* Convenience cast wrapper. */ |
@@ -51,7 +51,7 @@ | |||
#define CS_LOCALS(context) \ | |||
struct r300_context* const cs_context_copy = (context); \ | |||
struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \ | |||
struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \ | |||
int cs_count = 0; (void) cs_count; | |||
#define CHECK_CS(size) \ | |||
@@ -105,22 +105,34 @@ | |||
cs_count--; \ | |||
} while (0) | |||
#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \ | |||
#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \ | |||
DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \ | |||
"domains (%d, %d, %d)\n", \ | |||
bo, offset, rd, wd, flags); \ | |||
assert(bo); \ | |||
cs_winsys->write_cs_dword(cs_winsys, offset); \ | |||
cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ | |||
r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ | |||
cs_count -= 3; \ | |||
} while (0) | |||
#define OUT_CS_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ | |||
#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \ | |||
DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \ | |||
"domains (%d, %d, %d)\n", \ | |||
tex, offset, rd, wd, flags); \ | |||
assert(tex); \ | |||
cs_winsys->write_cs_dword(cs_winsys, offset); \ | |||
r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \ | |||
cs_count -= 3; \ | |||
} while (0) | |||
#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ | |||
DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \ | |||
"domains (%d, %d, %d)\n", \ | |||
bo, rd, wd, flags); \ | |||
assert(bo); \ | |||
cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ | |||
r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ | |||
cs_count -= 2; \ | |||
} while (0) | |||
@@ -32,6 +32,8 @@ | |||
#include "r300_emit.h" | |||
#include "r300_fs.h" | |||
#include "r300_screen.h" | |||
#include "r300_screen_buffer.h" | |||
#include "r300_state_inlines.h" | |||
#include "r300_vs.h" | |||
void r300_emit_blend_state(struct r300_context* r300, | |||
@@ -415,10 +417,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) | |||
assert(tex && tex->buffer && "cbuf is marked, but NULL!"); | |||
OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); | |||
OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); | |||
OUT_CS_RELOC(tex->buffer, tex->fb_state.colorpitch[surf->level], | |||
OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level], | |||
0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt); | |||
@@ -434,12 +436,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) | |||
assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); | |||
OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); | |||
OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format); | |||
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); | |||
OUT_CS_RELOC(tex->buffer, tex->fb_state.depthpitch[surf->level], | |||
OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level], | |||
0, RADEON_GEM_DOMAIN_VRAM, 0); | |||
} | |||
@@ -491,13 +493,13 @@ static void r300_emit_query_finish(struct r300_context *r300, | |||
/* pipe 3 only */ | |||
OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); | |||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); | |||
OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), | |||
0, RADEON_GEM_DOMAIN_GTT, 0); | |||
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(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), | |||
0, RADEON_GEM_DOMAIN_GTT, 0); | |||
case 2: | |||
/* pipe 1 only */ | |||
@@ -505,13 +507,13 @@ static void r300_emit_query_finish(struct r300_context *r300, | |||
OUT_CS_REG(R300_SU_REG_DEST, | |||
1 << (caps->high_second_pipe ? 3 : 1)); | |||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); | |||
OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), | |||
0, RADEON_GEM_DOMAIN_GTT, 0); | |||
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(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), | |||
0, RADEON_GEM_DOMAIN_GTT, 0); | |||
break; | |||
default: | |||
@@ -533,7 +535,7 @@ static void rv530_emit_query_single(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(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); | |||
END_CS; | |||
} | |||
@@ -546,10 +548,10 @@ static void rv530_emit_query_double(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(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
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(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); | |||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); | |||
END_CS; | |||
} | |||
@@ -747,7 +749,7 @@ void r300_emit_textures_state(struct r300_context *r300, | |||
OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); | |||
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); | |||
OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config, | |||
OUT_CS_TEX_RELOC(allstate->textures[i], texstate->tile_config, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); | |||
} | |||
} | |||
@@ -788,8 +790,8 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) | |||
} | |||
for (i = 0; i < aos_count; i++) { | |||
OUT_CS_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, | |||
RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
OUT_CS_BUF_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, | |||
RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
} | |||
END_CS; | |||
} | |||
@@ -814,7 +816,7 @@ void r300_emit_vertex_buffer(struct r300_context* r300) | |||
OUT_CS(r300->vertex_info.size | | |||
(r300->vertex_info.size << 8)); | |||
OUT_CS(r300->vbo_offset); | |||
OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
OUT_CS_BUF_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
END_CS; | |||
} | |||
@@ -1009,16 +1011,22 @@ void r300_emit_buffer_validate(struct r300_context *r300, | |||
unsigned i; | |||
boolean invalid = FALSE; | |||
/* upload buffers first */ | |||
if (r300->any_user_vbs) { | |||
r300_upload_user_buffers(r300); | |||
r300->any_user_vbs = false; | |||
} | |||
/* Clean out BOs. */ | |||
r300->winsys->reset_bos(r300->winsys); | |||
r300->rws->reset_bos(r300->rws); | |||
validate: | |||
/* Color buffers... */ | |||
for (i = 0; i < fb->nr_cbufs; i++) { | |||
tex = (struct r300_texture*)fb->cbufs[i]->texture; | |||
assert(tex && tex->buffer && "cbuf is marked, but NULL!"); | |||
if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, | |||
0, RADEON_GEM_DOMAIN_VRAM)) { | |||
if (!r300_add_texture(r300->rws, tex, | |||
0, RADEON_GEM_DOMAIN_VRAM)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
@@ -1027,8 +1035,8 @@ validate: | |||
if (fb->zsbuf) { | |||
tex = (struct r300_texture*)fb->zsbuf->texture; | |||
assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); | |||
if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, | |||
0, RADEON_GEM_DOMAIN_VRAM)) { | |||
if (!r300_add_texture(r300->rws, tex, | |||
0, RADEON_GEM_DOMAIN_VRAM)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
@@ -1038,24 +1046,24 @@ validate: | |||
tex = texstate->textures[i]; | |||
if (!tex || !texstate->sampler_states[i]) | |||
continue; | |||
if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { | |||
if (!r300_add_texture(r300->rws, tex, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
} | |||
/* ...occlusion query buffer... */ | |||
if (r300->dirty_state & R300_NEW_QUERY) { | |||
if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, | |||
0, RADEON_GEM_DOMAIN_GTT)) { | |||
if (!r300_add_buffer(r300->rws, r300->oqbo, | |||
0, RADEON_GEM_DOMAIN_GTT)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
} | |||
/* ...vertex buffer for SWTCL path... */ | |||
if (r300->vbo) { | |||
if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
if (!r300_add_buffer(r300->rws, r300->vbo, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
@@ -1065,23 +1073,22 @@ validate: | |||
for (i = 0; i < r300->velems->count; i++) { | |||
pbuf = vbuf[velem[i].vertex_buffer_index].buffer; | |||
if (!r300->winsys->add_buffer(r300->winsys, pbuf, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
if (!r300_add_buffer(r300->rws, pbuf, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
} | |||
} | |||
/* ...and index buffer for HWTCL path. */ | |||
if (index_buffer) { | |||
if (!r300->winsys->add_buffer(r300->winsys, index_buffer, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
if (!r300_add_buffer(r300->rws, index_buffer, | |||
RADEON_GEM_DOMAIN_GTT, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
goto validate; | |||
} | |||
} | |||
if (!r300->winsys->validate(r300->winsys)) { | |||
if (!r300->rws->validate(r300->rws)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
if (invalid) { | |||
/* Well, hell. */ |
@@ -30,10 +30,12 @@ | |||
#include "util/u_format.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_upload_mgr.h" | |||
#include "util/u_prim.h" | |||
#include "r300_cs.h" | |||
#include "r300_context.h" | |||
#include "r300_screen_buffer.h" | |||
#include "r300_emit.h" | |||
#include "r300_reg.h" | |||
#include "r300_render.h" | |||
@@ -123,7 +125,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, | |||
static boolean r300_reserve_cs_space(struct r300_context *r300, | |||
unsigned dwords) | |||
{ | |||
if (!r300->winsys->check_cs(r300->winsys, dwords)) { | |||
if (!r300->rws->check_cs(r300->rws, dwords)) { | |||
r300->context.flush(&r300->context, 0, NULL); | |||
return TRUE; | |||
} | |||
@@ -153,15 +155,14 @@ static boolean immd_is_good_idea(struct r300_context *r300, | |||
if (!checked[vbi]) { | |||
vbuf = &r300->vertex_buffer[vbi]; | |||
if (r300->winsys->is_buffer_referenced(r300->winsys, | |||
vbuf->buffer)) { | |||
if (r300_buffer_is_referenced(r300, | |||
vbuf->buffer)) { | |||
/* It's a very bad idea to map it... */ | |||
return FALSE; | |||
} | |||
checked[vbi] = TRUE; | |||
} | |||
} | |||
return TRUE; | |||
} | |||
@@ -345,8 +346,8 @@ static void r300_emit_draw_elements(struct r300_context *r300, | |||
OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | | |||
(0 << R300_INDX_BUFFER_SKIP_SHIFT)); | |||
OUT_CS(offset_dwords << 2); | |||
OUT_CS_RELOC(indexBuffer, count_dwords, | |||
RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
OUT_CS_BUF_RELOC(indexBuffer, count_dwords, | |||
RADEON_GEM_DOMAIN_GTT, 0, 0); | |||
END_CS; | |||
} | |||
@@ -413,12 +414,16 @@ void r300_draw_range_elements(struct pipe_context* pipe, | |||
r300_update_derived_state(r300); | |||
r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); | |||
/* 128 dwords for emit_aos and emit_draw_elements */ | |||
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); | |||
r300_emit_buffer_validate(r300, TRUE, indexBuffer); | |||
r300_emit_dirty_state(r300); | |||
r300_emit_aos(r300, 0); | |||
u_upload_flush(r300->upload_vb); | |||
u_upload_flush(r300->upload_ib); | |||
if (alt_num_verts || count <= 65535) { | |||
r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, | |||
maxIndex, mode, start, count); | |||
@@ -441,7 +446,7 @@ void r300_draw_range_elements(struct pipe_context* pipe, | |||
} | |||
if (indexBuffer != orgIndexBuffer) { | |||
pipe->screen->buffer_destroy(indexBuffer); | |||
pipe_buffer_reference( &indexBuffer, NULL ); | |||
} | |||
} | |||
@@ -505,6 +510,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, | |||
} | |||
} while (count); | |||
} | |||
u_upload_flush(r300->upload_vb); | |||
} | |||
} | |||
@@ -23,13 +23,14 @@ | |||
#include "util/u_format.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_simple_screen.h" | |||
#include "r300_context.h" | |||
#include "r300_texture.h" | |||
#include "radeon_winsys.h" | |||
#include "r300_screen_buffer.h" | |||
/* Return the identifier behind whom the brave coders responsible for this | |||
* amalgamation of code, sweat, and duct tape, routinely obscure their names. | |||
* | |||
@@ -253,15 +254,19 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, | |||
static void r300_destroy_screen(struct pipe_screen* pscreen) | |||
{ | |||
struct r300_screen* r300screen = r300_screen(pscreen); | |||
struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); | |||
if (rws) | |||
rws->destroy(rws); | |||
FREE(r300screen->caps); | |||
FREE(r300screen); | |||
} | |||
struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) | |||
struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws) | |||
{ | |||
struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen); | |||
struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities); | |||
struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen); | |||
struct r300_capabilities *caps = CALLOC_STRUCT(r300_capabilities); | |||
if (!r300screen || !caps) { | |||
FREE(r300screen); | |||
@@ -269,16 +274,16 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) | |||
return NULL; | |||
} | |||
caps->pci_id = radeon_winsys->pci_id; | |||
caps->num_frag_pipes = radeon_winsys->gb_pipes; | |||
caps->num_z_pipes = radeon_winsys->z_pipes; | |||
caps->pci_id = rws->get_value(rws, R300_VID_PCI_ID); | |||
caps->num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES); | |||
caps->num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES); | |||
r300_init_debug(r300screen); | |||
r300_parse_chipset(caps); | |||
r300screen->caps = caps; | |||
r300screen->radeon_winsys = radeon_winsys; | |||
r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys; | |||
r300screen->rws = rws; | |||
r300screen->screen.winsys = (struct pipe_winsys*)rws; | |||
r300screen->screen.destroy = r300_destroy_screen; | |||
r300screen->screen.get_name = r300_get_name; | |||
r300screen->screen.get_vendor = r300_get_vendor; | |||
@@ -288,8 +293,13 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) | |||
r300screen->screen.context_create = r300_create_context; | |||
r300_init_screen_texture_functions(&r300screen->screen); | |||
u_simple_screen_init(&r300screen->screen); | |||
r300_screen_init_buffer_functions(r300screen); | |||
return &r300screen->screen; | |||
} | |||
struct r300_winsys_screen * | |||
r300_winsys_screen(struct pipe_screen *screen) | |||
{ | |||
return r300_screen(screen)->rws; | |||
} |
@@ -36,7 +36,7 @@ struct r300_screen { | |||
/* Parent class */ | |||
struct pipe_screen screen; | |||
struct radeon_winsys* radeon_winsys; | |||
struct r300_winsys_screen *rws; | |||
/* Chipset capabilities */ | |||
struct r300_capabilities* caps; | |||
@@ -51,9 +51,6 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { | |||
return (struct r300_screen*)screen; | |||
} | |||
/* Creates a new r300 screen. */ | |||
struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); | |||
/* Debug functionality. */ | |||
/** |
@@ -0,0 +1,314 @@ | |||
/* | |||
* Copyright 2010 Red Hat Inc. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* on the rights to use, copy, modify, merge, publish, distribute, sub | |||
* license, and/or sell copies of the Software, and to permit persons to whom | |||
* the Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the next | |||
* paragraph) shall be included in all copies or substantial portions of the | |||
* Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, | |||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | |||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | |||
* USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: Dave Airlie | |||
*/ | |||
#include <stdio.h> | |||
#include "util/u_inlines.h" | |||
#include "util/u_format.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_upload_mgr.h" | |||
#include "util/u_math.h" | |||
#include "r300_screen_buffer.h" | |||
#include "r300_winsys.h" | |||
boolean r300_buffer_is_referenced(struct r300_context *r300, | |||
struct pipe_buffer *buf) | |||
{ | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
if (r300_buffer_is_user_buffer(buf)) | |||
return FALSE; | |||
return r300->rws->is_buffer_referenced(r300->rws, rbuf->buf); | |||
} | |||
int r300_upload_index_buffer(struct r300_context *r300, | |||
struct pipe_buffer **index_buffer, | |||
unsigned index_size, | |||
unsigned start, | |||
unsigned count) | |||
{ | |||
struct pipe_buffer *upload_buffer = NULL; | |||
unsigned index_offset = start * index_size; | |||
int ret = 0; | |||
if (r300_buffer_is_user_buffer(*index_buffer)) { | |||
ret = u_upload_buffer(r300->upload_ib, | |||
index_offset, | |||
count * index_size, | |||
*index_buffer, | |||
&index_offset, | |||
&upload_buffer); | |||
if (ret) { | |||
goto done; | |||
} | |||
*index_buffer = upload_buffer; | |||
} | |||
done: | |||
// if (upload_buffer) | |||
// pipe_buffer_reference(&upload_buffer, NULL); | |||
return ret; | |||
} | |||
int r300_upload_user_buffers(struct r300_context *r300) | |||
{ | |||
enum pipe_error ret = PIPE_OK; | |||
int i, nr; | |||
nr = r300->vertex_buffer_count; | |||
for (i = 0; i < nr; i++) { | |||
if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { | |||
struct pipe_buffer *upload_buffer = NULL; | |||
unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ | |||
unsigned size = r300->vertex_buffer[i].buffer->size; | |||
unsigned upload_offset; | |||
ret = u_upload_buffer(r300->upload_vb, | |||
offset, size, | |||
r300->vertex_buffer[i].buffer, | |||
&upload_offset, &upload_buffer); | |||
if (ret) | |||
return ret; | |||
pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); | |||
r300->vertex_buffer[i].buffer = upload_buffer; | |||
r300->vertex_buffer[i].buffer_offset = upload_offset; | |||
} | |||
} | |||
return ret; | |||
} | |||
static struct r300_winsys_buffer * | |||
r300_winsys_buffer_create(struct r300_screen *r300screen, | |||
unsigned alignment, | |||
unsigned usage, | |||
unsigned size) | |||
{ | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
struct r300_winsys_buffer *buf; | |||
buf = rws->buffer_create(rws, alignment, usage, size); | |||
return buf; | |||
} | |||
static void r300_winsys_buffer_destroy(struct r300_screen *r300screen, | |||
struct r300_buffer *rbuf) | |||
{ | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
if (rbuf->buf) { | |||
rws->buffer_reference(rws, &rbuf->buf, NULL); | |||
rbuf->buf = NULL; | |||
} | |||
} | |||
static struct pipe_buffer *r300_buffer_create(struct pipe_screen *screen, | |||
unsigned alignment, | |||
unsigned usage, | |||
unsigned size) | |||
{ | |||
struct r300_screen *r300screen = r300_screen(screen); | |||
struct r300_buffer *rbuf; | |||
rbuf = CALLOC_STRUCT(r300_buffer); | |||
if (!rbuf) | |||
goto error1; | |||
rbuf->magic = R300_BUFFER_MAGIC; | |||
pipe_reference_init(&rbuf->base.reference, 1); | |||
rbuf->base.screen = screen; | |||
rbuf->base.alignment = alignment; | |||
rbuf->base.usage = usage; | |||
rbuf->base.size = size; | |||
rbuf->buf = r300_winsys_buffer_create(r300screen, | |||
alignment, | |||
usage, | |||
size); | |||
if (!rbuf->buf) | |||
goto error2; | |||
return &rbuf->base; | |||
error2: | |||
FREE(rbuf); | |||
error1: | |||
return NULL; | |||
} | |||
static struct pipe_buffer *r300_user_buffer_create(struct pipe_screen *screen, | |||
void *ptr, | |||
unsigned bytes) | |||
{ | |||
struct r300_buffer *rbuf; | |||
rbuf = CALLOC_STRUCT(r300_buffer); | |||
if (!rbuf) | |||
goto no_rbuf; | |||
rbuf->magic = R300_BUFFER_MAGIC; | |||
pipe_reference_init(&rbuf->base.reference, 1); | |||
rbuf->base.screen = screen; | |||
rbuf->base.alignment = 1; | |||
rbuf->base.usage = 0; | |||
rbuf->base.size = bytes; | |||
rbuf->user_buffer = ptr; | |||
return &rbuf->base; | |||
no_rbuf: | |||
return NULL; | |||
} | |||
static void r300_buffer_destroy(struct pipe_buffer *buf) | |||
{ | |||
struct r300_screen *r300screen = r300_screen(buf->screen); | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
r300_winsys_buffer_destroy(r300screen, rbuf); | |||
FREE(rbuf); | |||
} | |||
static void * | |||
r300_buffer_map_range(struct pipe_screen *screen, | |||
struct pipe_buffer *buf, | |||
unsigned offset, unsigned length, | |||
unsigned usage ) | |||
{ | |||
struct r300_screen *r300screen = r300_screen(screen); | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
void *map; | |||
int flush = 0; | |||
int i; | |||
if (rbuf->user_buffer) | |||
return rbuf->user_buffer; | |||
if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) | |||
goto just_map; | |||
/* check if the mapping is to a range we already flushed */ | |||
if (usage & PIPE_BUFFER_USAGE_DISCARD) { | |||
for (i = 0; i < rbuf->num_ranges; i++) { | |||
if ((offset >= rbuf->ranges[i].start) && | |||
(offset < rbuf->ranges[i].end)) | |||
flush = 1; | |||
if (flush) { | |||
/* unreference this hw buffer and allocate a new one */ | |||
rws->buffer_reference(rws, &rbuf->buf, NULL); | |||
rbuf->num_ranges = 0; | |||
rbuf->map = NULL; | |||
rbuf->buf = r300_winsys_buffer_create(r300screen, | |||
rbuf->base.alignment, | |||
rbuf->base.usage, | |||
rbuf->base.size); | |||
break; | |||
} | |||
} | |||
} | |||
just_map: | |||
map = rws->buffer_map(rws, rbuf->buf, usage | R300_USAGE_FLAG_DONT_SYNC); | |||
return map; | |||
} | |||
static void | |||
r300_buffer_flush_mapped_range( struct pipe_screen *screen, | |||
struct pipe_buffer *buf, | |||
unsigned offset, | |||
unsigned length ) | |||
{ | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
int i; | |||
if (rbuf->user_buffer) | |||
return; | |||
if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) | |||
return; | |||
/* mark the range as used */ | |||
for(i = 0; i < rbuf->num_ranges; ++i) { | |||
if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+length)) { | |||
rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset); | |||
rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length)); | |||
return; | |||
} | |||
} | |||
rbuf->ranges[rbuf->num_ranges].start = offset; | |||
rbuf->ranges[rbuf->num_ranges].end = offset+length; | |||
rbuf->num_ranges++; | |||
} | |||
static void * | |||
r300_buffer_map(struct pipe_screen *screen, | |||
struct pipe_buffer *buf, | |||
unsigned usage) | |||
{ | |||
struct r300_screen *r300screen = r300_screen(screen); | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
void *map; | |||
if (rbuf->user_buffer) | |||
return rbuf->user_buffer; | |||
map = rws->buffer_map(rws, rbuf->buf, usage); | |||
return map; | |||
} | |||
static void | |||
r300_buffer_unmap(struct pipe_screen *screen, | |||
struct pipe_buffer *buf) | |||
{ | |||
struct r300_screen *r300screen = r300_screen(screen); | |||
struct r300_winsys_screen *rws = r300screen->rws; | |||
struct r300_buffer *rbuf = r300_buffer(buf); | |||
if (rbuf->buf) { | |||
rws->buffer_unmap(rws, rbuf->buf); | |||
} | |||
} | |||
void r300_screen_init_buffer_functions(struct r300_screen *r300screen) | |||
{ | |||
r300screen->screen.buffer_create = r300_buffer_create; | |||
r300screen->screen.user_buffer_create = r300_user_buffer_create; | |||
r300screen->screen.buffer_map = r300_buffer_map; | |||
r300screen->screen.buffer_map_range = r300_buffer_map_range; | |||
r300screen->screen.buffer_flush_mapped_range = r300_buffer_flush_mapped_range; | |||
r300screen->screen.buffer_unmap = r300_buffer_unmap; | |||
r300screen->screen.buffer_destroy = r300_buffer_destroy; | |||
} |
@@ -0,0 +1,99 @@ | |||
#ifndef R300_SCREEN_BUFFER_H | |||
#define R300_SCREEN_BUFFER_H | |||
#include <stdio.h> | |||
#include "pipe/p_compiler.h" | |||
#include "pipe/p_state.h" | |||
#include "r300_screen.h" | |||
#include "r300_winsys.h" | |||
#include "r300_context.h" | |||
#define R300_BUFFER_MAGIC 0xabcd1234 | |||
struct r300_buffer_range { | |||
uint32_t start; | |||
uint32_t end; | |||
}; | |||
#define R300_BUFFER_MAX_RANGES 32 | |||
struct r300_buffer | |||
{ | |||
struct pipe_buffer base; | |||
uint32_t magic; | |||
struct r300_winsys_buffer *buf; | |||
void *user_buffer; | |||
struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES]; | |||
unsigned num_ranges; | |||
void *map; | |||
}; | |||
static INLINE struct r300_buffer * | |||
r300_buffer(struct pipe_buffer *buffer) | |||
{ | |||
if (buffer) { | |||
assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC); | |||
return (struct r300_buffer *)buffer; | |||
} | |||
return NULL; | |||
} | |||
static INLINE boolean | |||
r300_buffer_is_user_buffer(struct pipe_buffer *buffer) | |||
{ | |||
return r300_buffer(buffer)->user_buffer ? true : false; | |||
} | |||
static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws, | |||
struct pipe_buffer *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); | |||
} | |||
void r300_screen_init_buffer_functions(struct r300_screen *r300screen); | |||
static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws, | |||
struct r300_buffer *buf, | |||
uint32_t rd, uint32_t wd, uint32_t flags) | |||
{ | |||
if (!buf->buf) | |||
return; | |||
rws->write_cs_reloc(rws, buf->buf, rd, wd, flags); | |||
} | |||
static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws, | |||
struct r300_texture *texture, | |||
uint32_t rd, uint32_t wd, uint32_t flags) | |||
{ | |||
rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags); | |||
} | |||
int r300_upload_user_buffers(struct r300_context *r300); | |||
int r300_upload_index_buffer(struct r300_context *r300, | |||
struct pipe_buffer **index_buffer, | |||
unsigned index_size, | |||
unsigned start, | |||
unsigned count); | |||
boolean r300_buffer_is_referenced(struct r300_context *r300, | |||
struct pipe_buffer *buf); | |||
#endif |
@@ -34,6 +34,7 @@ | |||
#include "r300_context.h" | |||
#include "r300_reg.h" | |||
#include "r300_screen.h" | |||
#include "r300_screen_buffer.h" | |||
#include "r300_state_inlines.h" | |||
#include "r300_fs.h" | |||
#include "r300_vs.h" | |||
@@ -525,7 +526,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, | |||
tex = (struct r300_texture*)old_state->cbufs[i]->texture; | |||
if (tex) { | |||
r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, | |||
r300->rws->buffer_set_tiling(r300->rws, tex->buffer, | |||
tex->pitch[0], | |||
tex->microtile != 0, | |||
tex->macrotile != 0); | |||
@@ -537,7 +538,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, | |||
tex = (struct r300_texture*)old_state->zsbuf->texture; | |||
if (tex) { | |||
r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, | |||
r300->rws->buffer_set_tiling(r300->rws, tex->buffer, | |||
tex->pitch[0], | |||
tex->microtile != 0, | |||
tex->macrotile != 0); | |||
@@ -549,7 +550,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, | |||
tex = (struct r300_texture*)new_state->cbufs[i]->texture; | |||
level = new_state->cbufs[i]->level; | |||
r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, | |||
r300->rws->buffer_set_tiling(r300->rws, tex->buffer, | |||
tex->pitch[level], | |||
tex->microtile != 0, | |||
tex->mip_macrotile[level] != 0); | |||
@@ -558,7 +559,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, | |||
tex = (struct r300_texture*)new_state->zsbuf->texture; | |||
level = new_state->zsbuf->level; | |||
r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, | |||
r300->rws->buffer_set_tiling(r300->rws, tex->buffer, | |||
tex->pitch[level], | |||
tex->microtile != 0, | |||
tex->mip_macrotile[level] != 0); | |||
@@ -1040,17 +1041,30 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, | |||
const struct pipe_vertex_buffer* buffers) | |||
{ | |||
struct r300_context* r300 = r300_context(pipe); | |||
unsigned i, max_index = (1 << 24) - 1; | |||
int i; | |||
unsigned max_index = (1 << 24) - 1; | |||
boolean any_user_buffer = false; | |||
memcpy(r300->vertex_buffer, buffers, | |||
sizeof(struct pipe_vertex_buffer) * count); | |||
if (count == r300->vertex_buffer_count && | |||
memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0) | |||
return; | |||
for (i = 0; i < count; i++) { | |||
pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer); | |||
if (r300_buffer_is_user_buffer(buffers[i].buffer)) | |||
any_user_buffer = true; | |||
max_index = MIN2(buffers[i].max_index, max_index); | |||
} | |||
for ( ; i < r300->vertex_buffer_count; i++) | |||
pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); | |||
memcpy(r300->vertex_buffer, buffers, | |||
sizeof(struct pipe_vertex_buffer) * count); | |||
r300->vertex_buffer_count = count; | |||
r300->vertex_buffer_max_index = max_index; | |||
r300->any_user_vbs = any_user_buffer; | |||
if (r300->draw) { | |||
draw_flush(r300->draw); |
@@ -773,7 +773,7 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, | |||
{ | |||
struct r300_texture* tex = CALLOC_STRUCT(r300_texture); | |||
struct r300_screen* rscreen = r300_screen(screen); | |||
struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; | |||
if (!tex) { | |||
return NULL; | |||
@@ -790,13 +790,13 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, | |||
r300_setup_miptree(rscreen, tex); | |||
r300_setup_texture_state(rscreen, tex); | |||
tex->buffer = screen->buffer_create(screen, 2048, | |||
PIPE_BUFFER_USAGE_PIXEL, | |||
tex->size); | |||
winsys->buffer_set_tiling(winsys, tex->buffer, | |||
tex->pitch[0], | |||
tex->microtile != R300_BUFFER_LINEAR, | |||
tex->macrotile != R300_BUFFER_LINEAR); | |||
tex->buffer = rws->buffer_create(rws, 2048, | |||
PIPE_BUFFER_USAGE_PIXEL, | |||
tex->size); | |||
rws->buffer_set_tiling(rws, tex->buffer, | |||
tex->pitch[0], | |||
tex->microtile != R300_BUFFER_LINEAR, | |||
tex->macrotile != R300_BUFFER_LINEAR); | |||
if (!tex->buffer) { | |||
FREE(tex); | |||
@@ -809,9 +809,9 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, | |||
static void r300_texture_destroy(struct pipe_texture* texture) | |||
{ | |||
struct r300_texture* tex = (struct r300_texture*)texture; | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; | |||
pipe_buffer_reference(&tex->buffer, NULL); | |||
rws->buffer_reference(rws, &tex->buffer, NULL); | |||
FREE(tex); | |||
} | |||
@@ -857,9 +857,9 @@ static struct pipe_texture* | |||
const struct pipe_texture* base, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; | |||
struct r300_screen* rscreen = r300_screen(screen); | |||
struct pipe_buffer *buffer; | |||
struct r300_winsys_buffer *buffer; | |||
struct r300_texture* tex; | |||
unsigned stride; | |||
@@ -870,7 +870,7 @@ static struct pipe_texture* | |||
return NULL; | |||
} | |||
buffer = winsys->buffer_from_handle(winsys, screen, whandle, &stride); | |||
buffer = rws->buffer_from_handle(rws, screen, whandle, &stride); | |||
if (!buffer) { | |||
return NULL; | |||
} | |||
@@ -901,7 +901,7 @@ static boolean | |||
struct pipe_texture *texture, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; | |||
struct r300_texture* tex = (struct r300_texture*)texture; | |||
unsigned stride; | |||
@@ -911,7 +911,7 @@ static boolean | |||
stride = r300_texture_get_stride(r300_screen(screen), tex, 0); | |||
winsys->buffer_get_handle(winsys, tex->buffer, stride, whandle); | |||
rws->buffer_get_handle(rws, tex->buffer, stride, whandle); | |||
return TRUE; | |||
} | |||
@@ -977,3 +977,25 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen) | |||
screen->video_surface_destroy= r300_video_surface_destroy; | |||
} | |||
boolean r300_get_texture_buffer(struct pipe_screen* screen, | |||
struct pipe_texture* texture, | |||
struct r300_winsys_buffer** buffer, | |||
unsigned* stride) | |||
{ | |||
struct r300_texture* tex = (struct r300_texture*)texture; | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; | |||
struct r300_winsys_buffer *buf; | |||
if (!tex) { | |||
return FALSE; | |||
} | |||
rws->buffer_reference(rws, &buf, tex->buffer); | |||
if (stride) { | |||
*stride = r300_texture_get_stride(r300_screen(screen), tex, 0); | |||
} | |||
*buffer = buf; | |||
return TRUE; | |||
} |
@@ -63,8 +63,8 @@ r300_video_surface(struct pipe_video_surface *pvs) | |||
/* Used internally for texture_is_referenced() | |||
*/ | |||
boolean r300_get_texture_buffer(struct pipe_screen* screen, | |||
struct pipe_texture* texture, | |||
struct pipe_buffer** buffer, | |||
struct pipe_texture *texture, | |||
struct r300_winsys_buffer** buffer, | |||
unsigned* stride); | |||
#endif /* R300_TEXTURE_H */ |
@@ -26,6 +26,8 @@ | |||
#include "r300_texture.h" | |||
#include "r300_screen.h" | |||
#include "r300_winsys.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_format.h" | |||
@@ -225,6 +227,7 @@ static void r300_tex_transfer_destroy(struct pipe_context *ctx, | |||
static void* r300_transfer_map(struct pipe_context *ctx, | |||
struct pipe_transfer *transfer) | |||
{ | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; | |||
struct r300_transfer *r300transfer = r300_transfer(transfer); | |||
struct r300_texture *tex = (struct r300_texture*)transfer->texture; | |||
char *map; | |||
@@ -233,12 +236,12 @@ static void* r300_transfer_map(struct pipe_context *ctx, | |||
if (r300transfer->detiled_texture) { | |||
/* The detiled texture is of the same size as the region being mapped | |||
* (no offset needed). */ | |||
return pipe_buffer_map(ctx->screen, | |||
return rws->buffer_map(rws, | |||
r300transfer->detiled_texture->buffer, | |||
pipe_transfer_buffer_flags(transfer)); | |||
} else { | |||
/* Tiling is disabled. */ | |||
map = pipe_buffer_map(ctx->screen, tex->buffer, | |||
map = rws->buffer_map(rws, tex->buffer, | |||
pipe_transfer_buffer_flags(transfer)); | |||
if (!map) { | |||
@@ -254,13 +257,14 @@ static void* r300_transfer_map(struct pipe_context *ctx, | |||
static void r300_transfer_unmap(struct pipe_context *ctx, | |||
struct pipe_transfer *transfer) | |||
{ | |||
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; | |||
struct r300_transfer *r300transfer = r300_transfer(transfer); | |||
struct r300_texture *tex = (struct r300_texture*)transfer->texture; | |||
if (r300transfer->detiled_texture) { | |||
pipe_buffer_unmap(ctx->screen, r300transfer->detiled_texture->buffer); | |||
rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); | |||
} else { | |||
pipe_buffer_unmap(ctx->screen, tex->buffer); | |||
rws->buffer_unmap(rws, tex->buffer); | |||
} | |||
} | |||
@@ -23,10 +23,6 @@ | |||
#ifndef R300_WINSYS_H | |||
#define R300_WINSYS_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/* 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. */ | |||
@@ -34,14 +30,146 @@ extern "C" { | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_state.h" | |||
struct radeon_winsys; | |||
struct r300_winsys_screen; | |||
/* Creates a new r300 screen. */ | |||
struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); | |||
struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws); | |||
struct r300_winsys_buffer; | |||
boolean r300_get_texture_buffer(struct pipe_screen* screen, | |||
struct pipe_texture* texture, | |||
struct r300_winsys_buffer** buffer, | |||
unsigned *stride); | |||
enum r300_value_id { | |||
R300_VID_PCI_ID, | |||
R300_VID_GB_PIPES, | |||
R300_VID_Z_PIPES, | |||
}; | |||
#define R300_USAGE_FLAG_DONT_SYNC (1 << 17) | |||
struct r300_winsys_screen { | |||
void (*destroy)(struct r300_winsys_screen *ws); | |||
/** | |||
* 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, | |||
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. | |||
*/ | |||
void *(*buffer_map)( struct r300_winsys_screen *ws, | |||
struct r300_winsys_buffer *buf, | |||
unsigned usage); | |||
void (*buffer_unmap)( struct r300_winsys_screen *ws, | |||
struct r300_winsys_buffer *buf ); | |||
void (*buffer_destroy)( struct r300_winsys_buffer *buf ); | |||
void (*buffer_reference)(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer **pdst, | |||
struct r300_winsys_buffer *src); | |||
boolean (*buffer_references)(struct r300_winsys_buffer *a, | |||
struct r300_winsys_buffer *b); | |||
void (*buffer_flush_range)(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer *buf, | |||
unsigned offset, | |||
unsigned length); | |||
/* Add a pipe_buffer to the list of buffer objects to validate. */ | |||
boolean (*add_buffer)(struct r300_winsys_screen *winsys, | |||
struct r300_winsys_buffer *buf, | |||
uint32_t rd, | |||
uint32_t wd); | |||
/* Revalidate all currently setup pipe_buffers. | |||
* Returns TRUE if a flush is required. */ | |||
boolean (*validate)(struct r300_winsys_screen* winsys); | |||
/* Check to see if there's room for commands. */ | |||
boolean (*check_cs)(struct r300_winsys_screen* winsys, int size); | |||
/* Start a command emit. */ | |||
void (*begin_cs)(struct r300_winsys_screen* winsys, | |||
int size, | |||
const char* file, | |||
const char* function, | |||
int line); | |||
/* Write a dword to the command buffer. */ | |||
void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword); | |||
/* Write a relocated dword to the command buffer. */ | |||
void (*write_cs_reloc)(struct r300_winsys_screen *winsys, | |||
struct r300_winsys_buffer *buf, | |||
uint32_t rd, | |||
uint32_t wd, | |||
uint32_t flags); | |||
/* Finish a command emit. */ | |||
void (*end_cs)(struct r300_winsys_screen* winsys, | |||
const char* file, | |||
const char* function, | |||
int line); | |||
/* 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_set_tiling)(struct r300_winsys_screen *winsys, | |||
struct r300_winsys_buffer *buffer, | |||
uint32_t pitch, | |||
boolean microtiled, | |||
boolean 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 pipe_screen *screen, | |||
struct winsys_handle *whandle, | |||
unsigned *stride); | |||
boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys, | |||
struct r300_winsys_buffer *buffer, | |||
unsigned stride, | |||
struct winsys_handle *whandle); | |||
boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys, | |||
struct r300_winsys_buffer *buffer); | |||
}; | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
struct r300_winsys_screen * | |||
r300_winsys_screen(struct pipe_screen *screen); | |||
#endif /* R300_WINSYS_H */ |
@@ -5,7 +5,7 @@ include $(TOP)/configs/current | |||
LIBNAME = radeonwinsys | |||
C_SOURCES = \ | |||
radeon_buffer.c \ | |||
radeon_drm_buffer.c \ | |||
radeon_drm.c \ | |||
radeon_r300.c | |||
@@ -30,48 +30,56 @@ | |||
#ifndef RADEON_BUFFER_H | |||
#define RADEON_BUFFER_H | |||
#include <stdio.h> | |||
#include "pipe/p_defines.h" | |||
#include "util/u_inlines.h" | |||
#include "pipebuffer/pb_buffer.h" | |||
#include "pipebuffer/pb_bufmgr.h" | |||
#include "radeon_bo.h" | |||
#include "radeon_cs.h" | |||
#include "radeon_winsys.h" | |||
struct radeon_pipe_buffer { | |||
struct pipe_buffer base; | |||
/* Pointer to GPU-backed BO. */ | |||
struct radeon_bo *bo; | |||
/* Pointer to fallback PB buffer. */ | |||
struct pb_buffer *pb; | |||
boolean flinked; | |||
uint32_t flink; | |||
}; | |||
#define RADEON_MAX_BOS 24 | |||
struct radeon_winsys_priv { | |||
/* DRM FD */ | |||
int fd; | |||
static INLINE struct pb_buffer * | |||
radeon_pb_buffer(struct r300_winsys_buffer *buffer) | |||
{ | |||
return (struct pb_buffer *)buffer; | |||
} | |||
/* Radeon BO manager. */ | |||
struct radeon_bo_manager* bom; | |||
static INLINE struct r300_winsys_buffer * | |||
radeon_libdrm_winsys_buffer(struct pb_buffer *buffer) | |||
{ | |||
return (struct r300_winsys_buffer *)buffer; | |||
} | |||
/* Radeon CS manager. */ | |||
struct radeon_cs_manager* csm; | |||
struct pb_manager * | |||
radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws); | |||
/* Current CS. */ | |||
struct radeon_cs* cs; | |||
boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, | |||
uint32_t rd, uint32_t wd); | |||
/* Flush CB */ | |||
void (*flush_cb)(void *); | |||
void *flush_data; | |||
}; | |||
struct radeon_winsys* radeon_pipe_winsys(int fb); | |||
#if 0 | |||
struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context, | |||
uint32_t handle, | |||
enum pipe_format format, | |||
int w, int h, int pitch); | |||
#endif | |||
void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, | |||
uint32_t rd, uint32_t wd, | |||
uint32_t flags); | |||
struct radeon_libdrm_winsys* radeon_pipe_winsys(int fd); | |||
struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, | |||
uint32_t handle); | |||
void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch); | |||
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); | |||
#endif |
@@ -41,8 +41,22 @@ | |||
#include "xf86drm.h" | |||
#include <sys/ioctl.h> | |||
static struct radeon_libdrm_winsys * | |||
radeon_winsys_create(int fd) | |||
{ | |||
struct radeon_libdrm_winsys *rws; | |||
rws = CALLOC_STRUCT(radeon_libdrm_winsys); | |||
if (rws == NULL) { | |||
return NULL; | |||
} | |||
rws->fd = fd; | |||
return rws; | |||
} | |||
/* Helper function to do the ioctls needed for setup and init. */ | |||
static void do_ioctls(int fd, struct radeon_winsys* winsys) | |||
static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys) | |||
{ | |||
struct drm_radeon_gem_info gem_info = {0}; | |||
struct drm_radeon_info info = {0}; | |||
@@ -133,19 +147,28 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, | |||
int drmFB, | |||
struct drm_create_screen_arg *arg) | |||
{ | |||
struct radeon_winsys* rwinsys = radeon_pipe_winsys(drmFB); | |||
do_ioctls(drmFB, rwinsys); | |||
struct radeon_libdrm_winsys* rws; | |||
boolean ret; | |||
rws = radeon_winsys_create(drmFB); | |||
if (!rws) | |||
return NULL; | |||
do_ioctls(drmFB, rws); | |||
/* The state tracker can organize a softpipe fallback if no hw | |||
* driver is found. | |||
*/ | |||
if (is_r3xx(rwinsys->pci_id)) { | |||
radeon_setup_winsys(drmFB, rwinsys); | |||
return r300_create_screen(rwinsys); | |||
} else { | |||
FREE(rwinsys); | |||
return NULL; | |||
if (is_r3xx(rws->pci_id)) { | |||
ret = radeon_setup_winsys(drmFB, rws); | |||
if (ret == FALSE) | |||
goto fail; | |||
return r300_create_screen(&rws->base); | |||
} | |||
fail: | |||
FREE(rws); | |||
return NULL; | |||
} | |||
static void radeon_drm_api_destroy(struct drm_api *api) |
@@ -37,6 +37,22 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, | |||
int drmFB, | |||
struct drm_create_screen_arg *arg); | |||
boolean radeon_buffer_from_texture(struct drm_api* api, | |||
struct pipe_screen* screen, | |||
struct pipe_texture* texture, | |||
struct pipe_buffer** buffer, | |||
unsigned* stride); | |||
boolean radeon_handle_from_buffer(struct drm_api* api, | |||
struct pipe_screen* screen, | |||
struct pipe_buffer* buffer, | |||
unsigned* handle); | |||
boolean radeon_global_handle_from_buffer(struct drm_api* api, | |||
struct pipe_screen* screen, | |||
struct pipe_buffer* buffer, | |||
unsigned* handle); | |||
void radeon_destroy_drm_api(struct drm_api* api); | |||
/* Guess at whether this chipset should use r300g. |
@@ -0,0 +1,368 @@ | |||
#include <sys/ioctl.h> | |||
#include "radeon_drm.h" | |||
#include "radeon_bo_gem.h" | |||
#include "radeon_cs_gem.h" | |||
#include "radeon_buffer.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_simple_list.h" | |||
#include "pipebuffer/pb_buffer.h" | |||
#include "pipebuffer/pb_bufmgr.h" | |||
#include "radeon_winsys.h" | |||
struct radeon_drm_bufmgr; | |||
struct radeon_drm_buffer { | |||
struct pb_buffer base; | |||
struct radeon_drm_bufmgr *mgr; | |||
struct radeon_bo *bo; | |||
boolean flinked; | |||
uint32_t flink; | |||
boolean mapped; | |||
struct radeon_drm_buffer *next, *prev; | |||
}; | |||
extern const struct pb_vtbl radeon_drm_buffer_vtbl; | |||
static INLINE struct radeon_drm_buffer * | |||
radeon_drm_buffer(struct pb_buffer *buf) | |||
{ | |||
assert(buf); | |||
assert(buf->vtbl == &radeon_drm_buffer_vtbl); | |||
return (struct radeon_drm_buffer *)buf; | |||
} | |||
struct radeon_drm_bufmgr { | |||
struct pb_manager base; | |||
struct radeon_libdrm_winsys *rws; | |||
struct radeon_drm_buffer buffer_map_list; | |||
}; | |||
static INLINE struct radeon_drm_bufmgr * | |||
radeon_drm_bufmgr(struct pb_manager *mgr) | |||
{ | |||
assert(mgr); | |||
return (struct radeon_drm_bufmgr *)mgr; | |||
} | |||
static void | |||
radeon_drm_buffer_destroy(struct pb_buffer *_buf) | |||
{ | |||
struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); | |||
if (buf->mapped) { | |||
remove_from_list(buf); | |||
radeon_bo_unmap(buf->bo); | |||
buf->mapped = false; | |||
} | |||
radeon_bo_unref(buf->bo); | |||
FREE(buf); | |||
} | |||
static void * | |||
radeon_drm_buffer_map(struct pb_buffer *_buf, | |||
unsigned flags) | |||
{ | |||
struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); | |||
int write; | |||
if (buf->mapped) | |||
return buf->bo->ptr; | |||
if (flags & PIPE_BUFFER_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 (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { | |||
write = 1; | |||
} | |||
if (radeon_bo_map(buf->bo, write)) { | |||
return NULL; | |||
} | |||
buf->mapped = true; | |||
insert_at_tail(&buf->mgr->buffer_map_list, buf); | |||
return buf->bo->ptr; | |||
} | |||
static void | |||
radeon_drm_buffer_unmap(struct pb_buffer *_buf) | |||
{ | |||
(void)_buf; | |||
} | |||
static void | |||
radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf, | |||
struct pb_buffer **base_buf, | |||
unsigned *offset) | |||
{ | |||
*base_buf = buf; | |||
*offset = 0; | |||
} | |||
static enum pipe_error | |||
radeon_drm_buffer_validate(struct pb_buffer *_buf, | |||
struct pb_validate *vl, | |||
unsigned flags) | |||
{ | |||
/* Always pinned */ | |||
return PIPE_OK; | |||
} | |||
static void | |||
radeon_drm_buffer_fence(struct pb_buffer *buf, | |||
struct pipe_fence_handle *fence) | |||
{ | |||
} | |||
const struct pb_vtbl radeon_drm_buffer_vtbl = { | |||
radeon_drm_buffer_destroy, | |||
radeon_drm_buffer_map, | |||
radeon_drm_buffer_unmap, | |||
radeon_drm_buffer_validate, | |||
radeon_drm_buffer_fence, | |||
radeon_drm_buffer_get_base_buffer, | |||
}; | |||
static uint32_t radeon_domain_from_usage(unsigned usage) | |||
{ | |||
uint32_t domain = 0; | |||
if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { | |||
domain |= RADEON_GEM_DOMAIN_VRAM; | |||
} | |||
if (usage & PIPE_BUFFER_USAGE_PIXEL) { | |||
domain |= RADEON_GEM_DOMAIN_VRAM; | |||
} | |||
if (usage & PIPE_BUFFER_USAGE_VERTEX) { | |||
domain |= RADEON_GEM_DOMAIN_GTT; | |||
} | |||
if (usage & PIPE_BUFFER_USAGE_INDEX) { | |||
domain |= RADEON_GEM_DOMAIN_GTT; | |||
} | |||
return domain; | |||
} | |||
struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, | |||
uint32_t handle) | |||
{ | |||
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); | |||
struct radeon_libdrm_winsys *rws = mgr->rws; | |||
struct radeon_drm_buffer *buf; | |||
struct radeon_bo *bo; | |||
bo = radeon_bo_open(rws->bom, handle, 0, | |||
0, 0, 0); | |||
if (bo == NULL) | |||
return NULL; | |||
buf = CALLOC_STRUCT(radeon_drm_buffer); | |||
if (!buf) { | |||
radeon_bo_unref(bo); | |||
return NULL; | |||
} | |||
make_empty_list(buf); | |||
pipe_reference_init(&buf->base.base.reference, 1); | |||
buf->base.base.alignment = 0; | |||
buf->base.base.usage = PIPE_BUFFER_USAGE_PIXEL; | |||
buf->base.base.size = 0; | |||
buf->base.vtbl = &radeon_drm_buffer_vtbl; | |||
buf->mgr = mgr; | |||
buf->bo = bo; | |||
return &buf->base; | |||
} | |||
static struct pb_buffer * | |||
radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, | |||
pb_size size, | |||
const struct pb_desc *desc) | |||
{ | |||
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); | |||
struct radeon_libdrm_winsys *rws = mgr->rws; | |||
struct radeon_drm_buffer *buf; | |||
uint32_t domain; | |||
buf = CALLOC_STRUCT(radeon_drm_buffer); | |||
if (!buf) | |||
goto error1; | |||
pipe_reference_init(&buf->base.base.reference, 1); | |||
buf->base.base.alignment = desc->alignment; | |||
buf->base.base.usage = desc->usage; | |||
buf->base.base.size = size; | |||
buf->base.vtbl = &radeon_drm_buffer_vtbl; | |||
buf->mgr = mgr; | |||
make_empty_list(buf); | |||
domain = radeon_domain_from_usage(desc->usage); | |||
buf->bo = radeon_bo_open(rws->bom, 0, size, | |||
desc->alignment, domain, 0); | |||
if (buf->bo == NULL) | |||
goto error2; | |||
return &buf->base; | |||
error2: | |||
FREE(buf); | |||
error1: | |||
return NULL; | |||
} | |||
static void | |||
radeon_drm_bufmgr_flush(struct pb_manager *mgr) | |||
{ | |||
/* NOP */ | |||
} | |||
static void | |||
radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) | |||
{ | |||
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); | |||
FREE(mgr); | |||
} | |||
struct pb_manager * | |||
radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws) | |||
{ | |||
struct radeon_drm_bufmgr *mgr; | |||
mgr = CALLOC_STRUCT(radeon_drm_bufmgr); | |||
if (!mgr) | |||
return NULL; | |||
mgr->base.destroy = radeon_drm_bufmgr_destroy; | |||
mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer; | |||
mgr->base.flush = radeon_drm_bufmgr_flush; | |||
mgr->rws = rws; | |||
make_empty_list(&mgr->buffer_map_list); | |||
return &mgr->base; | |||
} | |||
static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf) | |||
{ | |||
struct radeon_drm_buffer *buf; | |||
if (_buf->vtbl == &radeon_drm_buffer_vtbl) { | |||
buf = radeon_drm_buffer(_buf); | |||
} else { | |||
struct pb_buffer *base_buf; | |||
pb_size offset; | |||
pb_get_base_buffer(_buf, &base_buf, &offset); | |||
buf = radeon_drm_buffer(base_buf); | |||
} | |||
return buf; | |||
} | |||
boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, | |||
struct winsys_handle *whandle) | |||
{ | |||
int retval, fd; | |||
struct drm_gem_flink flink; | |||
struct radeon_drm_buffer *buf = get_drm_buffer(_buf); | |||
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { | |||
if (!buf->flinked) { | |||
fd = buf->mgr->rws->fd; | |||
flink.handle = buf->bo->handle; | |||
retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); | |||
if (retval) { | |||
return false; | |||
} | |||
buf->flinked = TRUE; | |||
buf->flink = flink.name; | |||
} | |||
whandle->handle = buf->flink; | |||
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { | |||
whandle->handle = buf->bo->handle; | |||
} | |||
return TRUE; | |||
} | |||
void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch) | |||
{ | |||
struct radeon_drm_buffer *buf = get_drm_buffer(_buf); | |||
uint32_t flags = 0; | |||
if (microtiled) | |||
flags |= RADEON_BO_FLAGS_MICRO_TILE; | |||
if (macrotiled) | |||
flags |= RADEON_BO_FLAGS_MACRO_TILE; | |||
radeon_bo_set_tiling(buf->bo, flags, pitch); | |||
} | |||
boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, | |||
uint32_t rd, uint32_t wd) | |||
{ | |||
struct radeon_drm_buffer *buf = get_drm_buffer(_buf); | |||
radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo, | |||
rd, wd); | |||
return true; | |||
} | |||
void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, | |||
uint32_t rd, uint32_t wd, | |||
uint32_t flags) | |||
{ | |||
struct radeon_drm_buffer *buf = get_drm_buffer(_buf); | |||
int retval; | |||
retval = radeon_cs_write_reloc(buf->mgr->rws->cs, | |||
buf->bo, rd, wd, flags); | |||
if (retval) { | |||
debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", | |||
buf, rd, wd, flags); | |||
} | |||
} | |||
boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf) | |||
{ | |||
struct radeon_drm_buffer *buf = get_drm_buffer(_buf); | |||
uint32_t domain; | |||
return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) || | |||
radeon_bo_is_busy(buf->bo, &domain)); | |||
} | |||
void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) | |||
{ | |||
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); | |||
struct radeon_drm_buffer *rpb, *t_rpb; | |||
foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { | |||
rpb->mapped = 0; | |||
radeon_bo_unmap(rpb->bo); | |||
remove_from_list(rpb); | |||
} | |||
make_empty_list(&mgr->buffer_map_list); | |||
} |
@@ -23,31 +23,139 @@ | |||
#include "radeon_r300.h" | |||
#include "radeon_buffer.h" | |||
#include "radeon_bo_gem.h" | |||
#include "radeon_cs_gem.h" | |||
#include "state_tracker/drm_api.h" | |||
static void radeon_set_flush_cb(struct radeon_winsys *winsys, | |||
static struct r300_winsys_buffer * | |||
radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws, | |||
unsigned alignment, | |||
unsigned usage, | |||
unsigned size) | |||
{ | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
struct pb_desc desc; | |||
struct pb_manager *provider; | |||
struct pb_buffer *buffer; | |||
memset(&desc, 0, sizeof(desc)); | |||
desc.alignment = alignment; | |||
desc.usage = usage; | |||
if (usage & PIPE_BUFFER_USAGE_CONSTANT) | |||
provider = ws->mman; | |||
else | |||
provider = ws->kman; | |||
buffer = provider->create_buffer(provider, size, &desc); | |||
if (!buffer) | |||
return NULL; | |||
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, | |||
boolean microtiled, | |||
boolean macrotiled) | |||
{ | |||
struct pb_buffer *_buf = radeon_pb_buffer(buf); | |||
radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch); | |||
} | |||
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_reference(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer **pdst, | |||
struct r300_winsys_buffer *src) | |||
{ | |||
struct pb_buffer *_src = radeon_pb_buffer(src); | |||
struct pb_buffer *_dst = radeon_pb_buffer(*pdst); | |||
pb_reference(&_dst, _src); | |||
*pdst = radeon_libdrm_winsys_buffer(_dst); | |||
} | |||
static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer *buf) | |||
{ | |||
struct pb_buffer *_buf = radeon_pb_buffer(buf); | |||
return radeon_drm_bufmgr_is_buffer_referenced(_buf); | |||
} | |||
static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, | |||
struct pipe_screen *screen, | |||
struct winsys_handle *whandle, | |||
unsigned *stride) | |||
{ | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
struct pb_buffer *_buf; | |||
_buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle); | |||
*stride = whandle->stride; | |||
return radeon_libdrm_winsys_buffer(_buf); | |||
} | |||
static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer *buffer, | |||
unsigned stride, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct pb_buffer *_buf = radeon_pb_buffer(buffer); | |||
boolean ret; | |||
ret = radeon_drm_bufmgr_get_handle(_buf, whandle); | |||
if (ret) | |||
whandle->stride = stride; | |||
return ret; | |||
} | |||
static void radeon_set_flush_cb(struct r300_winsys_screen *rws, | |||
void (*flush_cb)(void *), | |||
void *data) | |||
{ | |||
winsys->priv->flush_cb = flush_cb; | |||
winsys->priv->flush_data = data; | |||
radeon_cs_space_set_flush(winsys->priv->cs, flush_cb, 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 radeon_winsys* winsys, | |||
struct pipe_buffer* pbuffer, | |||
static boolean radeon_add_buffer(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer *buf, | |||
uint32_t rd, | |||
uint32_t wd) | |||
{ | |||
struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; | |||
struct pb_buffer *_buf = radeon_pb_buffer(buf); | |||
radeon_cs_space_add_persistent_bo(winsys->priv->cs, bo, rd, wd); | |||
return TRUE; | |||
return radeon_drm_bufmgr_add_buffer(_buf, rd, wd); | |||
} | |||
static boolean radeon_validate(struct radeon_winsys* winsys) | |||
static boolean radeon_validate(struct r300_winsys_screen *rws) | |||
{ | |||
if (radeon_cs_space_check(winsys->priv->cs) < 0) { | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
if (radeon_cs_space_check(ws->cs) < 0) { | |||
return FALSE; | |||
} | |||
@@ -55,108 +163,175 @@ static boolean radeon_validate(struct radeon_winsys* winsys) | |||
return TRUE; | |||
} | |||
static boolean radeon_check_cs(struct radeon_winsys* winsys, int size) | |||
static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size) | |||
{ | |||
struct radeon_cs* cs = winsys->priv->cs; | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
struct radeon_cs *cs = ws->cs; | |||
return radeon_validate(winsys) && cs->cdw + size <= cs->ndw; | |||
return radeon_validate(rws) && cs->cdw + size <= cs->ndw; | |||
} | |||
static void radeon_begin_cs(struct radeon_winsys* winsys, | |||
static void radeon_begin_cs(struct r300_winsys_screen *rws, | |||
int size, | |||
const char* file, | |||
const char* function, | |||
int line) | |||
{ | |||
radeon_cs_begin(winsys->priv->cs, size, file, function, line); | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
radeon_cs_begin(ws->cs, size, file, function, line); | |||
} | |||
static void radeon_write_cs_dword(struct radeon_winsys* winsys, | |||
static void radeon_write_cs_dword(struct r300_winsys_screen *rws, | |||
uint32_t dword) | |||
{ | |||
radeon_cs_write_dword(winsys->priv->cs, dword); | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
radeon_cs_write_dword(ws->cs, dword); | |||
} | |||
static void radeon_write_cs_reloc(struct radeon_winsys* winsys, | |||
struct pipe_buffer* pbuffer, | |||
static void radeon_write_cs_reloc(struct r300_winsys_screen *rws, | |||
struct r300_winsys_buffer *buf, | |||
uint32_t rd, | |||
uint32_t wd, | |||
uint32_t flags) | |||
{ | |||
int retval = 0; | |||
struct radeon_pipe_buffer* radeon_buffer = | |||
(struct radeon_pipe_buffer*)pbuffer; | |||
assert(!radeon_buffer->pb); | |||
retval = radeon_cs_write_reloc(winsys->priv->cs, radeon_buffer->bo, | |||
rd, wd, flags); | |||
if (retval) { | |||
debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", | |||
pbuffer, rd, wd, flags); | |||
} | |||
struct pb_buffer *_buf = radeon_pb_buffer(buf); | |||
radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags); | |||
} | |||
static void radeon_reset_bos(struct radeon_winsys *winsys) | |||
static void radeon_reset_bos(struct r300_winsys_screen *rws) | |||
{ | |||
radeon_cs_space_reset_bos(winsys->priv->cs); | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
radeon_cs_space_reset_bos(ws->cs); | |||
} | |||
static void radeon_end_cs(struct radeon_winsys* winsys, | |||
static void radeon_end_cs(struct r300_winsys_screen *rws, | |||
const char* file, | |||
const char* function, | |||
int line) | |||
{ | |||
radeon_cs_end(winsys->priv->cs, file, function, line); | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
radeon_cs_end(ws->cs, file, function, line); | |||
} | |||
static void radeon_flush_cs(struct radeon_winsys* winsys) | |||
static void radeon_flush_cs(struct r300_winsys_screen *rws) | |||
{ | |||
struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); | |||
int retval; | |||
/* Don't flush a zero-sized CS. */ | |||
if (!winsys->priv->cs->cdw) { | |||
if (!ws->cs->cdw) { | |||
return; | |||
} | |||
radeon_drm_bufmgr_flush_maps(ws->kman); | |||
/* Emit the CS. */ | |||
retval = radeon_cs_emit(winsys->priv->cs); | |||
retval = radeon_cs_emit(ws->cs); | |||
if (retval) { | |||
debug_printf("radeon: Bad CS, dumping...\n"); | |||
radeon_cs_print(winsys->priv->cs, stderr); | |||
radeon_cs_print(ws->cs, stderr); | |||
} | |||
/* Reset CS. | |||
* 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(winsys->priv->cs); | |||
radeon_cs_erase(ws->cs); | |||
} | |||
void | |||
radeon_setup_winsys(int fd, struct radeon_winsys* winsys) | |||
static uint32_t radeon_get_value(struct r300_winsys_screen *rws, | |||
enum r300_value_id id) | |||
{ | |||
struct radeon_winsys_priv* priv = winsys->priv; | |||
struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws; | |||
priv->csm = radeon_cs_manager_gem_ctor(fd); | |||
switch(id) { | |||
case R300_VID_PCI_ID: | |||
return ws->pci_id; | |||
case R300_VID_GB_PIPES: | |||
return ws->gb_pipes; | |||
case R300_VID_Z_PIPES: | |||
return ws->z_pipes; | |||
} | |||
return 0; | |||
} | |||
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->kman->destroy(ws->kman); | |||
ws->mman->destroy(ws->mman); | |||
radeon_bo_manager_gem_dtor(ws->bom); | |||
radeon_cs_manager_gem_dtor(ws->csm); | |||
} | |||
boolean | |||
radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws) | |||
{ | |||
ws->csm = radeon_cs_manager_gem_ctor(fd); | |||
if (!ws->csm) | |||
goto fail; | |||
ws->bom = radeon_bo_manager_gem_ctor(fd); | |||
if (!ws->bom) | |||
goto fail; | |||
ws->kman = radeon_drm_bufmgr_create(ws); | |||
if (!ws->kman) | |||
goto fail; | |||
ws->mman = pb_malloc_bufmgr_create(); | |||
if (!ws->mman) | |||
goto fail; | |||
/* Size limit on IBs is 64 kibibytes. */ | |||
priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4); | |||
radeon_cs_set_limit(priv->cs, | |||
RADEON_GEM_DOMAIN_GTT, winsys->gart_size); | |||
radeon_cs_set_limit(priv->cs, | |||
RADEON_GEM_DOMAIN_VRAM, winsys->vram_size); | |||
winsys->add_buffer = radeon_add_buffer; | |||
winsys->validate = radeon_validate; | |||
winsys->check_cs = radeon_check_cs; | |||
winsys->begin_cs = radeon_begin_cs; | |||
winsys->write_cs_dword = radeon_write_cs_dword; | |||
winsys->write_cs_reloc = radeon_write_cs_reloc; | |||
winsys->end_cs = radeon_end_cs; | |||
winsys->flush_cs = radeon_flush_cs; | |||
winsys->reset_bos = radeon_reset_bos; | |||
winsys->set_flush_cb = radeon_set_flush_cb; | |||
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.check_cs = radeon_check_cs; | |||
ws->base.begin_cs = radeon_begin_cs; | |||
ws->base.write_cs_dword = radeon_write_cs_dword; | |||
ws->base.write_cs_reloc = radeon_write_cs_reloc; | |||
ws->base.end_cs = radeon_end_cs; | |||
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_map = radeon_r300_winsys_buffer_map; | |||
ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap; | |||
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; | |||
return TRUE; | |||
fail: | |||
if (ws->csm) | |||
radeon_cs_manager_gem_dtor(ws->csm); | |||
if (ws->bom) | |||
radeon_bo_manager_gem_dtor(ws->bom); | |||
if (ws->kman) | |||
ws->kman->destroy(ws->kman); | |||
if (ws->mman) | |||
ws->mman->destroy(ws->mman); | |||
if (ws->cs) | |||
radeon_cs_destroy(ws->cs); | |||
return FALSE; | |||
} |
@@ -25,6 +25,6 @@ | |||
#include "radeon_winsys.h" | |||
void radeon_setup_winsys(int fd, struct radeon_winsys* winsys); | |||
boolean radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* winsys); | |||
#endif /* RADEON_R300_H */ |
@@ -30,16 +30,15 @@ | |||
#ifndef RADEON_WINSYS_H | |||
#define RADEON_WINSYS_H | |||
#include "util/u_simple_screen.h" | |||
#include "r300_winsys.h" | |||
struct radeon_winsys_priv; | |||
struct radeon_winsys { | |||
struct radeon_libdrm_winsys { | |||
/* Parent class. */ | |||
struct pipe_winsys base; | |||
struct r300_winsys_screen base; | |||
struct pb_manager *kman; | |||
/* Winsys private */ | |||
struct radeon_winsys_priv* priv; | |||
struct pb_manager *mman; | |||
/* PCI ID */ | |||
uint32_t pci_id; | |||
@@ -56,71 +55,27 @@ struct radeon_winsys { | |||
/* VRAM size. */ | |||
uint32_t vram_size; | |||
/* Create a buffer from a winsys handle. */ | |||
struct pipe_buffer *(*buffer_from_handle)(struct radeon_winsys *winsys, | |||
struct pipe_screen *screen, | |||
struct winsys_handle *whandle, | |||
unsigned *stride); | |||
/* Get the handle from a buffer. */ | |||
boolean (*buffer_get_handle)(struct radeon_winsys *winsys, | |||
struct pipe_buffer *buffer, | |||
unsigned stride, | |||
struct winsys_handle *whandle); | |||
/* Add a pipe_buffer to the list of buffer objects to validate. */ | |||
boolean (*add_buffer)(struct radeon_winsys* winsys, | |||
struct pipe_buffer* pbuffer, | |||
uint32_t rd, | |||
uint32_t wd); | |||
/* Revalidate all currently setup pipe_buffers. | |||
* Returns TRUE if a flush is required. */ | |||
boolean (*validate)(struct radeon_winsys* winsys); | |||
/* Check to see if there's room for commands. */ | |||
boolean (*check_cs)(struct radeon_winsys* winsys, int size); | |||
/* Start a command emit. */ | |||
void (*begin_cs)(struct radeon_winsys* winsys, | |||
int size, | |||
const char* file, | |||
const char* function, | |||
int line); | |||
/* Write a dword to the command buffer. */ | |||
void (*write_cs_dword)(struct radeon_winsys* winsys, uint32_t dword); | |||
/* Write a relocated dword to the command buffer. */ | |||
void (*write_cs_reloc)(struct radeon_winsys* winsys, | |||
struct pipe_buffer* bo, | |||
uint32_t rd, | |||
uint32_t wd, | |||
uint32_t flags); | |||
/* Finish a command emit. */ | |||
void (*end_cs)(struct radeon_winsys* winsys, | |||
const char* file, | |||
const char* function, | |||
int line); | |||
/* Flush the CS. */ | |||
void (*flush_cs)(struct radeon_winsys* winsys); | |||
/* winsys flush - callback from winsys when flush required */ | |||
void (*set_flush_cb)(struct radeon_winsys *winsys, | |||
void (*flush_cb)(void *), void *data); | |||
void (*reset_bos)(struct radeon_winsys *winsys); | |||
void (*buffer_set_tiling)(struct radeon_winsys* winsys, | |||
struct pipe_buffer* buffer, | |||
uint32_t pitch, | |||
boolean microtiled, | |||
boolean macrotiled); | |||
boolean (*is_buffer_referenced)(struct radeon_winsys *winsys, | |||
struct pipe_buffer *buffer); | |||
/* DRM FD */ | |||
int fd; | |||
/* Radeon BO manager. */ | |||
struct radeon_bo_manager *bom; | |||
/* Radeon CS manager. */ | |||
struct radeon_cs_manager *csm; | |||
/* Current CS. */ | |||
struct radeon_cs *cs; | |||
/* Flush CB */ | |||
void (*flush_cb)(void *); | |||
void *flush_data; | |||
}; | |||
static INLINE struct radeon_libdrm_winsys * | |||
radeon_winsys_screen(struct r300_winsys_screen *base) | |||
{ | |||
return (struct radeon_libdrm_winsys *)base; | |||
} | |||
#endif |