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