~ubuntu-branches/ubuntu/precise/mesa/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/r300/radeon_bo_legacy.c

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2012-02-02 12:05:48 UTC
  • mfrom: (1.7.1) (3.3.27 sid)
  • Revision ID: package-import@ubuntu.com-20120202120548-nvkma85jq0h4coix
Tags: 8.0~rc2-0ubuntu4
Drop drisearchdir handling, it is no longer needed with multiarch
and dri-alternates being removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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