raedon/r200/r300: mega-FBO commits.
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_bo_legacy.c
index 65b0a9a0ce0c018e60a685620e3f36ea9adeefa2..03a6299ed8ac5861be9c91fea4b907aaccc8b9dc 100644 (file)
@@ -32,6 +32,7 @@
  *      Jérôme Glisse <glisse@freedesktop.org>
  */
 #include <stdio.h>
+#include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include "radeon_common.h"
 #include "radeon_bocs_wrapper.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;
@@ -87,11 +91,12 @@ struct bo_manager_legacy {
 
 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)
@@ -243,7 +248,6 @@ static void legacy_track_pending(struct bo_manager_legacy *boml, int debug)
 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;
@@ -253,6 +257,23 @@ static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
     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,
@@ -281,7 +302,6 @@ static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml,
     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;
@@ -373,13 +393,13 @@ static void bo_free(struct bo_legacy *bo_legacy)
             /* dma buffers */
             bo_dma_free(&bo_legacy->base);
         } else {
-           if (bo_legacy->got_dri_texture_obj)
-               driCleanupTextureObject(&bo_legacy->dri_texture_obj);
-
+           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);
 }
 
@@ -518,24 +538,41 @@ 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, 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) {
+
+    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]) {
         /* Copy to VRAM using a blit.
          * All memory is 4K aligned. We're using 1024 pixels wide blits.
          */
@@ -573,16 +610,26 @@ static int bo_vram_validate(struct radeon_bo *bo,
             }
         } 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",
@@ -595,9 +642,18 @@ int radeon_bo_legacy_validate(struct radeon_bo *bo,
         return 0;
     }
     if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
+
         r = bo_vram_validate(bo, soffset, eoffset);
         if (r) {
-            return 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;
@@ -641,6 +697,7 @@ void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom)
         bo_free(bo_legacy);
         bo_legacy = next;
     }
+    driDestroyTextureHeap(boml->texture_heap);
     free(boml->free_handles);
     free(boml);
 }
@@ -676,6 +733,8 @@ struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *sc
         return NULL;
     }
 
+    make_empty_list(&bom->texture_swapped);
+
     bom->texture_heap = driCreateTextureHeap(0,
                                              bom,
                                              scrn->texSize[0],
@@ -684,7 +743,7 @@ struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *sc
                                              (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];