summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/r600
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/r600')
-rw-r--r--src/gallium/winsys/r600/drm/radeon.c11
-rw-r--r--src/gallium/winsys/r600/drm/radeon_ctx.c160
-rw-r--r--src/gallium/winsys/r600/drm/radeon_draw.c92
-rw-r--r--src/gallium/winsys/r600/drm/radeon_priv.h29
-rw-r--r--src/gallium/winsys/r600/drm/radeon_state.c70
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 24d821d5cf..7e65669806 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 af270d5d20..6b0eba0b28 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 53699eb0b1..4413ed79fb 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 80392cda96..b91421f438 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 d7cd1d7a94..308288557a 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;
}