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