~ubuntu-branches/ubuntu/trusty/xserver-xorg-video-ati-lts-utopic/trusty-proposed

« back to all changes in this revision

Viewing changes to src/radeon_vbo.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2015-01-06 10:39:09 UTC
  • Revision ID: package-import@ubuntu.com-20150106103909-ltfacktu9diqgnx5
Tags: upstream-7.4.0
Import upstream version 7.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2009 Red Hat, Inc.
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
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 NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
21
 * SOFTWARE.
 
22
 *
 
23
 * Authors:
 
24
 *    Dave Airlie <airlied@redhat.com>
 
25
 *
 
26
 */
 
27
#ifdef HAVE_CONFIG_H
 
28
#include "config.h"
 
29
#endif
 
30
 
 
31
#include <errno.h>
 
32
#include "radeon.h"
 
33
#include "radeon_bo.h"
 
34
#include "radeon_cs.h"
 
35
 
 
36
#define VBO_SIZE (16*1024)
 
37
 
 
38
/* KMS vertex buffer support - for R600 only but could be used on previous gpus */
 
39
 
 
40
static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn);
 
41
 
 
42
void radeon_vbo_put(ScrnInfoPtr pScrn, struct radeon_vbo_object *vbo)
 
43
{
 
44
 
 
45
    if (vbo->vb_bo) {
 
46
        radeon_bo_unmap(vbo->vb_bo);
 
47
        radeon_bo_unref(vbo->vb_bo);
 
48
        vbo->vb_bo = NULL;
 
49
        vbo->vb_total = 0;
 
50
    }
 
51
 
 
52
    vbo->vb_offset = 0;
 
53
}
 
54
 
 
55
void radeon_vbo_get(ScrnInfoPtr pScrn, struct radeon_vbo_object *vbo)
 
56
{
 
57
    int ret;
 
58
 
 
59
    vbo->vb_bo = radeon_vbo_get_bo(pScrn);
 
60
    if (vbo->vb_bo) {
 
61
        radeon_bo_ref(vbo->vb_bo);
 
62
        ret = radeon_bo_map(vbo->vb_bo, 1);
 
63
        if (ret)
 
64
            FatalError("Failed to map vb %d\n", ret);
 
65
    }
 
66
 
 
67
    vbo->vb_total = VBO_SIZE;
 
68
    vbo->vb_offset = 0;
 
69
    vbo->vb_start_op = vbo->vb_offset;
 
70
}
 
71
 
 
72
/* these functions could migrate to libdrm and
 
73
   be shared with the radeon 3D driver */
 
74
static int radeon_bo_is_idle(struct radeon_bo *bo)
 
75
{
 
76
    uint32_t domain;
 
77
    int ret = radeon_bo_is_busy(bo, &domain);
 
78
    return ret != -EBUSY;
 
79
}
 
80
 
 
81
void radeon_vbo_init_lists(ScrnInfoPtr pScrn)
 
82
{
 
83
    RADEONInfoPtr info = RADEONPTR(pScrn);
 
84
    struct radeon_accel_state *accel_state = info->accel_state;
 
85
 
 
86
    accel_state->use_vbos = TRUE;
 
87
    make_empty_list(&accel_state->bo_free);
 
88
    make_empty_list(&accel_state->bo_wait);
 
89
    make_empty_list(&accel_state->bo_reserved);
 
90
}
 
91
 
 
92
void radeon_vbo_free_lists(ScrnInfoPtr pScrn)
 
93
{
 
94
    RADEONInfoPtr info = RADEONPTR(pScrn);
 
95
    struct radeon_accel_state *accel_state = info->accel_state;
 
96
    struct radeon_dma_bo *dma_bo, *temp;
 
97
 
 
98
    foreach_s(dma_bo, temp, &accel_state->bo_free) {
 
99
        remove_from_list(dma_bo);
 
100
        radeon_bo_unref(dma_bo->bo);
 
101
        free(dma_bo);
 
102
    }
 
103
 
 
104
    foreach_s(dma_bo, temp, &accel_state->bo_wait) {
 
105
        remove_from_list(dma_bo);
 
106
        radeon_bo_unref(dma_bo->bo);
 
107
        free(dma_bo);
 
108
    }
 
109
 
 
110
    foreach_s(dma_bo, temp, &accel_state->bo_reserved) {
 
111
        remove_from_list(dma_bo);
 
112
        radeon_bo_unref(dma_bo->bo);
 
113
        free(dma_bo);
 
114
    }
 
115
}
 
116
 
 
117
void radeon_vbo_flush_bos(ScrnInfoPtr pScrn)
 
118
{
 
119
    RADEONInfoPtr info = RADEONPTR(pScrn);
 
120
    struct radeon_accel_state *accel_state = info->accel_state;
 
121
    struct radeon_dma_bo *dma_bo, *temp;
 
122
    const int expire_at = ++accel_state->bo_free.expire_counter + DMA_BO_FREE_TIME;
 
123
    const int time = accel_state->bo_free.expire_counter;
 
124
 
 
125
    foreach_s(dma_bo, temp, &accel_state->bo_wait) {
 
126
        if (dma_bo->expire_counter == time) {
 
127
            ErrorF("leaking dma buffer\n");
 
128
            while ((dma_bo->bo = radeon_bo_unref(dma_bo->bo))) {}
 
129
            remove_from_list(dma_bo);
 
130
            free(dma_bo);
 
131
            continue;
 
132
        }
 
133
 
 
134
        if (!radeon_bo_is_idle(dma_bo->bo))
 
135
            continue;
 
136
 
 
137
        if (dma_bo->bo->ptr) {
 
138
            ErrorF("bo with pointer on wait list!\n");
 
139
            continue;
 
140
        }
 
141
 
 
142
        remove_from_list(dma_bo);
 
143
        dma_bo->expire_counter = expire_at;
 
144
        insert_at_tail(&accel_state->bo_free, dma_bo);
 
145
    }
 
146
 
 
147
    /* move reserved to wait list */
 
148
    foreach_s(dma_bo, temp, &accel_state->bo_reserved) {
 
149
        remove_from_list(dma_bo);
 
150
        dma_bo->expire_counter = expire_at;
 
151
        insert_at_tail(&accel_state->bo_wait, dma_bo);
 
152
    }
 
153
 
 
154
    /* free bos that have been unused */
 
155
    foreach_s(dma_bo, temp, &accel_state->bo_free) {
 
156
        if (dma_bo->expire_counter != time)
 
157
            break;
 
158
        /* always keep one hanging around at end */
 
159
        if (at_end(&accel_state->bo_free, dma_bo)) {
 
160
            dma_bo->expire_counter = time + DMA_BO_FREE_TIME;
 
161
            break;
 
162
        }
 
163
 
 
164
        remove_from_list(dma_bo);
 
165
        radeon_bo_unref(dma_bo->bo);
 
166
        free(dma_bo);
 
167
    }
 
168
}
 
169
 
 
170
static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn)
 
171
{
 
172
    RADEONInfoPtr info = RADEONPTR(pScrn);
 
173
    struct radeon_accel_state *accel_state = info->accel_state;
 
174
    struct radeon_dma_bo *dma_bo = NULL;
 
175
    struct radeon_bo *bo;
 
176
 
 
177
    if (is_empty_list(&accel_state->bo_free)) {
 
178
        dma_bo = calloc(1, sizeof(struct radeon_dma_bo));
 
179
        if (!dma_bo)
 
180
            return NULL;
 
181
 
 
182
again_alloc:
 
183
        dma_bo->bo = radeon_bo_open(info->bufmgr, 0, VBO_SIZE,
 
184
                                    0, RADEON_GEM_DOMAIN_GTT, 0);
 
185
 
 
186
        if (!dma_bo->bo) {
 
187
            ErrorF("failure to allocate DMA BO\n");
 
188
            return NULL;
 
189
        }
 
190
        insert_at_head(&accel_state->bo_reserved, dma_bo);
 
191
    } else {
 
192
        dma_bo = last_elem(&accel_state->bo_free);
 
193
        remove_from_list(dma_bo);
 
194
        insert_at_head(&accel_state->bo_reserved, dma_bo);
 
195
    }
 
196
 
 
197
    if (is_empty_list(&accel_state->bo_reserved))
 
198
        goto again_alloc;
 
199
 
 
200
    bo = first_elem(&accel_state->bo_reserved)->bo;
 
201
 
 
202
    /* need a space check */
 
203
    if (radeon_cs_space_check_with_bo(info->cs,
 
204
                                      bo,
 
205
                                      RADEON_GEM_DOMAIN_GTT, 0))
 
206
        ErrorF("failed to revalidate\n");
 
207
 
 
208
    return bo;
 
209
}
 
210