/* Switch to next buffer, optionally wait for it to be available */ static int switch_next_buffer(struct etna_ctx *ctx) { int next_buf_id = (ctx->cur_buf + 1) % NUM_COMMAND_BUFFERS; #if 0 fprintf(stderr, "Switching to new buffer %i\n", next_buf_id); #endif if(viv_user_signal_wait(ctx->conn, ctx->cmdbufi[next_buf_id].sig_id, VIV_WAIT_INDEFINITE) != 0) { #ifdef DEBUG fprintf(stderr, "Error waiting for command buffer sync signal\n"); #endif return ETNA_INTERNAL_ERROR; } clear_buffer(ctx->cmdbuf[next_buf_id]); ctx->cur_buf = next_buf_id; ctx->buf = VIV_TO_PTR(ctx->cmdbuf[next_buf_id]->logical); ctx->offset = ctx->cmdbuf[next_buf_id]->offset / 4; #ifdef DEBUG fprintf(stderr, "Switched to command buffer %i\n", ctx->cur_buf); #endif return ETNA_OK; }
/** Finish building context buffer. * final_pipe is the current pipe at the end of the context buffer. */ static int gpu_context_build_end(struct etna_ctx *ctx, enum etna_pipe final_pipe) { if(ctx->cur_buf != ETNA_CTX_BUFFER) return ETNA_INTERNAL_ERROR; /* If closing pipe of context is different from entry pipe, add a switch * command, as we want the context to end in the entry pipe. The kernel * will handle switching to the entry pipe only when this is a new context. */ if(final_pipe != GCCTX(ctx)->entryPipe) { etna_set_pipe(ctx, GCCTX(ctx)->entryPipe); } /* Set current size -- finishing up context before flush * will add space for a LINK command and inUse flag. */ GCCTX(ctx)->bufferSize = ctx->offset * 4; /* Switch back to stored buffer */ ctx->cur_buf = ctx->stored_buf; ctx->buf = VIV_TO_PTR(ctx->cmdbuf[ctx->cur_buf]->logical); ctx->offset = ctx->cmdbuf[ctx->cur_buf]->offset / 4; return ETNA_OK; }
int etna_free(struct etna_ctx *ctx) { if(ctx == NULL) return ETNA_INVALID_ADDR; /* Free kernel command queue */ etna_queue_free(ctx->queue); #ifdef GCABI_HAVE_CONTEXT /* Free context buffer */ gpu_context_free_buffer(ctx, &ctx->ctx_info, false); #endif /* Free command buffers */ for(int x=0; x<NUM_COMMAND_BUFFERS; ++x) { viv_free_contiguous(ctx->conn, ctx->cmdbufi[x].bytes, (viv_addr_t)ctx->cmdbufi[x].physical, VIV_TO_PTR(ctx->cmdbufi[x].logical)); ETNA_FREE(ctx->cmdbuf[x]); } ETNA_FREE(ctx); return ETNA_OK; }