From b8fb1d75ce95fe5d404b301ab31ca0c323967d14 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Mon, 10 May 2010 03:27:58 +0200 Subject: r600g: adapt to latest interfaces changes - Wrapped the buffer and texture create/destroy/transfer/... functions using u_resource, which is then used to implement the resource functions. - Implemented texture transfers. I left the buffer and texture transfers separate because one day we'll need a special codepath for textures. - Added index_bias to the draw_*elements functions. - Removed nonexistent *REP and *FOR instructions. - Some pipe formats have changed channel ordering, so I've removed/fixed nonexistent ones. - Added stubs for create/set/destroy sampler views. - Added a naive implementation of vertex elements state (new CSO). - Reworked {texture,buffer}_{from,to}_handle. - Reorganized winsys files, removed dri,egl,python directories. - Added a new build target dri-r600. --- src/gallium/winsys/r600/drm/radeon_ctx.c | 407 +++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 src/gallium/winsys/r600/drm/radeon_ctx.c (limited to 'src/gallium/winsys/r600/drm/radeon_ctx.c') diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c b/src/gallium/winsys/r600/drm/radeon_ctx.c new file mode 100644 index 0000000000..0c8f1fac18 --- /dev/null +++ b/src/gallium/winsys/r600/drm/radeon_ctx.c @@ -0,0 +1,407 @@ +/* + * Copyright 2010 Jerome Glisse + * + * 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: + * Jerome Glisse + */ +#include +#include +#include +#include "radeon_priv.h" +#include "radeon_drm.h" +#include "bof.h" + +int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo) +{ + 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; +} + +struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc) +{ + struct radeon_cs_reloc *greloc; + unsigned i; + + greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4); + for (i = 0; i < ctx->nbo; i++) { + if (ctx->bo[i]->handle == greloc->handle) { + return radeon_bo_incref(ctx->radeon, ctx->bo[i]); + } + } + fprintf(stderr, "%s no bo for reloc[%d 0x%08X] %d\n", __func__, reloc, greloc->handle, ctx->nbo); + return NULL; +} + +void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement) +{ + struct radeon_cs_reloc *greloc; + unsigned i; + + placement[0] = 0; + placement[1] = 0; + greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4); + for (i = 0; i < ctx->nbo; i++) { + if (ctx->bo[i]->handle == greloc->handle) { + placement[0] = greloc->read_domain | greloc->write_domain; + placement[1] = placement[0]; + return; + } + } +} + +struct radeon_ctx *radeon_ctx(struct radeon *radeon) +{ + 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; +} + +struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *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); + 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) +{ + unsigned i, j; + int r; + + if (state == NULL) + return 0; + for (i = 0; i < state->nbo; i++) { + for (j = 0; j < ctx->nbo; j++) { + if (state->bo[i] == ctx->bo[j]) + break; + } + if (j == ctx->nbo) { + radeon_bo_incref(ctx->radeon, state->bo[i]); + r = radeon_ctx_set_bo_new(ctx, state->bo[i]); + if (r) + return r; + } + } + return 0; +} + + +int radeon_ctx_submit(struct radeon_ctx *ctx) +{ + struct drm_radeon_cs drmib; + struct drm_radeon_cs_chunk chunks[2]; + uint64_t chunk_array[2]; + int r = 0; + +#if 0 + for (r = 0; r < ctx->cpm4; r++) { + fprintf(stderr, "0x%08X\n", ctx->pm4[r]); + } +#endif + drmib.num_chunks = 2; + drmib.chunks = (uint64_t)(uintptr_t)chunk_array; + chunks[0].chunk_id = RADEON_CHUNK_ID_IB; + chunks[0].length_dw = ctx->cpm4; + chunks[0].chunk_data = (uint64_t)(uintptr_t)ctx->pm4; + chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + chunks[1].length_dw = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4; + chunks[1].chunk_data = (uint64_t)(uintptr_t)ctx->reloc; + chunk_array[0] = (uint64_t)(uintptr_t)&chunks[0]; + chunk_array[1] = (uint64_t)(uintptr_t)&chunks[1]; +#if 1 + r = drmCommandWriteRead(ctx->radeon->fd, DRM_RADEON_CS, &drmib, + sizeof(struct drm_radeon_cs)); +#endif + return r; +} + +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) { + ctx->pm4[id] = i * sizeof(struct radeon_cs_reloc) / 4; + return 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; +} + +static int radeon_ctx_state_schedule(struct radeon_ctx *ctx, struct radeon_state *state) +{ + unsigned i, rid, bid, cid; + int r; + + if (state == NULL) + return 0; + memcpy(&ctx->pm4[ctx->id], state->pm4, state->cpm4 * 4); + for (i = 0; i < state->nreloc; i++) { + rid = state->reloc_pm4_id[i]; + bid = state->reloc_bo_id[i]; + cid = ctx->id + rid; + r = radeon_ctx_reloc(ctx, state->bo[bid], cid, + &state->placement[bid * 2]); + if (r) { + fprintf(stderr, "%s state %d failed to reloc\n", __func__, state->type); + return r; + } + } + ctx->id += state->cpm4; + return 0; +} + +int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw) +{ + 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]); + if (r) + return r; + } + r = radeon_draw_check(draw); + if (r) + return r; + if (draw->cpm4 >= RADEON_CTX_MAX_PM4) { + fprintf(stderr, "%s single draw too big %d, max %d\n", + __func__, draw->cpm4, RADEON_CTX_MAX_PM4); + return -EINVAL; + } + 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; + } + } + } + /* The last state is the draw state always add it */ + if (draw->state[i] == NULL) { + fprintf(stderr, "%s no draw command\n", __func__); + return -EINVAL; + } + 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->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; + int r; + + 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", + __func__, ctx->draw_cpm4, ctx->id); + return -EINVAL; + } + ctx->cpm4 = ctx->draw_cpm4; + return 0; +} + +void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file) +{ + bof_t *bcs, *blob, *array, *bo, *size, *handle, *device_id, *root; + char tmp[256]; + unsigned i; + + root = device_id = bcs = blob = array = bo = size = handle = NULL; + root = bof_object(); + if (root == NULL) + goto out_err; + device_id = bof_int32(ctx->radeon->device); + if (device_id == NULL) + return; + if (bof_object_set(root, "device_id", device_id)) + goto out_err; + bof_decref(device_id); + device_id = NULL; + /* dump relocs */ +printf("%d relocs\n", ctx->nreloc); + blob = bof_blob(ctx->nreloc * 16, ctx->reloc); + if (blob == NULL) + goto out_err; + if (bof_object_set(root, "reloc", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + /* dump cs */ +printf("%d pm4\n", ctx->cpm4); + blob = bof_blob(ctx->cpm4 * 4, ctx->pm4); + if (blob == NULL) + goto out_err; + if (bof_object_set(root, "pm4", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + /* dump bo */ + array = bof_array(); + if (array == NULL) + goto out_err; + for (i = 0; i < ctx->nbo; i++) { + bo = bof_object(); + if (bo == NULL) + goto out_err; + size = bof_int32(ctx->bo[i]->size); +printf("[%d] %d bo\n", i, size); + if (size == NULL) + goto out_err; + if (bof_object_set(bo, "size", size)) + goto out_err; + bof_decref(size); + size = NULL; + handle = bof_int32(ctx->bo[i]->handle); + if (handle == NULL) + goto out_err; + if (bof_object_set(bo, "handle", handle)) + goto out_err; + bof_decref(handle); + handle = NULL; + radeon_bo_map(ctx->radeon, ctx->bo[i]); + blob = bof_blob(ctx->bo[i]->size, ctx->bo[i]->data); + radeon_bo_unmap(ctx->radeon, ctx->bo[i]); + if (blob == NULL) + goto out_err; + if (bof_object_set(bo, "data", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + if (bof_array_append(array, bo)) + goto out_err; + bof_decref(bo); + bo = NULL; + } + if (bof_object_set(root, "bo", array)) + goto out_err; + bof_dump_file(root, file); +printf("done dump\n"); +out_err: + bof_decref(blob); + bof_decref(array); + bof_decref(bo); + bof_decref(size); + bof_decref(handle); + bof_decref(device_id); + bof_decref(root); +} -- cgit v1.2.3