diff options
Diffstat (limited to 'src/mesa/drivers/dri/radeon/radeon_bo_legacy.c')
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_bo_legacy.c | 912 |
1 files changed, 912 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c new file mode 100644 index 0000000000..5575da6971 --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c @@ -0,0 +1,912 @@ +/* + * Copyright © 2008 Nicolai Haehnle + * Copyright © 2008 Dave Airlie + * Copyright © 2008 Jérôme Glisse + * All Rights Reserved. + * + * 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 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 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 COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ +/* + * Authors: + * Aapo Tahkola <aet@rasterburn.org> + * Nicolai Haehnle <prefect_@gmx.net> + * Dave Airlie + * Jérôme Glisse <glisse@freedesktop.org> + */ +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include "xf86drm.h" +#include "texmem.h" +#include "main/simple_list.h" + +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_common.h" +#include "radeon_bocs_wrapper.h" +#include "radeon_macros.h" + +/* no seriously texmem.c is this screwed up */ +struct bo_legacy_texture_object { + driTextureObject base; + struct bo_legacy *parent; +}; + +struct bo_legacy { + struct radeon_bo base; + int map_count; + uint32_t pending; + int is_pending; + int static_bo; + uint32_t offset; + struct bo_legacy_texture_object *tobj; + int validated; + int dirty; + void *ptr; + struct bo_legacy *next, *prev; + struct bo_legacy *pnext, *pprev; +}; + +struct bo_manager_legacy { + struct radeon_bo_manager base; + unsigned nhandle; + unsigned nfree_handles; + unsigned cfree_handles; + uint32_t current_age; + struct bo_legacy bos; + struct bo_legacy pending_bos; + uint32_t fb_location; + uint32_t texture_offset; + unsigned dma_alloc_size; + uint32_t dma_buf_count; + unsigned cpendings; + driTextureObject texture_swapped; + driTexHeap *texture_heap; + struct radeon_screen *screen; + unsigned *free_handles; +}; + +static void bo_legacy_tobj_destroy(void *data, driTextureObject *t) +{ + struct bo_legacy_texture_object *tobj = (struct bo_legacy_texture_object *)t; + + if (tobj->parent) { + tobj->parent->tobj = NULL; + tobj->parent->validated = 0; + } +} + +static void inline clean_handles(struct bo_manager_legacy *bom) +{ + while (bom->cfree_handles > 0 && + !bom->free_handles[bom->cfree_handles - 1]) + bom->cfree_handles--; + +} +static int legacy_new_handle(struct bo_manager_legacy *bom, uint32_t *handle) +{ + uint32_t tmp; + + *handle = 0; + if (bom->nhandle == 0xFFFFFFFF) { + return -EINVAL; + } + if (bom->cfree_handles > 0) { + tmp = bom->free_handles[--bom->cfree_handles]; + clean_handles(bom); + } else { + bom->cfree_handles = 0; + tmp = bom->nhandle++; + } + assert(tmp); + *handle = tmp; + return 0; +} + +static int legacy_free_handle(struct bo_manager_legacy *bom, uint32_t handle) +{ + uint32_t *handles; + + if (!handle) { + return 0; + } + if (handle == (bom->nhandle - 1)) { + int i; + + bom->nhandle--; + for (i = bom->cfree_handles - 1; i >= 0; i--) { + if (bom->free_handles[i] == (bom->nhandle - 1)) { + bom->nhandle--; + bom->free_handles[i] = 0; + } + } + clean_handles(bom); + return 0; + } + if (bom->cfree_handles < bom->nfree_handles) { + bom->free_handles[bom->cfree_handles++] = handle; + return 0; + } + bom->nfree_handles += 0x100; + handles = (uint32_t*)realloc(bom->free_handles, bom->nfree_handles * 4); + if (handles == NULL) { + bom->nfree_handles -= 0x100; + return -ENOMEM; + } + bom->free_handles = handles; + bom->free_handles[bom->cfree_handles++] = handle; + return 0; +} + +static void legacy_get_current_age(struct bo_manager_legacy *boml) +{ + drm_radeon_getparam_t gp; + unsigned char *RADEONMMIO = NULL; + int r; + + if ( IS_R300_CLASS(boml->screen) + || IS_R600_CLASS(boml->screen) ) + { + gp.param = RADEON_PARAM_LAST_CLEAR; + gp.value = (int *)&boml->current_age; + r = drmCommandWriteRead(boml->base.fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (r) { + fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r); + exit(1); + } + } + else { + RADEONMMIO = boml->screen->mmio.map; + boml->current_age = boml->screen->scratch[3]; + boml->current_age = INREG(RADEON_GUI_SCRATCH_REG3); + } +} + +static int legacy_is_pending(struct radeon_bo *bo) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + if (bo_legacy->is_pending <= 0) { + bo_legacy->is_pending = 0; + return 0; + } + if (boml->current_age >= bo_legacy->pending) { + if (boml->pending_bos.pprev == bo_legacy) { + boml->pending_bos.pprev = bo_legacy->pprev; + } + bo_legacy->pprev->pnext = bo_legacy->pnext; + if (bo_legacy->pnext) { + bo_legacy->pnext->pprev = bo_legacy->pprev; + } + assert(bo_legacy->is_pending <= bo->cref); + while (bo_legacy->is_pending--) { + bo = radeon_bo_unref(bo); + if (!bo) + break; + } + if (bo) + bo_legacy->is_pending = 0; + boml->cpendings--; + return 0; + } + return 1; +} + +static int legacy_wait_pending(struct radeon_bo *bo) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + if (!bo_legacy->is_pending) { + return 0; + } + /* FIXME: lockup and userspace busy looping that's all the folks */ + legacy_get_current_age(boml); + while (legacy_is_pending(bo)) { + usleep(10); + legacy_get_current_age(boml); + } + return 0; +} + +static void legacy_track_pending(struct bo_manager_legacy *boml, int debug) +{ + struct bo_legacy *bo_legacy; + struct bo_legacy *next; + + legacy_get_current_age(boml); + bo_legacy = boml->pending_bos.pnext; + while (bo_legacy) { + if (debug) + fprintf(stderr,"pending %p %d %d %d\n", bo_legacy, bo_legacy->base.size, + boml->current_age, bo_legacy->pending); + next = bo_legacy->pnext; + if (legacy_is_pending(&(bo_legacy->base))) { + } + bo_legacy = next; + } +} + +static int legacy_wait_any_pending(struct bo_manager_legacy *boml) +{ + struct bo_legacy *bo_legacy; + + legacy_get_current_age(boml); + bo_legacy = boml->pending_bos.pnext; + if (!bo_legacy) + return -1; + legacy_wait_pending(&bo_legacy->base); + return 0; +} + +static void legacy_kick_all_buffers(struct bo_manager_legacy *boml) +{ + struct bo_legacy *legacy; + + legacy = boml->bos.next; + while (legacy != &boml->bos) { + if (legacy->tobj) { + if (legacy->validated) { + driDestroyTextureObject(&legacy->tobj->base); + legacy->tobj = 0; + legacy->validated = 0; + } + } + legacy = legacy->next; + } +} + +static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml, + uint32_t size, + uint32_t alignment, + uint32_t domains, + uint32_t flags) +{ + struct bo_legacy *bo_legacy; + static int pgsize; + + if (pgsize == 0) + pgsize = getpagesize() - 1; + + size = (size + pgsize) & ~pgsize; + + bo_legacy = (struct bo_legacy*)calloc(1, sizeof(struct bo_legacy)); + if (bo_legacy == NULL) { + return NULL; + } + bo_legacy->base.bom = (struct radeon_bo_manager*)boml; + bo_legacy->base.handle = 0; + bo_legacy->base.size = size; + bo_legacy->base.alignment = alignment; + bo_legacy->base.domains = domains; + bo_legacy->base.flags = flags; + bo_legacy->base.ptr = NULL; + bo_legacy->map_count = 0; + bo_legacy->next = NULL; + bo_legacy->prev = NULL; + bo_legacy->pnext = NULL; + bo_legacy->pprev = NULL; + bo_legacy->next = boml->bos.next; + bo_legacy->prev = &boml->bos; + boml->bos.next = bo_legacy; + if (bo_legacy->next) { + bo_legacy->next->prev = bo_legacy; + } + + return bo_legacy; +} + +static int bo_dma_alloc(struct radeon_bo *bo) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + drm_radeon_mem_alloc_t alloc; + unsigned size; + int base_offset; + int r; + + /* align size on 4Kb */ + size = (((4 * 1024) - 1) + bo->size) & ~((4 * 1024) - 1); + alloc.region = RADEON_MEM_REGION_GART; + alloc.alignment = bo_legacy->base.alignment; + alloc.size = size; + alloc.region_offset = &base_offset; + r = drmCommandWriteRead(bo->bom->fd, + DRM_RADEON_ALLOC, + &alloc, + sizeof(alloc)); + if (r) { + /* ptr is set to NULL if dma allocation failed */ + bo_legacy->ptr = NULL; + return r; + } + bo_legacy->ptr = boml->screen->gartTextures.map + base_offset; + bo_legacy->offset = boml->screen->gart_texture_offset + base_offset; + bo->size = size; + boml->dma_alloc_size += size; + boml->dma_buf_count++; + return 0; +} + +static int bo_dma_free(struct radeon_bo *bo) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + drm_radeon_mem_free_t memfree; + int r; + + if (bo_legacy->ptr == NULL) { + /* ptr is set to NULL if dma allocation failed */ + return 0; + } + legacy_get_current_age(boml); + memfree.region = RADEON_MEM_REGION_GART; + memfree.region_offset = bo_legacy->offset; + memfree.region_offset -= boml->screen->gart_texture_offset; + r = drmCommandWrite(boml->base.fd, + DRM_RADEON_FREE, + &memfree, + sizeof(memfree)); + if (r) { + fprintf(stderr, "Failed to free bo[%p] at %08x\n", + &bo_legacy->base, memfree.region_offset); + fprintf(stderr, "ret = %s\n", strerror(-r)); + return r; + } + boml->dma_alloc_size -= bo_legacy->base.size; + boml->dma_buf_count--; + return 0; +} + +static void bo_free(struct bo_legacy *bo_legacy) +{ + struct bo_manager_legacy *boml; + + if (bo_legacy == NULL) { + return; + } + boml = (struct bo_manager_legacy *)bo_legacy->base.bom; + bo_legacy->prev->next = bo_legacy->next; + if (bo_legacy->next) { + bo_legacy->next->prev = bo_legacy->prev; + } + if (!bo_legacy->static_bo) { + legacy_free_handle(boml, bo_legacy->base.handle); + if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) { + /* dma buffers */ + bo_dma_free(&bo_legacy->base); + } else { + driDestroyTextureObject(&bo_legacy->tobj->base); + bo_legacy->tobj = NULL; + /* free backing store */ + free(bo_legacy->ptr); + } + } + memset(bo_legacy, 0 , sizeof(struct bo_legacy)); + free(bo_legacy); +} + +static struct radeon_bo *bo_open(struct radeon_bo_manager *bom, + uint32_t handle, + uint32_t size, + uint32_t alignment, + uint32_t domains, + uint32_t flags) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom; + struct bo_legacy *bo_legacy; + int r; + + if (handle) { + bo_legacy = boml->bos.next; + while (bo_legacy) { + if (bo_legacy->base.handle == handle) { + radeon_bo_ref(&(bo_legacy->base)); + return (struct radeon_bo*)bo_legacy; + } + bo_legacy = bo_legacy->next; + } + return NULL; + } + bo_legacy = bo_allocate(boml, size, alignment, domains, flags); + bo_legacy->static_bo = 0; + r = legacy_new_handle(boml, &bo_legacy->base.handle); + if (r) { + bo_free(bo_legacy); + return NULL; + } + if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) + { +retry: + legacy_track_pending(boml, 0); + /* dma buffers */ + + r = bo_dma_alloc(&(bo_legacy->base)); + if (r) + { + if (legacy_wait_any_pending(boml) == -1) + { + bo_free(bo_legacy); + return NULL; + } + goto retry; + return NULL; + } + } + else + { + bo_legacy->ptr = malloc(bo_legacy->base.size); + if (bo_legacy->ptr == NULL) { + bo_free(bo_legacy); + return NULL; + } + } + radeon_bo_ref(&(bo_legacy->base)); + + return (struct radeon_bo*)bo_legacy; +} + +static void bo_ref(struct radeon_bo *bo) +{ +} + +static struct radeon_bo *bo_unref(struct radeon_bo *bo) +{ + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + if (bo->cref <= 0) { + bo_legacy->prev->next = bo_legacy->next; + if (bo_legacy->next) { + bo_legacy->next->prev = bo_legacy->prev; + } + if (!bo_legacy->is_pending) { + bo_free(bo_legacy); + } + return NULL; + } + return bo; +} + +static int bo_map(struct radeon_bo *bo, int write) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + legacy_wait_pending(bo); + bo_legacy->validated = 0; + bo_legacy->dirty = 1; + bo_legacy->map_count++; + bo->ptr = bo_legacy->ptr; + /* Read the first pixel in the frame buffer. This should + * be a noop, right? In fact without this conform fails as reading + * from the framebuffer sometimes produces old results -- the + * on-card read cache gets mixed up and doesn't notice that the + * framebuffer has been updated. + * + * Note that we should probably be reading some otherwise unused + * region of VRAM, otherwise we might get incorrect results when + * reading pixels from the top left of the screen. + * + * I found this problem on an R420 with glean's texCube test. + * Note that the R200 span code also *writes* the first pixel in the + * framebuffer, but I've found this to be unnecessary. + * -- Nicolai Hähnle, June 2008 + */ + if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) { + int p; + volatile int *buf = (int*)boml->screen->driScreen->pFB; + p = *buf; + } + + return 0; +} + +static int bo_unmap(struct radeon_bo *bo) +{ + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + if (--bo_legacy->map_count > 0) + { + return 0; + } + + bo->ptr = NULL; + + return 0; +} + + +static int bo_is_static(struct radeon_bo *bo) +{ + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + return bo_legacy->static_bo; +} + +static struct radeon_bo_funcs bo_legacy_funcs = { + bo_open, + bo_ref, + bo_unref, + bo_map, + bo_unmap, + NULL, + bo_is_static, + NULL, + NULL, +}; + +static int bo_vram_validate(struct radeon_bo *bo, + uint32_t *soffset, + uint32_t *eoffset) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + int r; + int retry_count = 0, pending_retry = 0; + + if (!bo_legacy->tobj) { + bo_legacy->tobj = CALLOC(sizeof(struct bo_legacy_texture_object)); + bo_legacy->tobj->parent = bo_legacy; + make_empty_list(&bo_legacy->tobj->base); + bo_legacy->tobj->base.totalSize = bo->size; + retry: + r = driAllocateTexture(&boml->texture_heap, 1, + &bo_legacy->tobj->base); + if (r) { + pending_retry = 0; + while(boml->cpendings && pending_retry++ < 10000) { + legacy_track_pending(boml, 0); + retry_count++; + if (retry_count > 2) { + free(bo_legacy->tobj); + bo_legacy->tobj = NULL; + fprintf(stderr, "Ouch! vram_validate failed %d\n", r); + return -1; + } + goto retry; + } + } + bo_legacy->offset = boml->texture_offset + + bo_legacy->tobj->base.memBlock->ofs; + bo_legacy->dirty = 1; + } + + assert(bo_legacy->tobj->base.memBlock); + + if (bo_legacy->tobj) + driUpdateTextureLRU(&bo_legacy->tobj->base); + + if (bo_legacy->dirty || bo_legacy->tobj->base.dirty_images[0]) { + if (IS_R600_CLASS(boml->screen)) { + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; + + tex.offset = bo_legacy->offset; + tex.image = &tmp; + assert(!(tex.offset & 1023)); + + tmp.x = 0; + tmp.y = 0; + tmp.width = bo->size; + tmp.height = 1; + tmp.data = bo_legacy->ptr; + tex.format = RADEON_TXFORMAT_ARGB8888; + tex.width = tmp.width; + tex.height = tmp.height; + tex.pitch = bo->size; + do { + ret = drmCommandWriteRead(bo->bom->fd, + DRM_RADEON_TEXTURE, + &tex, + sizeof(drm_radeon_texture_t)); + if (ret) { + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n"); + usleep(1); + } + } while (ret == -EAGAIN); + } else { + /* Copy to VRAM using a blit. + * All memory is 4K aligned. We're using 1024 pixels wide blits. + */ + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; + + tex.offset = bo_legacy->offset; + tex.image = &tmp; + assert(!(tex.offset & 1023)); + + tmp.x = 0; + tmp.y = 0; + if (bo->size < 4096) { + tmp.width = (bo->size + 3) / 4; + tmp.height = 1; + } else { + tmp.width = 1024; + tmp.height = (bo->size + 4095) / 4096; + } + tmp.data = bo_legacy->ptr; + tex.format = RADEON_TXFORMAT_ARGB8888; + tex.width = tmp.width; + tex.height = tmp.height; + tex.pitch = MAX2(tmp.width / 16, 1); + do { + ret = drmCommandWriteRead(bo->bom->fd, + DRM_RADEON_TEXTURE, + &tex, + sizeof(drm_radeon_texture_t)); + if (ret) { + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n"); + usleep(1); + } + } while (ret == -EAGAIN); + } + bo_legacy->dirty = 0; + bo_legacy->tobj->base.dirty_images[0] = 0; + } + return 0; +} + +/* + * radeon_bo_legacy_validate - + * returns: + * 0 - all good + * -EINVAL - mapped buffer can't be validated + * -EAGAIN - restart validation we've kicked all the buffers out + */ +int radeon_bo_legacy_validate(struct radeon_bo *bo, + uint32_t *soffset, + uint32_t *eoffset) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + int r; + int retries = 0; + + if (bo_legacy->map_count) { + fprintf(stderr, "bo(%p, %d) is mapped (%d) can't valide it.\n", + bo, bo->size, bo_legacy->map_count); + return -EINVAL; + } + if (bo_legacy->static_bo || bo_legacy->validated) { + *soffset = bo_legacy->offset; + *eoffset = bo_legacy->offset + bo->size; + + return 0; + } + if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) { + + r = bo_vram_validate(bo, soffset, eoffset); + if (r) { + legacy_track_pending(boml, 0); + legacy_kick_all_buffers(boml); + retries++; + if (retries == 2) { + fprintf(stderr,"legacy bo: failed to get relocations into aperture\n"); + assert(0); + exit(-1); + } + return -EAGAIN; + } + } + *soffset = bo_legacy->offset; + *eoffset = bo_legacy->offset + bo->size; + bo_legacy->validated = 1; + + return 0; +} + +void radeon_bo_legacy_pending(struct radeon_bo *bo, uint32_t pending) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom; + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + bo_legacy->pending = pending; + bo_legacy->is_pending++; + /* add to pending list */ + radeon_bo_ref(bo); + if (bo_legacy->is_pending > 1) { + return; + } + bo_legacy->pprev = boml->pending_bos.pprev; + bo_legacy->pnext = NULL; + bo_legacy->pprev->pnext = bo_legacy; + boml->pending_bos.pprev = bo_legacy; + boml->cpendings++; +} + +void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom; + struct bo_legacy *bo_legacy; + + if (bom == NULL) { + return; + } + bo_legacy = boml->bos.next; + while (bo_legacy) { + struct bo_legacy *next; + + next = bo_legacy->next; + bo_free(bo_legacy); + bo_legacy = next; + } + driDestroyTextureHeap(boml->texture_heap); + free(boml->free_handles); + free(boml); +} + +static struct bo_legacy *radeon_legacy_bo_alloc_static(struct bo_manager_legacy *bom, + int size, + uint32_t offset) +{ + struct bo_legacy *bo; + + bo = bo_allocate(bom, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); + + if (bo == NULL) + return NULL; + bo->static_bo = 1; + bo->offset = offset + bom->fb_location; + bo->base.handle = bo->offset; + bo->ptr = bom->screen->driScreen->pFB + offset; + if (bo->base.handle > bom->nhandle) { + bom->nhandle = bo->base.handle + 1; + } + radeon_bo_ref(&(bo->base)); + return bo; +} + +struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *scrn) +{ + struct bo_manager_legacy *bom; + struct bo_legacy *bo; + unsigned size; + + bom = (struct bo_manager_legacy*) + calloc(1, sizeof(struct bo_manager_legacy)); + if (bom == NULL) { + return NULL; + } + + make_empty_list(&bom->texture_swapped); + + bom->texture_heap = driCreateTextureHeap(0, + bom, + scrn->texSize[0], + 12, + RADEON_NR_TEX_REGIONS, + (drmTextureRegionPtr)scrn->sarea->tex_list[0], + &scrn->sarea->tex_age[0], + &bom->texture_swapped, + sizeof(struct bo_legacy_texture_object), + &bo_legacy_tobj_destroy); + bom->texture_offset = scrn->texOffset[0]; + + bom->base.funcs = &bo_legacy_funcs; + bom->base.fd = scrn->driScreen->fd; + bom->bos.next = NULL; + bom->bos.prev = NULL; + bom->pending_bos.pprev = &bom->pending_bos; + bom->pending_bos.pnext = NULL; + bom->screen = scrn; + bom->fb_location = scrn->fbLocation; + bom->nhandle = 1; + bom->cfree_handles = 0; + bom->nfree_handles = 0x400; + bom->free_handles = (uint32_t*)malloc(bom->nfree_handles * 4); + if (bom->free_handles == NULL) { + radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom); + return NULL; + } + + /* biggest framebuffer size */ + size = 4096*4096*4; + + /* allocate front */ + bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->frontOffset); + + if (!bo) { + radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom); + return NULL; + } + if (scrn->sarea->tiling_enabled) { + bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE; + } + + /* allocate back */ + bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->backOffset); + + if (!bo) { + radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom); + return NULL; + } + if (scrn->sarea->tiling_enabled) { + bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE; + } + + /* allocate depth */ + bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->depthOffset); + + if (!bo) { + radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom); + return NULL; + } + bo->base.flags = 0; + if (scrn->sarea->tiling_enabled) { + bo->base.flags |= RADEON_BO_FLAGS_MACRO_TILE; + bo->base.flags |= RADEON_BO_FLAGS_MICRO_TILE; + } + return (struct radeon_bo_manager*)bom; +} + +void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom; + DRI_AGE_TEXTURES(boml->texture_heap); +} + +unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo) +{ + struct bo_legacy *bo_legacy = (struct bo_legacy*)bo; + + if (bo_legacy->static_bo || (bo->domains & RADEON_GEM_DOMAIN_GTT)) { + return 0; + } + return bo->size; +} + +/* + * Fake up a bo for things like texture image_override. + * bo->offset already includes fb_location + */ +struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom, + int size, + uint32_t offset) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom; + struct bo_legacy *bo; + + bo = bo_allocate(boml, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); + + if (bo == NULL) + return NULL; + bo->static_bo = 1; + bo->offset = offset; + bo->base.handle = bo->offset; + bo->ptr = boml->screen->driScreen->pFB + (offset - boml->fb_location); + if (bo->base.handle > boml->nhandle) { + boml->nhandle = bo->base.handle + 1; + } + radeon_bo_ref(&(bo->base)); + return &(bo->base); +} + |