Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / radeon / radeon_bo_legacy.c
1 /* 
2  * Copyright © 2008 Nicolai Haehnle
3  * Copyright © 2008 Dave Airlie
4  * Copyright © 2008 Jérôme Glisse
5  * All Rights Reserved.
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * The above copyright notice and this permission notice (including the
24  * next paragraph) shall be included in all copies or substantial portions
25  * of the Software.
26  */
27 /*
28  * Authors:
29  *      Aapo Tahkola <aet@rasterburn.org>
30  *      Nicolai Haehnle <prefect_@gmx.net>
31  *      Dave Airlie
32  *      Jérôme Glisse <glisse@freedesktop.org>
33  */
34 #include <stdio.h>
35 #include <stddef.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <sys/mman.h>
42 #include <sys/ioctl.h>
43 #include "xf86drm.h"
44 #include "texmem.h"
45 #include "main/simple_list.h"
46
47 #include "drm.h"
48 #include "radeon_drm.h"
49 #include "radeon_common.h"
50 #include "radeon_bocs_wrapper.h"
51 #include "radeon_macros.h"
52
53 #ifdef HAVE_LIBDRM_RADEON
54 #include "radeon_bo_int.h"
55 #else
56 #include "radeon_bo_int_drm.h"
57 #endif
58
59 /* no seriously texmem.c is this screwed up */
60 struct bo_legacy_texture_object {
61     driTextureObject    base;
62     struct bo_legacy *parent;
63 };
64
65 struct bo_legacy {
66     struct radeon_bo_int    base;
67     int                 map_count;
68     uint32_t            pending;
69     int                 is_pending;
70     int                 static_bo;
71     uint32_t            offset;
72     struct bo_legacy_texture_object *tobj;
73     int                 validated;
74     int                 dirty;
75     void                *ptr;
76     struct bo_legacy    *next, *prev;
77     struct bo_legacy    *pnext, *pprev;
78 };
79
80 struct bo_manager_legacy {
81     struct radeon_bo_manager    base;
82     unsigned                    nhandle;
83     unsigned                    nfree_handles;
84     unsigned                    cfree_handles;
85     uint32_t                    current_age;
86     struct bo_legacy            bos;
87     struct bo_legacy            pending_bos;
88     uint32_t                    fb_location;
89     uint32_t                    texture_offset;
90     unsigned                    dma_alloc_size;
91     uint32_t                    dma_buf_count;
92     unsigned                    cpendings;
93     driTextureObject            texture_swapped;
94     driTexHeap                  *texture_heap;
95     struct radeon_screen        *screen;
96     unsigned                    *free_handles;
97 };
98
99 static void bo_legacy_tobj_destroy(void *data, driTextureObject *t)
100 {
101     struct bo_legacy_texture_object *tobj = (struct bo_legacy_texture_object *)t;
102     
103     if (tobj->parent) {
104         tobj->parent->tobj = NULL;
105         tobj->parent->validated = 0;
106     }
107 }
108
109 static void inline clean_handles(struct bo_manager_legacy *bom)
110 {
111   while (bom->cfree_handles > 0 &&
112          !bom->free_handles[bom->cfree_handles - 1])
113     bom->cfree_handles--;
114
115 }
116 static int legacy_new_handle(struct bo_manager_legacy *bom, uint32_t *handle)
117 {
118     uint32_t tmp;
119
120     *handle = 0;
121     if (bom->nhandle == 0xFFFFFFFF) {
122         return -EINVAL;
123     }
124     if (bom->cfree_handles > 0) {
125         tmp = bom->free_handles[--bom->cfree_handles];
126         clean_handles(bom);
127     } else {
128         bom->cfree_handles = 0;
129         tmp = bom->nhandle++;
130     }
131     assert(tmp);
132     *handle = tmp;
133     return 0;
134 }
135
136 static int legacy_free_handle(struct bo_manager_legacy *bom, uint32_t handle)
137 {
138     uint32_t *handles;
139
140     if (!handle) {
141         return 0;
142     }
143     if (handle == (bom->nhandle - 1)) {
144         int i;
145
146         bom->nhandle--;
147         for (i = bom->cfree_handles - 1; i >= 0; i--) {
148             if (bom->free_handles[i] == (bom->nhandle - 1)) {
149                 bom->nhandle--;
150                 bom->free_handles[i] = 0;
151             }
152         }
153         clean_handles(bom);
154         return 0;
155     }
156     if (bom->cfree_handles < bom->nfree_handles) {
157         bom->free_handles[bom->cfree_handles++] = handle;
158         return 0;
159     }
160     bom->nfree_handles += 0x100;
161     handles = (uint32_t*)realloc(bom->free_handles, bom->nfree_handles * 4);
162     if (handles == NULL) {
163         bom->nfree_handles -= 0x100;
164         return -ENOMEM;
165     }
166     bom->free_handles = handles;
167     bom->free_handles[bom->cfree_handles++] = handle;
168     return 0;
169 }
170
171 static void legacy_get_current_age(struct bo_manager_legacy *boml)
172 {
173     drm_radeon_getparam_t gp;
174     unsigned char *RADEONMMIO = NULL;
175     int r;
176
177     if (   IS_R300_CLASS(boml->screen) 
178         || IS_R600_CLASS(boml->screen) ) 
179     {
180         gp.param = RADEON_PARAM_LAST_CLEAR;
181         gp.value = (int *)&boml->current_age;
182         r = drmCommandWriteRead(boml->base.fd, DRM_RADEON_GETPARAM,
183                              &gp, sizeof(gp));
184         if (r) {
185          fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r);
186          exit(1);
187        }
188     } 
189     else {
190         RADEONMMIO = boml->screen->mmio.map;
191         boml->current_age = boml->screen->scratch[3];
192         boml->current_age = INREG(RADEON_GUI_SCRATCH_REG3);
193     }
194 }
195
196 static int legacy_is_pending(struct radeon_bo_int *boi)
197 {
198     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)boi->bom;
199     struct bo_legacy *bo_legacy = (struct bo_legacy*)boi;
200
201     if (bo_legacy->is_pending <= 0) {
202         bo_legacy->is_pending = 0;
203         return 0;
204     }
205     if (boml->current_age >= bo_legacy->pending) {
206         if (boml->pending_bos.pprev == bo_legacy) {
207             boml->pending_bos.pprev = bo_legacy->pprev;
208         }
209         bo_legacy->pprev->pnext = bo_legacy->pnext;
210         if (bo_legacy->pnext) {
211             bo_legacy->pnext->pprev = bo_legacy->pprev;
212         }
213         assert(bo_legacy->is_pending <= boi->cref);
214         while (bo_legacy->is_pending--) {
215             boi = (struct radeon_bo_int *)radeon_bo_unref((struct radeon_bo *)boi);
216             if (!boi)
217               break;
218         }
219         if (boi)
220           bo_legacy->is_pending = 0;
221         boml->cpendings--;
222         return 0;
223     }
224     return 1;
225 }
226
227 static int legacy_wait_pending(struct radeon_bo_int *bo)
228 {
229     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
230     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
231
232     if (!bo_legacy->is_pending) {
233         return 0;
234     }
235     /* FIXME: lockup and userspace busy looping that's all the folks */
236     legacy_get_current_age(boml);
237     while (legacy_is_pending(bo)) {
238         usleep(10);
239         legacy_get_current_age(boml);
240     }
241     return 0;
242 }
243
244 void legacy_track_pending(struct radeon_bo_manager *bom, int debug)
245 {
246     struct bo_manager_legacy *boml = (struct bo_manager_legacy*) bom;
247     struct bo_legacy *bo_legacy;
248     struct bo_legacy *next;
249
250     legacy_get_current_age(boml);
251     bo_legacy = boml->pending_bos.pnext;
252     while (bo_legacy) {
253         if (debug)
254             fprintf(stderr,"pending %p %d %d %d\n", bo_legacy, bo_legacy->base.size,
255                     boml->current_age, bo_legacy->pending);
256         next = bo_legacy->pnext;
257         if (legacy_is_pending(&(bo_legacy->base))) {
258         }
259         bo_legacy = next;
260     } 
261 }
262
263 static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
264 {
265     struct bo_legacy *bo_legacy;
266
267     legacy_get_current_age(boml);
268     bo_legacy = boml->pending_bos.pnext;
269     if (!bo_legacy)
270       return -1;
271     legacy_wait_pending(&bo_legacy->base);
272     return 0;
273 }
274
275 static void legacy_kick_all_buffers(struct bo_manager_legacy *boml)
276 {
277     struct bo_legacy *legacy;
278
279     legacy = boml->bos.next;
280     while (legacy != &boml->bos) {
281         if (legacy->tobj) {
282             if (legacy->validated) {
283                 driDestroyTextureObject(&legacy->tobj->base);
284                 legacy->tobj = 0;
285                 legacy->validated = 0;
286             }
287         }
288         legacy = legacy->next;
289     }
290 }
291
292 static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml,
293                                      uint32_t size,
294                                      uint32_t alignment,
295                                      uint32_t domains,
296                                      uint32_t flags)
297 {
298     struct bo_legacy *bo_legacy;
299     static int pgsize;
300
301     if (pgsize == 0)
302         pgsize = getpagesize() - 1;
303
304     size = (size + pgsize) & ~pgsize;
305
306     bo_legacy = (struct bo_legacy*)calloc(1, sizeof(struct bo_legacy));
307     if (bo_legacy == NULL) {
308         return NULL;
309     }
310     bo_legacy->base.bom = (struct radeon_bo_manager*)boml;
311     bo_legacy->base.handle = 0;
312     bo_legacy->base.size = size;
313     bo_legacy->base.alignment = alignment;
314     bo_legacy->base.domains = domains;
315     bo_legacy->base.flags = flags;
316     bo_legacy->base.ptr = NULL;
317     bo_legacy->map_count = 0;
318     bo_legacy->next = NULL;
319     bo_legacy->prev = NULL;
320     bo_legacy->pnext = NULL;
321     bo_legacy->pprev = NULL;
322     bo_legacy->next = boml->bos.next;
323     bo_legacy->prev = &boml->bos;
324     boml->bos.next = bo_legacy;
325     if (bo_legacy->next) {
326         bo_legacy->next->prev = bo_legacy;
327     }
328
329     return bo_legacy;
330 }
331
332 static int bo_dma_alloc(struct radeon_bo_int *bo)
333 {
334     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
335     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
336     drm_radeon_mem_alloc_t alloc;
337     unsigned size;
338     int base_offset;
339     int r;
340
341     /* align size on 4Kb */
342     size = (((4 * 1024) - 1) + bo_legacy->base.size) & ~((4 * 1024) - 1);
343     alloc.region = RADEON_MEM_REGION_GART;
344     alloc.alignment = bo_legacy->base.alignment;
345     alloc.size = size;
346     alloc.region_offset = &base_offset;
347     r = drmCommandWriteRead(bo->bom->fd,
348                             DRM_RADEON_ALLOC,
349                             &alloc,
350                             sizeof(alloc));
351     if (r) {
352         /* ptr is set to NULL if dma allocation failed */
353         bo_legacy->ptr = NULL;
354         return r;
355     }
356     bo_legacy->ptr = boml->screen->gartTextures.map + base_offset;
357     bo_legacy->offset = boml->screen->gart_texture_offset + base_offset;
358     bo->size = size;
359     boml->dma_alloc_size += size;
360     boml->dma_buf_count++;
361     return 0;
362 }
363
364 static int bo_dma_free(struct radeon_bo_int *bo)
365 {
366     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
367     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
368     drm_radeon_mem_free_t memfree;
369     int r;
370
371     if (bo_legacy->ptr == NULL) {
372         /* ptr is set to NULL if dma allocation failed */
373         return 0;
374     }
375     legacy_get_current_age(boml);
376     memfree.region = RADEON_MEM_REGION_GART;
377     memfree.region_offset  = bo_legacy->offset;
378     memfree.region_offset -= boml->screen->gart_texture_offset;
379     r = drmCommandWrite(boml->base.fd,
380                         DRM_RADEON_FREE,
381                         &memfree,
382                         sizeof(memfree));
383     if (r) {
384         fprintf(stderr, "Failed to free bo[%p] at %08x\n",
385                 &bo_legacy->base, memfree.region_offset);
386         fprintf(stderr, "ret = %s\n", strerror(-r));
387         return r;
388     }
389     boml->dma_alloc_size -= bo_legacy->base.size;
390     boml->dma_buf_count--;
391     return 0;
392 }
393
394 static void bo_free(struct bo_legacy *bo_legacy)
395 {
396     struct bo_manager_legacy *boml;
397
398     if (bo_legacy == NULL) {
399         return;
400     }
401     boml = (struct bo_manager_legacy *)bo_legacy->base.bom;
402     bo_legacy->prev->next = bo_legacy->next;
403     if (bo_legacy->next) {
404         bo_legacy->next->prev = bo_legacy->prev;
405     }
406     if (!bo_legacy->static_bo) {
407         legacy_free_handle(boml, bo_legacy->base.handle);
408         if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
409             /* dma buffers */
410             bo_dma_free(&bo_legacy->base);
411         } else {
412             driDestroyTextureObject(&bo_legacy->tobj->base);
413             bo_legacy->tobj = NULL;
414             /* free backing store */
415             free(bo_legacy->ptr);
416         }
417     }
418     memset(bo_legacy, 0 , sizeof(struct bo_legacy));
419     free(bo_legacy);
420 }
421
422 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
423                                  uint32_t handle,
424                                  uint32_t size,
425                                  uint32_t alignment,
426                                  uint32_t domains,
427                                  uint32_t flags)
428 {
429     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
430     struct bo_legacy *bo_legacy;
431     int r;
432
433     if (handle) {
434         bo_legacy = boml->bos.next;
435         while (bo_legacy) {
436             if (bo_legacy->base.handle == handle) {
437                 radeon_bo_ref((struct radeon_bo *)&(bo_legacy->base));
438                 return (struct radeon_bo*)bo_legacy;
439             }
440             bo_legacy = bo_legacy->next;
441         }
442         return NULL;
443     }
444     bo_legacy = bo_allocate(boml, size, alignment, domains, flags);
445     bo_legacy->static_bo = 0;
446     r = legacy_new_handle(boml, &bo_legacy->base.handle);
447     if (r) {
448         bo_free(bo_legacy);
449         return NULL;
450     }
451     if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) 
452     {
453 retry:
454         legacy_track_pending(&boml->base, 0);
455         /* dma buffers */
456
457         r = bo_dma_alloc(&(bo_legacy->base));
458         if (r) 
459         {
460                  if (legacy_wait_any_pending(boml) == -1) 
461              {
462                   bo_free(bo_legacy);
463                       return NULL;
464              }
465                  goto retry;
466                  return NULL;
467         }
468     } 
469     else 
470     {
471         bo_legacy->ptr = malloc(bo_legacy->base.size);
472         if (bo_legacy->ptr == NULL) {
473             bo_free(bo_legacy);
474             return NULL;
475         }
476     }
477     radeon_bo_ref((struct radeon_bo *)&(bo_legacy->base));
478
479     return (struct radeon_bo*)bo_legacy;
480 }
481
482 static void bo_ref(struct radeon_bo_int *bo)
483 {
484 }
485
486 static struct radeon_bo *bo_unref(struct radeon_bo_int *boi)
487 {
488     struct bo_legacy *bo_legacy = (struct bo_legacy*)boi;
489
490     if (boi->cref <= 0) {
491         bo_legacy->prev->next = bo_legacy->next;
492         if (bo_legacy->next) {
493             bo_legacy->next->prev = bo_legacy->prev;
494         }
495         if (!bo_legacy->is_pending) {
496             bo_free(bo_legacy);
497         }
498         return NULL;
499     }
500     return (struct radeon_bo *)boi;
501 }
502
503 static int bo_map(struct radeon_bo_int *bo, int write)
504 {
505     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
506     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
507
508     legacy_wait_pending(bo);
509     bo_legacy->validated = 0;
510     bo_legacy->dirty = 1;
511     bo_legacy->map_count++;
512     bo->ptr = bo_legacy->ptr;
513     /* Read the first pixel in the frame buffer.  This should
514      * be a noop, right?  In fact without this conform fails as reading
515      * from the framebuffer sometimes produces old results -- the
516      * on-card read cache gets mixed up and doesn't notice that the
517      * framebuffer has been updated.
518      *
519      * Note that we should probably be reading some otherwise unused
520      * region of VRAM, otherwise we might get incorrect results when
521      * reading pixels from the top left of the screen.
522      *
523      * I found this problem on an R420 with glean's texCube test.
524      * Note that the R200 span code also *writes* the first pixel in the
525      * framebuffer, but I've found this to be unnecessary.
526      *  -- Nicolai Hähnle, June 2008
527      */
528     if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
529         int p;
530         volatile int *buf = (int*)boml->screen->driScreen->pFB;
531         p = *buf;
532     }
533
534     return 0;
535 }
536
537 static int bo_unmap(struct radeon_bo_int *bo)
538 {
539     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
540
541     if (--bo_legacy->map_count > 0) 
542     {
543         return 0;
544     }
545     
546     bo->ptr = NULL;
547
548     return 0;
549 }
550
551 static int bo_is_busy(struct radeon_bo_int *bo, uint32_t *domain)
552 {
553     *domain = 0;
554     if (bo->domains & RADEON_GEM_DOMAIN_GTT)
555         *domain = RADEON_GEM_DOMAIN_GTT;
556     else
557         *domain = RADEON_GEM_DOMAIN_CPU;
558     if (legacy_is_pending(bo))
559         return -EBUSY;
560     else
561         return 0;
562 }
563
564 static int bo_is_static(struct radeon_bo_int *bo)
565 {
566     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
567     return bo_legacy->static_bo;
568 }
569
570 static struct radeon_bo_funcs bo_legacy_funcs = {
571     bo_open,
572     bo_ref,
573     bo_unref,
574     bo_map,
575     bo_unmap,
576     NULL,
577     bo_is_static,
578     NULL,
579     NULL,
580     bo_is_busy
581 };
582
583 static int bo_vram_validate(struct radeon_bo_int *bo,
584                             uint32_t *soffset,
585                             uint32_t *eoffset)
586 {
587     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
588     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
589     int r;
590     int retry_count = 0, pending_retry = 0;
591     
592     if (!bo_legacy->tobj) {
593         bo_legacy->tobj = CALLOC(sizeof(struct bo_legacy_texture_object));
594         bo_legacy->tobj->parent = bo_legacy;
595         make_empty_list(&bo_legacy->tobj->base);
596         bo_legacy->tobj->base.totalSize = bo->size;
597     retry:
598         r = driAllocateTexture(&boml->texture_heap, 1,
599                                &bo_legacy->tobj->base);
600         if (r) {
601                 pending_retry = 0;
602                 while(boml->cpendings && pending_retry++ < 10000) {
603                         legacy_track_pending(&boml->base, 0);
604                         retry_count++;
605                         if (retry_count > 2) {
606                                 free(bo_legacy->tobj);
607                                 bo_legacy->tobj = NULL;
608                                 fprintf(stderr, "Ouch! vram_validate failed %d\n", r);
609                                 return -1;
610                         }
611                         goto retry;
612                 }
613         }
614         bo_legacy->offset = boml->texture_offset +
615                             bo_legacy->tobj->base.memBlock->ofs;
616         bo_legacy->dirty = 1;
617     }
618
619     assert(bo_legacy->tobj->base.memBlock);
620
621     driUpdateTextureLRU(&bo_legacy->tobj->base);
622
623     if (bo_legacy->dirty || bo_legacy->tobj->base.dirty_images[0]) {
624             if (IS_R600_CLASS(boml->screen)) {
625                     drm_radeon_texture_t tex;
626                     drm_radeon_tex_image_t tmp;
627                     int ret;
628
629                     tex.offset = bo_legacy->offset;
630                     tex.image = &tmp;
631                     assert(!(tex.offset & 1023));
632
633                     tmp.x = 0;
634                     tmp.y = 0;
635                     tmp.width = bo->size;
636                     tmp.height = 1;
637                     tmp.data = bo_legacy->ptr;
638                     tex.format = RADEON_TXFORMAT_ARGB8888;
639                     tex.width = tmp.width;
640                     tex.height = tmp.height;
641                     tex.pitch = bo->size;
642                     do {
643                             ret = drmCommandWriteRead(bo->bom->fd,
644                                                       DRM_RADEON_TEXTURE,
645                                                       &tex,
646                                                       sizeof(drm_radeon_texture_t));
647                             if (ret) {
648                                     if (RADEON_DEBUG & RADEON_IOCTL)
649                                             fprintf(stderr, "DRM_RADEON_TEXTURE:  again!\n");
650                                     usleep(1);
651                             }
652                     } while (ret == -EAGAIN);
653             } else {
654                     /* Copy to VRAM using a blit.
655                      * All memory is 4K aligned. We're using 1024 pixels wide blits.
656                      */
657                     drm_radeon_texture_t tex;
658                     drm_radeon_tex_image_t tmp;
659                     int ret;
660
661                     tex.offset = bo_legacy->offset;
662                     tex.image = &tmp;
663                     assert(!(tex.offset & 1023));
664
665                     tmp.x = 0;
666                     tmp.y = 0;
667                     if (bo->size < 4096) {
668                             tmp.width = (bo->size + 3) / 4;
669                             tmp.height = 1;
670                     } else {
671                             tmp.width = 1024;
672                             tmp.height = (bo->size + 4095) / 4096;
673                     }
674                     tmp.data = bo_legacy->ptr;
675                     tex.format = RADEON_TXFORMAT_ARGB8888;
676                     tex.width = tmp.width;
677                     tex.height = tmp.height;
678                     tex.pitch = MAX2(tmp.width / 16, 1);
679                     do {
680                             ret = drmCommandWriteRead(bo->bom->fd,
681                                                       DRM_RADEON_TEXTURE,
682                                                       &tex,
683                                                       sizeof(drm_radeon_texture_t));
684                             if (ret) {
685                                     if (RADEON_DEBUG & RADEON_IOCTL)
686                                             fprintf(stderr, "DRM_RADEON_TEXTURE:  again!\n");
687                                     usleep(1);
688                             }
689                     } while (ret == -EAGAIN);
690             }
691             bo_legacy->dirty = 0;
692             bo_legacy->tobj->base.dirty_images[0] = 0;
693     }
694     return 0;
695 }
696
697 /* 
698  *  radeon_bo_legacy_validate -
699  *  returns:
700  *  0 - all good
701  *  -EINVAL - mapped buffer can't be validated
702  *  -EAGAIN - restart validation we've kicked all the buffers out
703  */
704 int radeon_bo_legacy_validate(struct radeon_bo *bo,
705                               uint32_t *soffset,
706                               uint32_t *eoffset)
707 {
708     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
709     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)boi->bom;
710     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
711     int r;
712     int retries = 0;
713
714     if (bo_legacy->map_count) {
715         fprintf(stderr, "bo(%p, %d) is mapped (%d) can't valide it.\n",
716                 bo, boi->size, bo_legacy->map_count);
717         return -EINVAL;
718     }
719     if(boi->size == 0) {
720         fprintf(stderr, "bo(%p) has size 0.\n", bo);
721         return -EINVAL;
722     }
723     if (bo_legacy->static_bo || bo_legacy->validated) {
724         *soffset = bo_legacy->offset;
725         *eoffset = bo_legacy->offset + boi->size;
726
727         return 0;
728     }
729     if (!(boi->domains & RADEON_GEM_DOMAIN_GTT)) {
730
731         r = bo_vram_validate(boi, soffset, eoffset);
732         if (r) {
733             legacy_track_pending(&boml->base, 0);
734             legacy_kick_all_buffers(boml);
735             retries++;
736             if (retries == 2) {
737                 fprintf(stderr,"legacy bo: failed to get relocations into aperture\n");
738                 assert(0);
739                 exit(-1);
740             }
741             return -EAGAIN;
742         }
743     }
744     *soffset = bo_legacy->offset;
745     *eoffset = bo_legacy->offset + boi->size;
746     bo_legacy->validated = 1;
747
748     return 0;
749 }
750
751 void radeon_bo_legacy_pending(struct radeon_bo *bo, uint32_t pending)
752 {
753     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
754     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)boi->bom;
755     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
756
757     bo_legacy->pending = pending;
758     bo_legacy->is_pending++;
759     /* add to pending list */
760     radeon_bo_ref(bo);
761     if (bo_legacy->is_pending > 1) {
762         return;    
763     }
764     bo_legacy->pprev = boml->pending_bos.pprev;
765     bo_legacy->pnext = NULL;
766     bo_legacy->pprev->pnext = bo_legacy;
767     boml->pending_bos.pprev = bo_legacy;
768     boml->cpendings++;
769 }
770
771 void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom)
772 {
773     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
774     struct bo_legacy *bo_legacy;
775
776     if (bom == NULL) {
777         return;
778     }
779     bo_legacy = boml->bos.next;
780     while (bo_legacy) {
781         struct bo_legacy *next;
782
783         next = bo_legacy->next;
784         bo_free(bo_legacy);
785         bo_legacy = next;
786     }
787     driDestroyTextureHeap(boml->texture_heap);
788     free(boml->free_handles);
789     free(boml);
790 }
791
792 static struct bo_legacy *radeon_legacy_bo_alloc_static(struct bo_manager_legacy *bom,
793                                                        int size,
794                                                        uint32_t offset)
795 {
796     struct bo_legacy *bo;
797
798     bo = bo_allocate(bom, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
799
800     if (bo == NULL)
801         return NULL;
802     bo->static_bo = 1;
803     bo->offset = offset + bom->fb_location;
804     bo->base.handle = bo->offset;
805     bo->ptr = bom->screen->driScreen->pFB + offset;
806     if (bo->base.handle > bom->nhandle) {
807         bom->nhandle = bo->base.handle + 1;
808     }
809     radeon_bo_ref((struct radeon_bo *)&(bo->base));
810     return bo;
811 }
812
813 struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *scrn)
814 {
815     struct bo_manager_legacy *bom;
816     struct bo_legacy *bo;
817     unsigned size;
818
819     bom = (struct bo_manager_legacy*)
820           calloc(1, sizeof(struct bo_manager_legacy));
821     if (bom == NULL) {
822         return NULL;
823     }
824
825     make_empty_list(&bom->texture_swapped);
826
827     bom->texture_heap = driCreateTextureHeap(0,
828                                              bom,
829                                              scrn->texSize[0],
830                                              12,
831                                              RADEON_NR_TEX_REGIONS,
832                                              (drmTextureRegionPtr)scrn->sarea->tex_list[0],
833                                              &scrn->sarea->tex_age[0],
834                                              &bom->texture_swapped,
835                                              sizeof(struct bo_legacy_texture_object),
836                                              &bo_legacy_tobj_destroy);
837     bom->texture_offset = scrn->texOffset[0];
838
839     bom->base.funcs = &bo_legacy_funcs;
840     bom->base.fd = scrn->driScreen->fd;
841     bom->bos.next = NULL;
842     bom->bos.prev = NULL;
843     bom->pending_bos.pprev = &bom->pending_bos;
844     bom->pending_bos.pnext = NULL;
845     bom->screen = scrn;
846     bom->fb_location = scrn->fbLocation;
847     bom->nhandle = 1;
848     bom->cfree_handles = 0;
849     bom->nfree_handles = 0x400;
850     bom->free_handles = (uint32_t*)malloc(bom->nfree_handles * 4);
851     if (bom->free_handles == NULL) {
852         radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
853         return NULL;
854     }
855
856     /* biggest framebuffer size */
857     size = 4096*4096*4; 
858
859     /* allocate front */
860     bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->frontOffset);
861
862     if (!bo) {
863         radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
864         return NULL;
865     }
866     if (scrn->sarea->tiling_enabled) {
867         bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
868     }
869
870     /* allocate back */
871     bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->backOffset);
872
873     if (!bo) {
874         radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
875         return NULL;
876     }
877     if (scrn->sarea->tiling_enabled) {
878         bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
879     }
880
881     /* allocate depth */
882     bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->depthOffset);
883
884     if (!bo) {
885         radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
886         return NULL;
887     }
888     bo->base.flags = 0;
889     if (scrn->sarea->tiling_enabled) {
890         bo->base.flags |= RADEON_BO_FLAGS_MACRO_TILE;
891         bo->base.flags |= RADEON_BO_FLAGS_MICRO_TILE;
892     }
893     return (struct radeon_bo_manager*)bom;
894 }
895
896 void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom)
897 {
898     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
899     DRI_AGE_TEXTURES(boml->texture_heap);
900 }
901
902 unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo)
903 {
904     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
905     struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
906
907     if (bo_legacy->static_bo || (boi->domains & RADEON_GEM_DOMAIN_GTT)) {
908         return 0;
909     }
910     return boi->size;
911 }
912
913 /*
914  * Fake up a bo for things like texture image_override.
915  * bo->offset already includes fb_location
916  */
917 struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom,
918                                               int size,
919                                               uint32_t offset)
920 {
921     struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
922     struct bo_legacy *bo;
923
924     bo = bo_allocate(boml, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
925
926     if (bo == NULL)
927         return NULL;
928     bo->static_bo = 1;
929     bo->offset = offset;
930     bo->base.handle = bo->offset;
931     bo->ptr = boml->screen->driScreen->pFB + (offset - boml->fb_location);
932     if (bo->base.handle > boml->nhandle) {
933         boml->nhandle = bo->base.handle + 1;
934     }
935     radeon_bo_ref((struct radeon_bo *)&(bo->base));
936     return (struct radeon_bo *)&(bo->base);
937 }
938