radeon_vbo.c revision ad43ddac
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#ifdef XF86DRM_MODE 41 42static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn); 43 44void radeon_vbo_put(ScrnInfoPtr pScrn) 45{ 46 RADEONInfoPtr info = RADEONPTR(pScrn); 47 struct radeon_accel_state *accel_state = info->accel_state; 48 49 if (accel_state->vb_bo) { 50 radeon_bo_unmap(accel_state->vb_bo); 51 radeon_bo_unref(accel_state->vb_bo); 52 accel_state->vb_bo = NULL; 53 accel_state->vb_total = 0; 54 } 55 56 accel_state->vb_offset = 0; 57} 58 59void radeon_vbo_get(ScrnInfoPtr pScrn) 60{ 61 RADEONInfoPtr info = RADEONPTR(pScrn); 62 struct radeon_accel_state *accel_state = info->accel_state; 63 64 accel_state->vb_bo = radeon_vbo_get_bo(pScrn); 65 66 accel_state->vb_total = VBO_SIZE; 67 accel_state->vb_offset = 0; 68 accel_state->vb_start_op = accel_state->vb_offset; 69} 70 71/* these functions could migrate to libdrm and 72 be shared with the radeon 3D driver */ 73static int radeon_bo_is_idle(struct radeon_bo *bo) 74{ 75 uint32_t domain; 76 int ret = radeon_bo_is_busy(bo, &domain); 77 return ret != -EBUSY; 78} 79 80void radeon_vbo_init_lists(ScrnInfoPtr pScrn) 81{ 82 RADEONInfoPtr info = RADEONPTR(pScrn); 83 struct radeon_accel_state *accel_state = info->accel_state; 84 85 accel_state->use_vbos = TRUE; 86 make_empty_list(&accel_state->bo_free); 87 make_empty_list(&accel_state->bo_wait); 88 make_empty_list(&accel_state->bo_reserved); 89} 90 91void radeon_vbo_free_lists(ScrnInfoPtr pScrn) 92{ 93 RADEONInfoPtr info = RADEONPTR(pScrn); 94 struct radeon_accel_state *accel_state = info->accel_state; 95 struct radeon_dma_bo *dma_bo, *temp; 96 97 foreach_s(dma_bo, temp, &accel_state->bo_free) { 98 remove_from_list(dma_bo); 99 radeon_bo_unref(dma_bo->bo); 100 xfree(dma_bo); 101 } 102 103 foreach_s(dma_bo, temp, &accel_state->bo_wait) { 104 remove_from_list(dma_bo); 105 radeon_bo_unref(dma_bo->bo); 106 xfree(dma_bo); 107 } 108 109 foreach_s(dma_bo, temp, &accel_state->bo_reserved) { 110 remove_from_list(dma_bo); 111 radeon_bo_unref(dma_bo->bo); 112 xfree(dma_bo); 113 } 114} 115 116void radeon_vbo_flush_bos(ScrnInfoPtr pScrn) 117{ 118 RADEONInfoPtr info = RADEONPTR(pScrn); 119 struct radeon_accel_state *accel_state = info->accel_state; 120 struct radeon_dma_bo *dma_bo, *temp; 121 const int expire_at = ++accel_state->bo_free.expire_counter + DMA_BO_FREE_TIME; 122 const int time = accel_state->bo_free.expire_counter; 123 124 foreach_s(dma_bo, temp, &accel_state->bo_wait) { 125 if (dma_bo->expire_counter == time) { 126 ErrorF("leaking dma buffer\n"); 127 while ((dma_bo->bo = radeon_bo_unref(dma_bo->bo))) {} 128 remove_from_list(dma_bo); 129 xfree(dma_bo); 130 continue; 131 } 132 133 if (!radeon_bo_is_idle(dma_bo->bo)) 134 continue; 135 136 remove_from_list(dma_bo); 137 dma_bo->expire_counter = expire_at; 138 insert_at_tail(&accel_state->bo_free, dma_bo); 139 } 140 141 /* move reserved to wait list */ 142 foreach_s(dma_bo, temp, &accel_state->bo_reserved) { 143 remove_from_list(dma_bo); 144 dma_bo->expire_counter = expire_at; 145 insert_at_tail(&accel_state->bo_wait, dma_bo); 146 } 147 148 /* free bos that have been unused */ 149 foreach_s(dma_bo, temp, &accel_state->bo_free) { 150 if (dma_bo->expire_counter != time) 151 break; 152 /* always keep one hanging around at end */ 153 if (at_end(&accel_state->bo_free, dma_bo)) { 154 dma_bo->expire_counter = time + DMA_BO_FREE_TIME; 155 break; 156 } 157 158 remove_from_list(dma_bo); 159 radeon_bo_unref(dma_bo->bo); 160 xfree(dma_bo); 161 } 162} 163 164static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn) 165{ 166 RADEONInfoPtr info = RADEONPTR(pScrn); 167 struct radeon_accel_state *accel_state = info->accel_state; 168 struct radeon_dma_bo *dma_bo = NULL; 169 struct radeon_bo *bo; 170 171 if (is_empty_list(&accel_state->bo_free)) { 172 dma_bo = xcalloc(1, sizeof(struct radeon_dma_bo)); 173 if (!dma_bo) 174 return NULL; 175 176again_alloc: 177 dma_bo->bo = radeon_bo_open(info->bufmgr, 0, VBO_SIZE, 178 0, RADEON_GEM_DOMAIN_GTT, 0); 179 180 if (!dma_bo->bo) { 181 ErrorF("failure to allocate DMA BO\n"); 182 return NULL; 183 } 184 insert_at_head(&accel_state->bo_reserved, dma_bo); 185 } else { 186 dma_bo = last_elem(&accel_state->bo_free); 187 remove_from_list(dma_bo); 188 insert_at_head(&accel_state->bo_reserved, dma_bo); 189 } 190 191 /* need a space check */ 192 if (radeon_cs_space_check_with_bo(info->cs, 193 first_elem(&accel_state->bo_reserved)->bo, 194 RADEON_GEM_DOMAIN_GTT, 0)) 195 fprintf(stderr,"failed to revalidated\n"); 196 197 if (is_empty_list(&accel_state->bo_reserved)) { 198 goto again_alloc; 199 } 200 201 bo = first_elem(&accel_state->bo_reserved)->bo; 202 radeon_bo_ref(bo); 203 return bo; 204} 205 206#endif 207