Browse Source

r300g: rebuild screen/winsys interface

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
Dave Airlie 15 years ago
parent
commit
68e58a96e8

+ 1
- 0
src/gallium/drivers/r300/Makefile View File

@@ -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 \

+ 28
- 6
src/gallium/drivers/r300/r300_context.c View File

@@ -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;
}

+ 7
- 2
src/gallium/drivers/r300/r300_context.h View File

@@ -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. */

+ 17
- 5
src/gallium/drivers/r300/r300_cs.h View File

@@ -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)


+ 40
- 33
src/gallium/drivers/r300/r300_emit.c View File

@@ -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. */

+ 13
- 7
src/gallium/drivers/r300/r300_render.c View File

@@ -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);
}
}


+ 20
- 10
src/gallium/drivers/r300/r300_screen.c View File

@@ -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;
}

+ 1
- 4
src/gallium/drivers/r300/r300_screen.h View File

@@ -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. */

/**

+ 314
- 0
src/gallium/drivers/r300/r300_screen_buffer.c View File

@@ -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;
}

+ 99
- 0
src/gallium/drivers/r300/r300_screen_buffer.h View File

@@ -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

+ 21
- 7
src/gallium/drivers/r300/r300_state.c View File

@@ -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);

+ 37
- 15
src/gallium/drivers/r300/r300_texture.c View File

@@ -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;
}

+ 2
- 2
src/gallium/drivers/r300/r300_texture.h View File

@@ -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 */

+ 8
- 4
src/gallium/drivers/r300/r300_transfer.c View File

@@ -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);
}
}


+ 137
- 9
src/gallium/drivers/r300/r300_winsys.h View File

@@ -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 */

+ 1
- 1
src/gallium/winsys/drm/radeon/core/Makefile View File

@@ -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


+ 37
- 29
src/gallium/winsys/drm/radeon/core/radeon_buffer.h View File

@@ -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

+ 32
- 9
src/gallium/winsys/drm/radeon/core/radeon_drm.c View File

@@ -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)

+ 16
- 0
src/gallium/winsys/drm/radeon/core/radeon_drm.h View File

@@ -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.

+ 368
- 0
src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c View File

@@ -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);

}

+ 238
- 63
src/gallium/winsys/drm/radeon/core/radeon_r300.c View File

@@ -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;
}

+ 1
- 1
src/gallium/winsys/drm/radeon/core/radeon_r300.h View File

@@ -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 */

+ 27
- 72
src/gallium/winsys/drm/radeon/core/radeon_winsys.h View File

@@ -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

Loading…
Cancel
Save