* Jérôme Glisse <glisse@freedesktop.org>
*/
#include <stdio.h>
+#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.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;
- driTextureObject tobj_base;
int map_count;
uint32_t pending;
int is_pending;
- int validated;
int static_bo;
- int got_dri_texture_obj;
- int dirty;
uint32_t offset;
- driTextureObject dri_texture_obj;
+ struct bo_legacy_texture_object *tobj;
+ int validated;
+ int dirty;
void *ptr;
struct bo_legacy *next, *prev;
struct bo_legacy *pnext, *pprev;
static void bo_legacy_tobj_destroy(void *data, driTextureObject *t)
{
- struct bo_legacy *bo_legacy;
-
- bo_legacy = (struct bo_legacy*)((char*)t)-sizeof(struct radeon_bo);
- bo_legacy->got_dri_texture_obj = 0;
- bo_legacy->validated = 0;
+ 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)
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)) {
+ 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,
fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r);
exit(1);
}
- } else
- boml->current_age = boml->screen->scratch[3];
+ }
+ 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)
return 0;
}
-static void legacy_track_pending(struct bo_manager_legacy *boml, int debug)
+void legacy_track_pending(struct radeon_bo_manager *bom, int debug)
{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy*) bom;
struct bo_legacy *bo_legacy;
struct bo_legacy *next;
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);
+ 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))) {
}
static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
{
struct bo_legacy *bo_legacy;
- struct bo_legacy *next;
legacy_get_current_age(boml);
bo_legacy = boml->pending_bos.pnext;
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,
bo_legacy->map_count = 0;
bo_legacy->next = NULL;
bo_legacy->prev = NULL;
- bo_legacy->got_dri_texture_obj = 0;
bo_legacy->pnext = NULL;
bo_legacy->pprev = NULL;
bo_legacy->next = boml->bos.next;
if (bo_legacy->next) {
bo_legacy->next->prev = bo_legacy;
}
+
return bo_legacy;
}
/* 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);
}
}
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);
bo_free(bo_legacy);
return NULL;
}
- if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
- retry:
- legacy_track_pending(boml, 0);
+ if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT)
+ {
+retry:
+ legacy_track_pending(&boml->base, 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;
+ if (r)
+ {
+ if (legacy_wait_any_pending(boml) == -1)
+ {
+ bo_free(bo_legacy);
+ return NULL;
+ }
+ goto retry;
+ return NULL;
}
- } else {
+ }
+ else
+ {
bo_legacy->ptr = malloc(bo_legacy->base.size);
if (bo_legacy->ptr == NULL) {
bo_free(bo_legacy);
}
}
radeon_bo_ref(&(bo_legacy->base));
+
return (struct radeon_bo*)bo_legacy;
}
{
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;
volatile int *buf = (int*)boml->screen->driScreen->pFB;
p = *buf;
}
+
return 0;
}
{
struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
- if (--bo_legacy->map_count > 0) {
+ if (--bo_legacy->map_count > 0)
+ {
return 0;
}
+
bo->ptr = NULL;
+
return 0;
}
+static int bo_is_busy(struct radeon_bo *bo, uint32_t *domain)
+{
+ *domain = 0;
+ if (bo->domains & RADEON_GEM_DOMAIN_GTT)
+ *domain = RADEON_GEM_DOMAIN_GTT;
+ else
+ *domain = RADEON_GEM_DOMAIN_CPU;
+ if (legacy_is_pending(bo))
+ return -EBUSY;
+ else
+ 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
+ bo_unmap,
+ NULL,
+ bo_is_static,
+ NULL,
+ NULL,
+ bo_is_busy
};
static int bo_vram_validate(struct radeon_bo *bo,
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->got_dri_texture_obj) {
- make_empty_list(&bo_legacy->dri_texture_obj);
- bo_legacy->dri_texture_obj.totalSize = bo->size;
+ 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->dri_texture_obj);
+ &bo_legacy->tobj->base);
if (r) {
- uint8_t *segfault=NULL;
- fprintf(stderr, "Ouch! vram_validate failed %d\n", r);
- *segfault=1;
- return -1;
- }
+ pending_retry = 0;
+ while(boml->cpendings && pending_retry++ < 10000) {
+ legacy_track_pending(&boml->base, 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->dri_texture_obj.memBlock->ofs;
- bo_legacy->got_dri_texture_obj = 1;
+ bo_legacy->tobj->base.memBlock->ofs;
bo_legacy->dirty = 1;
}
- if (bo_legacy->dirty) {
- /* 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;
+
+ 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 & RADEON_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 & RADEON_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",
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) {
- return r;
+ legacy_track_pending(&boml->base, 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;
}
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)
+ 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;
return NULL;
}
+ make_empty_list(&bom->texture_swapped);
+
bom->texture_heap = driCreateTextureHeap(0,
bom,
scrn->texSize[0],
(drmTextureRegionPtr)scrn->sarea->tex_list[0],
&scrn->sarea->tex_age[0],
&bom->texture_swapped,
- sizeof(struct bo_legacy),
+ sizeof(struct bo_legacy_texture_object),
&bo_legacy_tobj_destroy);
bom->texture_offset = scrn->texOffset[0];
/* 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;
/* 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;
/* 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;
return bo->size;
}
-int radeon_legacy_bo_is_static(struct radeon_bo *bo)
+/*
+ * 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_legacy *bo_legacy = (struct bo_legacy*)bo;
- return bo_legacy->static_bo;
+ 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);
}