Merge remote branch 'origin/master' into radeon-rewrite
[mesa.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
52 /* no seriously texmem.c is this screwed up */
53 struct bo_legacy_texture_object {
54 driTextureObject base;
55 struct bo_legacy *parent;
56 };
57
58 struct bo_legacy {
59 struct radeon_bo base;
60 int map_count;
61 uint32_t pending;
62 int is_pending;
63 int static_bo;
64 uint32_t offset;
65 struct bo_legacy_texture_object *tobj;
66 int validated;
67 int dirty;
68 void *ptr;
69 struct bo_legacy *next, *prev;
70 struct bo_legacy *pnext, *pprev;
71 };
72
73 struct bo_manager_legacy {
74 struct radeon_bo_manager base;
75 unsigned nhandle;
76 unsigned nfree_handles;
77 unsigned cfree_handles;
78 uint32_t current_age;
79 struct bo_legacy bos;
80 struct bo_legacy pending_bos;
81 uint32_t fb_location;
82 uint32_t texture_offset;
83 unsigned dma_alloc_size;
84 uint32_t dma_buf_count;
85 unsigned cpendings;
86 driTextureObject texture_swapped;
87 driTexHeap *texture_heap;
88 struct radeon_screen *screen;
89 unsigned *free_handles;
90 };
91
92 static void bo_legacy_tobj_destroy(void *data, driTextureObject *t)
93 {
94 struct bo_legacy_texture_object *tobj = (struct bo_legacy_texture_object *)t;
95
96 if (tobj->parent) {
97 tobj->parent->tobj = NULL;
98 tobj->parent->validated = 0;
99 }
100 }
101
102 static void inline clean_handles(struct bo_manager_legacy *bom)
103 {
104 while (bom->cfree_handles > 0 &&
105 !bom->free_handles[bom->cfree_handles - 1])
106 bom->cfree_handles--;
107
108 }
109 static int legacy_new_handle(struct bo_manager_legacy *bom, uint32_t *handle)
110 {
111 uint32_t tmp;
112
113 *handle = 0;
114 if (bom->nhandle == 0xFFFFFFFF) {
115 return -EINVAL;
116 }
117 if (bom->cfree_handles > 0) {
118 tmp = bom->free_handles[--bom->cfree_handles];
119 clean_handles(bom);
120 } else {
121 bom->cfree_handles = 0;
122 tmp = bom->nhandle++;
123 }
124 assert(tmp);
125 *handle = tmp;
126 return 0;
127 }
128
129 static int legacy_free_handle(struct bo_manager_legacy *bom, uint32_t handle)
130 {
131 uint32_t *handles;
132
133 if (!handle) {
134 return 0;
135 }
136 if (handle == (bom->nhandle - 1)) {
137 int i;
138
139 bom->nhandle--;
140 for (i = bom->cfree_handles - 1; i >= 0; i--) {
141 if (bom->free_handles[i] == (bom->nhandle - 1)) {
142 bom->nhandle--;
143 bom->free_handles[i] = 0;
144 }
145 }
146 clean_handles(bom);
147 return 0;
148 }
149 if (bom->cfree_handles < bom->nfree_handles) {
150 bom->free_handles[bom->cfree_handles++] = handle;
151 return 0;
152 }
153 bom->nfree_handles += 0x100;
154 handles = (uint32_t*)realloc(bom->free_handles, bom->nfree_handles * 4);
155 if (handles == NULL) {
156 bom->nfree_handles -= 0x100;
157 return -ENOMEM;
158 }
159 bom->free_handles = handles;
160 bom->free_handles[bom->cfree_handles++] = handle;
161 return 0;
162 }
163
164 static void legacy_get_current_age(struct bo_manager_legacy *boml)
165 {
166 drm_radeon_getparam_t gp;
167 int r;
168
169 if (IS_R300_CLASS(boml->screen)) {
170 gp.param = RADEON_PARAM_LAST_CLEAR;
171 gp.value = (int *)&boml->current_age;
172 r = drmCommandWriteRead(boml->base.fd, DRM_RADEON_GETPARAM,
173 &gp, sizeof(gp));
174 if (r) {
175 fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r);
176 exit(1);
177 }
178 } else
179 boml->current_age = boml->screen->scratch[3];
180 }
181
182 static int legacy_is_pending(struct radeon_bo *bo)
183 {
184 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
185 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
186
187 if (bo_legacy->is_pending <= 0) {
188 bo_legacy->is_pending = 0;
189 return 0;
190 }
191 if (boml->current_age >= bo_legacy->pending) {
192 if (boml->pending_bos.pprev == bo_legacy) {
193 boml->pending_bos.pprev = bo_legacy->pprev;
194 }
195 bo_legacy->pprev->pnext = bo_legacy->pnext;
196 if (bo_legacy->pnext) {
197 bo_legacy->pnext->pprev = bo_legacy->pprev;
198 }
199 assert(bo_legacy->is_pending <= bo->cref);
200 while (bo_legacy->is_pending--) {
201 bo = radeon_bo_unref(bo);
202 if (!bo)
203 break;
204 }
205 if (bo)
206 bo_legacy->is_pending = 0;
207 boml->cpendings--;
208 return 0;
209 }
210 return 1;
211 }
212
213 static int legacy_wait_pending(struct radeon_bo *bo)
214 {
215 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
216 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
217
218 if (!bo_legacy->is_pending) {
219 return 0;
220 }
221 /* FIXME: lockup and userspace busy looping that's all the folks */
222 legacy_get_current_age(boml);
223 while (legacy_is_pending(bo)) {
224 usleep(10);
225 legacy_get_current_age(boml);
226 }
227 return 0;
228 }
229
230 static void legacy_track_pending(struct bo_manager_legacy *boml, int debug)
231 {
232 struct bo_legacy *bo_legacy;
233 struct bo_legacy *next;
234
235 legacy_get_current_age(boml);
236 bo_legacy = boml->pending_bos.pnext;
237 while (bo_legacy) {
238 if (debug)
239 fprintf(stderr,"pending %p %d %d %d\n", bo_legacy, bo_legacy->base.size,
240 boml->current_age, bo_legacy->pending);
241 next = bo_legacy->pnext;
242 if (legacy_is_pending(&(bo_legacy->base))) {
243 }
244 bo_legacy = next;
245 }
246 }
247
248 static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
249 {
250 struct bo_legacy *bo_legacy;
251
252 legacy_get_current_age(boml);
253 bo_legacy = boml->pending_bos.pnext;
254 if (!bo_legacy)
255 return -1;
256 legacy_wait_pending(&bo_legacy->base);
257 return 0;
258 }
259
260 static void legacy_kick_all_buffers(struct bo_manager_legacy *boml)
261 {
262 struct bo_legacy *legacy;
263
264 legacy = boml->bos.next;
265 while (legacy != &boml->bos) {
266 if (legacy->tobj) {
267 if (legacy->validated) {
268 driDestroyTextureObject(&legacy->tobj->base);
269 legacy->tobj = 0;
270 legacy->validated = 0;
271 }
272 }
273 legacy = legacy->next;
274 }
275 }
276
277 static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml,
278 uint32_t size,
279 uint32_t alignment,
280 uint32_t domains,
281 uint32_t flags)
282 {
283 struct bo_legacy *bo_legacy;
284 static int pgsize;
285
286 if (pgsize == 0)
287 pgsize = getpagesize() - 1;
288
289 size = (size + pgsize) & ~pgsize;
290
291 bo_legacy = (struct bo_legacy*)calloc(1, sizeof(struct bo_legacy));
292 if (bo_legacy == NULL) {
293 return NULL;
294 }
295 bo_legacy->base.bom = (struct radeon_bo_manager*)boml;
296 bo_legacy->base.handle = 0;
297 bo_legacy->base.size = size;
298 bo_legacy->base.alignment = alignment;
299 bo_legacy->base.domains = domains;
300 bo_legacy->base.flags = flags;
301 bo_legacy->base.ptr = NULL;
302 bo_legacy->map_count = 0;
303 bo_legacy->next = NULL;
304 bo_legacy->prev = NULL;
305 bo_legacy->pnext = NULL;
306 bo_legacy->pprev = NULL;
307 bo_legacy->next = boml->bos.next;
308 bo_legacy->prev = &boml->bos;
309 boml->bos.next = bo_legacy;
310 if (bo_legacy->next) {
311 bo_legacy->next->prev = bo_legacy;
312 }
313 return bo_legacy;
314 }
315
316 static int bo_dma_alloc(struct radeon_bo *bo)
317 {
318 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
319 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
320 drm_radeon_mem_alloc_t alloc;
321 unsigned size;
322 int base_offset;
323 int r;
324
325 /* align size on 4Kb */
326 size = (((4 * 1024) - 1) + bo->size) & ~((4 * 1024) - 1);
327 alloc.region = RADEON_MEM_REGION_GART;
328 alloc.alignment = bo_legacy->base.alignment;
329 alloc.size = size;
330 alloc.region_offset = &base_offset;
331 r = drmCommandWriteRead(bo->bom->fd,
332 DRM_RADEON_ALLOC,
333 &alloc,
334 sizeof(alloc));
335 if (r) {
336 /* ptr is set to NULL if dma allocation failed */
337 bo_legacy->ptr = NULL;
338 return r;
339 }
340 bo_legacy->ptr = boml->screen->gartTextures.map + base_offset;
341 bo_legacy->offset = boml->screen->gart_texture_offset + base_offset;
342 bo->size = size;
343 boml->dma_alloc_size += size;
344 boml->dma_buf_count++;
345 return 0;
346 }
347
348 static int bo_dma_free(struct radeon_bo *bo)
349 {
350 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
351 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
352 drm_radeon_mem_free_t memfree;
353 int r;
354
355 if (bo_legacy->ptr == NULL) {
356 /* ptr is set to NULL if dma allocation failed */
357 return 0;
358 }
359 legacy_get_current_age(boml);
360 memfree.region = RADEON_MEM_REGION_GART;
361 memfree.region_offset = bo_legacy->offset;
362 memfree.region_offset -= boml->screen->gart_texture_offset;
363 r = drmCommandWrite(boml->base.fd,
364 DRM_RADEON_FREE,
365 &memfree,
366 sizeof(memfree));
367 if (r) {
368 fprintf(stderr, "Failed to free bo[%p] at %08x\n",
369 &bo_legacy->base, memfree.region_offset);
370 fprintf(stderr, "ret = %s\n", strerror(-r));
371 return r;
372 }
373 boml->dma_alloc_size -= bo_legacy->base.size;
374 boml->dma_buf_count--;
375 return 0;
376 }
377
378 static void bo_free(struct bo_legacy *bo_legacy)
379 {
380 struct bo_manager_legacy *boml;
381
382 if (bo_legacy == NULL) {
383 return;
384 }
385 boml = (struct bo_manager_legacy *)bo_legacy->base.bom;
386 bo_legacy->prev->next = bo_legacy->next;
387 if (bo_legacy->next) {
388 bo_legacy->next->prev = bo_legacy->prev;
389 }
390 if (!bo_legacy->static_bo) {
391 legacy_free_handle(boml, bo_legacy->base.handle);
392 if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
393 /* dma buffers */
394 bo_dma_free(&bo_legacy->base);
395 } else {
396 driDestroyTextureObject(&bo_legacy->tobj->base);
397 bo_legacy->tobj = NULL;
398 /* free backing store */
399 free(bo_legacy->ptr);
400 }
401 }
402 memset(bo_legacy, 0 , sizeof(struct bo_legacy));
403 free(bo_legacy);
404 }
405
406 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
407 uint32_t handle,
408 uint32_t size,
409 uint32_t alignment,
410 uint32_t domains,
411 uint32_t flags)
412 {
413 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
414 struct bo_legacy *bo_legacy;
415 int r;
416
417 if (handle) {
418 bo_legacy = boml->bos.next;
419 while (bo_legacy) {
420 if (bo_legacy->base.handle == handle) {
421 radeon_bo_ref(&(bo_legacy->base));
422 return (struct radeon_bo*)bo_legacy;
423 }
424 bo_legacy = bo_legacy->next;
425 }
426 return NULL;
427 }
428
429 bo_legacy = bo_allocate(boml, size, alignment, domains, flags);
430 bo_legacy->static_bo = 0;
431 r = legacy_new_handle(boml, &bo_legacy->base.handle);
432 if (r) {
433 bo_free(bo_legacy);
434 return NULL;
435 }
436 if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
437 retry:
438 legacy_track_pending(boml, 0);
439 /* dma buffers */
440
441 r = bo_dma_alloc(&(bo_legacy->base));
442 if (r) {
443 if (legacy_wait_any_pending(boml) == -1) {
444 bo_free(bo_legacy);
445 return NULL;
446 }
447 goto retry;
448 return NULL;
449 }
450 } else {
451 bo_legacy->ptr = malloc(bo_legacy->base.size);
452 if (bo_legacy->ptr == NULL) {
453 bo_free(bo_legacy);
454 return NULL;
455 }
456 }
457 radeon_bo_ref(&(bo_legacy->base));
458 return (struct radeon_bo*)bo_legacy;
459 }
460
461 static void bo_ref(struct radeon_bo *bo)
462 {
463 }
464
465 static struct radeon_bo *bo_unref(struct radeon_bo *bo)
466 {
467 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
468
469 if (bo->cref <= 0) {
470 bo_legacy->prev->next = bo_legacy->next;
471 if (bo_legacy->next) {
472 bo_legacy->next->prev = bo_legacy->prev;
473 }
474 if (!bo_legacy->is_pending) {
475 bo_free(bo_legacy);
476 }
477 return NULL;
478 }
479 return bo;
480 }
481
482 static int bo_map(struct radeon_bo *bo, int write)
483 {
484 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
485 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
486
487 legacy_wait_pending(bo);
488 bo_legacy->validated = 0;
489 bo_legacy->dirty = 1;
490 bo_legacy->map_count++;
491 bo->ptr = bo_legacy->ptr;
492 /* Read the first pixel in the frame buffer. This should
493 * be a noop, right? In fact without this conform fails as reading
494 * from the framebuffer sometimes produces old results -- the
495 * on-card read cache gets mixed up and doesn't notice that the
496 * framebuffer has been updated.
497 *
498 * Note that we should probably be reading some otherwise unused
499 * region of VRAM, otherwise we might get incorrect results when
500 * reading pixels from the top left of the screen.
501 *
502 * I found this problem on an R420 with glean's texCube test.
503 * Note that the R200 span code also *writes* the first pixel in the
504 * framebuffer, but I've found this to be unnecessary.
505 * -- Nicolai Hähnle, June 2008
506 */
507 if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
508 int p;
509 volatile int *buf = (int*)boml->screen->driScreen->pFB;
510 p = *buf;
511 }
512 return 0;
513 }
514
515 static int bo_unmap(struct radeon_bo *bo)
516 {
517 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
518
519 if (--bo_legacy->map_count > 0) {
520 return 0;
521 }
522 bo->ptr = NULL;
523 return 0;
524 }
525
526 static struct radeon_bo_funcs bo_legacy_funcs = {
527 bo_open,
528 bo_ref,
529 bo_unref,
530 bo_map,
531 bo_unmap
532 };
533
534 static int bo_vram_validate(struct radeon_bo *bo,
535 uint32_t *soffset,
536 uint32_t *eoffset)
537 {
538 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
539 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
540 int r;
541 int retry_count = 0, pending_retry = 0;
542
543 if (!bo_legacy->tobj) {
544 bo_legacy->tobj = CALLOC(sizeof(struct bo_legacy_texture_object));
545 bo_legacy->tobj->parent = bo_legacy;
546 make_empty_list(&bo_legacy->tobj->base);
547 bo_legacy->tobj->base.totalSize = bo->size;
548 retry:
549 r = driAllocateTexture(&boml->texture_heap, 1,
550 &bo_legacy->tobj->base);
551 if (r) {
552 pending_retry = 0;
553 while(boml->cpendings && pending_retry++ < 10000) {
554 legacy_track_pending(boml, 0);
555 retry_count++;
556 if (retry_count > 2) {
557 free(bo_legacy->tobj);
558 bo_legacy->tobj = NULL;
559 fprintf(stderr, "Ouch! vram_validate failed %d\n", r);
560 return -1;
561 }
562 goto retry;
563 }
564 }
565 bo_legacy->offset = boml->texture_offset +
566 bo_legacy->tobj->base.memBlock->ofs;
567 bo_legacy->dirty = 1;
568 }
569
570 assert(bo_legacy->tobj->base.memBlock);
571
572 if (bo_legacy->tobj)
573 driUpdateTextureLRU(&bo_legacy->tobj->base);
574
575 if (bo_legacy->dirty || bo_legacy->tobj->base.dirty_images[0]) {
576 /* Copy to VRAM using a blit.
577 * All memory is 4K aligned. We're using 1024 pixels wide blits.
578 */
579 drm_radeon_texture_t tex;
580 drm_radeon_tex_image_t tmp;
581 int ret;
582
583 tex.offset = bo_legacy->offset;
584 tex.image = &tmp;
585 assert(!(tex.offset & 1023));
586
587 tmp.x = 0;
588 tmp.y = 0;
589 if (bo->size < 4096) {
590 tmp.width = (bo->size + 3) / 4;
591 tmp.height = 1;
592 } else {
593 tmp.width = 1024;
594 tmp.height = (bo->size + 4095) / 4096;
595 }
596 tmp.data = bo_legacy->ptr;
597 tex.format = RADEON_TXFORMAT_ARGB8888;
598 tex.width = tmp.width;
599 tex.height = tmp.height;
600 tex.pitch = MAX2(tmp.width / 16, 1);
601 do {
602 ret = drmCommandWriteRead(bo->bom->fd,
603 DRM_RADEON_TEXTURE,
604 &tex,
605 sizeof(drm_radeon_texture_t));
606 if (ret) {
607 if (RADEON_DEBUG & DEBUG_IOCTL)
608 fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
609 usleep(1);
610 }
611 } while (ret == -EAGAIN);
612 bo_legacy->dirty = 0;
613 bo_legacy->tobj->base.dirty_images[0] = 0;
614 }
615 return 0;
616 }
617
618 /*
619 * radeon_bo_legacy_validate -
620 * returns:
621 * 0 - all good
622 * -EINVAL - mapped buffer can't be validated
623 * -EAGAIN - restart validation we've kicked all the buffers out
624 */
625 int radeon_bo_legacy_validate(struct radeon_bo *bo,
626 uint32_t *soffset,
627 uint32_t *eoffset)
628 {
629 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
630 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
631 int r;
632 int retries = 0;
633
634 if (bo_legacy->map_count) {
635 fprintf(stderr, "bo(%p, %d) is mapped (%d) can't valide it.\n",
636 bo, bo->size, bo_legacy->map_count);
637 return -EINVAL;
638 }
639 if (bo_legacy->static_bo || bo_legacy->validated) {
640 *soffset = bo_legacy->offset;
641 *eoffset = bo_legacy->offset + bo->size;
642 return 0;
643 }
644 if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
645
646 r = bo_vram_validate(bo, soffset, eoffset);
647 if (r) {
648 legacy_track_pending(boml, 0);
649 legacy_kick_all_buffers(boml);
650 retries++;
651 if (retries == 2) {
652 fprintf(stderr,"legacy bo: failed to get relocations into aperture\n");
653 assert(0);
654 exit(-1);
655 }
656 return -EAGAIN;
657 }
658 }
659 *soffset = bo_legacy->offset;
660 *eoffset = bo_legacy->offset + bo->size;
661 bo_legacy->validated = 1;
662 return 0;
663 }
664
665 void radeon_bo_legacy_pending(struct radeon_bo *bo, uint32_t pending)
666 {
667 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
668 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
669
670 bo_legacy->pending = pending;
671 bo_legacy->is_pending++;
672 /* add to pending list */
673 radeon_bo_ref(bo);
674 if (bo_legacy->is_pending > 1) {
675 return;
676 }
677 bo_legacy->pprev = boml->pending_bos.pprev;
678 bo_legacy->pnext = NULL;
679 bo_legacy->pprev->pnext = bo_legacy;
680 boml->pending_bos.pprev = bo_legacy;
681 boml->cpendings++;
682 }
683
684 void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom)
685 {
686 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
687 struct bo_legacy *bo_legacy;
688
689 if (bom == NULL) {
690 return;
691 }
692 bo_legacy = boml->bos.next;
693 while (bo_legacy) {
694 struct bo_legacy *next;
695
696 next = bo_legacy->next;
697 bo_free(bo_legacy);
698 bo_legacy = next;
699 }
700 driDestroyTextureHeap(boml->texture_heap);
701 free(boml->free_handles);
702 free(boml);
703 }
704
705 static struct bo_legacy *radeon_legacy_bo_alloc_static(struct bo_manager_legacy *bom,
706 int size, uint32_t offset)
707 {
708 struct bo_legacy *bo;
709
710 bo = bo_allocate(bom, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
711 if (bo == NULL)
712 return NULL;
713 bo->static_bo = 1;
714 bo->offset = offset + bom->fb_location;
715 bo->base.handle = bo->offset;
716 bo->ptr = bom->screen->driScreen->pFB + offset;
717 if (bo->base.handle > bom->nhandle) {
718 bom->nhandle = bo->base.handle + 1;
719 }
720 radeon_bo_ref(&(bo->base));
721 return bo;
722 }
723
724 struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *scrn)
725 {
726 struct bo_manager_legacy *bom;
727 struct bo_legacy *bo;
728 unsigned size;
729
730 bom = (struct bo_manager_legacy*)
731 calloc(1, sizeof(struct bo_manager_legacy));
732 if (bom == NULL) {
733 return NULL;
734 }
735
736 make_empty_list(&bom->texture_swapped);
737
738 bom->texture_heap = driCreateTextureHeap(0,
739 bom,
740 scrn->texSize[0],
741 12,
742 RADEON_NR_TEX_REGIONS,
743 (drmTextureRegionPtr)scrn->sarea->tex_list[0],
744 &scrn->sarea->tex_age[0],
745 &bom->texture_swapped,
746 sizeof(struct bo_legacy_texture_object),
747 &bo_legacy_tobj_destroy);
748 bom->texture_offset = scrn->texOffset[0];
749
750 bom->base.funcs = &bo_legacy_funcs;
751 bom->base.fd = scrn->driScreen->fd;
752 bom->bos.next = NULL;
753 bom->bos.prev = NULL;
754 bom->pending_bos.pprev = &bom->pending_bos;
755 bom->pending_bos.pnext = NULL;
756 bom->screen = scrn;
757 bom->fb_location = scrn->fbLocation;
758 bom->nhandle = 1;
759 bom->cfree_handles = 0;
760 bom->nfree_handles = 0x400;
761 bom->free_handles = (uint32_t*)malloc(bom->nfree_handles * 4);
762 if (bom->free_handles == NULL) {
763 radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
764 return NULL;
765 }
766
767 /* biggest framebuffer size */
768 size = 4096*4096*4;
769
770 /* allocate front */
771 bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->frontOffset);
772 if (!bo) {
773 radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
774 return NULL;
775 }
776 if (scrn->sarea->tiling_enabled) {
777 bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
778 }
779
780 /* allocate back */
781 bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->backOffset);
782 if (!bo) {
783 radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
784 return NULL;
785 }
786 if (scrn->sarea->tiling_enabled) {
787 bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
788 }
789
790 /* allocate depth */
791 bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->depthOffset);
792 if (!bo) {
793 radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
794 return NULL;
795 }
796 bo->base.flags = 0;
797 if (scrn->sarea->tiling_enabled) {
798 bo->base.flags |= RADEON_BO_FLAGS_MACRO_TILE;
799 bo->base.flags |= RADEON_BO_FLAGS_MICRO_TILE;
800 }
801 return (struct radeon_bo_manager*)bom;
802 }
803
804 void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom)
805 {
806 struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
807 DRI_AGE_TEXTURES(boml->texture_heap);
808 }
809
810 unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo)
811 {
812 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
813
814 if (bo_legacy->static_bo || (bo->domains & RADEON_GEM_DOMAIN_GTT)) {
815 return 0;
816 }
817 return bo->size;
818 }
819
820 int radeon_legacy_bo_is_static(struct radeon_bo *bo)
821 {
822 struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
823 return bo_legacy->static_bo;
824 }
825