Exemple #1
0
struct etna_bo* etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags)
{
    struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
    if(mem == NULL) return NULL;

    if((flags & DRM_ETNA_GEM_TYPE_MASK) == DRM_ETNA_GEM_TYPE_CMD)
    {
        mem->bo_type = ETNA_BO_TYPE_CONTIGUOUS;
        /* Command buffers must be allocated with viv_alloc_contiguous */
        if(viv_alloc_contiguous(conn, bytes,
                    &mem->address,
                    &mem->logical,
                    &mem->size)!=0)
        {
            ETNA_FREE(mem);
            return NULL;
        }
    } else {
        enum viv_surf_type type = VIV_SURF_UNKNOWN;
        enum viv_pool pool = VIV_POOL_DEFAULT;
        /* Convert GEM bits to surface type */
        switch(flags & DRM_ETNA_GEM_TYPE_MASK)
        {
        case DRM_ETNA_GEM_TYPE_IDX: type = VIV_SURF_INDEX; break;
        case DRM_ETNA_GEM_TYPE_VTX: type = VIV_SURF_VERTEX; break;
        case DRM_ETNA_GEM_TYPE_TEX: type = VIV_SURF_TEXTURE; break;
        case DRM_ETNA_GEM_TYPE_RT:  type = VIV_SURF_RENDER_TARGET; break;
        case DRM_ETNA_GEM_TYPE_ZS:  type = VIV_SURF_DEPTH; break;
        case DRM_ETNA_GEM_TYPE_HZ:  type = VIV_SURF_HIERARCHICAL_DEPTH; break;
        case DRM_ETNA_GEM_TYPE_BMP: type = VIV_SURF_BITMAP; break;
        case DRM_ETNA_GEM_TYPE_TS:  type = VIV_SURF_TILE_STATUS; break;
        default: /* Invalid type */
            ETNA_FREE(mem);
            return NULL;
            break;
        }

        mem->bo_type = ETNA_BO_TYPE_VIDMEM;
        mem->type = type;
        if(viv_alloc_linear_vidmem(conn, bytes, ETNA_VIDMEM_ALIGNMENT, type, pool, &mem->node, &mem->size)!=0)
        {
#ifdef DEBUG
            fprintf(stderr, "Error allocating memory\n");
#endif
            return NULL;
        }
#ifdef DEBUG
        printf("Allocated: mem=%p node=%08x size=%08x\n", mem, (uint32_t)mem->node, mem->size);
#endif
        int status = etna_bo_lock(conn, mem);
        if(status != ETNA_OK)
        {
            etna_bo_del(conn, mem, NULL);
            return NULL;
        }
    }
    return mem;
}
Exemple #2
0
int etna_queue_create(struct etna_ctx *ctx, struct etna_queue **queue_out)
{
    struct etna_queue *queue = ETNA_CALLOC_STRUCT(etna_queue);
    if(queue == NULL)
    {
        return ETNA_OUT_OF_MEMORY;
    }
    queue->ctx = ctx;
    queue->queue = ETNA_CALLOC_STRUCT_ARRAY(ETNA_QUEUE_CAPACITY, _gcsQUEUE);
    queue->last = NULL;
    queue->count = 0;
    queue->max_count = ETNA_QUEUE_CAPACITY;

    *queue_out = queue;
    return ETNA_OK;
}
Exemple #3
0
struct etna_bo *etna_bo_from_name(struct viv_conn *conn, uint32_t name)
{
    struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
    if(mem == NULL) return NULL;

    mem->bo_type = ETNA_BO_TYPE_VIDMEM_EXTERNAL;
    mem->node = (viv_node_t)name;

    /* Lock to this address space */
    int status = etna_bo_lock(conn, mem);
    if(status != ETNA_OK)
    {
        free(mem);
        return NULL;
    }
    return mem;
}
Exemple #4
0
struct etna_bo *etna_bo_from_usermem(struct viv_conn *conn, void *memory, size_t size)
{
    struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
    if(mem == NULL) return NULL;

    mem->bo_type = ETNA_BO_TYPE_USERMEM;
    mem->logical = memory;
    mem->size = size;

    if(viv_map_user_memory(conn, memory, size, &mem->usermem_info, &mem->address)!=0)
    {
        ETNA_FREE(mem);
        return NULL;
    }

    return mem;
}
Exemple #5
0
struct etna_bo *etna_bo_from_fbdev(struct viv_conn *conn, int fd, size_t offset, size_t size)
{
    struct fb_fix_screeninfo finfo;
    struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
    if(mem == NULL) return NULL;

    if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo))
        goto error;

    mem->bo_type = ETNA_BO_TYPE_PHYSICAL;
    if((mem->logical = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == NULL)
        goto error;
    mem->address = finfo.smem_start + offset;
    mem->size = size;
    return mem;
error:
    ETNA_FREE(mem);
    return NULL;
}
Exemple #6
0
static int gpu_context_initialize(struct etna_ctx *ctx)
{
    gcoCONTEXT vctx = ETNA_CALLOC_STRUCT(_gcoCONTEXT);
    if(vctx == NULL)
    {
        return ETNA_OUT_OF_MEMORY;
    }
    vctx->object.type = gcvOBJ_CONTEXT;
    vctx->id = 0x0; /* Actual ID will be returned here by kernel */

    vctx->pipe3DIndex = vctx->pipe2DIndex =     /* Any non-zero value will do, as kernel does not use */
        vctx->linkIndex = vctx->inUseIndex = 1; /*  the actual values, just checks for zero */
    vctx->initialPipe = ETNA_PIPE_3D; /* Pipe to be active at beginning of context buffer */
    vctx->entryPipe = ETNA_PIPE_3D; /* Pipe at beginning of command buffer (needs to be added to context as well if */
                                    /* pipe at end of context is different from entry pipe) */
    vctx->currentPipe = ETNA_PIPE_3D; /* Pipe at end of command buffer */

    /* CPU address of buffer */
    vctx->logical = 0;
    /* Number of bytes to read from command buffer by GPU */
    vctx->bufferSize = 0;
    /* Logical address of two NOP words at end of command buffer */
    vctx->link = NULL;
    /* Logical address of inUse flag as returned from kernel (within
     * consecutive array), must have one word of NOP */
    vctx->inUse = NULL;

    ctx->ctx = VIV_TO_HANDLE(vctx);
    /* Allocate initial context buffer */
    /*   XXX DRM_ETNA_GEM_CACHE_xxx */
    if((ctx->ctx_bo = etna_bo_new(ctx->conn, COMMAND_BUFFER_SIZE, DRM_ETNA_GEM_TYPE_CMD)) == NULL)
    {
        ETNA_FREE(vctx);
        return ETNA_OUT_OF_MEMORY;
    }
    /* Set context to initial sane values */
    gpu_context_clear(ctx);
    return ETNA_OK;
}
Exemple #7
0
int etna_create(struct viv_conn *conn, struct etna_ctx **ctx_out)
{
    int rv;
    if(ctx_out == NULL) return ETNA_INVALID_ADDR;
    struct etna_ctx *ctx = ETNA_CALLOC_STRUCT(etna_ctx);
    if(ctx == NULL) return ETNA_OUT_OF_MEMORY;
    ctx->conn = conn;

    if(gpu_context_initialize(ctx) != ETNA_OK)
    {
        ETNA_FREE(ctx);
        return ETNA_INTERNAL_ERROR;
    }

    /* Create synchronization signal */
    if(viv_user_signal_create(conn, 0, &ctx->sig_id) != 0) /* automatic resetting signal */
    {
#ifdef DEBUG
        fprintf(stderr, "Cannot create user signal\n");
#endif
        return ETNA_INTERNAL_ERROR;
    }
#ifdef DEBUG
    fprintf(stderr, "Created user signal %i\n", ctx->sig_id);
#endif

    /* Allocate command buffers, and create a synchronization signal for each.
     * Also signal the synchronization signal for the buffers to tell that the buffers are ready for use.
     */
    for(int x=0; x<NUM_COMMAND_BUFFERS; ++x)
    {
        ctx->cmdbuf[x] = ETNA_CALLOC_STRUCT(_gcoCMDBUF);
        if((ctx->cmdbufi[x].bo = etna_bo_new(conn, COMMAND_BUFFER_SIZE, DRM_ETNA_GEM_TYPE_CMD))==NULL)
        {
#ifdef DEBUG
            fprintf(stderr, "Error allocating host memory for command buffer\n");
#endif
            return ETNA_OUT_OF_MEMORY;
        }
        ctx->cmdbuf[x]->object.type = gcvOBJ_COMMANDBUFFER;
#ifdef GCABI_CMDBUF_HAS_PHYSICAL
        ctx->cmdbuf[x]->physical = PTR_TO_VIV((void*)etna_bo_gpu_address(ctx->cmdbufi[x].bo));
        ctx->cmdbuf[x]->bytes = ctx->cmdbufi[x].bytes;
#endif
        ctx->cmdbuf[x]->logical = PTR_TO_VIV((void*)etna_bo_map(ctx->cmdbufi[x].bo));

        if(viv_user_signal_create(conn, 0, &ctx->cmdbufi[x].sig_id) != 0 ||
           viv_user_signal_signal(conn, ctx->cmdbufi[x].sig_id, 1) != 0)
        {
#ifdef DEBUG
            fprintf(stderr, "Cannot create user signal\n");
#endif
            return ETNA_INTERNAL_ERROR;
        }
#ifdef DEBUG
        fprintf(stderr, "Allocated buffer %i: phys=%08x log=%08x bytes=%08x [signal %i]\n", x,
                (uint32_t)buf0_physical, (uint32_t)buf0_logical, buf0_bytes, ctx->cmdbufi[x].sig);
#endif
    }

    /* Allocate command queue */
    if((rv = etna_queue_create(ctx, &ctx->queue)) != ETNA_OK)
    {
#ifdef DEBUG
        fprintf(stderr, "Error allocating kernel command queue\n");
#endif
        return rv;
    }

    /* Set current buffer to ETNA_NO_BUFFER, to signify that we need to switch to buffer 0 before
     * queueing of commands can be started.
     */
    ctx->cur_buf = ETNA_NO_BUFFER;

    *ctx_out = ctx;
    return ETNA_OK;
}