diff options
Diffstat (limited to 'src/gallium/winsys/r600')
-rw-r--r-- | src/gallium/winsys/r600/drm/radeon.c | 11 | ||||
-rw-r--r-- | src/gallium/winsys/r600/drm/radeon_ctx.c | 160 | ||||
-rw-r--r-- | src/gallium/winsys/r600/drm/radeon_draw.c | 92 | ||||
-rw-r--r-- | src/gallium/winsys/r600/drm/radeon_priv.h | 29 | ||||
-rw-r--r-- | src/gallium/winsys/r600/drm/radeon_state.c | 70 |
5 files changed, 299 insertions, 63 deletions
diff --git a/src/gallium/winsys/r600/drm/radeon.c b/src/gallium/winsys/r600/drm/radeon.c index 24d821d5cf0..7e656698064 100644 --- a/src/gallium/winsys/r600/drm/radeon.c +++ b/src/gallium/winsys/r600/drm/radeon.c @@ -43,6 +43,16 @@ static int radeon_get_device(struct radeon *radeon) return r; } +/* symbol missing drove me crazy hack to get symbol exported */ +static void fake(void) +{ + struct radeon_ctx *ctx; + struct radeon_draw *draw; + + ctx = radeon_ctx(NULL); + draw = radeon_draw(NULL); +} + struct radeon *radeon_new(int fd, unsigned device) { struct radeon *radeon; @@ -50,6 +60,7 @@ struct radeon *radeon_new(int fd, unsigned device) radeon = calloc(1, sizeof(*radeon)); if (radeon == NULL) { + fake(); return NULL; } radeon->fd = fd; diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c b/src/gallium/winsys/r600/drm/radeon_ctx.c index af270d5d20b..6b0eba0b289 100644 --- a/src/gallium/winsys/r600/drm/radeon_ctx.c +++ b/src/gallium/winsys/r600/drm/radeon_ctx.c @@ -32,8 +32,13 @@ int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo) { - if (ctx->nbo >= 2048) - return -EBUSY; + void *ptr; + + ptr = realloc(ctx->bo, sizeof(struct radeon_bo) * (ctx->nbo + 1)); + if (ptr == NULL) { + return -ENOMEM; + } + ctx->bo = ptr; ctx->bo[ctx->nbo] = bo; ctx->nbo++; return 0; @@ -71,26 +76,49 @@ void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *place } } -static void radeon_ctx_clear(struct radeon_ctx *ctx) +struct radeon_ctx *radeon_ctx(struct radeon *radeon) { - ctx->draw_cpm4 = 0; - ctx->cpm4 = 0; - ctx->ndraw = 0; - ctx->nbo = 0; - ctx->nreloc = 0; + struct radeon_ctx *ctx; + + if (radeon == NULL) + return NULL; + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + ctx->radeon = radeon_incref(radeon); + return ctx; } -int radeon_ctx_init(struct radeon_ctx *ctx, struct radeon *radeon) +struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx) { - memset(ctx, 0, sizeof(struct radeon_ctx)); - ctx->radeon = radeon_incref(radeon); - radeon_ctx_clear(ctx); + ctx->refcount++; + return ctx; +} + +struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx) +{ + unsigned i; + + if (ctx == NULL) + return NULL; + if (--ctx->refcount > 0) { + return NULL; + } + + for (i = 0; i < ctx->ndraw; i++) { + ctx->draw[i] = radeon_draw_decref(ctx->draw[i]); + } + for (i = 0; i < ctx->nbo; i++) { + ctx->bo[i] = radeon_bo_decref(ctx->radeon, ctx->bo[i]); + } + ctx->radeon = radeon_decref(ctx->radeon); + free(ctx->draw); + free(ctx->bo); free(ctx->pm4); - ctx->cpm4 = 0; - ctx->pm4 = malloc(64 * 1024); - if (ctx->pm4 == NULL) - return -ENOMEM; - return 0; + free(ctx->reloc); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); + return NULL; } static int radeon_ctx_state_bo(struct radeon_ctx *ctx, struct radeon_state *state) @@ -115,6 +143,7 @@ static int radeon_ctx_state_bo(struct radeon_ctx *ctx, struct radeon_state *stat return 0; } + int radeon_ctx_submit(struct radeon_ctx *ctx) { struct drm_radeon_cs drmib; @@ -141,7 +170,6 @@ int radeon_ctx_submit(struct radeon_ctx *ctx) r = drmCommandWriteRead(ctx->radeon->fd, DRM_RADEON_CS, &drmib, sizeof(struct drm_radeon_cs)); #endif - radeon_ctx_clear(ctx); return r; } @@ -149,6 +177,7 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_bo *bo, unsigned id, unsigned *placement) { unsigned i; + struct radeon_cs_reloc *ptr; for (i = 0; i < ctx->nreloc; i++) { if (ctx->reloc[i].handle == bo->handle) { @@ -156,12 +185,14 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_bo *bo, return 0; } } - if (ctx->nreloc >= 2048) - return -EINVAL; - ctx->reloc[ctx->nreloc].handle = bo->handle; - ctx->reloc[ctx->nreloc].read_domain = placement[0] | placement [1]; - ctx->reloc[ctx->nreloc].write_domain = placement[0] | placement [1]; - ctx->reloc[ctx->nreloc].flags = 0; + ptr = realloc(ctx->reloc, sizeof(struct radeon_cs_reloc) * (ctx->nreloc + 1)); + if (ptr == NULL) + return -ENOMEM; + ctx->reloc = ptr; + ptr[ctx->nreloc].handle = bo->handle; + ptr[ctx->nreloc].read_domain = placement[0] | placement [1]; + ptr[ctx->nreloc].write_domain = placement[0] | placement [1]; + ptr[ctx->nreloc].flags = 0; ctx->pm4[id] = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4; ctx->nreloc++; return 0; @@ -190,13 +221,21 @@ static int radeon_ctx_state_schedule(struct radeon_ctx *ctx, struct radeon_state return 0; } -int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw) +int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw) { - unsigned cpm4, i; + struct radeon_draw *pdraw = NULL; + struct radeon_draw **ndraw; + struct radeon_state *nstate, *ostate; + unsigned cpm4, i, cstate; + void *tmp; int r = 0; + ndraw = realloc(ctx->draw, sizeof(void*) * (ctx->ndraw + 1)); + if (ndraw == NULL) + return -ENOMEM; + ctx->draw = ndraw; for (i = 0; i < draw->nstate; i++) { - r = radeon_ctx_state_bo(ctx, &draw->state[i]); + r = radeon_ctx_state_bo(ctx, draw->state[i]); if (r) return r; } @@ -208,48 +247,69 @@ int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw) __func__, draw->cpm4, RADEON_CTX_MAX_PM4); return -EINVAL; } - ctx->draw[ctx->ndraw] = *draw; - for (i = 0, cpm4 = 0; i < draw->nstate - 1; i++) { - ctx->draw[ctx->ndraw].state[i].valid &= ~2; - if (ctx->draw[ctx->ndraw].state[i].valid) { - if (ctx->ndraw > 1 && ctx->draw[ctx->ndraw - 1].state[i].valid) { - if (ctx->draw[ctx->ndraw - 1].state[i].pm4_crc == draw->state[i].pm4_crc) - continue; + tmp = realloc(ctx->state, (ctx->nstate + draw->nstate) * sizeof(void*)); + if (tmp == NULL) + return -ENOMEM; + ctx->state = tmp; + pdraw = ctx->cdraw; + for (i = 0, cpm4 = 0, cstate = ctx->nstate; i < draw->nstate - 1; i++) { + nstate = draw->state[i]; + if (nstate) { + if (pdraw && pdraw->state[i]) { + ostate = pdraw->state[i]; + if (ostate->pm4_crc != nstate->pm4_crc) { + ctx->state[cstate++] = nstate; + cpm4 += nstate->cpm4; + } + } else { + ctx->state[cstate++] = nstate; + cpm4 += nstate->cpm4; } - ctx->draw[ctx->ndraw].state[i].valid |= 2; - cpm4 += ctx->draw[ctx->ndraw].state[i].cpm4; } } /* The last state is the draw state always add it */ - if (!draw->state[i].valid) { + if (draw->state[i] == NULL) { fprintf(stderr, "%s no draw command\n", __func__); return -EINVAL; } - ctx->draw[ctx->ndraw].state[i].valid |= 2; - cpm4 += ctx->draw[ctx->ndraw].state[i].cpm4; + ctx->state[cstate++] = draw->state[i]; + cpm4 += draw->state[i]->cpm4; if ((ctx->draw_cpm4 + cpm4) > RADEON_CTX_MAX_PM4) { /* need to flush */ return -EBUSY; } ctx->draw_cpm4 += cpm4; - ctx->ndraw++; + ctx->nstate = cstate; + ctx->draw[ctx->ndraw++] = draw; + ctx->cdraw = draw; return 0; } +int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw) +{ + int r; + + radeon_draw_incref(draw); + r = radeon_ctx_set_draw_new(ctx, draw); + if (r) + radeon_draw_decref(draw); + return r; +} + int radeon_ctx_pm4(struct radeon_ctx *ctx) { - unsigned i, j, c; + unsigned i; int r; - for (i = 0, c = 0, ctx->id = 0; i < ctx->ndraw; i++) { - for (j = 0; j < ctx->draw[i].nstate; j++) { - if (ctx->draw[i].state[j].valid & 2) { - r = radeon_ctx_state_schedule(ctx, &ctx->draw[i].state[j]); - if (r) - return r; - c += ctx->draw[i].state[j].cpm4; - } - } + free(ctx->pm4); + ctx->cpm4 = 0; + ctx->pm4 = malloc(ctx->draw_cpm4 * 4); + if (ctx->pm4 == NULL) + return -EINVAL; + for (i = 0, ctx->id = 0; i < ctx->nstate; i++) { + r = radeon_ctx_state_schedule(ctx, ctx->state[i]); + if (r) + return r; } if (ctx->id != ctx->draw_cpm4) { fprintf(stderr, "%s miss predicted pm4 size %d for %d\n", diff --git a/src/gallium/winsys/r600/drm/radeon_draw.c b/src/gallium/winsys/r600/drm/radeon_draw.c index 53699eb0b1c..4413ed79fbd 100644 --- a/src/gallium/winsys/r600/drm/radeon_draw.c +++ b/src/gallium/winsys/r600/drm/radeon_draw.c @@ -31,33 +31,111 @@ /* * draw functions */ -int radeon_draw_init(struct radeon_draw *draw, struct radeon *radeon) +struct radeon_draw *radeon_draw(struct radeon *radeon) { - memset(draw, 0, sizeof(struct radeon_draw)); + struct radeon_draw *draw; + + draw = calloc(1, sizeof(*draw)); + if (draw == NULL) + return NULL; draw->nstate = radeon->nstate; draw->radeon = radeon; - return 0; + draw->refcount = 1; + draw->state = calloc(1, sizeof(void*) * draw->nstate); + if (draw->state == NULL) { + free(draw); + return NULL; + } + return draw; } -int radeon_draw_set(struct radeon_draw *draw, struct radeon_state *state) +struct radeon_draw *radeon_draw_incref(struct radeon_draw *draw) +{ + draw->refcount++; + return draw; +} + +struct radeon_draw *radeon_draw_decref(struct radeon_draw *draw) +{ + unsigned i; + + if (draw == NULL) + return NULL; + if (--draw->refcount > 0) + return NULL; + for (i = 0; i < draw->nstate; i++) { + draw->state[i] = radeon_state_decref(draw->state[i]); + } + free(draw->state); + memset(draw, 0, sizeof(*draw)); + free(draw); + return NULL; +} + +int radeon_draw_set_new(struct radeon_draw *draw, struct radeon_state *state) { if (state == NULL) return 0; if (state->type >= draw->radeon->ntype) return -EINVAL; - draw->state[state->id] = *state; + draw->state[state->id] = radeon_state_decref(draw->state[state->id]); + draw->state[state->id] = state; return 0; } +int radeon_draw_set(struct radeon_draw *draw, struct radeon_state *state) +{ + if (state == NULL) + return 0; + radeon_state_incref(state); + return radeon_draw_set_new(draw, state); +} + int radeon_draw_check(struct radeon_draw *draw) { unsigned i; int r; + r = radeon_draw_pm4(draw); + if (r) + return r; for (i = 0, draw->cpm4 = 0; i < draw->nstate; i++) { - if (draw->state[i].valid) { - draw->cpm4 += draw->state[i].cpm4; + if (draw->state[i]) { + draw->cpm4 += draw->state[i]->cpm4; } } return 0; } + +struct radeon_draw *radeon_draw_duplicate(struct radeon_draw *draw) +{ + struct radeon_draw *ndraw; + unsigned i; + + if (draw == NULL) + return NULL; + ndraw = radeon_draw(draw->radeon); + if (ndraw == NULL) { + return NULL; + } + for (i = 0; i < draw->nstate; i++) { + if (radeon_draw_set(ndraw, draw->state[i])) { + radeon_draw_decref(ndraw); + return NULL; + } + } + return ndraw; +} + +int radeon_draw_pm4(struct radeon_draw *draw) +{ + unsigned i; + int r; + + for (i = 0; i < draw->nstate; i++) { + r = radeon_state_pm4(draw->state[i]); + if (r) + return r; + } + return 0; +} diff --git a/src/gallium/winsys/r600/drm/radeon_priv.h b/src/gallium/winsys/r600/drm/radeon_priv.h index 80392cda967..b91421f4389 100644 --- a/src/gallium/winsys/r600/drm/radeon_priv.h +++ b/src/gallium/winsys/r600/drm/radeon_priv.h @@ -24,6 +24,7 @@ #include "radeon.h" struct radeon; +struct radeon_ctx; /* * radeon functions @@ -70,6 +71,34 @@ extern unsigned radeon_type_from_id(struct radeon *radeon, unsigned id); /* * radeon context functions */ +#pragma pack(1) +struct radeon_cs_reloc { + uint32_t handle; + uint32_t read_domain; + uint32_t write_domain; + uint32_t flags; +}; +#pragma pack() + +struct radeon_ctx { + int refcount; + struct radeon *radeon; + u32 *pm4; + u32 cpm4; + u32 draw_cpm4; + unsigned id; + unsigned next_id; + unsigned nreloc; + struct radeon_cs_reloc *reloc; + unsigned nbo; + struct radeon_bo **bo; + unsigned ndraw; + struct radeon_draw *cdraw; + struct radeon_draw **draw; + unsigned nstate; + struct radeon_state **state; +}; + int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo); struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc); void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement); diff --git a/src/gallium/winsys/r600/drm/radeon_state.c b/src/gallium/winsys/r600/drm/radeon_state.c index d7cd1d7a946..308288557a4 100644 --- a/src/gallium/winsys/r600/drm/radeon_state.c +++ b/src/gallium/winsys/r600/drm/radeon_state.c @@ -32,23 +32,82 @@ /* * state core functions */ -int radeon_state_init(struct radeon_state *state, struct radeon *radeon, u32 type, u32 id) +struct radeon_state *radeon_state(struct radeon *radeon, u32 type, u32 id) { + struct radeon_state *state; + if (type > radeon->ntype) { fprintf(stderr, "%s invalid type %d\n", __func__, type); - return -EINVAL; + return NULL; } if (id > radeon->nstate) { fprintf(stderr, "%s invalid state id %d\n", __func__, id); - return -EINVAL; + return NULL; } - memset(state, 0, sizeof(struct radeon_state)); + state = calloc(1, sizeof(*state)); + if (state == NULL) + return NULL; state->radeon = radeon; state->type = type; state->id = id; + state->refcount = 1; state->npm4 = radeon->type[type].npm4; state->nstates = radeon->type[type].nstates; - return 0; + state->states = calloc(1, state->nstates * 4); + state->pm4 = calloc(1, radeon->type[type].npm4 * 4); + if (state->states == NULL || state->pm4 == NULL) { + radeon_state_decref(state); + return NULL; + } + return state; +} + +struct radeon_state *radeon_state_duplicate(struct radeon_state *state) +{ + struct radeon_state *nstate = radeon_state(state->radeon, state->type, state->id); + unsigned i; + + if (state == NULL) + return NULL; + nstate->cpm4 = state->cpm4; + nstate->nbo = state->nbo; + nstate->nreloc = state->nreloc; + memcpy(nstate->states, state->states, state->nstates * 4); + memcpy(nstate->pm4, state->pm4, state->npm4 * 4); + memcpy(nstate->placement, state->placement, 8 * 4); + memcpy(nstate->reloc_pm4_id, state->reloc_pm4_id, 8 * 4); + memcpy(nstate->reloc_bo_id, state->reloc_bo_id, 8 * 4); + memcpy(nstate->bo_dirty, state->bo_dirty, 4 * 4); + for (i = 0; i < state->nbo; i++) { + nstate->bo[i] = radeon_bo_incref(state->radeon, state->bo[i]); + } + return nstate; +} + +struct radeon_state *radeon_state_incref(struct radeon_state *state) +{ + state->refcount++; + return state; +} + +struct radeon_state *radeon_state_decref(struct radeon_state *state) +{ + unsigned i; + + if (state == NULL) + return NULL; + if (--state->refcount > 0) { + return NULL; + } + for (i = 0; i < state->nbo; i++) { + state->bo[i] = radeon_bo_decref(state->radeon, state->bo[i]); + } + free(state->immd); + free(state->states); + free(state->pm4); + memset(state, 0, sizeof(*state)); + free(state); + return NULL; } int radeon_state_replace_always(struct radeon_state *ostate, @@ -97,7 +156,6 @@ int radeon_state_pm4(struct radeon_state *state) return r; } state->pm4_crc = crc32(state->pm4, state->cpm4 * 4); - state->valid = 1; return 0; } |